[SD3] first commit with SD3 inplace - not complete yet

This commit is contained in:
Antz 2016-03-27 20:47:30 +01:00 committed by Antz
parent 35415eb738
commit afc2df2f7d
603 changed files with 222771 additions and 1729 deletions

View file

@ -48,8 +48,7 @@ option(ACE_USE_EXTERNAL "Use external ACE" OFF)
option(POSTGRESQL "Use PostgreSQL instead of MySQL" OFF)
option(BUILD_TOOLS "Build the map/vmap/mmap extractors" ON)
option(SCRIPT_LIB_ELUNA "Compile with support for Eluna scripts" OFF)
option(SCRIPT_LIB_SD2 "Compile with support for ScriptDev2 scripts" ON)
#option(SCRIPT_LIB_SD3 "Compile with support for ScriptDev3 scripts" OFF)
option(SCRIPT_LIB_SD3 "Compile with support for ScriptDev2 scripts" ON)
option(PLAYERBOTS "Enable Player Bots" OFF)
option(SOAP "Enable remote access via SOAP" OFF)
# Hidden option to enable/disable PCH. DEV ONLY!
@ -70,8 +69,7 @@ message(
SOAP Enable remote access via SOAP
Scripting engines:
SCRIPT_LIB_ELUNA Compile with support for Eluna scripts
SCRIPT_LIB_SD2 Compile with support for ScriptDev2 scripts
SCRIPT_LIB_SD3 Compile with support for ScriptDev3 scripts
SCRIPT_LIB_SD3 Compile with support for ScriptDev2 scripts
Modules:
PLAYERBOTS Enable Player Bots
To set an option simply type -D<OPTION>=<VALUE> after 'cmake <srcs>'.
@ -173,20 +171,13 @@ else()
message(STATUS "Script engine Eluna : No (default)")
endif()
if(SCRIPT_LIB_SD2)
message(STATUS "Script engine SD2 : Yes (default)")
add_definitions(-DENABLE_SD2)
if(SCRIPT_LIB_SD3)
message(STATUS "Script engine SD3 : Yes (default)")
add_definitions(-DENABLE_SD3)
else()
message(STATUS "Script engine SD2 : No")
message(STATUS "Script engine SD3 : No")
endif()
#if(SCRIPT_LIB_SD3)
# message(STATUS "Script engine SD3 : Yes")
# add_definitions(-DENABLE_SD3)
#else()
# message(STATUS "Script engine SD3 : No (default)")
#endif()
#if(PLAYERBOTS)
# message(STATUS "Enable Player Bots : Yes (default)")
# add_definitions(-DENABLE_PLAYERBOTS)

View file

@ -172,8 +172,8 @@ endif()
# add_dependencies(${LIBRARY_NAME} Bots)
#endif()
if(SCRIPT_LIB_SD2)
include_directories(${CMAKE_SOURCE_DIR}/src/modules/SD2)
if(SCRIPT_LIB_SD3)
include_directories(${CMAKE_SOURCE_DIR}/src/modules/SD3)
target_link_libraries(${LIBRARY_NAME} mangosscript)
add_dependencies(${LIBRARY_NAME} mangosscript)
endif()

View file

@ -358,7 +358,7 @@ bool ChatHandler::HandleGPSCommand(char* args)
GridMapLiquidStatus res = terrain->getLiquidStatus(obj->GetPositionX(), obj->GetPositionY(), obj->GetPositionZ(), MAP_ALL_LIQUIDS, &liquid_status);
if (res)
{
PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.type_flags, res);
PSendSysMessage(LANG_LIQUID_STATUS, liquid_status.level, liquid_status.depth_level, liquid_status.CreatureTypeFlags, res);
}
// Additional vmap debugging help

View file

@ -2180,12 +2180,12 @@ bool ChatHandler::HandleNpcFactionIdCommand(char* args)
// update in memory
if (CreatureInfo const* cinfo = pCreature->GetCreatureInfo())
{
const_cast<CreatureInfo*>(cinfo)->faction_A = factionId;
const_cast<CreatureInfo*>(cinfo)->faction_H = factionId;
const_cast<CreatureInfo*>(cinfo)->FactionAlliance = factionId;
const_cast<CreatureInfo*>(cinfo)->FactionHorde = factionId;
}
// and DB
WorldDatabase.PExecuteLog("UPDATE creature_template SET faction_A = '%u', faction_H = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
WorldDatabase.PExecuteLog("UPDATE creature_template SET factionAlliance = '%u', factionHorde = '%u' WHERE entry = '%u'", factionId, factionId, pCreature->GetEntry());
return true;
}

View file

@ -533,7 +533,7 @@ NavTerrain PathFinder::getNavTerrain(float x, float y, float z)
GridMapLiquidData data;
m_sourceUnit->GetTerrain()->getLiquidStatus(x, y, z, MAP_ALL_LIQUIDS, &data);
switch (data.type_flags)
switch (data.CreatureTypeFlags)
{
case MAP_LIQUID_TYPE_WATER:
case MAP_LIQUID_TYPE_OCEAN:

View file

@ -55,6 +55,9 @@
#include "CellImpl.h"
#include "movement/MoveSplineInit.h"
#include "CreatureLinkingMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
// apply implementation of the singletons
#include "Policies/Singleton.h"
@ -69,7 +72,7 @@ TrainerSpell const* TrainerSpellData::Find(uint32 spell_id) const
{
TrainerSpellMap::const_iterator itr = spellList.find(spell_id);
if (itr != spellList.end())
return &itr->second;
{ return &itr->second; }
return NULL;
}
@ -165,7 +168,7 @@ Creature::Creature(CreatureSubtype subtype) : Unit(),
m_corpseDecayTimer(0), m_respawnTime(0), m_respawnDelay(25), m_corpseDelay(60), m_respawnradius(5.0f),
m_subtype(subtype), m_defaultMovementType(IDLE_MOTION_TYPE), m_equipmentId(0),
m_AlreadyCallAssistance(false), m_AlreadySearchedAssistance(false),
m_regenHealth(true), m_AI_locked(false), m_isDeadByDefault(false),
m_regenHealth(true), m_AI_locked(false), m_IsDeadByDefault(false),
m_temporaryFactionFlags(TEMPFACTION_NONE),
m_meleeDamageSchoolMask(SPELL_SCHOOL_MASK_NORMAL), m_originalEntry(0),
m_creatureInfo(NULL)
@ -175,10 +178,11 @@ Creature::Creature(CreatureSubtype subtype) : Unit(),
m_valuesCount = UNIT_END;
for (int i = 0; i < CREATURE_MAX_SPELLS; ++i)
m_spells[i] = 0;
{ m_spells[i] = 0; }
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
DisableReputationGain = false;
SetWalk(true, true);
}
@ -195,18 +199,28 @@ Creature::~Creature()
void Creature::AddToWorld()
{
#ifdef ENABLE_ELUNA
if (!IsInWorld())
sEluna->OnAddToWorld(this);
#endif /* ENABLE_ELUNA */
///- Register the creature for guid lookup
if (!IsInWorld() && GetObjectGuid().IsCreatureOrVehicle())
GetMap()->GetObjectsStore().insert<Creature>(GetObjectGuid(), (Creature*)this);
{ GetMap()->GetObjectsStore().insert<Creature>(GetObjectGuid(), (Creature*)this); }
Unit::AddToWorld();
}
void Creature::RemoveFromWorld()
{
#ifdef ENABLE_ELUNA
if (IsInWorld())
sEluna->OnRemoveFromWorld(this);
#endif /* ENABLE_ELUNA */
///- Remove the creature from the accessor
if (IsInWorld() && GetObjectGuid().IsCreatureOrVehicle())
GetMap()->GetObjectsStore().erase<Creature>(GetObjectGuid(), (Creature*)NULL);
{ GetMap()->GetObjectsStore().erase<Creature>(GetObjectGuid(), (Creature*)NULL); }
Unit::RemoveFromWorld();
}
@ -215,13 +229,13 @@ void Creature::RemoveCorpse()
{
// since pool system can fail to roll unspawned object, this one can remain spawned, so must set respawn nevertheless
if (uint16 poolid = sPoolMgr.IsPartOfAPool<Creature>(GetGUIDLow()))
sPoolMgr.UpdatePool<Creature>(*GetMap()->GetPersistentState(), poolid, GetGUIDLow());
{ sPoolMgr.UpdatePool<Creature>(*GetMap()->GetPersistentState(), poolid, GetGUIDLow()); }
if (!IsInWorld()) // can be despawned by update pool
return;
if (!IsInWorld()) // can be despawned by update pool
{ return; }
if ((getDeathState() != CORPSE && !m_isDeadByDefault) || (getDeathState() != ALIVE && m_isDeadByDefault))
return;
if ((getDeathState() != CORPSE && !m_IsDeadByDefault) || (getDeathState() != ALIVE && m_IsDeadByDefault))
{ return; }
DEBUG_FILTER_LOG(LOG_FILTER_AI_AND_MOVEGENSS, "Removing corpse of %s ", GetGuidStr().c_str());
@ -236,11 +250,11 @@ void Creature::RemoveCorpse()
uint32 respawnDelay = 0;
if (AI())
AI()->CorpseRemoved(respawnDelay);
{ AI()->CorpseRemoved(respawnDelay); }
// script can set time (in seconds) explicit, override the original
if (respawnDelay)
m_respawnTime = time(NULL) + respawnDelay;
{ m_respawnTime = time(NULL) + respawnDelay; }
float x, y, z, o;
GetRespawnCoord(x, y, z, &o);
@ -254,14 +268,14 @@ void Creature::RemoveCorpse()
UpdateObjectVisibility();
}
/*
/**
* change the entry of creature until respawn
*/
bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameEventCreatureData const* eventData /*=NULL*/)
{
// use game event entry if any instead default suggested
if (eventData && eventData->entry_id)
Entry = eventData->entry_id;
{ Entry = eventData->entry_id; }
CreatureInfo const* normalInfo = ObjectMgr::GetCreatureTemplate(Entry);
if (!normalInfo)
@ -270,6 +284,8 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
return false;
}
// difficulties for dungeons/battleground ordered in normal way
// and if more high version not exist must be used lesser version
CreatureInfo const* cinfo = normalInfo;
for (Difficulty diff = GetMap()->GetDifficulty(); diff > REGULAR_DIFFICULTY; diff = GetPrevDifficulty(diff, GetMap()->IsRaid()))
{
@ -288,7 +304,7 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
SetEntry(Entry); // normal entry always
m_creatureInfo = cinfo; // map mode related always
SetObjectScale(cinfo->scale);
SetObjectScale(cinfo->Scale);
// equal to player Race field, but creature does not have race
SetByteValue(UNIT_FIELD_BYTES_0, 0, 0);
@ -326,10 +342,10 @@ bool Creature::InitEntry(uint32 Entry, CreatureData const* data /*=NULL*/, GameE
}
else if (!data || data->equipmentId == 0)
{
if (cinfo->equipmentId == 0)
LoadEquipment(normalInfo->equipmentId); // use default from normal template if diff does not have any
if (cinfo->EquipmentTemplateId == 0)
LoadEquipment(normalInfo->EquipmentTemplateId); // use default from normal template if diff does not have any
else
LoadEquipment(cinfo->equipmentId); // else use from diff template
LoadEquipment(cinfo->EquipmentTemplateId); // else use from diff template
}
else if (data && data->equipmentId != -1)
{
@ -366,9 +382,9 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
SelectLevel(GetCreatureInfo(), preserveHPAndPower ? GetHealthPercent() : 100.0f, 100.0f);
if (team == HORDE)
setFaction(GetCreatureInfo()->faction_H);
setFaction(GetCreatureInfo()->FactionHorde);
else
setFaction(GetCreatureInfo()->faction_A);
setFaction(GetCreatureInfo()->FactionAlliance);
SetUInt32Value(UNIT_NPC_FLAGS, GetCreatureInfo()->npcflag);
@ -404,7 +420,7 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
UpdateAllStats();
// checked and error show at loading templates
if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(GetCreatureInfo()->faction_A))
if (FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(GetCreatureInfo()->FactionAlliance))
{
if (factionTemplate->factionFlags & FACTION_TEMPLATE_FLAG_PVP)
SetPvP(true);
@ -420,7 +436,7 @@ bool Creature::UpdateEntry(uint32 Entry, Team team, const CreatureData* data /*=
for (int i = 0; i < CREATURE_MAX_SPELLS; ++i)
m_spells[i] = templateSpells->spells[i];
SetVehicleId(GetCreatureInfo()->vehicleId, 0);
SetVehicleId(GetCreatureInfo()->VehicleTemplateId, 0);
// if eventData set then event active and need apply spell_start
if (eventData)
@ -520,7 +536,7 @@ void Creature::Update(uint32 update_diff, uint32 diff)
SelectLevel(cinfo);
SetUInt32Value(UNIT_DYNAMIC_FLAGS, UNIT_DYNFLAG_NONE);
if (m_isDeadByDefault)
if (m_IsDeadByDefault)
{
SetDeathState(JUST_DIED);
SetHealth(0);
@ -546,7 +562,7 @@ void Creature::Update(uint32 update_diff, uint32 diff)
{
Unit::Update(update_diff, diff);
if (m_isDeadByDefault)
if (m_IsDeadByDefault)
break;
if (m_corpseDecayTimer <= update_diff)
@ -568,7 +584,7 @@ void Creature::Update(uint32 update_diff, uint32 diff)
}
case ALIVE:
{
if (m_isDeadByDefault)
if (m_IsDeadByDefault)
{
if (m_corpseDecayTimer <= update_diff)
{
@ -764,7 +780,7 @@ bool Creature::Create(uint32 guidlow, CreatureCreatePos& cPos, CreatureInfo cons
if (InstanceData* iData = GetMap()->GetInstanceData())
iData->OnCreatureCreate(this);
switch (GetCreatureInfo()->rank)
switch (GetCreatureInfo()->Rank)
{
case CREATURE_ELITE_RARE:
m_corpseDelay = sWorld.getConfig(CONFIG_UINT32_CORPSE_DECAY_RARE);
@ -1110,7 +1126,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
data.currentwaypoint = 0;
data.curhealth = GetHealth();
data.curmana = GetPower(POWER_MANA);
data.is_dead = m_isDeadByDefault;
data.is_dead = m_IsDeadByDefault;
// prevent add data integrity problems
data.movementType = !m_respawnradius && GetDefaultMovementType() == RANDOM_MOTION_TYPE
? IDLE_MOTION_TYPE : GetDefaultMovementType();
@ -1148,7 +1164,7 @@ void Creature::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
void Creature::SelectLevel(const CreatureInfo* cinfo, float percentHealth, float percentMana)
{
uint32 rank = IsPet() ? 0 : cinfo->rank;
uint32 rank = IsPet() ? 0 : cinfo->Rank;
// level
uint32 minlevel = std::min(cinfo->maxlevel, cinfo->minlevel);
@ -1304,8 +1320,8 @@ bool Creature::LoadFromDB(uint32 guidlow, Map* map)
m_respawnDelay = data->spawntimesecs;
m_corpseDelay = std::min(m_respawnDelay * 9 / 10, m_corpseDelay); // set corpse delay to 90% of the respawn delay
m_isDeadByDefault = data->is_dead;
m_deathState = m_isDeadByDefault ? DEAD : ALIVE;
m_IsDeadByDefault = data->is_dead;
m_deathState = m_IsDeadByDefault ? DEAD : ALIVE;
m_respawnTime = map->GetPersistentState()->GetCreatureRespawnTime(GetGUIDLow());
@ -1329,7 +1345,7 @@ bool Creature::LoadFromDB(uint32 guidlow, Map* map)
uint32 curhealth = data->curhealth;
if (curhealth)
{
curhealth = uint32(curhealth * _GetHealthMod(GetCreatureInfo()->rank));
curhealth = uint32(curhealth * _GetHealthMod(GetCreatureInfo()->Rank));
if (curhealth < 1)
curhealth = 1;
}
@ -1505,7 +1521,7 @@ float Creature::GetAttackDistance(Unit const* pl) const
void Creature::SetDeathState(DeathState s)
{
if ((s == JUST_DIED && !m_isDeadByDefault) || (s == JUST_ALIVED && m_isDeadByDefault))
if ((s == JUST_DIED && !m_IsDeadByDefault) || (s == JUST_ALIVED && m_IsDeadByDefault))
{
m_corpseDecayTimer = m_corpseDelay * IN_MILLISECONDS; // the max/default time for corpse decay (before creature is looted/AllLootRemovedFromCorpse() is called)
m_respawnTime = time(NULL) + m_respawnDelay; // respawn delay (spawntimesecs)
@ -1618,7 +1634,7 @@ bool Creature::IsImmuneToSpellEffect(SpellEntry const* spellInfo, SpellEffectInd
return true;
// Taunt immunity special flag check
if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NOT_TAUNTABLE)
if (GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NOT_TAUNTABLE)
{
// Taunt aura apply check
if (spellEffect->Effect == SPELL_EFFECT_APPLY_AURA)
@ -1759,13 +1775,13 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
if (pl->isGameMaster())
return true;
if (GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_INVISIBLE)
if (GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_INVISIBLE)
return false;
// Live player (or with not release body see live creatures or death creatures with corpse disappearing time > 0
if (pl->IsAlive() || pl->GetDeathTimer() > 0)
{
return (IsAlive() || m_corpseDecayTimer > 0 || (m_isDeadByDefault && m_deathState == CORPSE));
return (IsAlive() || m_corpseDecayTimer > 0 || (m_IsDeadByDefault && m_deathState == CORPSE));
}
// Dead player see live creatures near own corpse
@ -1781,7 +1797,7 @@ bool Creature::IsVisibleInGridForPlayer(Player* pl) const
}
// Dead player can see ghosts
if (GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_GHOST_VISIBLE)
if (GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_GHOST_VISIBLE)
return true;
// and not see any other
@ -2450,7 +2466,7 @@ void Creature::ClearTemporaryFaction()
return;
// Reset to original faction
setFaction(GetCreatureInfo()->faction_A);
setFaction(GetCreatureInfo()->FactionAlliance);
// Reset UNIT_FLAG_NON_ATTACKABLE, UNIT_FLAG_OOC_NOT_ATTACKABLE or UNIT_FLAG_PASSIVE flags
if (m_temporaryFactionFlags & TEMPFACTION_TOGGLE_NON_ATTACKABLE && GetCreatureInfo()->unit_flags & UNIT_FLAG_NON_ATTACKABLE)
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE);

View file

@ -90,13 +90,13 @@ struct CreatureInfo
uint32 minmana;
uint32 maxmana;
uint32 armor;
uint32 faction_A;
uint32 faction_H;
uint32 FactionAlliance;
uint32 FactionHorde;
uint32 npcflag;
float speed_walk;
float speed_run;
float scale;
uint32 rank;
float Scale;
uint32 Rank;
float mindmg;
float maxdmg;
uint32 dmgschool;
@ -117,7 +117,7 @@ struct CreatureInfo
float maxrangedmg;
uint32 rangedattackpower;
uint32 type; // enum CreatureType values
uint32 type_flags; // enum CreatureTypeFlags mask values
uint32 CreatureTypeFlags; // enum CreatureTypeFlags mask values
uint32 lootid;
uint32 pickpocketLootId;
uint32 SkinLootId;
@ -139,42 +139,42 @@ struct CreatureInfo
uint32 questItems[6];
uint32 movementId;
bool RegenHealth;
uint32 vehicleId;
uint32 equipmentId;
uint32 VehicleTemplateId;
uint32 EquipmentTemplateId;
uint32 trainerId;
uint32 vendorId;
uint32 MechanicImmuneMask;
uint32 flags_extra;
uint32 ExtraFlags;
uint32 ScriptID;
// helpers
HighGuid GetHighGuid() const
{
return vehicleId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT;
return VehicleTemplateId ? HIGHGUID_VEHICLE : HIGHGUID_UNIT;
}
ObjectGuid GetObjectGuid(uint32 lowguid) const { return ObjectGuid(GetHighGuid(), Entry, lowguid); }
SkillType GetRequiredLootSkill() const
{
if (type_flags & CREATURE_TYPEFLAGS_HERBLOOT)
return SKILL_HERBALISM;
else if (type_flags & CREATURE_TYPEFLAGS_MININGLOOT)
return SKILL_MINING;
else if (type_flags & CREATURE_TYPEFLAGS_ENGINEERLOOT)
if (CreatureTypeFlags & CREATURE_TYPEFLAGS_HERBLOOT)
{ return SKILL_HERBALISM; }
else if (CreatureTypeFlags & CREATURE_TYPEFLAGS_MININGLOOT)
{ return SKILL_MINING; }
else if (CreatureTypeFlags & CREATURE_TYPEFLAGS_ENGINEERLOOT)
return SKILL_ENGINEERING;
else
return SKILL_SKINNING; // normal case
{ return SKILL_SKINNING; } // normal case
}
bool IsExotic() const
{
return (type_flags & CREATURE_TYPEFLAGS_EXOTIC);
return (CreatureTypeFlags & CREATURE_TYPEFLAGS_EXOTIC);
}
bool isTameable(bool exotic) const
{
if (type != CREATURE_TYPE_BEAST || family == 0 || (type_flags & CREATURE_TYPEFLAGS_TAMEABLE) == 0)
if (type != CREATURE_TYPE_BEAST || family == 0 || (CreatureTypeFlags & CREATURE_TYPEFLAGS_TAMEABLE) == 0)
return false;
// if can tame exotic then can tame any temable
@ -376,7 +376,7 @@ struct VendorItemData
void Clear()
{
for (VendorItemList::const_iterator itr = m_items.begin(); itr != m_items.end(); ++itr)
delete(*itr);
{ delete(*itr); }
m_items.clear();
}
};
@ -488,7 +488,7 @@ enum TemporaryFactionFlags // Used at real fact
TEMPFACTION_ALL,
};
class Creature : public Unit
class Creature : public Unit
{
CreatureAI* i_AI;
@ -521,15 +521,15 @@ class Creature : public Unit
bool IsCorpse() const { return getDeathState() == CORPSE; }
bool IsDespawned() const { return getDeathState() == DEAD; }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
uint32 GetCorpseDelay() const { return m_corpseDelay; }
void SetCorpseDelay(uint32 delay) { m_corpseDelay = delay; }
uint32 GetCorpseDelay() const { return m_corpseDelay; }
bool IsRacialLeader() const { return GetCreatureInfo()->RacialLeader; }
bool IsCivilian() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_CIVILIAN; }
bool IsGuard() const { return GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_GUARD; }
bool IsCivilian() const { return GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_CIVILIAN; }
bool IsGuard() const { return GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_GUARD; }
bool CanWalk() const { return GetCreatureInfo()->InhabitType & INHABIT_GROUND; }
virtual bool CanSwim() const { return GetCreatureInfo()->InhabitType & INHABIT_WATER; }
bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_UNK_2) || HasAuraType(SPELL_AURA_FLY); }
bool CanFly() const { return (GetCreatureInfo()->InhabitType & INHABIT_AIR) || (GetByteValue(UNIT_FIELD_BYTES_1, 3) & UNIT_BYTE1_FLAG_FLY_ANIM) || HasAuraType(SPELL_AURA_FLY); }
bool IsTrainerOf(Player* player, bool msg) const;
bool CanInteractWithBattleMaster(Player* player, bool msg) const;
@ -545,18 +545,18 @@ class Creature : public Unit
bool IsElite() const
{
if (IsPet())
return false;
{ return false; }
uint32 rank = GetCreatureInfo()->rank;
return rank != CREATURE_ELITE_NORMAL && rank != CREATURE_ELITE_RARE;
uint32 Rank = GetCreatureInfo()->Rank;
return Rank != CREATURE_ELITE_NORMAL && Rank != CREATURE_ELITE_RARE;
}
bool IsWorldBoss() const
{
if (IsPet())
return false;
{ return false; }
return GetCreatureInfo()->rank == CREATURE_ELITE_WORLDBOSS;
return GetCreatureInfo()->Rank == CREATURE_ELITE_WORLDBOSS;
}
uint32 GetLevelForTarget(Unit const* target) const override; // overwrite Unit::GetLevelForTarget for boss level support
@ -634,17 +634,50 @@ class Creature : public Unit
virtual void DeleteFromDB(); // overwrited in Pet
static void DeleteFromDB(uint32 lowguid, CreatureData const* data);
/// Represent the loots available on the creature.
Loot loot;
/// Indicates whether the creature has has been pickpocked.
bool lootForPickPocketed;
/// Indicates whether the creature has been checked.
bool lootForBody;
/// Indicates whether the creature has been skinned.
bool lootForSkin;
/**
* Method preparing the creature for the loot state. Based on the previous loot state, the loot ID provided in the database and the creature's type,
* this method updates the state of the creature for loots.
*
* At the end of this method, the creature loot state may be:
* Lootable: UNIT_DYNFLAG_LOOTABLE
* Skinnable: UNIT_FLAG_SKINNABLE
* Not lootable: No flag
*/
void PrepareBodyLootState();
/**
* function returning the GUID of the loot recipient (a player GUID).
*
* \return ObjectGuid Player GUID.
*/
ObjectGuid GetLootRecipientGuid() const { return m_lootRecipientGuid; }
uint32 GetLootGroupRecipientId() const { return m_lootGroupRecipientId; }
Player* GetLootRecipient() const; // use group cases as prefered
Group* GetGroupLootRecipient() const;
/**
* function indicating whether the whether the creature has a looter recipient defined (either a group ID, either a player GUID).
*
* \return boolean true if the creature has a recipient defined, false otherwise.
*/
bool HasLootRecipient() const { return m_lootGroupRecipientId || m_lootRecipientGuid; }
/**
* function indicating whether the recipient is a group.
*
* \return boolean true if the creature's recipient is a group, false otherwise.
*/
bool IsGroupLootRecipient() const { return m_lootGroupRecipientId; }
void SetLootRecipient(Unit* unit);
void AllLootRemovedFromCorpse();
@ -680,7 +713,7 @@ class Creature : public Unit
bool IsVisibleInGridForPlayer(Player* pl) const override;
void RemoveCorpse();
bool IsDeadByDefault() const { return m_isDeadByDefault; };
bool IsDeadByDefault() const { return m_IsDeadByDefault; };
void ForcedDespawn(uint32 timeMSToDespawn = 0);
@ -718,9 +751,9 @@ class Creature : public Unit
virtual uint32 GetPetAutoSpellOnPos(uint8 pos) const
{
if (pos >= CREATURE_MAX_SPELLS || m_charmInfo->GetCharmSpell(pos)->GetType() != ACT_ENABLED)
return 0;
{ return 0; }
else
return m_charmInfo->GetCharmSpell(pos)->GetAction();
{ return m_charmInfo->GetCharmSpell(pos)->GetAction(); }
}
void SetCombatStartPosition(float x, float y, float z) { m_combatStartX = x; m_combatStartY = y; m_combatStartZ = z; }
@ -731,7 +764,7 @@ class Creature : public Unit
void GetRespawnCoord(float& x, float& y, float& z, float* ori = NULL, float* dist = NULL) const;
void ResetRespawnCoord();
void SetDeadByDefault(bool death_state) { m_isDeadByDefault = death_state; }
void SetDeadByDefault(bool death_state) { m_IsDeadByDefault = death_state; }
void SetFactionTemporary(uint32 factionId, uint32 tempFactionFlags = TEMPFACTION_ALL);
void ClearTemporaryFaction();
@ -739,11 +772,10 @@ class Creature : public Unit
void SendAreaSpiritHealerQueryOpcode(Player* pl);
void SetVirtualItem(VirtualItemSlot slot, uint32 item_id) { SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + slot, item_id); }
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
bool IsReputationGainDisabled() { return DisableReputationGain; }
void SetVirtualItem(VirtualItemSlot slot, uint32 item_id) { SetUInt32Value(UNIT_VIRTUAL_ITEM_SLOT_ID + slot, item_id); }
void SetDisableReputationGain(bool disable) { DisableReputationGain = disable; }
bool IsReputationGainDisabled() { return DisableReputationGain; }
protected:
bool MeetsSelectAttackingRequirement(Unit* pTarget, SpellEntry const* pSpellInfo, uint32 selectFlags) const;
@ -785,7 +817,7 @@ class Creature : public Unit
bool m_AlreadySearchedAssistance;
bool m_regenHealth;
bool m_AI_locked;
bool m_isDeadByDefault;
bool m_IsDeadByDefault;
uint32 m_temporaryFactionFlags; // used for real faction changes (not auras etc)
SpellSchoolMask m_meleeDamageSchoolMask;
@ -795,9 +827,9 @@ class Creature : public Unit
float m_combatStartY;
float m_combatStartZ;
Position m_respawnPos;
Position m_respawnPos;
bool DisableReputationGain;
bool DisableReputationGain;
private:
GridReference<Creature> m_gridRef;

View file

@ -30,6 +30,8 @@
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
static_assert(MAXIMAL_AI_EVENT_EVENTAI <= 32, "Maximal 32 AI_EVENTs supported with EventAI");
CreatureAI::~CreatureAI()
{
}
@ -37,7 +39,7 @@ CreatureAI::~CreatureAI()
void CreatureAI::AttackedBy(Unit* attacker)
{
if (!m_creature->getVictim())
AttackStart(attacker);
{ AttackStart(attacker); }
}
CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry* pSpell, bool isTriggered)
@ -47,17 +49,17 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry* pSpell,
{
// State does not allow
if (m_creature->hasUnitState(UNIT_STAT_CAN_NOT_REACT_OR_LOST_CONTROL))
return CAST_FAIL_STATE;
{ return CAST_FAIL_STATE; }
if (pSpell->GetPreventionType() == SPELL_PREVENTION_TYPE_SILENCE && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
return CAST_FAIL_STATE;
{ return CAST_FAIL_STATE; }
if (pSpell->GetPreventionType() == SPELL_PREVENTION_TYPE_PACIFY && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED))
return CAST_FAIL_STATE;
{ return CAST_FAIL_STATE; }
// Check for power (also done by Spell::CheckCast())
if (m_creature->GetPower((Powers)pSpell->powerType) < Spell::CalculatePowerCost(pSpell, m_creature))
return CAST_FAIL_POWER;
{ return CAST_FAIL_POWER; }
}
if (const SpellRangeEntry* pSpellRange = sSpellRangeStore.LookupEntry(pSpell->rangeIndex))
@ -68,18 +70,18 @@ CanCastResult CreatureAI::CanCastSpell(Unit* pTarget, const SpellEntry* pSpell,
float fDistance = m_creature->GetCombatDistance(pTarget, pSpell->rangeIndex == SPELL_RANGE_IDX_COMBAT);
if (fDistance > (m_creature->IsHostileTo(pTarget) ? pSpellRange->maxRange : pSpellRange->maxRangeFriendly))
return CAST_FAIL_TOO_FAR;
{ return CAST_FAIL_TOO_FAR; }
float fMinRange = m_creature->IsHostileTo(pTarget) ? pSpellRange->minRange : pSpellRange->minRangeFriendly;
if (fMinRange && fDistance < fMinRange)
return CAST_FAIL_TOO_CLOSE;
{ return CAST_FAIL_TOO_CLOSE; }
}
return CAST_OK;
}
else
return CAST_FAIL_OTHER;
{ return CAST_FAIL_OTHER; }
}
CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32 uiCastFlags, ObjectGuid uiOriginalCasterGUID)
@ -87,7 +89,7 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
Unit* pCaster = m_creature;
if (uiCastFlags & CAST_FORCE_TARGET_SELF)
pCaster = pTarget;
{ pCaster = pTarget; }
// Allowed to cast only if not casting (unless we interrupt ourself) or if spell is triggered
if (!pCaster->IsNonMeleeSpellCasted(false) || (uiCastFlags & (CAST_TRIGGERED | CAST_INTERRUPT_PREVIOUS)))
@ -98,21 +100,21 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
if (uiCastFlags & CAST_AURA_NOT_PRESENT)
{
if (pTarget->HasAura(uiSpell))
return CAST_FAIL_TARGET_AURA;
{ return CAST_FAIL_TARGET_AURA; }
}
// Check if cannot cast spell
// Check if can not cast spell
if (!(uiCastFlags & (CAST_FORCE_TARGET_SELF | CAST_FORCE_CAST)))
{
CanCastResult castResult = CanCastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED);
if (castResult != CAST_OK)
return castResult;
{ return castResult; }
}
// Interrupt any previous spell
if (uiCastFlags & CAST_INTERRUPT_PREVIOUS && pCaster->IsNonMeleeSpellCasted(false))
pCaster->InterruptNonMeleeSpells(false);
{ pCaster->InterruptNonMeleeSpells(false); }
pCaster->CastSpell(pTarget, pSpell, uiCastFlags & CAST_TRIGGERED, NULL, NULL, uiOriginalCasterGUID);
return CAST_OK;
@ -124,7 +126,7 @@ CanCastResult CreatureAI::DoCastSpellIfCan(Unit* pTarget, uint32 uiSpell, uint32
}
}
else
return CAST_FAIL_IS_CASTING;
{ return CAST_FAIL_IS_CASTING; }
}
bool CreatureAI::DoMeleeAttackIfReady()
@ -179,7 +181,7 @@ class AiDelayEventAround : public BasicEvent
// Pushing guids because in delay can happen some creature gets despawned => invalid pointer
m_receiverGuids.reserve(receivers.size());
for (std::list<Creature*>::const_iterator itr = receivers.begin(); itr != receivers.end(); ++itr)
m_receiverGuids.push_back((*itr)->GetObjectGuid());
{ m_receiverGuids.push_back((*itr)->GetObjectGuid()); }
}
bool Execute(uint64 /*e_time*/, uint32 /*p_time*/) override
@ -207,12 +209,12 @@ class AiDelayEventAround : public BasicEvent
private:
AiDelayEventAround();
ObjectGuid m_invokerGuid;
GuidVector m_receiverGuids;
Creature& m_owner;
AIEventType m_eventType;
ObjectGuid m_invokerGuid;
Creature& m_owner;
uint32 m_miscValue;
GuidVector m_receiverGuids;
};
void CreatureAI::SendAIEventAround(AIEventType eventType, Unit* pInvoker, uint32 uiDelay, float fRadius, uint32 miscValue /*=0*/) const

View file

@ -52,7 +52,8 @@ enum CanCastResult
CAST_FAIL_TOO_CLOSE = 4,
CAST_FAIL_POWER = 5,
CAST_FAIL_STATE = 6,
CAST_FAIL_TARGET_AURA = 7
CAST_FAIL_TARGET_AURA = 7,
CAST_FAIL_NO_LOS = 8
};
enum CastFlags
@ -65,6 +66,14 @@ enum CastFlags
CAST_AURA_NOT_PRESENT = 0x20, // Only casts the spell if the target does not have an aura from the spell
};
enum CombatMovementFlags
{
COMBAT_MOVEMENT_SCRIPT = 0x01, // Combat movement enforced by script
COMBAT_MOVEMENT_LOS = 0x02, // Combat movement triggered by LoS issues
COMBAT_MOVEMENT_OOM = 0x04, // Combat movement triggered by power exhaustion
COMBAT_MOVEMENT_DISTANCE = 0x08 // Combat movement triggered by distance checks
};
enum AIEventType
{
// Usable with Event AI
@ -81,14 +90,14 @@ enum AIEventType
// Internal Use
AI_EVENT_CALL_ASSISTANCE = 10, // Sender = Attacked Npc, Invoker = Enemy
// Predefined for SD2
// Predefined for SD3
AI_EVENT_START_ESCORT = 100, // Invoker = Escorting Player
AI_EVENT_START_ESCORT_B = 101, // Invoker = Escorting Player
AI_EVENT_START_EVENT = 102, // Invoker = EventStarter
AI_EVENT_START_EVENT_A = 103, // Invoker = EventStarter
AI_EVENT_START_EVENT_B = 104, // Invoker = EventStarter
// Some IDs for special cases in SD2
// Some IDs for special cases in SD3
AI_EVENT_CUSTOM_A = 1000,
AI_EVENT_CUSTOM_B = 1001,
AI_EVENT_CUSTOM_C = 1002,
@ -97,7 +106,7 @@ enum AIEventType
AI_EVENT_CUSTOM_F = 1005,
};
class CreatureAI
class CreatureAI
{
public:
explicit CreatureAI(Creature* creature) :
@ -111,7 +120,7 @@ class CreatureAI
///== Information about AI ========================
/**
* This funcion is used to display information about the AI.
* This function is used to display information about the AI.
* It is called when the .npc aiinfo command is used.
* Use this for on-the-fly debugging
* @param reader is a ChatHandler to send messages to.
@ -150,7 +159,7 @@ class CreatureAI
* @param pHealer Unit* which deals the heal
* @param uiHealedAmount Amount of healing received
*/
virtual void HealedBy(Unit* /*pHealer*/, uint32& /*uiHealedAmount*/) {}
virtual void HealedBy(Unit * /*pHealer*/, uint32& /*uiHealedAmount*/) {}
/**
* Called at any Damage to any victim (before damage apply)
@ -342,6 +351,8 @@ class CreatureAI
*/
virtual void ReceiveAIEvent(AIEventType /*eventType*/, Creature* /*pSender*/, Unit* /*pInvoker*/, uint32 /*miscValue*/) {}
virtual void Reset() {}
protected:
void HandleMovementOnAttackStart(Unit* victim);

View file

@ -119,7 +119,7 @@ namespace MaNGOS
{
if (u->GetTypeId() == TYPEID_UNIT && (
((Creature*)u)->IsTotem() || ((Creature*)u)->IsPet() ||
(((Creature*)u)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)))
(((Creature*)u)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)))
return 0;
uint32 xp_gain = BaseGain(pl->getLevel(), u->getLevel(), GetContentLevelsForMapAndZone(pl->GetMapId(), pl->GetZoneId()));

File diff suppressed because it is too large Load diff

View file

@ -30,6 +30,7 @@
#include "Object.h"
#include "LootMgr.h"
#include "Database/DatabaseEnv.h"
#include "Utilities/EventProcessor.h"
// GCC have alternative #pragma pack(N) syntax and old gcc version not support pack(push,N), also any gcc version not support it at some platform
#if defined( __GNUC__ )
@ -294,7 +295,7 @@ struct GameObjectInfo
uint32 maxLevel; // 1
uint32 areaID; // 2
} meetingstone;
// 24 GAMEOBJECT_TYPE_FLAGSTAND
// 24 GAMEOBJECT_CreatureTypeFlagsTAND
struct
{
uint32 lockId; // 0
@ -450,7 +451,7 @@ struct GameObjectInfo
case GAMEOBJECT_TYPE_GOOBER: return goober.lockId;
case GAMEOBJECT_TYPE_AREADAMAGE: return areadamage.lockId;
case GAMEOBJECT_TYPE_CAMERA: return camera.lockId;
case GAMEOBJECT_TYPE_FLAGSTAND: return flagstand.lockId;
case GAMEOBJECT_CreatureTypeFlagsTAND: return flagstand.lockId;
case GAMEOBJECT_TYPE_FISHINGHOLE: return fishinghole.lockId;
case GAMEOBJECT_TYPE_FLAGDROP: return flagdrop.lockId;
default: return 0;
@ -465,7 +466,7 @@ struct GameObjectInfo
case GAMEOBJECT_TYPE_BUTTON: return button.noDamageImmune;
case GAMEOBJECT_TYPE_QUESTGIVER: return questgiver.noDamageImmune;
case GAMEOBJECT_TYPE_GOOBER: return goober.noDamageImmune;
case GAMEOBJECT_TYPE_FLAGSTAND: return flagstand.noDamageImmune;
case GAMEOBJECT_CreatureTypeFlagsTAND: return flagstand.noDamageImmune;
case GAMEOBJECT_TYPE_FLAGDROP: return flagdrop.noDamageImmune;
default: return true;
}
@ -691,9 +692,9 @@ class GameObject : public WorldObject
{
time_t now = time(NULL);
if (m_respawnTime > now)
return m_respawnTime;
{ return m_respawnTime; }
else
return now;
{ return now; }
}
void SetRespawnTime(time_t respawn)
@ -799,10 +800,15 @@ class GameObject : public WorldObject
void SetCapturePointSlider(float value);
float GetCapturePointSlider() const { return m_captureSlider; }
uint32 GetScriptId();
GridReference<GameObject>& GetGridRef() { return m_gridRef; }
GameObjectModel* m_model;
// Event Handler
EventProcessor m_Events;
protected:
uint32 m_spellId;
time_t m_respawnTime; // (secs) time of next respawn (or despawn if GO have owner()),

View file

@ -29,6 +29,9 @@
#include "Database/DatabaseEnv.h"
#include "ItemEnchantmentMgr.h"
#include "SQLStorages.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#endif /* ENABLE_ELUNA */
void AddItemsSetItem(Player* player, Item* item)
{
@ -44,7 +47,7 @@ void AddItemsSetItem(Player* player, Item* item)
}
if (set->required_skill_id && player->GetSkillValue(set->required_skill_id) < set->required_skill_value)
return;
{ return; }
ItemSetEffect* eff = NULL;
@ -66,12 +69,12 @@ void AddItemsSetItem(Player* player, Item* item)
size_t x = 0;
for (; x < player->ItemSetEff.size(); ++x)
if (!player->ItemSetEff[x])
break;
{ break; }
if (x < player->ItemSetEff.size())
player->ItemSetEff[x] = eff;
{ player->ItemSetEff[x] = eff; }
else
player->ItemSetEff.push_back(eff);
{ player->ItemSetEff.push_back(eff); }
}
++eff->item_count;
@ -79,18 +82,18 @@ void AddItemsSetItem(Player* player, Item* item)
for (uint32 x = 0; x < 8; ++x)
{
if (!set->spells[x])
continue;
{ continue; }
// not enough for spell
if (set->items_to_triggerspell[x] > eff->item_count)
continue;
{ continue; }
uint32 z = 0;
for (; z < 8; ++z)
if (eff->spells[z] && eff->spells[z]->Id == set->spells[x])
break;
{ break; }
if (z < 8)
continue;
{ continue; }
// new spell
for (uint32 y = 0; y < 8; ++y)
@ -138,18 +141,18 @@ void RemoveItemsSetItem(Player* player, ItemPrototype const* proto)
// can be in case now enough skill requirement for set appling but set has been appliend when skill requirement not enough
if (!eff)
return;
{ return; }
--eff->item_count;
for (uint32 x = 0; x < 8; ++x)
{
if (!set->spells[x])
continue;
{ continue; }
// enough for spell
if (set->items_to_triggerspell[x] <= eff->item_count)
continue;
{ continue; }
for (uint32 z = 0; z < 8; ++z)
{
@ -174,7 +177,7 @@ void RemoveItemsSetItem(Player* player, ItemPrototype const* proto)
bool ItemCanGoIntoBag(ItemPrototype const* pProto, ItemPrototype const* pBagProto)
{
if (!pProto || !pBagProto)
return false;
{ return false; }
switch (pBagProto->Class)
{
@ -185,15 +188,15 @@ bool ItemCanGoIntoBag(ItemPrototype const* pProto, ItemPrototype const* pBagProt
return true;
case ITEM_SUBCLASS_SOUL_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_SOUL_SHARDS))
return false;
{ return false; }
return true;
case ITEM_SUBCLASS_HERB_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_HERBS))
return false;
{ return false; }
return true;
case ITEM_SUBCLASS_ENCHANTING_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_ENCHANTING_SUPP))
return false;
{ return false; }
return true;
case ITEM_SUBCLASS_MINING_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_MINING_SUPP))
@ -201,7 +204,7 @@ bool ItemCanGoIntoBag(ItemPrototype const* pProto, ItemPrototype const* pBagProt
return true;
case ITEM_SUBCLASS_ENGINEERING_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_ENGINEERING_SUPP))
return false;
{ return false; }
return true;
case ITEM_SUBCLASS_GEM_CONTAINER:
if (!(pProto->BagFamily & BAG_FAMILY_GEMS))
@ -227,11 +230,11 @@ bool ItemCanGoIntoBag(ItemPrototype const* pProto, ItemPrototype const* pBagProt
{
case ITEM_SUBCLASS_QUIVER:
if (!(pProto->BagFamily & BAG_FAMILY_ARROWS))
return false;
{ return false; }
return true;
case ITEM_SUBCLASS_AMMO_POUCH:
if (!(pProto->BagFamily & BAG_FAMILY_BULLETS))
return false;
{ return false; }
return true;
default:
return false;
@ -383,6 +386,10 @@ Item::Item() :
m_lootState = ITEM_LOOT_NONE;
}
Item::~Item()
{
}
bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
{
Object::_Create(guidlow, 0, HIGHGUID_ITEM);
@ -395,14 +402,14 @@ bool Item::Create(uint32 guidlow, uint32 itemid, Player const* owner)
ItemPrototype const* itemProto = ObjectMgr::GetItemPrototype(itemid);
if (!itemProto)
return false;
{ return false; }
SetUInt32Value(ITEM_FIELD_STACK_COUNT, 1);
SetUInt32Value(ITEM_FIELD_MAXDURABILITY, itemProto->MaxDurability);
SetUInt32Value(ITEM_FIELD_DURABILITY, itemProto->MaxDurability);
for (int i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
SetSpellCharges(i, itemProto->Spells[i].SpellCharges);
{ SetSpellCharges(i, itemProto->Spells[i].SpellCharges); }
SetUInt32Value(ITEM_FIELD_DURATION, itemProto->Duration);
@ -419,12 +426,17 @@ bool Item::IsNotEmptyBag() const
void Item::UpdateDuration(Player* owner, uint32 diff)
{
if (!GetUInt32Value(ITEM_FIELD_DURATION))
return;
{ return; }
// DEBUG_LOG("Item::UpdateDuration Item (Entry: %u Duration %u Diff %u)", GetEntry(), GetUInt32Value(ITEM_FIELD_DURATION), diff);
if (GetUInt32Value(ITEM_FIELD_DURATION) <= diff)
{
// Used by Eluna
#ifdef ENABLE_ELUNA
sEluna->OnExpire(owner, GetProto());
#endif /* ENABLE_ELUNA */
if (uint32 newItemId = sObjectMgr.GetItemExpireConvert(GetEntry()))
owner->ConvertItem(this, newItemId);
else
@ -451,7 +463,7 @@ void Item::SaveToDB()
std::ostringstream ss;
for (uint16 i = 0; i < m_valuesCount; ++i)
ss << GetUInt32Value(i) << " ";
{ ss << GetUInt32Value(i) << " "; }
stmt = CharacterDatabase.CreateStatement(insItem, "INSERT INTO item_instance (guid,owner_guid,data,text) VALUES (?, ?, ?, ?)");
stmt.PExecute(guid, GetOwnerGuid().GetCounter(), ss.str().c_str(), m_text.c_str());
@ -465,7 +477,7 @@ void Item::SaveToDB()
std::ostringstream ss;
for (uint16 i = 0; i < m_valuesCount; ++i)
ss << GetUInt32Value(i) << " ";
{ ss << GetUInt32Value(i) << " "; }
stmt.PExecute(ss.str().c_str(), GetOwnerGuid().GetCounter(), m_text.c_str(), guid);
@ -534,11 +546,11 @@ void Item::SaveToDB()
LootItem* item = loot.LootItemInSlot(i, owner, &qitem);
if (!item)
continue;
{ continue; }
// questitems use the blocked field for other purposes
if (!qitem && item->is_blocked)
continue;
{ continue; }
stmt.addUInt32(GetGUIDLow());
stmt.addUInt32(owner->GetGUIDLow());
@ -553,7 +565,7 @@ void Item::SaveToDB()
}
if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_TEMPORARY)
SetLootState(ITEM_LOOT_UNCHANGED);
{ SetLootState(ITEM_LOOT_UNCHANGED); }
SetState(ITEM_UNCHANGED);
}
@ -584,14 +596,14 @@ bool Item::LoadFromDB(uint32 guidLow, Field* fields, ObjectGuid ownerGuid)
ItemPrototype const* proto = GetProto();
if (!proto)
return false;
{ return false; }
// update max durability (and durability) if need
if (proto->MaxDurability != GetUInt32Value(ITEM_FIELD_MAXDURABILITY))
{
SetUInt32Value(ITEM_FIELD_MAXDURABILITY, proto->MaxDurability);
if (GetUInt32Value(ITEM_FIELD_DURABILITY) > proto->MaxDurability)
SetUInt32Value(ITEM_FIELD_DURABILITY, proto->MaxDurability);
{ SetUInt32Value(ITEM_FIELD_DURABILITY, proto->MaxDurability); }
need_save = true;
}
@ -649,7 +661,7 @@ bool Item::LoadFromDB(uint32 guidLow, Field* fields, ObjectGuid ownerGuid)
std::ostringstream ss;
for (uint16 i = 0; i < m_valuesCount; ++i)
ss << GetUInt32Value(i) << " ";
{ ss << GetUInt32Value(i) << " "; }
stmt.addString(ss);
stmt.addUInt32(GetOwnerGuid().GetCounter());
@ -756,15 +768,15 @@ uint32 Item::GetSkill()
{
case ITEM_CLASS_WEAPON:
if (proto->SubClass >= MAX_ITEM_SUBCLASS_WEAPON)
return 0;
{ return 0; }
else
return item_weapon_skills[proto->SubClass];
{ return item_weapon_skills[proto->SubClass]; }
case ITEM_CLASS_ARMOR:
if (proto->SubClass >= MAX_ITEM_SUBCLASS_ARMOR)
return 0;
{ return 0; }
else
return item_armor_skills[proto->SubClass];
{ return item_armor_skills[proto->SubClass]; }
default:
return 0;
@ -776,7 +788,7 @@ int32 Item::GenerateItemRandomPropertyId(uint32 item_id)
ItemPrototype const* itemProto = sItemStorage.LookupEntry<ItemPrototype>(item_id);
if (!itemProto)
return 0;
{ return 0; }
// item must have one from this field values not null if it can have random enchantments
if ((!itemProto->RandomProperty) && (!itemProto->RandomSuffix))
@ -813,7 +825,7 @@ int32 Item::GenerateItemRandomPropertyId(uint32 item_id)
void Item::SetItemRandomProperties(int32 randomPropId)
{
if (!randomPropId)
return;
{ return; }
if (randomPropId > 0)
{
@ -863,7 +875,7 @@ void Item::SetState(ItemUpdateState state, Player* forplayer)
{
// pretend the item never existed
if (forplayer || GetOwnerGuid())
RemoveFromUpdateQueueOf(forplayer);
{ RemoveFromUpdateQueueOf(forplayer); }
delete this;
return;
}
@ -871,10 +883,10 @@ void Item::SetState(ItemUpdateState state, Player* forplayer)
if (state != ITEM_UNCHANGED)
{
// new items must stay in new state until saved
if (uState != ITEM_NEW) uState = state;
if (uState != ITEM_NEW) { uState = state; }
if (forplayer || GetOwnerGuid())
AddToUpdateQueueOf(forplayer);
{ AddToUpdateQueueOf(forplayer); }
}
else
{
@ -888,7 +900,7 @@ void Item::SetState(ItemUpdateState state, Player* forplayer)
void Item::AddToUpdateQueueOf(Player* player)
{
if (IsInUpdateQueue())
return;
{ return; }
if (!player)
{
@ -909,7 +921,7 @@ void Item::AddToUpdateQueueOf(Player* player)
}
if (player->m_itemUpdateQueueBlocked)
return;
{ return; }
player->m_itemUpdateQueue.push_back(this);
uQueuePos = player->m_itemUpdateQueue.size() - 1;
@ -918,7 +930,7 @@ void Item::AddToUpdateQueueOf(Player* player)
void Item::RemoveFromUpdateQueueOf(Player* player)
{
if (!IsInUpdateQueue())
return;
{ return; }
if (!player)
{
@ -939,7 +951,7 @@ void Item::RemoveFromUpdateQueueOf(Player* player)
}
if (player->m_itemUpdateQueueBlocked)
return;
{ return; }
player->m_itemUpdateQueue[uQueuePos] = NULL;
uQueuePos = -1;
@ -958,24 +970,23 @@ bool Item::IsEquipped() const
bool Item::CanBeTraded(bool mail) const
{
if ((!mail || !IsBoundAccountWide()) && IsSoulBound())
return false;
{ return false; }
if (IsBag() && (Player::IsBagPos(GetPos()) || !((Bag const*)this)->IsEmpty()))
return false;
{ return false; }
if (Player* owner = GetOwner())
{
if (owner->CanUnequipItem(GetPos(), false) != EQUIP_ERR_OK)
return false;
{ return false; }
if (owner->GetLootGuid() == GetObjectGuid())
return false;
{ return false; }
}
if (HasGeneratedLoot())
return false;
{ return false; }
if (IsBoundByEnchant())
return false;
{ return false; }
return true;
}
@ -987,7 +998,7 @@ bool Item::IsBoundByEnchant() const
{
uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
if (!enchant_id)
continue;
{ continue; }
if (enchant_slot == TRANSMOGRIFY_ENCHANTMENT_SLOT)
return true;
@ -997,10 +1008,10 @@ bool Item::IsBoundByEnchant() const
SpellItemEnchantmentEntry const* enchantEntry = sSpellItemEnchantmentStore.LookupEntry(enchant_id);
if (!enchantEntry)
continue;
{ continue; }
if (enchantEntry->slot & ENCHANTMENT_CAN_SOULBOUND)
return true;
{ return true; }
}
return false;
}
@ -1032,12 +1043,12 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
if (equippedItems->EquippedItemClass != -1) // -1 == any item class
{
if (equippedItems->EquippedItemClass != int32(proto->Class))
return false; // wrong item class
{ return false; } // wrong item class
if (equippedItems->EquippedItemSubClassMask != 0) // 0 == any subclass
{
if ((equippedItems->EquippedItemSubClassMask & (1 << proto->SubClass)) == 0)
return false; // subclass not present in mask
{ return false; } // subclass not present in mask
}
}
@ -1047,7 +1058,7 @@ bool Item::IsFitToSpellRequirements(SpellEntry const* spellInfo) const
if (equippedItems->EquippedItemInventoryTypeMask != 0 && (spellInfo->GetTargets() & TARGET_FLAG_ITEM)) // 0 == any inventory type
{
if ((equippedItems->EquippedItemInventoryTypeMask & (1 << proto->InventoryType)) == 0)
return false; // inventory type not present in mask
{ return false; } // inventory type not present in mask
}
return true;
@ -1058,24 +1069,23 @@ bool Item::IsTargetValidForItemUse(Unit* pUnitTarget)
ItemRequiredTargetMapBounds bounds = sObjectMgr.GetItemRequiredTargetMapBounds(GetProto()->ItemId);
if (bounds.first == bounds.second)
return true;
{ return true; }
if (!pUnitTarget)
return false;
{ return false; }
for (ItemRequiredTargetMap::const_iterator itr = bounds.first; itr != bounds.second; ++itr)
if (itr->second.IsFitToRequirements(pUnitTarget))
return true;
{ return true; }
return false;
}
void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint32 charges, ObjectGuid casterGuid /*= ObjectGuid()*/)
{
// Better lost small time at check in comparison lost time at item save to DB.
if ((GetEnchantmentId(slot) == id) && (GetEnchantmentDuration(slot) == duration) && (GetEnchantmentCharges(slot) == charges))
return;
{ return; }
if (slot < MAX_INSPECTED_ENCHANTMENT_SLOT)
{
@ -1096,7 +1106,7 @@ void Item::SetEnchantment(EnchantmentSlot slot, uint32 id, uint32 duration, uint
void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
{
if (GetEnchantmentDuration(slot) == duration)
return;
{ return; }
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot * MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_DURATION_OFFSET, duration);
SetState(ITEM_CHANGED);
@ -1105,7 +1115,7 @@ void Item::SetEnchantmentDuration(EnchantmentSlot slot, uint32 duration)
void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
{
if (GetEnchantmentCharges(slot) == charges)
return;
{ return; }
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot * MAX_ENCHANTMENT_OFFSET + ENCHANTMENT_CHARGES_OFFSET, charges);
SetState(ITEM_CHANGED);
@ -1114,7 +1124,7 @@ void Item::SetEnchantmentCharges(EnchantmentSlot slot, uint32 charges)
void Item::ClearEnchantment(EnchantmentSlot slot)
{
if (!GetEnchantmentId(slot))
return;
{ return; }
for (uint8 x = 0; x < 3; ++x)
SetUInt32Value(ITEM_FIELD_ENCHANTMENT_1_1 + slot * MAX_ENCHANTMENT_OFFSET + x, 0);
@ -1136,7 +1146,7 @@ bool Item::GemsFitSockets() const
bool fits = true;
for (uint32 enchant_slot = SOCK_ENCHANTMENT_SLOT; enchant_slot < SOCK_ENCHANTMENT_SLOT + MAX_GEM_SOCKETS; ++enchant_slot)
{
uint8 SocketColor = GetProto()->Socket[enchant_slot - SOCK_ENCHANTMENT_SLOT].Color;
uint8 SocketColor = GetProto()->Socket[enchant_slot-SOCK_ENCHANTMENT_SLOT].Color;
uint32 enchant_id = GetEnchantmentId(EnchantmentSlot(enchant_slot));
if (!enchant_id)
@ -1226,7 +1236,7 @@ void Item::SendTimeUpdate(Player* owner)
{
uint32 duration = GetUInt32Value(ITEM_FIELD_DURATION);
if (!duration)
return;
{ return; }
WorldPacket data(SMSG_ITEM_TIME_UPDATE, (8 + 4));
data << ObjectGuid(GetObjectGuid());
@ -1237,12 +1247,12 @@ void Item::SendTimeUpdate(Player* owner)
Item* Item::CreateItem(uint32 item, uint32 count, Player const* player, uint32 randomPropertyId)
{
if (count < 1)
return NULL; // don't create item at zero count
{ return NULL; } // don't create item at zero count
if (ItemPrototype const* pProto = ObjectMgr::GetItemPrototype(item))
{
if (count > pProto->GetMaxStackSize())
count = pProto->GetMaxStackSize();
{ count = pProto->GetMaxStackSize(); }
MANGOS_ASSERT(count != 0 && "pProto->Stackable == 0 but checked at loading already");
@ -1251,12 +1261,12 @@ Item* Item::CreateItem(uint32 item, uint32 count, Player const* player, uint32 r
{
pItem->SetCount(count);
if (uint32 randId = randomPropertyId ? randomPropertyId : Item::GenerateItemRandomPropertyId(item))
pItem->SetItemRandomProperties(randId);
{ pItem->SetItemRandomProperties(randId); }
return pItem;
}
else
delete pItem;
{ delete pItem; }
}
return NULL;
}
@ -1265,7 +1275,7 @@ Item* Item::CloneItem(uint32 count, Player const* player) const
{
Item* newItem = CreateItem(GetEntry(), count, player, GetItemRandomPropertyId());
if (!newItem)
return NULL;
{ return NULL; }
newItem->SetGuidValue(ITEM_FIELD_CREATOR, GetGuidValue(ITEM_FIELD_CREATOR));
newItem->SetGuidValue(ITEM_FIELD_GIFTCREATOR, GetGuidValue(ITEM_FIELD_GIFTCREATOR));
@ -1278,15 +1288,15 @@ bool Item::IsBindedNotWith(Player const* player) const
{
// own item
if (GetOwnerGuid() == player->GetObjectGuid())
return false;
{ return false; }
// has loot with diff owner
if (HasGeneratedLoot())
return true;
{ return true; }
// not binded item
if (!IsSoulBound())
return false;
{ return false; }
// not BOA item case
if (!IsBoundAccountWide())
@ -1307,19 +1317,19 @@ bool Item::IsBindedNotWith(Player const* player) const
void Item::AddToClientUpdateList()
{
if (Player* pl = GetOwner())
pl->GetMap()->AddUpdateObject(this);
{ pl->GetMap()->AddUpdateObject(this); }
}
void Item::RemoveFromClientUpdateList()
{
if (Player* pl = GetOwner())
pl->GetMap()->RemoveUpdateObject(this);
{ pl->GetMap()->RemoveUpdateObject(this); }
}
void Item::BuildUpdateData(UpdateDataMapType& update_players)
{
if (Player* pl = GetOwner())
BuildUpdateDataForPlayer(pl, update_players);
{ BuildUpdateDataForPlayer(pl, update_players); }
ClearUpdateMask(false);
}
@ -1328,15 +1338,15 @@ InventoryResult Item::CanBeMergedPartlyWith(ItemPrototype const* proto) const
{
// check item type
if (GetEntry() != proto->ItemId)
return EQUIP_ERR_ITEM_CANT_STACK;
{ return EQUIP_ERR_ITEM_CANT_STACK; }
// check free space (full stacks can't be target of merge
if (GetCount() >= proto->GetMaxStackSize())
return EQUIP_ERR_ITEM_CANT_STACK;
{ return EQUIP_ERR_ITEM_CANT_STACK; }
// not allow merge looting currently items
if (HasGeneratedLoot())
return EQUIP_ERR_ALREADY_LOOTED;
{ return EQUIP_ERR_ALREADY_LOOTED; }
return EQUIP_ERR_OK;
}
@ -1344,10 +1354,10 @@ InventoryResult Item::CanBeMergedPartlyWith(ItemPrototype const* proto) const
bool ItemRequiredTarget::IsFitToRequirements(Unit* pUnitTarget) const
{
if (pUnitTarget->GetTypeId() != TYPEID_UNIT)
return false;
{ return false; }
if (pUnitTarget->GetEntry() != m_uiTargetEntry)
return false;
{ return false; }
switch (m_uiType)
{
@ -1403,15 +1413,15 @@ void Item::SetLootState(ItemLootUpdateState state)
case ITEM_LOOT_CHANGED:
// new loot must stay in new state until saved, temporary must stay until remove
if (m_lootState != ITEM_LOOT_NEW && m_lootState != ITEM_LOOT_TEMPORARY)
m_lootState = m_lootState == ITEM_LOOT_NONE ? ITEM_LOOT_NEW : state;
{ m_lootState = m_lootState == ITEM_LOOT_NONE ? ITEM_LOOT_NEW : state; }
break;
case ITEM_LOOT_UNCHANGED:
// expected that called after DB update or load
if (m_lootState == ITEM_LOOT_REMOVED)
m_lootState = ITEM_LOOT_NONE;
{ m_lootState = ITEM_LOOT_NONE; }
// temporary must stay until remove (ignore any changes)
else if (m_lootState != ITEM_LOOT_TEMPORARY)
m_lootState = ITEM_LOOT_UNCHANGED;
{ m_lootState = ITEM_LOOT_UNCHANGED; }
break;
case ITEM_LOOT_REMOVED:
// if loot not saved then it existence in past can be just ignored
@ -1426,7 +1436,12 @@ void Item::SetLootState(ItemLootUpdateState state)
}
if (m_lootState != ITEM_LOOT_NONE && m_lootState != ITEM_LOOT_UNCHANGED && m_lootState != ITEM_LOOT_TEMPORARY)
SetState(ITEM_CHANGED);
{ SetState(ITEM_CHANGED); }
}
uint32 Item::GetScriptId() const
{
return sScriptMgr.GetBoundScriptId(SCRIPTED_ITEM, GetEntry());
}
uint32 Item::GetSpecialPrice(ItemPrototype const* proto, uint32 minimumPrice /*= 10000*/)

View file

@ -283,13 +283,14 @@ struct ItemRequiredTarget
bool ItemCanGoIntoBag(ItemPrototype const* proto, ItemPrototype const* pBagProto);
class Item : public Object
class Item : public Object
{
public:
static Item* CreateItem(uint32 item, uint32 count, Player const* player = NULL, uint32 randomPropertyId = 0);
Item* CloneItem(uint32 count, Player const* player = NULL) const;
Item();
~Item();
virtual bool Create(uint32 guidlow, uint32 itemid, Player const* owner);
@ -397,6 +398,7 @@ class Item : public Object
bool HasInvolvedQuest(uint32 /*quest_id*/) const override { return false; }
bool IsPotion() const { return GetProto()->IsPotion(); }
bool IsConjuredConsumable() const { return GetProto()->IsConjuredConsumable(); }
uint32 GetScriptId() const;
void AddToClientUpdateList() override;
void RemoveFromClientUpdateList() override;

View file

@ -49,6 +49,10 @@
#include "TemporarySummon.h"
#include "movement/packet_builder.h"
#include "CreatureLinkingMgr.h"
#ifdef ENABLE_ELUNA
#include "LuaEngine.h"
#include "ElunaEventMgr.h"
#endif /* ENABLE_ELUNA */
Object::Object()
{
@ -93,7 +97,7 @@ void Object::_InitValues()
void Object::_Create(uint32 guidlow, uint32 entry, HighGuid guidhigh)
{
if (!m_uint32Values)
_InitValues();
{ _InitValues(); }
ObjectGuid guid = ObjectGuid(guidhigh, entry, guidlow);
SetGuidValue(OBJECT_FIELD_GUID, guid);
@ -109,7 +113,7 @@ void Object::SetObjectScale(float newScale)
void Object::SendForcedObjectUpdate()
{
if (!m_inWorld || !m_objectUpdated)
return;
{ return; }
UpdateDataMapType update_players;
@ -128,14 +132,14 @@ void Object::SendForcedObjectUpdate()
void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const
{
if (!target)
return;
{ return; }
uint8 updatetype = UPDATETYPE_CREATE_OBJECT;
uint16 updateFlags = m_updateFlag;
/** lower flag1 **/
if (target == this) // building packet for yourself
updateFlags |= UPDATEFLAG_SELF;
{ updateFlags |= UPDATEFLAG_SELF; }
switch (GetObjectGuid().GetHigh())
{
@ -168,7 +172,7 @@ void Object::BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) c
{
case GAMEOBJECT_TYPE_TRAP:
case GAMEOBJECT_TYPE_DUEL_ARBITER:
case GAMEOBJECT_TYPE_FLAGSTAND:
case GAMEOBJECT_CreatureTypeFlagsTAND:
case GAMEOBJECT_TYPE_FLAGDROP:
updatetype = UPDATETYPE_CREATE_OBJECT2;
break;
@ -245,7 +249,7 @@ void Object::DestroyForPlayer(Player* target, bool anim) const
target->GetSession()->SendPacket(&data);
}
void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
void Object::BuildMovementUpdate(ByteBuffer* data, uint16 updateFlags) const
{
ObjectGuid Guid = GetObjectGuid();
@ -542,7 +546,7 @@ void Object::BuildMovementUpdate(ByteBuffer * data, uint16 updateFlags) const
void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* updateMask, Player* target) const
{
if (!target)
return;
{ return; }
uint32 valuesCount = m_valuesCount;
if(GetTypeId() == TYPEID_PLAYER && target != this)
@ -556,7 +560,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
{
if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
IsActivateToQuest = true;
{ IsActivateToQuest = true; }
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
}
@ -574,7 +578,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
if (isType(TYPEMASK_GAMEOBJECT) && !((GameObject*)this)->IsTransport())
{
if (((GameObject*)this)->ActivateToQuest(target) || target->isGameMaster())
IsActivateToQuest = true;
{ IsActivateToQuest = true; }
updateMask->SetBit(GAMEOBJECT_DYNAMIC);
updateMask->SetBit(GAMEOBJECT_BYTES_1); // why do we need this here?
@ -619,7 +623,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
if (appendValue & UNIT_NPC_FLAG_STABLEMASTER)
{
if (target->getClass() != CLASS_HUNTER)
appendValue &= ~UNIT_NPC_FLAG_STABLEMASTER;
{ appendValue &= ~UNIT_NPC_FLAG_STABLEMASTER; }
}
}
@ -731,7 +735,7 @@ void Object::BuildValuesUpdate(uint8 updatetype, ByteBuffer* data, UpdateMask* u
*data << uint32(m_uint32Values[index]);
}
else
*data << m_uint32Values[index]; // other cases
{ *data << m_uint32Values[index]; } // other cases
}
}
}
@ -753,25 +757,25 @@ void Object::ClearUpdateMask(bool remove)
if (m_uint32Values)
{
for (uint16 index = 0; index < m_valuesCount; ++index)
m_changedValues[index] = false;
{ m_changedValues[index] = false; }
}
if (m_objectUpdated)
{
if (remove)
RemoveFromClientUpdateList();
{ RemoveFromClientUpdateList(); }
m_objectUpdated = false;
}
}
bool Object::LoadValues(const char* data)
{
if (!m_uint32Values) _InitValues();
if (!m_uint32Values) { _InitValues(); }
Tokens tokens = StrSplit(data, " ");
if (tokens.size() != m_valuesCount)
return false;
{ return false; }
Tokens::iterator iter;
int index;
@ -783,7 +787,7 @@ bool Object::LoadValues(const char* data)
return true;
}
void Object::_SetUpdateBits(UpdateMask *updateMask, Player* target) const
void Object::_SetUpdateBits(UpdateMask* updateMask, Player* target) const
{
uint32 valuesCount = m_valuesCount;
if(GetTypeId() == TYPEID_PLAYER && target != this)
@ -791,10 +795,10 @@ void Object::_SetUpdateBits(UpdateMask *updateMask, Player* target) const
for (uint16 index = 0; index < valuesCount; ++index )
if (m_changedValues[index])
updateMask->SetBit(index);
{ updateMask->SetBit(index); }
}
void Object::_SetCreateBits(UpdateMask *updateMask, Player* target) const
void Object::_SetCreateBits(UpdateMask* updateMask, Player* target) const
{
uint32 valuesCount = m_valuesCount;
if(GetTypeId() == TYPEID_PLAYER && target != this)
@ -802,7 +806,7 @@ void Object::_SetCreateBits(UpdateMask *updateMask, Player* target) const
for (uint16 index = 0; index < valuesCount; ++index)
if (GetUInt32Value(index) != 0)
updateMask->SetBit(index);
{ updateMask->SetBit(index); }
}
void Object::SetInt32Value(uint16 index, int32 value)
@ -903,7 +907,7 @@ void Object::SetUInt16Value(uint16 index, uint8 offset, uint16 value)
void Object::SetStatFloatValue(uint16 index, float value)
{
if (value < 0)
value = 0.0f;
{ value = 0.0f; }
SetFloatValue(index, value);
}
@ -911,7 +915,7 @@ void Object::SetStatFloatValue(uint16 index, float value)
void Object::SetStatInt32Value(uint16 index, int32 value)
{
if (value < 0)
value = 0;
{ value = 0; }
SetUInt32Value(index, uint32(value));
}
@ -921,7 +925,7 @@ void Object::ApplyModUInt32Value(uint16 index, int32 val, bool apply)
int32 cur = GetUInt32Value(index);
cur += (apply ? val : -val);
if (cur < 0)
cur = 0;
{ cur = 0; }
SetUInt32Value(index, cur);
}
@ -944,7 +948,7 @@ void Object::ApplyModPositiveFloatValue(uint16 index, float val, bool apply)
float cur = GetFloatValue(index);
cur += (apply ? val : -val);
if (cur < 0)
cur = 0;
{ cur = 0; }
SetFloatValue(index, cur);
}
@ -1052,7 +1056,6 @@ bool Object::PrintEntryError(char const* descr) const
return false;
}
void Object::BuildUpdateDataForPlayer(Player* pl, UpdateDataMapType& update_players)
{
UpdateDataMapType::iterator iter = update_players.find(pl);
@ -1098,17 +1101,36 @@ void Object::MarkForClientUpdate()
}
WorldObject::WorldObject() :
m_transportInfo(NULL), m_currMap(NULL),
#ifdef ENABLE_ELUNA
elunaEvents(NULL),
#endif /* ENABLE_ELUNA */
m_transportInfo(NULL),
m_currMap(NULL),
m_mapId(0), m_InstanceId(0), m_phaseMask(PHASEMASK_NORMAL),
m_isActiveObject(false)
{
}
WorldObject::~WorldObject()
{
#ifdef ENABLE_ELUNA
delete elunaEvents;
elunaEvents = NULL;
#endif /* ENABLE_ELUNA */
}
void WorldObject::CleanupsBeforeDelete()
{
RemoveFromWorld();
}
void WorldObject::Update(uint32 update_diff, uint32 time_diff)
{
#ifdef ENABLE_ELUNA
elunaEvents->Update(update_diff);
#endif /* ENABLE_ELUNA */
}
void WorldObject::_Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask)
{
Object::_Create(guidlow, 0, guidhigh);
@ -1123,7 +1145,7 @@ void WorldObject::Relocate(float x, float y, float z, float orientation)
m_position.o = NormalizeOrientation(orientation);
if (isType(TYPEMASK_UNIT))
((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation);
{ ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, orientation); }
}
void WorldObject::Relocate(float x, float y, float z)
@ -1133,7 +1155,7 @@ void WorldObject::Relocate(float x, float y, float z)
m_position.z = z;
if (isType(TYPEMASK_UNIT))
((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, GetOrientation());
{ ((Unit*)this)->m_movementInfo.ChangePosition(x, y, z, GetOrientation()); }
}
void WorldObject::SetOrientation(float orientation)
@ -1141,7 +1163,7 @@ void WorldObject::SetOrientation(float orientation)
m_position.o = NormalizeOrientation(orientation);
if (isType(TYPEMASK_UNIT))
((Unit*)this)->m_movementInfo.ChangeOrientation(orientation);
{ ((Unit*)this)->m_movementInfo.ChangeOrientation(orientation); }
}
uint32 WorldObject::GetZoneId() const
@ -1254,11 +1276,10 @@ bool WorldObject::_IsWithinDist(WorldObject const* obj, float dist2compare, bool
bool WorldObject::IsWithinLOSInMap(const WorldObject* obj) const
{
if (!IsInMap(obj))
return false;
if (!IsInMap(obj)) { return false; }
float ox, oy, oz;
obj->GetPosition(ox, oy, oz);
return IsWithinLOS(ox, oy, oz);
return(IsWithinLOS(ox, oy, oz));
}
bool WorldObject::IsWithinLOS(float ox, float oy, float oz) const
@ -1309,7 +1330,7 @@ bool WorldObject::IsInRange(WorldObject const* obj, float minRange, float maxRan
{
float mindist = minRange + sizefactor;
if (distsq < mindist * mindist)
return false;
{ return false; }
}
float maxdist = maxRange + sizefactor;
@ -1329,7 +1350,7 @@ bool WorldObject::IsInRange2d(float x, float y, float minRange, float maxRange)
{
float mindist = minRange + sizefactor;
if (distsq < mindist * mindist)
return false;
{ return false; }
}
float maxdist = maxRange + sizefactor;
@ -1350,7 +1371,7 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m
{
float mindist = minRange + sizefactor;
if (distsq < mindist * mindist)
return false;
{ return false; }
}
float maxdist = maxRange + sizefactor;
@ -1360,7 +1381,7 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m
float WorldObject::GetAngle(const WorldObject* obj) const
{
if (!obj)
return 0.0f;
{ return 0.0f; }
// Rework the assert, when more cases where such a call can happen have been fixed
// MANGOS_ASSERT(obj != this || PrintEntryError("GetAngle (for self)"));
@ -1387,7 +1408,7 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
{
// always have self in arc
if (obj == this)
return true;
{ return true; }
float arc = arcangle;
@ -1400,7 +1421,7 @@ bool WorldObject::HasInArc(const float arcangle, const WorldObject* obj) const
// move angle to range -pi ... +pi
angle = NormalizeOrientation(angle);
if (angle > M_PI_F)
angle -= 2.0f * M_PI_F;
{ angle -= 2.0f * M_PI_F; }
float lborder = -1 * (arc / 2.0f); // in range -pi..0
float rborder = (arc / 2.0f); // in range 0..pi
@ -1454,7 +1475,7 @@ void WorldObject::UpdateGroundPositionZ(float x, float y, float& z) const
{
float new_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
if (new_z > INVALID_HEIGHT)
z = new_z + 0.05f; // just to be sure that we are not a few pixel under the surface
{ z = new_z + 0.05f; } // just to be sure that we are not a few pixel under the surface
}
void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
@ -1475,16 +1496,16 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
z = max_z;
{ z = max_z; }
else if (z < ground_z)
z = ground_z;
{ z = ground_z; }
}
}
else
{
float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
if (z < ground_z)
z = ground_z;
{ z = ground_z; }
}
break;
}
@ -1498,9 +1519,9 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
if (max_z > INVALID_HEIGHT)
{
if (z > max_z)
z = max_z;
{ z = max_z; }
else if (z < ground_z)
z = ground_z;
{ z = ground_z; }
}
}
else
@ -1515,7 +1536,7 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float& z) const
{
float ground_z = GetMap()->GetHeight(GetPhaseMask(), x, y, z);
if (ground_z > INVALID_HEIGHT)
z = ground_z;
{ z = ground_z; }
break;
}
}
@ -1551,7 +1572,7 @@ void WorldObject::MonsterTextEmote(const char* text, Unit const* target, bool Is
void WorldObject::MonsterWhisper(const char* text, Unit const* target, bool IsBossWhisper) const
{
if (!target || target->GetTypeId() != TYPEID_PLAYER)
return;
{ return; }
WorldPacket data(SMSG_MESSAGECHAT, 200);
BuildMonsterChat(&data, GetObjectGuid(), IsBossWhisper ? CHAT_MSG_RAID_BOSS_WHISPER : CHAT_MSG_MONSTER_WHISPER, text, LANG_UNIVERSAL,
@ -1666,14 +1687,14 @@ void WorldObject::SendMessageToSet(WorldPacket* data, bool /*bToSelf*/) const
{
// if object is in world, map for it already created!
if (IsInWorld())
GetMap()->MessageBroadcast(this, data);
{ GetMap()->MessageBroadcast(this, data); }
}
void WorldObject::SendMessageToSetInRange(WorldPacket* data, float dist, bool /*bToSelf*/) const
{
// if object is in world, map for it already created!
if (IsInWorld())
GetMap()->MessageDistBroadcast(this, data, dist);
{ GetMap()->MessageDistBroadcast(this, data, dist); }
}
void WorldObject::SendMessageToSetExcept(WorldPacket* data, Player const* skipped_receiver) const
@ -1708,6 +1729,17 @@ void WorldObject::SetMap(Map* map)
// lets save current map's Id/instanceId
m_mapId = map->GetId();
m_InstanceId = map->GetInstanceId();
#ifdef ENABLE_ELUNA
delete elunaEvents;
// On multithread replace this with a pointer to map's Eluna pointer stored in a map
elunaEvents = new ElunaEventProcessor(&Eluna::GEluna, this);
#endif
#ifdef ENABLE_ELUNA
delete elunaEvents;
elunaEvents = NULL;
#endif
}
TerrainInfo const* WorldObject::GetTerrain() const
@ -1734,12 +1766,12 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
Team team = TEAM_NONE;
if (GetTypeId() == TYPEID_PLAYER)
team = ((Player*)this)->GetTeam();
{ team = ((Player*)this)->GetTeam(); }
CreatureCreatePos pos(GetMap(), x, y, z, ang, GetPhaseMask());
if (x == 0.0f && y == 0.0f && z == 0.0f)
pos = CreatureCreatePos(this, GetOrientation(), CONTACT_DISTANCE, ang);
{ pos = CreatureCreatePos(this, GetOrientation(), CONTACT_DISTANCE, ang); }
if (!pCreature->Create(GetMap()->GenerateLocalLowGuid(cinfo->GetHighGuid()), pos, cinfo, team))
{
@ -1755,11 +1787,16 @@ Creature* WorldObject::SummonCreature(uint32 id, float x, float y, float z, floa
pCreature->Summon(spwtype, despwtime); // Also initializes the AI and MMGen
if (GetTypeId() == TYPEID_UNIT && ((Creature*)this)->AI())
((Creature*)this)->AI()->JustSummoned(pCreature);
{ ((Creature*)this)->AI()->JustSummoned(pCreature); }
#ifdef ENABLE_ELUNA
if (Unit* summoner = ToUnit())
sEluna->OnSummoned(pCreature, summoner);
#endif /* ENABLE_ELUNA */
// Creature Linking, Initial load is handled like respawn
if (pCreature->IsLinkingEventTrigger())
GetMap()->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_RESPAWN, pCreature);
{ GetMap()->GetCreatureLinkingHolder()->DoCreatureLinkingEvent(LINKING_EVENT_RESPAWN, pCreature); }
// return the creature therewith the summoner has access to it
return pCreature;
@ -1771,7 +1808,7 @@ GameObject* WorldObject::SummonGameObject(uint32 id, float x, float y, float z,
Map *map = GetMap();
if (!map)
if(!map)
return NULL;
if (!pGameObj->Create(map->GenerateLocalLowGuid(HIGHGUID_GAMEOBJECT), id, map, GetPhaseMask(), x, y, z, angle))
@ -1780,7 +1817,7 @@ GameObject* WorldObject::SummonGameObject(uint32 id, float x, float y, float z,
return NULL;
}
pGameObj->SetRespawnTime(despwtime / IN_MILLISECONDS);
pGameObj->SetRespawnTime(despwtime/IN_MILLISECONDS);
map->Add(pGameObj);
@ -1805,7 +1842,7 @@ namespace MaNGOS
{
// skip self or target
if (c == i_searcher || c == &i_object)
return;
{ return; }
float x, y, z;
@ -1823,7 +1860,7 @@ namespace MaNGOS
{
// skip self or target
if (u == i_searcher || u == &i_object)
return;
{ return; }
float x, y;
@ -1843,21 +1880,21 @@ namespace MaNGOS
// It is ok for the objects to require a bit more space
float delta = u->GetObjectBoundingRadius();
if (i_selector.m_searchPosFor && i_selector.m_searchPosFor != u)
delta += i_selector.m_searchPosFor->GetObjectBoundingRadius();
{ delta += i_selector.m_searchPosFor->GetObjectBoundingRadius(); }
delta *= OCCUPY_POS_DEPTH_FACTOR; // Increase by factor
// u is too near/far away from i_object. Do not consider it to occupy space
if (fabs(i_selector.m_searcherDist - dist2d) > delta)
return;
{ return; }
float angle = i_object.GetAngle(u) - i_absAngle;
// move angle to range -pi ... +pi, range before is -2Pi..2Pi
if (angle > M_PI_F)
angle -= 2.0f * M_PI_F;
{ angle -= 2.0f * M_PI_F; }
else if (angle < -M_PI_F)
angle += 2.0f * M_PI_F;
{ angle += 2.0f * M_PI_F; }
i_selector.AddUsedArea(u, angle, dist2d);
}
@ -1891,7 +1928,7 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
return;
}
@ -1919,10 +1956,10 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
return;
{ return; }
first_los_conflict = true; // first point have LOS problems
}
@ -1941,10 +1978,10 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
return;
{ return; }
}
// BAD NEWS: not free pos (or used or have LOS problems)
@ -1957,7 +1994,7 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
return;
}
@ -1973,10 +2010,10 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
if (fabs(init_z - z) < dist && IsWithinLOS(x, y, z))
return;
{ return; }
}
// BAD BAD NEWS: all found pos (free and used) have LOS problem :(
@ -1986,7 +2023,7 @@ void WorldObject::GetNearPoint(WorldObject const* searcher, float& x, float& y,
if (searcher)
searcher->UpdateAllowedPositionZ(x, y, z); // update to LOS height if available
else
UpdateGroundPositionZ(x, y, z);
{ UpdateGroundPositionZ(x, y, z); }
}
void WorldObject::SetPhaseMask(uint32 newPhaseMask, bool update)
@ -2004,9 +2041,9 @@ void WorldObject::PlayDistanceSound(uint32 sound_id, Player const* target /*= NU
data << GetObjectGuid();
data << GetObjectGuid();
if (target)
target->SendDirectMessage(&data);
{ target->SendDirectMessage(&data); }
else
SendMessageToSet(&data, true);
{ SendMessageToSet(&data, true); }
}
void WorldObject::PlayDirectSound(uint32 sound_id, Player const* target /*= NULL*/) const
@ -2020,6 +2057,16 @@ void WorldObject::PlayDirectSound(uint32 sound_id, Player const* target /*= NULL
SendMessageToSet(&data, true);
}
void WorldObject::PlayMusic(uint32 sound_id, Player const* target /*= NULL*/) const
{
WorldPacket data(SMSG_PLAY_MUSIC, 4);
data << uint32(sound_id);
if (target)
{ target->SendDirectMessage(&data); }
else
{ SendMessageToSet(&data, true); }
}
void WorldObject::UpdateVisibilityAndView()
{
GetViewPoint().Call_UpdateVisibilityForOwner();
@ -2054,7 +2101,7 @@ struct WorldObjectChangeAccumulator
// send self fields changes in another way, otherwise
// with new camera system when player's camera too far from player, camera wouldn't receive packets and changes from player
if (i_object.isType(TYPEMASK_PLAYER))
i_object.BuildUpdateDataForPlayer((Player*)&i_object, i_updateDatas);
{ i_object.BuildUpdateDataForPlayer((Player*)&i_object, i_updateDatas); }
}
void Visit(CameraMapType& m)
@ -2063,7 +2110,7 @@ struct WorldObjectChangeAccumulator
{
Player* owner = iter->getSource()->GetOwner();
if (owner != &i_object && owner->HaveAtClient(&i_object))
i_object.BuildUpdateDataForPlayer(owner, i_updateDatas);
{ i_object.BuildUpdateDataForPlayer(owner, i_updateDatas); }
}
}
@ -2105,16 +2152,16 @@ bool WorldObject::PrintCoordinatesError(float x, float y, float z, char const* d
void WorldObject::SetActiveObjectState(bool active)
{
if (m_isActiveObject == active || (isType(TYPEMASK_PLAYER) && !active)) // player shouldn't became inactive, never
return;
{ return; }
if (IsInWorld() && !isType(TYPEMASK_PLAYER))
// player's update implemented in a different from other active worldobject's way
// it's considired to use generic way in future
{
if (isActiveObject() && !active)
GetMap()->RemoveFromActive(this);
{ GetMap()->RemoveFromActive(this); }
else if (!isActiveObject() && active)
GetMap()->AddToActive(this);
{ GetMap()->AddToActive(this); }
}
m_isActiveObject = active;
}

View file

@ -22,8 +22,8 @@
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef _OBJECT_H
#define _OBJECT_H
#ifndef MANGOS_H_OBJECT
#define MANGOS_H_OBJECT
#include "Common.h"
#include "ByteBuffer.h"
@ -39,13 +39,13 @@
#define CONTACT_DISTANCE 0.5f
#define INTERACTION_DISTANCE 5.0f
#define ATTACK_DISTANCE 5.0f
#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards
#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards
#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards
#define MAX_VISIBILITY_DISTANCE 333.0f // max distance for visible object show, limited in 333 yards
#define DEFAULT_VISIBILITY_DISTANCE 90.0f // default visible distance, 90 yards on continents
#define DEFAULT_VISIBILITY_INSTANCE 120.0f // default visible distance in instances, 120 yards
#define DEFAULT_VISIBILITY_BGARENAS 180.0f // default visible distance in BG/Arenas, 180 yards
#define DEFAULT_WORLD_OBJECT_SIZE 0.388999998569489f // currently used (correctly?) for any non Unit world objects. This is actually the bounding_radius, like player/creature from creature_model_data
#define DEFAULT_OBJECT_SCALE 1.0f // player/item scale as default, npc/go from database, pets from dbc
#define DEFAULT_OBJECT_SCALE 1.0f // player/item Scale as default, npc/go from database, pets from dbc
#define MAX_STEALTH_DETECT_RANGE 45.0f
@ -73,6 +73,7 @@ class WorldPacket;
class UpdateData;
class WorldSession;
class Creature;
class GameObject;
class Player;
class Unit;
class Group;
@ -84,6 +85,7 @@ class TerrainInfo;
class ElunaEventProcessor;
#endif /* ENABLE_ELUNA */
class TransportInfo;
struct MangosStringLocale;
typedef UNORDERED_MAP<Player*, UpdateData> UpdateDataMapType;
@ -107,6 +109,7 @@ struct WorldLocation
: mapid(loc.mapid), coord_x(loc.coord_x), coord_y(loc.coord_y), coord_z(loc.coord_z), orientation(NormalizeOrientation(loc.orientation)) {}
};
// use this class to measure time between world update ticks
// essential for units updating their spells after cells become active
class WorldUpdateCounter
@ -117,7 +120,7 @@ class WorldUpdateCounter
time_t timeElapsed()
{
if (!m_tmStart)
m_tmStart = WorldTimer::tickPrevTime();
{ m_tmStart = WorldTimer::tickPrevTime(); }
return WorldTimer::getMSTimeDiff(m_tmStart, WorldTimer::tickTime());
}
@ -128,7 +131,7 @@ class WorldUpdateCounter
uint32 m_tmStart;
};
class Object
class Object
{
public:
virtual ~Object();
@ -137,7 +140,7 @@ class Object
virtual void AddToWorld()
{
if (m_inWorld)
return;
{ return; }
m_inWorld = true;
@ -243,8 +246,8 @@ class Object
DynamicObject const* ToDynObject() const { if (GetTypeId() == TYPEID_DYNAMICOBJECT) return reinterpret_cast<DynamicObject const*>(this); else return NULL; }
void SetInt32Value(uint16 index, int32 value);
void SetUInt32Value(uint16 index, uint32 value);
void UpdateUInt32Value(uint16 index, uint32 value);
void SetUInt32Value(uint16 index, uint32 value);
void UpdateUInt32Value(uint16 index, uint32 value);
void SetUInt64Value(uint16 index, const uint64& value);
void SetFloatValue(uint16 index, float value);
void SetByteValue(uint16 index, uint8 offset, uint8 value);
@ -272,11 +275,19 @@ class Object
void ToggleFlag(uint16 index, uint32 flag)
{
if (HasFlag(index, flag))
RemoveFlag(index, flag);
{ RemoveFlag(index, flag); }
else
SetFlag(index, flag);
{ SetFlag(index, flag); }
}
/**
* Checks if a certain flag is set.
* @param index The index to check, values may originate from at least \ref EUnitFields
* @param flag Which flag to check, value may originate from a lot of places, see code
* for examples of what
* @return true if the flag is set, false otherwise
* \todo More info on these flags and where they come from, also, which indexes can be used?
*/
bool HasFlag(uint16 index, uint32 flag) const
{
MANGOS_ASSERT(index < m_valuesCount || PrintIndexError(index , false));
@ -286,9 +297,9 @@ class Object
void ApplyModFlag(uint16 index, uint32 flag, bool apply)
{
if (apply)
SetFlag(index, flag);
{ SetFlag(index, flag); }
else
RemoveFlag(index, flag);
{ RemoveFlag(index, flag); }
}
void SetByteFlag(uint16 index, uint8 offset, uint8 newFlag);
@ -297,9 +308,9 @@ class Object
void ToggleByteFlag(uint16 index, uint8 offset, uint8 flag)
{
if (HasByteFlag(index, offset, flag))
RemoveByteFlag(index, offset, flag);
{ RemoveByteFlag(index, offset, flag); }
else
SetByteFlag(index, offset, flag);
{ SetByteFlag(index, offset, flag); }
}
bool HasByteFlag(uint16 index, uint8 offset, uint8 flag) const
@ -312,9 +323,9 @@ class Object
void ApplyModByteFlag(uint16 index, uint8 offset, uint32 flag, bool apply)
{
if (apply)
SetByteFlag(index, offset, flag);
{ SetByteFlag(index, offset, flag); }
else
RemoveByteFlag(index, offset, flag);
{ RemoveByteFlag(index, offset, flag); }
}
void SetShortFlag(uint16 index, bool highpart, uint16 newFlag);
@ -323,9 +334,9 @@ class Object
void ToggleShortFlag(uint16 index, bool highpart, uint8 flag)
{
if (HasShortFlag(index, highpart, flag))
RemoveShortFlag(index, highpart, flag);
{ RemoveShortFlag(index, highpart, flag); }
else
SetShortFlag(index, highpart, flag);
{ SetShortFlag(index, highpart, flag); }
}
bool HasShortFlag(uint16 index, bool highpart, uint8 flag) const
@ -337,9 +348,9 @@ class Object
void ApplyModShortFlag(uint16 index, bool highpart, uint32 flag, bool apply)
{
if (apply)
SetShortFlag(index, highpart, flag);
{ SetShortFlag(index, highpart, flag); }
else
RemoveShortFlag(index, highpart, flag);
{ RemoveShortFlag(index, highpart, flag); }
}
void SetFlag64(uint16 index, uint64 newFlag)
@ -359,9 +370,9 @@ class Object
void ToggleFlag64(uint16 index, uint64 flag)
{
if (HasFlag64(index, flag))
RemoveFlag64(index, flag);
{ RemoveFlag64(index, flag); }
else
SetFlag64(index, flag);
{ SetFlag64(index, flag); }
}
bool HasFlag64(uint16 index, uint64 flag) const
@ -373,9 +384,9 @@ class Object
void ApplyModFlag64(uint16 index, uint64 flag, bool apply)
{
if (apply)
SetFlag64(index, flag);
{ SetFlag64(index, flag); }
else
RemoveFlag64(index, flag);
{ RemoveFlag64(index, flag); }
}
void ClearUpdateMask(bool remove);
@ -435,7 +446,7 @@ class Object
struct WorldObjectChangeAccumulator;
class WorldObject : public Object
class WorldObject : public Object
{
friend struct WorldObjectChangeAccumulator;
@ -443,7 +454,7 @@ class WorldObject : public Object
// class is used to manipulate with WorldUpdateCounter
// it is needed in order to get time diff between two object's Update() calls
class UpdateHelper
class UpdateHelper
{
public:
explicit UpdateHelper(WorldObject* obj) : m_obj(obj) {}
@ -462,9 +473,9 @@ class WorldObject : public Object
WorldObject* const m_obj;
};
virtual ~WorldObject() {}
virtual ~WorldObject();
virtual void Update(uint32 /*update_diff*/, uint32 /*time_diff*/) {}
virtual void Update(uint32 /*update_diff*/, uint32 /*time_diff*/);
void _Create(uint32 guidlow, HighGuid guidhigh, uint32 phaseMask);
@ -485,6 +496,7 @@ class WorldObject : public Object
void GetPosition(WorldLocation& loc) const
{ loc.mapid = m_mapId; GetPosition(loc.coord_x, loc.coord_y, loc.coord_z); loc.orientation = GetOrientation(); }
float GetOrientation() const { return m_position.o; }
/// Gives a 2d-point in distance distance2d in direction absAngle around the current position (point-to-point)
void GetNearPoint2D(float& x, float& y, float distance2d, float absAngle) const;
/** Gives a "free" spot for searcher in distance distance2d in direction absAngle on "good" height
@ -602,6 +614,7 @@ class WorldObject : public Object
void PlayDistanceSound(uint32 sound_id, Player const* target = NULL) const;
void PlayDirectSound(uint32 sound_id, Player const* target = NULL) const;
void PlayMusic(uint32 sound_id, Player const* target = NULL) const;
void SendObjectDeSpawnAnim(ObjectGuid guid);
void SendGameObjectCustomAnim(ObjectGuid guid, uint32 animId = 0);
@ -645,8 +658,7 @@ class WorldObject : public Object
// ASSERT print helper
bool PrintCoordinatesError(float x, float y, float z, char const* descr) const;
virtual void StartGroupLoot(Group* /*group*/, uint32 /*timer*/) {}
virtual void StartGroupLoot(Group* /*group*/, uint32 /*timer*/) { }
#ifdef ENABLE_ELUNA
ElunaEventProcessor* elunaEvents;
#endif /* ENABLE_ELUNA */

View file

@ -585,13 +585,13 @@ void ObjectMgr::LoadCreatureTemplates()
if (!ok)
continue;
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_A);
FactionTemplateEntry const* factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->FactionAlliance);
if (!factionTemplate)
sLog.outErrorDb("Creature (Entry: %u) has nonexistent faction_A template (%u)", cInfo->Entry, cInfo->faction_A);
sLog.outErrorDb("Creature (Entry: %u) has nonexistent factionAlliance template (%u)", cInfo->Entry, cInfo->FactionAlliance);
factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->faction_H);
factionTemplate = sFactionTemplateStore.LookupEntry(cInfo->FactionHorde);
if (!factionTemplate)
sLog.outErrorDb("Creature (Entry: %u) has nonexistent faction_H template (%u)", cInfo->Entry, cInfo->faction_H);
sLog.outErrorDb("Creature (Entry: %u) has nonexistent factionHorde template (%u)", cInfo->Entry, cInfo->FactionHorde);
for (int k = 0; k < MAX_KILL_CREDIT; ++k)
{
@ -605,7 +605,7 @@ void ObjectMgr::LoadCreatureTemplates()
}
}
// used later for scale
// used later for Scale
CreatureDisplayInfoEntry const* displayScaleEntry = NULL;
for (int i = 0; i < MAX_CREATURE_MODEL; ++i)
@ -701,18 +701,18 @@ void ObjectMgr::LoadCreatureTemplates()
const_cast<CreatureInfo*>(cInfo)->MovementType = IDLE_MOTION_TYPE;
}
if (cInfo->vehicleId && !sVehicleStore.LookupEntry(cInfo->vehicleId))
if (cInfo->VehicleTemplateId && !sVehicleStore.LookupEntry(cInfo->VehicleTemplateId))
{
sLog.outErrorDb("Creature (Entry: %u) has non-existing vehicle_id (%u), set to 0.", cInfo->Entry, cInfo->vehicleId);
const_cast<CreatureInfo*>(cInfo)->vehicleId = 0;
sLog.outErrorDb("Creature (Entry: %u) has non-existing vehicle_id (%u), set to 0.", cInfo->Entry, cInfo->VehicleTemplateId);
const_cast<CreatureInfo*>(cInfo)->VehicleTemplateId = 0;
}
if (cInfo->equipmentId > 0) // 0 no equipment
if (cInfo->EquipmentTemplateId > 0) // 0 no equipment
{
if (!GetEquipmentInfo(cInfo->equipmentId))
if (!GetEquipmentInfo(cInfo->EquipmentTemplateId))
{
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->equipmentId);
const_cast<CreatureInfo*>(cInfo)->equipmentId = 0;
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with equipment_id %u not found in table `creature_equip_template`, set to no equipment.", cInfo->Entry, cInfo->EquipmentTemplateId);
const_cast<CreatureInfo*>(cInfo)->EquipmentTemplateId = 0;
}
}
@ -722,13 +722,13 @@ void ObjectMgr::LoadCreatureTemplates()
sLog.outErrorDb("Table `creature_template` have creature (Entry: %u) with vendor_id %u but not have flag UNIT_NPC_FLAG_VENDOR (%u), vendor items will ignored.", cInfo->Entry, cInfo->vendorId, UNIT_NPC_FLAG_VENDOR);
}
/// if not set custom creature scale then load scale from CreatureDisplayInfo.dbc
if (cInfo->scale <= 0.0f)
/// if not set custom creature Scale then load Scale from CreatureDisplayInfo.dbc
if (cInfo->Scale <= 0.0f)
{
if (displayScaleEntry)
const_cast<CreatureInfo*>(cInfo)->scale = displayScaleEntry->scale;
const_cast<CreatureInfo*>(cInfo)->Scale = displayScaleEntry->Scale;
else
const_cast<CreatureInfo*>(cInfo)->scale = DEFAULT_OBJECT_SCALE;
const_cast<CreatureInfo*>(cInfo)->Scale = DEFAULT_OBJECT_SCALE;
}
}
}
@ -1403,17 +1403,17 @@ void ObjectMgr::LoadCreatures()
data.curhealth = cInfo->minhealth;
}
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
if (cInfo->ExtraFlags & CREATURE_FLAG_EXTRA_INSTANCE_BIND)
{
if (!mapEntry || !mapEntry->IsDungeon())
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_INSTANCE_BIND (%u) but creature are not in instance.",
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_FLAG_EXTRA_INSTANCE_BIND (%u) but creature are not in instance.",
guid, data.id, CREATURE_FLAG_EXTRA_INSTANCE_BIND);
}
if (cInfo->flags_extra & CREATURE_FLAG_EXTRA_AGGRO_ZONE)
if (cInfo->ExtraFlags & CREATURE_FLAG_EXTRA_AGGRO_ZONE)
{
if (!mapEntry || !mapEntry->IsDungeon())
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`flags_extra` including CREATURE_FLAG_EXTRA_AGGRO_ZONE (%u) but creature are not in instance.",
sLog.outErrorDb("Table `creature` have creature (GUID: %u Entry: %u) with `creature_template`.`ExtraFlags` including CREATURE_FLAG_EXTRA_AGGRO_ZONE (%u) but creature are not in instance.",
guid, data.id, CREATURE_FLAG_EXTRA_AGGRO_ZONE);
}
@ -6273,7 +6273,7 @@ void ObjectMgr::LoadGameobjectInfo()
{
GameObjectInfo const* goInfo = itr.getValue();
if (goInfo->size <= 0.0f) // prevent use too small scales
if (goInfo->size <= 0.0f) // prevent use too small Scales
{
ERROR_DB_STRICT_LOG("Gameobject (Entry: %u GoType: %u) have too small size=%f",
goInfo->id, goInfo->type, goInfo->size);
@ -6449,7 +6449,7 @@ void ObjectMgr::LoadGameobjectInfo()
CheckGOSpellId(goInfo, goInfo->spellcaster.spellId, 0);
break;
}
case GAMEOBJECT_TYPE_FLAGSTAND: // 24
case GAMEOBJECT_CreatureTypeFlagsTAND: // 24
{
if (goInfo->flagstand.lockId)
CheckGOLockId(goInfo, goInfo->flagstand.lockId, 0);

View file

@ -902,15 +902,15 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
CreatureFamilyEntry const* cFamily = sCreatureFamilyStore.LookupEntry(cinfo->family);
if (cFamily && cFamily->minScale > 0.0f && getPetType() == HUNTER_PET)
{
float scale;
float Scale;
if (getLevel() >= cFamily->maxScaleLevel)
scale = cFamily->maxScale;
Scale = cFamily->maxScale;
else if (getLevel() <= cFamily->minScaleLevel)
scale = cFamily->minScale;
Scale = cFamily->minScale;
else
scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
Scale = cFamily->minScale + float(getLevel() - cFamily->minScaleLevel) / cFamily->maxScaleLevel * (cFamily->maxScale - cFamily->minScale);
SetObjectScale(scale);
SetObjectScale(Scale);
UpdateModelData();
}
m_bonusdamage = 0;
@ -985,8 +985,8 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
sLog.outErrorDb("Summoned pet (Entry: %u) not have pet stats data in DB", cinfo->Entry);
// remove elite bonuses included in DB values
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel));
SetCreateMana(uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel));
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
SetCreateMana(uint32(((float(cinfo->maxmana) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);
@ -1024,7 +1024,7 @@ bool Pet::InitStatsForLevel(uint32 petlevel, Unit* owner)
sLog.outErrorDb("Hunter pet levelstats missing in DB");
// remove elite bonuses included in DB values
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->rank)) * petlevel));
SetCreateHealth(uint32(((float(cinfo->maxhealth) / cinfo->maxlevel) / (1 + 2 * cinfo->Rank)) * petlevel));
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);

View file

@ -674,7 +674,7 @@ bool Player::Create(uint32 guidlow, const std::string& name, uint8 race, uint8 c
SetByteValue(UNIT_FIELD_BYTES_0, 2, gender);
SetByteValue(UNIT_FIELD_BYTES_0, 3, powertype);
InitDisplayIds(); // model, scale and model data
InitDisplayIds(); // model, Scale and model data
SetByteFlag(UNIT_FIELD_BYTES_2, 1, UNIT_BYTE2_FLAG_PVP);
SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE);
@ -7151,13 +7151,13 @@ void Player::_ApplyItemMods(Item* item, uint8 slot, bool apply)
DEBUG_LOG("_ApplyItemMods complete.");
}
void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool apply, bool only_level_scale /*= false*/)
void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool apply, bool only_level_Scale /*= false*/)
{
if (slot >= INVENTORY_SLOT_BAG_END || !proto)
return;
ScalingStatDistributionEntry const* ssd = proto->ScalingStatDistribution ? sScalingStatDistributionStore.LookupEntry(proto->ScalingStatDistribution) : NULL;
if (only_level_scale && !ssd)
if (only_level_Scale && !ssd)
return;
// req. check at equip, but allow use for extended range if range limit max level, set proper level
@ -7166,7 +7166,7 @@ void Player::_ApplyItemBonuses(ItemPrototype const* proto, uint8 slot, bool appl
ssd_level = ssd->MaxLevel;
ScalingStatValuesEntry const* ssv = proto->StatScalingFactor ? sScalingStatValuesStore.LookupEntry(ssd_level) : NULL;
if (only_level_scale && !ssv)
if (only_level_Scale && !ssv)
return;
for (uint32 i = 0; i < MAX_ITEM_PROTO_STATS; ++i)
@ -15760,7 +15760,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SqlQueryHolder* holder)
_LoadIntoDataField(fields[54].GetString(), PLAYER_EXPLORED_ZONES_1, PLAYER_EXPLORED_ZONES_SIZE);
_LoadIntoDataField(fields[56].GetString(), PLAYER__FIELD_KNOWN_TITLES, KNOWN_TITLES_SIZE*2);
InitDisplayIds(); // model, scale and model data
InitDisplayIds(); // model, Scale and model data
SetFloatValue(UNIT_FIELD_HOVERHEIGHT, 1.0f);
@ -19449,7 +19449,7 @@ void Player::InitDisplayIds()
return;
}
// reset scale before reapply auras
// reset Scale before reapply auras
SetObjectScale(DEFAULT_OBJECT_SCALE);
uint8 gender = getGender();
@ -21484,7 +21484,7 @@ bool Player::isHonorOrXPTarget(Unit* pVictim) const
{
if (((Creature*)pVictim)->IsTotem() ||
((Creature*)pVictim)->IsPet() ||
((Creature*)pVictim)->GetCreatureInfo()->flags_extra & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
((Creature*)pVictim)->GetCreatureInfo()->ExtraFlags & CREATURE_FLAG_EXTRA_NO_XP_AT_KILL)
return false;
}
return true;
@ -21921,7 +21921,7 @@ void Player::UpdateUnderwaterState(Map* m, float x, float y, float z)
}
// All liquids type - check under water position
if (liquid_status.type_flags & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME))
if (liquid_status.CreatureTypeFlags & (MAP_LIQUID_TYPE_WATER | MAP_LIQUID_TYPE_OCEAN | MAP_LIQUID_TYPE_MAGMA | MAP_LIQUID_TYPE_SLIME))
{
if (res & LIQUID_MAP_UNDER_WATER)
m_MirrorTimerFlags |= UNDERWATER_INWATER;
@ -21930,13 +21930,13 @@ void Player::UpdateUnderwaterState(Map* m, float x, float y, float z)
}
// Allow travel in dark water on taxi or transport
if ((liquid_status.type_flags & MAP_LIQUID_TYPE_DARK_WATER) && !IsTaxiFlying() && !GetTransport())
if ((liquid_status.CreatureTypeFlags & MAP_LIQUID_TYPE_DARK_WATER) && !IsTaxiFlying() && !GetTransport())
m_MirrorTimerFlags |= UNDERWATER_INDARKWATER;
else
m_MirrorTimerFlags &= ~UNDERWATER_INDARKWATER;
// in lava check, anywhere in lava level
if (liquid_status.type_flags & MAP_LIQUID_TYPE_MAGMA)
if (liquid_status.CreatureTypeFlags & MAP_LIQUID_TYPE_MAGMA)
{
if (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER | LIQUID_MAP_WATER_WALK))
m_MirrorTimerFlags |= UNDERWATER_INLAVA;
@ -21944,7 +21944,7 @@ void Player::UpdateUnderwaterState(Map* m, float x, float y, float z)
m_MirrorTimerFlags &= ~UNDERWATER_INLAVA;
}
// in slime check, anywhere in slime level
if (liquid_status.type_flags & MAP_LIQUID_TYPE_SLIME)
if (liquid_status.CreatureTypeFlags & MAP_LIQUID_TYPE_SLIME)
{
if (res & (LIQUID_MAP_UNDER_WATER | LIQUID_MAP_IN_WATER | LIQUID_MAP_WATER_WALK))
m_MirrorTimerFlags |= UNDERWATER_INSLIME;

View file

@ -22,8 +22,8 @@
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef _PLAYER_H
#define _PLAYER_H
#ifndef MANGOS_H_PLAYER
#define MANGOS_H_PLAYER
#include "Common.h"
#include "ItemPrototype.h"
@ -194,8 +194,14 @@ struct ActionButton
ActionButtonUpdateState uState;
// helpers
ActionButtonType GetType() const { return ActionButtonType(ACTION_BUTTON_TYPE(packedData)); }
uint32 GetAction() const { return ACTION_BUTTON_ACTION(packedData); }
ActionButtonType GetType() const
{
return ActionButtonType(ACTION_BUTTON_TYPE(packedData));
}
uint32 GetAction() const
{
return ACTION_BUTTON_ACTION(packedData);
}
void SetActionAndType(uint32 action, ActionButtonType type)
{
uint32 newData = action | (uint32(type) << 24);
@ -203,7 +209,7 @@ struct ActionButton
{
packedData = newData;
if (uState != ACTIONBUTTON_NEW)
uState = ACTIONBUTTON_CHANGED;
{ uState = ACTIONBUTTON_CHANGED; }
}
}
};
@ -272,7 +278,10 @@ typedef std::list<PlayerCreateInfoItem> PlayerCreateInfoItems;
struct PlayerLevelInfo
{
PlayerLevelInfo() { for (int i = 0; i < MAX_STATS; ++i) stats[i] = 0; }
PlayerLevelInfo()
{
for (int i = 0; i < MAX_STATS; ++i) { stats[i] = 0; }
}
uint8 stats[MAX_STATS];
};
@ -788,21 +797,6 @@ enum EnviromentalDamage
DAMAGE_FALL_TO_VOID = 6 // custom case for fall without durability loss
};
/*
* This is defined in Chat.h (just like Zero, One, and Two)
* DELETE THIS IF ALL IS OK
enum PlayerChatTag
{
CHAT_TAG_NONE = 0x00,
CHAT_TAG_AFK = 0x01,
CHAT_TAG_DND = 0x02,
CHAT_TAG_GM = 0x04,
CHAT_TAG_COM = 0x08, // Commentator
CHAT_TAG_DEV = 0x10, // Developer
};
*/
enum PlayedTimeIndex
{
PLAYED_TIME_TOTAL = 0,
@ -886,7 +880,7 @@ enum PlayerRestState
REST_STATE_RAF_LINKED = 0x04 // Exact use unknown
};
class PlayerTaxi
class PlayerTaxi
{
public:
PlayerTaxi();
@ -911,7 +905,7 @@ class PlayerTaxi
return true;
}
else
return false;
{ return false; }
}
void AppendTaximaskTo(ByteBuffer& data, bool all);
@ -919,17 +913,32 @@ class PlayerTaxi
bool LoadTaxiDestinationsFromString(const std::string& values, Team team);
std::string SaveTaxiDestinationsToString();
void ClearTaxiDestinations() { m_TaxiDestinations.clear(); }
void AddTaxiDestination(uint32 dest) { m_TaxiDestinations.push_back(dest); }
uint32 GetTaxiSource() const { return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front(); }
uint32 GetTaxiDestination() const { return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1]; }
void ClearTaxiDestinations()
{
m_TaxiDestinations.clear();
}
void AddTaxiDestination(uint32 dest)
{
m_TaxiDestinations.push_back(dest);
}
uint32 GetTaxiSource() const
{
return m_TaxiDestinations.empty() ? 0 : m_TaxiDestinations.front();
}
uint32 GetTaxiDestination() const
{
return m_TaxiDestinations.size() < 2 ? 0 : m_TaxiDestinations[1];
}
uint32 GetCurrentTaxiPath() const;
uint32 NextTaxiDestination()
{
m_TaxiDestinations.pop_front();
return GetTaxiDestination();
}
bool empty() const { return m_TaxiDestinations.empty(); }
bool empty() const
{
return m_TaxiDestinations.empty();
}
friend std::ostringstream& operator<< (std::ostringstream& ss, PlayerTaxi const& taxi);
private:
@ -975,20 +984,38 @@ class TradeData
public: // access functions
Player* GetTrader() const { return m_trader; }
Player* GetTrader() const
{
return m_trader;
}
TradeData* GetTraderData() const;
Item* GetItem(TradeSlots slot) const;
bool HasItem(ObjectGuid item_guid) const;
uint32 GetSpell() const { return m_spell; }
uint32 GetSpell() const
{
return m_spell;
}
Item* GetSpellCastItem() const;
bool HasSpellCastItem() const { return !m_spellCastItem.IsEmpty(); }
bool HasSpellCastItem() const
{
return !m_spellCastItem.IsEmpty();
}
uint64 GetMoney() const { return m_money; }
uint64 GetMoney() const
{
return m_money;
}
bool IsAccepted() const { return m_accepted; }
bool IsInAcceptProcess() const { return m_acceptProccess; }
bool IsAccepted() const
{
return m_accepted;
}
bool IsInAcceptProcess() const
{
return m_acceptProccess;
}
public: // access functions
void SetItem(TradeSlots slot, Item* item);
@ -998,7 +1025,10 @@ class TradeData
void SetAccepted(bool state, bool crosssend = false);
// must be called only from accept handler helper functions
void SetInAcceptProcess(bool state) { m_acceptProccess = state; }
void SetInAcceptProcess(bool state)
{
m_acceptProccess = state;
}
private: // internal functions
@ -1020,7 +1050,7 @@ class TradeData
ObjectGuid m_items[TRADE_SLOT_COUNT]; // traded itmes from m_player side including non-traded slot
};
class Player : public Unit
class Player : public Unit
{
friend class WorldSession;
friend void Item::AddToUpdateQueueOf(Player* player);
@ -1086,14 +1116,23 @@ class Player : public Unit
void ToggleAFK();
void ToggleDND();
bool isAFK() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK); }
bool isDND() const { return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND); }
bool isAFK() const
{
return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_AFK);
}
bool isDND() const
{
return HasFlag(PLAYER_FLAGS, PLAYER_FLAGS_DND);
}
uint8 GetChatTag() const;
std::string autoReplyMsg;
uint32 GetBarberShopCost(uint8 newhairstyle, uint8 newhaircolor, uint8 newfacialhair, uint32 newskintone);
PlayerSocial* GetSocial() { return m_social; }
PlayerSocial* GetSocial()
{
return m_social;
}
PlayerTaxi m_taxi;
void InitTaxiNodesForLevel() { m_taxi.InitTaxiNodesForLevel(getRace(), getClass(), getLevel()); }
@ -1102,15 +1141,15 @@ class Player : public Unit
// mount_id can be used in scripting calls
void ContinueTaxiFlight();
bool isAcceptTickets() const { return GetSession()->GetSecurity() >= SEC_GAMEMASTER && (m_ExtraFlags & PLAYER_EXTRA_GM_ACCEPT_TICKETS); }
void SetAcceptTicket(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_ACCEPT_TICKETS; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_ACCEPT_TICKETS; }
void SetAcceptTicket(bool on) { if (on) { m_ExtraFlags |= PLAYER_EXTRA_GM_ACCEPT_TICKETS; } else { m_ExtraFlags &= ~PLAYER_EXTRA_GM_ACCEPT_TICKETS; } }
bool isAcceptWhispers() const { return m_ExtraFlags & PLAYER_EXTRA_ACCEPT_WHISPERS; }
void SetAcceptWhispers(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; else m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; }
void SetAcceptWhispers(bool on) { if (on) { m_ExtraFlags |= PLAYER_EXTRA_ACCEPT_WHISPERS; } else { m_ExtraFlags &= ~PLAYER_EXTRA_ACCEPT_WHISPERS; } }
bool isGameMaster() const { return m_ExtraFlags & PLAYER_EXTRA_GM_ON; }
void SetGameMaster(bool on);
bool isGMChat() const { return GetSession()->GetSecurity() >= SEC_MODERATOR && (m_ExtraFlags & PLAYER_EXTRA_GM_CHAT); }
void SetGMChat(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; else m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; }
void SetGMChat(bool on) { if (on) { m_ExtraFlags |= PLAYER_EXTRA_GM_CHAT; } else { m_ExtraFlags &= ~PLAYER_EXTRA_GM_CHAT; } }
bool IsTaxiCheater() const { return m_ExtraFlags & PLAYER_EXTRA_TAXICHEAT; }
void SetTaxiCheater(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; else m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; }
void SetTaxiCheater(bool on) { if (on) { m_ExtraFlags |= PLAYER_EXTRA_TAXICHEAT; } else { m_ExtraFlags &= ~PLAYER_EXTRA_TAXICHEAT; } }
bool isGMVisible() const { return !(m_ExtraFlags & PLAYER_EXTRA_GM_INVISIBLE); }
void SetGMVisible(bool on);
void SetPvPDeath(bool on) { if (on) m_ExtraFlags |= PLAYER_EXTRA_PVP_DEATH; else m_ExtraFlags &= ~PLAYER_EXTRA_PVP_DEATH; }
@ -1122,11 +1161,12 @@ class Player : public Unit
m_ExtraFlags &= ~(PLAYER_EXTRA_AUCTION_ENEMY | PLAYER_EXTRA_AUCTION_NEUTRAL);
if (state < 0)
m_ExtraFlags |= PLAYER_EXTRA_AUCTION_ENEMY;
{ m_ExtraFlags |= PLAYER_EXTRA_AUCTION_ENEMY; }
else if (state > 0)
m_ExtraFlags |= PLAYER_EXTRA_AUCTION_NEUTRAL;
{ m_ExtraFlags |= PLAYER_EXTRA_AUCTION_NEUTRAL; }
}
void GiveXP(uint32 xp, Unit* victim);
void GiveLevel(uint32 level);
@ -1137,22 +1177,39 @@ class Player : public Unit
time_t m_Last_tick;
uint32 m_Played_time[MAX_PLAYED_TIME_INDEX];
uint32 GetTotalPlayedTime() { return m_Played_time[PLAYED_TIME_TOTAL]; }
uint32 GetLevelPlayedTime() { return m_Played_time[PLAYED_TIME_LEVEL]; }
uint32 GetTotalPlayedTime()
{
return m_Played_time[PLAYED_TIME_TOTAL];
}
uint32 GetLevelPlayedTime()
{
return m_Played_time[PLAYED_TIME_LEVEL];
}
void ResetTimeSync();
void SendTimeSync();
void SetDeathState(DeathState s) override; // overwrite Unit::SetDeathState
float GetRestBonus() const { return m_rest_bonus; }
float GetRestBonus() const
{
return m_rest_bonus;
}
void SetRestBonus(float rest_bonus_new);
RestType GetRestType() const { return rest_type; }
RestType GetRestType() const
{
return rest_type;
}
void SetRestType(RestType n_r_type, uint32 areaTriggerId = 0);
time_t GetTimeInnEnter() const { return time_inn_enter; }
void UpdateInnerTime(time_t time) { time_inn_enter = time; }
time_t GetTimeInnEnter() const
{
return time_inn_enter;
}
void UpdateInnerTime(time_t time)
{
time_inn_enter = time;
}
void RemovePet(PetSaveMode mode);
@ -1181,7 +1238,10 @@ class Player : public Unit
Item* GetItemByPos(uint16 pos) const;
Item* GetItemByPos(uint8 bag, uint8 slot) const;
uint32 GetItemDisplayIdInSlot(uint8 bag, uint8 slot) const;
Item* GetWeaponForAttack(WeaponAttackType attackType) const { return GetWeaponForAttack(attackType, false, false); }
Item* GetWeaponForAttack(WeaponAttackType attackType) const
{
return GetWeaponForAttack(attackType, false, false);
}
Item* GetWeaponForAttack(WeaponAttackType attackType, bool nonbroken, bool useable) const;
Item* GetShield(bool useable = false) const;
static uint32 GetAttackBySlot(uint8 slot); // MAX_ATTACK if not weapon slot
@ -1211,7 +1271,7 @@ class Player : public Unit
InventoryResult CanStoreItem(uint8 bag, uint8 slot, ItemPosCountVec& dest, Item* pItem, bool swap = false) const
{
if (!pItem)
return EQUIP_ERR_ITEM_NOT_FOUND;
{ return EQUIP_ERR_ITEM_NOT_FOUND; }
uint32 count = pItem->GetCount();
return _CanStoreItem(bag, slot, dest, pItem->GetEntry(), count, pItem, swap, NULL);
}
@ -1246,7 +1306,10 @@ class Player : public Unit
void ApplyEquipCooldown(Item* pItem);
void SetAmmo(uint32 item);
void RemoveAmmo();
float GetAmmoDPS() const { return m_ammoDPS; }
float GetAmmoDPS() const
{
return m_ammoDPS;
}
bool CheckAmmoCompatibility(const ItemPrototype* ammo_proto) const;
void QuickEquipItem(uint16 pos, Item* pItem);
void VisualizeItem(uint8 slot, Item* pItem);
@ -1278,10 +1341,22 @@ class Player : public Unit
void SendEquipError(InventoryResult msg, Item* pItem, Item* pItem2 = NULL, uint32 itemid = 0) const;
void SendBuyError(BuyResult msg, Creature* pCreature, uint32 item, uint32 param);
void SendSellError(SellResult msg, Creature* pCreature, ObjectGuid itemGuid, uint32 param);
void AddWeaponProficiency(uint32 newflag) { m_WeaponProficiency |= newflag; }
void AddArmorProficiency(uint32 newflag) { m_ArmorProficiency |= newflag; }
uint32 GetWeaponProficiency() const { return m_WeaponProficiency; }
uint32 GetArmorProficiency() const { return m_ArmorProficiency; }
void AddWeaponProficiency(uint32 newflag)
{
m_WeaponProficiency |= newflag;
}
void AddArmorProficiency(uint32 newflag)
{
m_ArmorProficiency |= newflag;
}
uint32 GetWeaponProficiency() const
{
return m_WeaponProficiency;
}
uint32 GetArmorProficiency() const
{
return m_ArmorProficiency;
}
bool IsTwoHandUsed() const
{
Item* mainItem = GetItemByPos(INVENTORY_SLOT_BAG_0, EQUIPMENT_SLOT_MAINHAND);
@ -1366,7 +1441,7 @@ class Player : public Unit
void AddQuest(Quest const* pQuest, Object* questGiver);
void CompleteQuest(uint32 quest_id);
void IncompleteQuest(uint32 quest_id);
void RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce);
void RewardQuest(Quest const* pQuest, uint32 reward, Object* questGiver, bool announce = true);
void FailQuest(uint32 quest_id);
bool SatisfyQuestSkill(Quest const* qInfo, bool msg) const;
@ -1509,8 +1584,14 @@ class Player : public Unit
void RegenerateAll(uint32 diff = REGEN_TIME_FULL);
void Regenerate(Powers power, uint32 diff);
void RegenerateHealth(uint32 diff);
void setRegenTimer(uint32 time) {m_regenTimer = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
void setRegenTimer(uint32 time)
{
m_regenTimer = time;
}
void setWeaponChangeTimer(uint32 time)
{
m_weaponChangeTimer = time;
}
uint64 GetMoney() const { return GetUInt64Value(PLAYER_FIELD_COINAGE); }
void ModifyMoney(int64 d)
@ -1531,7 +1612,10 @@ class Player : public Unit
UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED);
}
QuestStatusMap& getQuestStatusMap() { return mQuestStatus; };
QuestStatusMap& getQuestStatusMap()
{
return mQuestStatus;
};
ObjectGuid const& GetSelectionGuid() const { return m_curSelectionGuid; }
void SetSelectionGuid(ObjectGuid guid) { m_curSelectionGuid = guid; SetTargetGuid(guid); }
@ -1550,12 +1634,24 @@ class Player : public Unit
void RemoveMail(uint32 id);
void AddMail(Mail* mail) { m_mail.push_front(mail);}// for call from WorldSession::SendMailTo
uint32 GetMailSize() { return m_mail.size(); }
void AddMail(Mail* mail)
{
m_mail.push_front(mail); // for call from WorldSession::SendMailTo
}
uint32 GetMailSize()
{
return m_mail.size();
}
Mail* GetMail(uint32 id);
PlayerMails::iterator GetMailBegin() { return m_mail.begin();}
PlayerMails::iterator GetMailEnd() { return m_mail.end();}
PlayerMails::iterator GetMailBegin()
{
return m_mail.begin();
}
PlayerMails::iterator GetMailEnd()
{
return m_mail.end();
}
/*********************************************************/
/*** MAILED ITEMS SYSTEM ***/
@ -1647,10 +1743,19 @@ class Player : public Unit
void SetFreePrimaryProfessions(uint16 profs) { SetUInt32Value(PLAYER_CHARACTER_POINTS, profs); }
void InitPrimaryProfessions();
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
PlayerSpellMap& GetSpellMap() { return m_spells; }
PlayerSpellMap const& GetSpellMap() const
{
return m_spells;
}
PlayerSpellMap& GetSpellMap()
{
return m_spells;
}
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
SpellCooldowns const& GetSpellCooldownMap() const
{
return m_spellCooldowns;
}
PlayerTalent const* GetKnownTalentById(int32 talentId) const;
SpellEntry const* GetKnownTalentRankById(int32 talentId) const;
@ -1679,8 +1784,10 @@ class Player : public Unit
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
GlobalCooldownMgr& GetGlobalCooldownMgr()
{
return m_GlobalCooldownMgr;
}
void RemoveArenaSpellCooldowns();
void RemoveAllSpellCooldown();
void _LoadSpellCooldowns(QueryResult* result);
@ -1704,8 +1811,14 @@ class Player : public Unit
bool isRessurectRequested() const { return !m_resurrectGuid.IsEmpty(); }
void ResurectUsingRequestData();
uint32 getCinematic() { return m_cinematic; }
void setCinematic(uint32 cine) { m_cinematic = cine; }
uint32 getCinematic()
{
return m_cinematic;
}
void setCinematic(uint32 cine)
{
m_cinematic = cine;
}
static bool IsActionButtonDataValid(uint8 button, uint32 action, uint8 type, Player* player, bool msg = true);
ActionButton* addActionButton(uint8 spec, uint8 button, uint32 action, uint8 type);
@ -1718,7 +1831,10 @@ class Player : public Unit
void UpdatePvP(bool state, bool ovrride = false);
void UpdateZone(uint32 newZone, uint32 newArea);
void UpdateArea(uint32 newArea);
uint32 GetCachedZoneId() const { return m_zoneUpdateId; }
uint32 GetCachedZoneId() const
{
return m_zoneUpdateId;
}
void UpdateZoneDependentAuras();
void UpdateAreaDependentAuras(); // subzones
@ -1727,7 +1843,10 @@ class Player : public Unit
void UpdateAfkReport(time_t currTime);
void UpdatePvPFlag(time_t currTime);
void UpdateContestedPvP(uint32 currTime);
void SetContestedPvPTimer(uint32 newTime) {m_contestedPvPTimer = newTime;}
void SetContestedPvPTimer(uint32 newTime)
{
m_contestedPvPTimer = newTime;
}
void ResetContestedPvP()
{
clearUnitState(UNIT_STAT_ATTACK_PLAYER);
@ -1737,7 +1856,10 @@ class Player : public Unit
/** todo: -maybe move UpdateDuelFlag+DuelComplete to independent DuelHandler.. **/
DuelInfo* duel;
bool IsInDuelWith(Player const* player) const { return duel && duel->opponent == player && duel->startTime != 0; }
bool IsInDuelWith(Player const* player) const
{
return duel && duel->opponent == player && duel->startTime != 0;
}
void UpdateDuelFlag(time_t currTime);
void CheckDuelDistance(time_t currTime);
void DuelComplete(DuelCompleteType type);
@ -1745,7 +1867,10 @@ class Player : public Unit
bool IsGroupVisibleFor(Player* p) const;
bool IsInSameGroupWith(Player const* p) const;
bool IsInSameRaidWith(Player const* p) const { return p == this || (GetGroup() != NULL && GetGroup() == p->GetGroup()); }
bool IsInSameRaidWith(Player const* p) const
{
return p == this || (GetGroup() != NULL && GetGroup() == p->GetGroup());
}
void UninviteFromGroup();
static void RemoveFromGroup(Group* group, ObjectGuid guid);
void RemoveFromGroup() { RemoveFromGroup(GetGroup(), GetObjectGuid()); }
@ -1858,20 +1983,38 @@ class Player : public Unit
void UpdateArmorSpecializations();
bool FitArmorSpecializationRules(SpellEntry const * spellProto) const;
ObjectGuid const& GetLootGuid() const { return m_lootGuid; }
void SetLootGuid(ObjectGuid const& guid) { m_lootGuid = guid; }
ObjectGuid const& GetLootGuid() const
{
return m_lootGuid;
}
void SetLootGuid(ObjectGuid const& guid)
{
m_lootGuid = guid;
}
void RemovedInsignia(Player* looterPlr);
WorldSession* GetSession() const { return m_session; }
void SetSession(WorldSession* s) { m_session = s; }
WorldSession* GetSession() const
{
return m_session;
}
void SetSession(WorldSession* s)
{
m_session = s;
}
void BuildCreateUpdateBlockForPlayer(UpdateData* data, Player* target) const override;
void DestroyForPlayer(Player* target, bool anim = false) const override;
void SendLogXPGain(uint32 GivenXP, Unit* victim, uint32 RestXP);
uint8 LastSwingErrorMsg() const { return m_swingErrorMsg; }
void SwingErrorMsg(uint8 val) { m_swingErrorMsg = val; }
uint8 LastSwingErrorMsg() const
{
return m_swingErrorMsg;
}
void SwingErrorMsg(uint8 val)
{
m_swingErrorMsg = val;
}
// notifiers
void SendAttackSwingCantAttack();
@ -2094,7 +2237,7 @@ class Player : public Unit
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId != BATTLEGROUND_QUEUE_NONE)
return true;
{ return true; }
return false;
}
@ -2110,14 +2253,14 @@ class Player : public Unit
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return i;
{ return i; }
return PLAYER_MAX_BATTLEGROUND_QUEUES;
}
bool IsInvitedForBattleGroundQueueType(BattleGroundQueueTypeId bgQueueTypeId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
return m_bgBattleGroundQueueID[i].invitedToInstance != 0;
{ return m_bgBattleGroundQueueID[i].invitedToInstance != 0; }
return false;
}
bool InBattleGroundQueueForBattleGroundQueueType(BattleGroundQueueTypeId bgQueueTypeId) const
@ -2148,7 +2291,7 @@ class Player : public Unit
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == BATTLEGROUND_QUEUE_NONE)
return true;
{ return true; }
return false;
}
void RemoveBattleGroundQueueId(BattleGroundQueueTypeId val)
@ -2167,13 +2310,13 @@ class Player : public Unit
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].bgQueueTypeId == bgQueueTypeId)
m_bgBattleGroundQueueID[i].invitedToInstance = instanceId;
{ m_bgBattleGroundQueueID[i].invitedToInstance = instanceId; }
}
bool IsInvitedForBattleGroundInstance(uint32 instanceId) const
{
for (int i = 0; i < PLAYER_MAX_BATTLEGROUND_QUEUES; ++i)
if (m_bgBattleGroundQueueID[i].invitedToInstance == instanceId)
return true;
{ return true; }
return false;
}
WorldLocation const& GetBattleGroundEntryPoint() const { return m_bgData.joinPos; }
@ -2207,7 +2350,7 @@ class Player : public Unit
void SetRestTime(uint32 v) { m_restTime = v; }
/*********************************************************/
/*** ENVIROMENTAL SYSTEM ***/
/*** ENVIRONMENTAL SYSTEM ***/
/*********************************************************/
uint32 EnvironmentalDamage(EnviromentalDamage type, uint32 damage);
@ -2612,7 +2755,7 @@ class Player : public Unit
uint32 m_questRewardTalentCount;
// Social
PlayerSocial *m_social;
PlayerSocial* m_social;
// Groups
GroupReference m_group;
@ -2664,7 +2807,7 @@ class Player : public Unit
void ScheduleDelayedOperation(uint32 operation)
{
if (operation < DELAYED_END)
m_DelayedOperations |= operation;
{ m_DelayedOperations |= operation; }
}
void _fillGearScoreData(Item* item, GearScoreVec* gearScore, uint32& twoHandScore);

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
/**Unit::GetPower
/**
* MaNGOS is a full featured server for World of Warcraft, supporting
* the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
*
@ -27,10 +27,8 @@
* @{
* \file
*/
#ifndef __UNIT_H
#define __UNIT_H
#ifndef MANGOS_H_UNIT
#define MANGOS_H_UNIT
#include "Common.h"
#include "Object.h"
@ -201,7 +199,7 @@ enum UnitStandFlags
enum UnitBytes1_Flags
{
UNIT_BYTE1_FLAG_ALWAYS_STAND = 0x01,
UNIT_BYTE1_FLAG_UNK_2 = 0x02, // Creature that can fly and are not on the ground appear to have this flag. If they are on the ground, flag is not present.
UNIT_BYTE1_FLAG_FLY_ANIM = 0x02, // Creature that can fly and are not on the ground appear to have this flag. If they are on the ground, flag is not present.
UNIT_BYTE1_FLAG_UNTRACKABLE = 0x04,
UNIT_BYTE1_FLAG_ALL = 0xFF
};
@ -358,17 +356,20 @@ enum DamageTypeToSchool
DAMAGE_TAKEN
};
/**
* This is what decides how an \ref Aura was removed, the cause of it being removed.
*/
enum AuraRemoveMode
{
AURA_REMOVE_BY_DEFAULT,
AURA_REMOVE_BY_STACK, // at replace by similar aura
AURA_REMOVE_BY_CANCEL,
AURA_REMOVE_BY_DISPEL,
AURA_REMOVE_BY_DEATH,
AURA_REMOVE_BY_DELETE, // use for speedup and prevent unexpected effects at player logout/pet unsummon (must be used _only_ after save), delete.
AURA_REMOVE_BY_SHIELD_BREAK, // when absorb shield is removed by damage, heal absorb debuf
AURA_REMOVE_BY_EXPIRE, // at duration end
AURA_REMOVE_BY_TRACKING, // aura is removed because of a conflicting tracked aura
AURA_REMOVE_BY_STACK, ///< at replace by similar aura
AURA_REMOVE_BY_CANCEL, ///< It was cancelled by the user (needs confirmation)
AURA_REMOVE_BY_DISPEL, ///< It was dispelled by ie Remove Magic
AURA_REMOVE_BY_DEATH, ///< The \ref Unit died and there for it was removed
AURA_REMOVE_BY_DELETE, ///< use for speedup and prevent unexpected effects at player logout/pet unsummon (must be used _only_ after save), delete.
AURA_REMOVE_BY_SHIELD_BREAK, ///< when absorb shield is removed by damage
AURA_REMOVE_BY_EXPIRE, ///< at duration end
AURA_REMOVE_BY_TRACKING ///< aura is removed because of a conflicting tracked aura
};
enum UnitMods
@ -866,10 +867,10 @@ namespace Movement
*/
enum DiminishingLevels
{
DIMINISHING_LEVEL_1 = 0, //< Won't make a difference to stun duration
DIMINISHING_LEVEL_2 = 1, //< Reduces stun time by 50%
DIMINISHING_LEVEL_3 = 2, //< Reduces stun time by 75%
DIMINISHING_LEVEL_IMMUNE = 3 //< The target is immune to the DiminishingGrouop
DIMINISHING_LEVEL_1 = 0, ///<Won't make a difference to stun duration
DIMINISHING_LEVEL_2 = 1, ///<Reduces stun time by 50%
DIMINISHING_LEVEL_3 = 2, ///<Reduces stun time by 75%
DIMINISHING_LEVEL_IMMUNE = 3 ///<The target is immune to the DiminishingGrouop
};
/**
@ -909,14 +910,16 @@ struct DiminishingReturn
uint32 hitCount;
};
// At least some values expected fixed and used in auras field, other custom
/**
* At least some values expected fixed and used in auras field, other custom
*/
enum MeleeHitOutcome
{
MELEE_HIT_EVADE = 0,
MELEE_HIT_MISS = 1,
MELEE_HIT_DODGE = 2, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_BLOCK = 3, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_PARRY = 4, // used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_DODGE = 2, ///< used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_BLOCK = 3, ///< used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_PARRY = 4, ///< used as misc in SPELL_AURA_IGNORE_COMBAT_RESULT
MELEE_HIT_GLANCING = 5,
MELEE_HIT_CRIT = 6,
MELEE_HIT_CRUSHING = 7,
@ -1012,6 +1015,10 @@ struct SpellNonMeleeDamage
uint32 HitInfo;
};
/**
* Used as a convenience struct for the \ref Unit::SendPeriodicAuraLog
* \todo Is it used in more places? Check SpellAuras.cpp for some examples and document it
*/
struct SpellPeriodicAuraLogInfo
{
SpellPeriodicAuraLogInfo(Aura* _aura, uint32 _damage, uint32 _overDamage, uint32 _absorb, uint32 _resist, float _multiplier, bool _critical = false)
@ -1153,6 +1160,11 @@ enum ActionBarIndex
#define MAX_UNIT_ACTION_BAR_INDEX (ACTION_BAR_INDEX_END-ACTION_BAR_INDEX_START)
/**
* This structure/class is used when someone is charming (ie: mind control spell and the like)
* someone else, to get the charmed ones action bar, the spells and such. It also takes care
* of pets the charmed one has etc.
*/
struct CharmInfo
{
public:
@ -1680,13 +1692,14 @@ class Unit : public WorldObject
* \see EUnitFields
* \see GetUInt32Value
*/
bool HealthAbovePctHealed(int32 pct, uint32 heal) const { return uint64(GetHealth()) + uint64(heal) > CountPctFromMaxHealth(pct); }
uint32 GetMaxHealth() const { return GetUInt32Value(UNIT_FIELD_MAXHEALTH); }
bool IsFullHealth() const { return GetHealth() == GetMaxHealth(); }
bool HealthBelowPct(int32 pct) const { return GetHealth() < CountPctFromMaxHealth(pct); }
bool HealthBelowPctDamaged(int32 pct, uint32 damage) const { return int64(GetHealth()) - int64(damage) < int64(CountPctFromMaxHealth(pct)); }
bool HealthAbovePct(int32 pct) const { return GetHealth() > CountPctFromMaxHealth(pct); }
/**
* Gets the percent of the health. The formula: (GetHealth() * 100) / GetMaxHealth()
* @return the current percent of the health
@ -2185,26 +2198,119 @@ class Unit : public WorldObject
}
bool IsSpiritService() const { return HasFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_SPIRITHEALER | UNIT_NPC_FLAG_SPIRITGUIDE); }
/**
* Is this unit flying in taxi?
* @return true if the Unit has the state \ref UNIT_STAT_TAXI_FLIGHT (is flying in taxi), false otherwise
* \see hasUnitState
*/
bool IsTaxiFlying() const { return hasUnitState(UNIT_STAT_TAXI_FLIGHT); }
/**
* Checks to see if a creature, whilst moving along a path, has reached a specific waypoint, or near to
* @param currentPositionX is the creature's current X ordinate in the game world
* @param currentPositionY is the creature's current Y ordinate in the game world
* @param currentPositionZ is the creature's current Z ordinate in the game world
* @param destinationPositionX is the in game ordinate that we wish to check against the creature's current X ordinate (are they the same, or very close?)
* @param destinationPositionY is the in game ordinate that we wish to check against the creature's current Y ordinate (are they the same, or very close?)
* @param destinationPositionZ is the in game ordinate that we wish to check against the creature's current Z ordinate (are they the same, or very close?)
* @param distanceX is the distance from the creature's current X ordinate to the destination X ordinate
* @param distanceY is the distance from the creature's current Y ordinate to the destination Y ordinate
* @param distanceZ is the distance from the creature's current Z ordinate to the destination Z ordinate
*
*/
bool IsNearWaypoint(float currentPositionX, float currentPositionY, float currentPositionZ, float destinationPositionX, float destinationPositionY, float destinationPositionZ, float distanceX, float distanceY, float distanceZ);
/**
* Is this unit in combat?
* @return true if the Unit has the flag \ref UNIT_FLAG_IN_COMBAT (is in combat), false otherwise
* \see EUnitFields
* \see UnitFlags
*/
bool IsInCombat() const { return HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IN_COMBAT); }
/**
* Sets this \ref Unit into combat, if it already was this has no bigger meaning if the
* PvP flag hasn't changed since last time it was applied.
* @param PvP whether this was a PvP combat or not, this is important for how quick the combat flag will wear away and possibly more
* @param enemy Our target that we are attacking, only does something if the attacked one is a creature it seems
* \see ClearInCombat
* \see SetInCombatWith
*/
void SetInCombatState(bool PvP, Unit* enemy = NULL);
/**
* Sets us in combat with the given enemy, this in turn just does a few small checks for if
* it's a duel or PvP and then calls \ref Unit::SetInCombatState with the correct value for
* PvP and enemy
* @param enemy the enemy that we are attacking/engaging
* \see ClearInCombat
* \see SetInCombatState
*/
void SetInCombatWith(Unit* enemy);
/**
* Clears the combat flag for this unit using \ref Object::RemoveFlag and clears
* the Unit state \ref UnitState::UNIT_STAT_ATTACK_PLAYER. This is not where a
* \ref Player s PvP flags are cleared, that is handled in \ref Player::UpdateContestedPvP
* \see EUnitFields
*/
void ClearInCombat();
/**
* Probably returns how long it is until this Unit should get out of PvP combat again,
* although not used in that sense.
* @return the time we have left from our start of PvP combat
* \todo Find out what this actually does/means
*/
uint32 GetCombatTimer() const { return m_CombatTimer; }
/**
* Gets all \ref SpellAuraHolder s that have the same given spell_id
* @param spell_id the spell_id to search for
* @return 2 iterators to the range of \ref SpellAuraHolder s that were found
*/
SpellAuraHolderBounds GetSpellAuraHolderBounds(uint32 spell_id)
{
return m_spellAuraHolders.equal_range(spell_id);
}
/**
* Same as \ref Unit::GetSpellAuraHolderBounds
*/
SpellAuraHolderConstBounds GetSpellAuraHolderBounds(uint32 spell_id) const
{
return m_spellAuraHolders.equal_range(spell_id);
}
/**
* Checks if this \ref Unit has the given AuraType
* @param auraType the type of aura to look for
* @return true if this \ref Unit is affected by the given \ref AuraType, false otherwise
*/
bool HasAuraType(AuraType auraType) const;
/**
* Checks if the given \ref SpellEntry affects the \ref AuraType in some way, this is done
* by calling \ref Aura::isAffectedOnSpell which in turn seems to check if the spellProto
* and the \ref Aura s own \ref SpellEntry have the same \ref SpellEntry::SpellFamilyName.
* (The \ref Aura get's it's \ref SpellEntry by calling \ref Aura::GetSpellProto)
* @param auraType the type of aura we want to check
* @param spellProto the spell we want to check for affecting the aura type
* @return true if the spell affects the given aura type, false otherwise
* \todo Is this actually correct, also, make it more clear what it actually checks
*/
bool HasAffectedAura(AuraType auraType, SpellEntry const* spellProto) const;
/**
* Checks if we have at least one \ref Aura that is associated with the given spell id
* and \ref SpellEffectIndex.
* @param spellId the spell id to look for
* @param effIndex the effect index the \ref Aura should have
* @return true if there was at least one \ref Aura associated with the id that belonged to
* the correct \ref SpellEffectIndex, false otherwise
*/
bool HasAura(uint32 spellId, SpellEffectIndex effIndex) const;
/**
* Checks if we have at least one \ref Aura that is associated with the given spell id via
* the \ref Unit::m_spellAuraHolders multimap. Generalized version of the other
* \ref Unit::HasAura
* @param spellId the spell id to look for
* @return true if there was at least one \ref Aura associated with the id, false otherwise
*/
bool HasAura(uint32 spellId) const
{
return m_spellAuraHolders.find(spellId) != m_spellAuraHolders.end();
@ -3197,7 +3303,7 @@ class Unit : public WorldObject
void setTransForm(uint32 spellid) { m_transform = spellid;}
uint32 getTransForm() const { return m_transform;}
// at any changes to scale and/or displayId
// at any changes to Scale and/or displayId
void UpdateModelData();
DynamicObject* GetDynObject(uint32 spellId, SpellEffectIndex effIndex);

View file

@ -753,7 +753,7 @@ struct CreatureDisplayInfoEntry
// 1 m_modelID
// 2 m_soundID
uint32 ExtendedDisplayInfoID; // 3 m_extendedDisplayInfoID -> CreatureDisplayInfoExtraEntry::DisplayExtraId
float scale; // 4 m_creatureModelScale
float Scale; // 4 m_creatureModelScale
// 5 m_creatureModelAlpha
// 6-8 m_textureVariation[3]
// 9 m_portraitTextureName

View file

@ -1627,7 +1627,7 @@ enum GameobjectTypes
GAMEOBJECT_TYPE_GUARDPOST = 21,
GAMEOBJECT_TYPE_SPELLCASTER = 22,
GAMEOBJECT_TYPE_MEETINGSTONE = 23,
GAMEOBJECT_TYPE_FLAGSTAND = 24,
GAMEOBJECT_CreatureTypeFlagsTAND = 24,
GAMEOBJECT_TYPE_FISHINGHOLE = 25,
GAMEOBJECT_TYPE_FLAGDROP = 26,
GAMEOBJECT_TYPE_MINI_GAME = 27,
@ -3140,7 +3140,7 @@ inline SkillType SkillByLockType(LockType locktype)
{
switch (locktype)
{
case LOCKTYPE_PICKLOCK: return SkillType(MAX_SKILL_TYPE); // no skill for such lock, 'skill' value scales with level
case LOCKTYPE_PICKLOCK: return SkillType(MAX_SKILL_TYPE); // no skill for such lock, 'skill' value Scales with level
case LOCKTYPE_HERBALISM: return SKILL_HERBALISM;
case LOCKTYPE_MINING: return SKILL_MINING;
case LOCKTYPE_FISHING: return SKILL_FISHING;

View file

@ -69,7 +69,7 @@ typedef ACE_Svc_Handler<ACE_SOCK_STREAM, ACE_NULL_SYNCH> WorldHandler;
* a queue where it stores packet if there is no place on
* the queue. The reason this is done, is because the server
* does really a lot of small-size writes to it, and it doesn't
* scale well to allocate memory for every. When something is
* Scale well to allocate memory for every. When something is
* written to the output buffer the socket is not immediately
* activated for output (again for the same reason), there
* is 10ms celling (thats why there is Update() override method).

View file

@ -429,7 +429,7 @@ ChatCommand* ChatHandler::getCommandTable()
{ "money", SEC_MODERATOR, false, &ChatHandler::HandleModifyMoneyCommand, "", NULL },
{ "speed", SEC_MODERATOR, false, &ChatHandler::HandleModifySpeedCommand, "", NULL },
{ "swim", SEC_MODERATOR, false, &ChatHandler::HandleModifySwimCommand, "", NULL },
{ "scale", SEC_MODERATOR, false, &ChatHandler::HandleModifyScaleCommand, "", NULL },
{ "Scale", SEC_MODERATOR, false, &ChatHandler::HandleModifyScaleCommand, "", NULL },
{ "bwalk", SEC_MODERATOR, false, &ChatHandler::HandleModifyBWalkCommand, "", NULL },
{ "fly", SEC_MODERATOR, false, &ChatHandler::HandleModifyFlyCommand, "", NULL },
{ "aspeed", SEC_MODERATOR, false, &ChatHandler::HandleModifyASpeedCommand, "", NULL },

View file

@ -584,7 +584,7 @@ GridMapLiquidStatus GridMap::getLiquidStatus(float x, float y, float z, uint8 Re
if (data)
{
data->entry = entry;
data->type_flags = type;
data->CreatureTypeFlags = type;
data->level = liquid_level;
data->depth_level = ground_level;
}
@ -1009,7 +1009,7 @@ GridMapLiquidStatus TerrainInfo::getLiquidStatus(float x, float y, float z, uint
data->depth_level = ground_level;
data->entry = liquid_type;
data->type_flags = 1 << liquidFlagType;
data->CreatureTypeFlags = 1 << liquidFlagType;
}
// For speed check as int values

View file

@ -117,7 +117,7 @@ enum GridMapLiquidStatus
struct GridMapLiquidData
{
uint32 type_flags;
uint32 CreatureTypeFlags;
uint32 entry;
float level;
float depth_level;

View file

@ -26,23 +26,24 @@
#include "Database/DatabaseEnv.h"
#include "Map.h"
#include "Log.h"
#include "WorldPacket.h"
void InstanceData::SaveToDB() const
{
// no reason to save BGs/Arenas
if (instance->IsBattleGroundOrArena())
return;
{ return; }
if (!Save())
return;
{ return; }
std::string data = Save();
CharacterDatabase.escape_string(data);
if (instance->Instanceable())
CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%u'", data.c_str(), instance->GetInstanceId());
{ CharacterDatabase.PExecute("UPDATE instance SET data = '%s' WHERE id = '%u'", data.c_str(), instance->GetInstanceId()); }
else
CharacterDatabase.PExecute("UPDATE world SET data = '%s' WHERE map = '%u'", data.c_str(), instance->GetId());
{ CharacterDatabase.PExecute("UPDATE world SET data = '%s' WHERE map = '%u'", data.c_str(), instance->GetId()); }
}
bool InstanceData::CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/ /*= NULL*/, uint32 /*miscvalue1*/ /*= 0*/) const

View file

@ -55,7 +55,7 @@ enum InstanceConditionIDs // Suggested values
INSTANCE_CONDITION_ID_ULDUAR = 33113,
};
class InstanceData
class InstanceData
{
public:
@ -94,16 +94,19 @@ class InstanceData
virtual void OnObjectCreate(GameObject*) {}
// called on creature creation
virtual void OnCreatureCreate(Creature * /*creature*/) {}
virtual void OnCreatureCreate(Creature* /*creature*/) {}
// called on creature enter combat
virtual void OnCreatureEnterCombat(Creature * /*creature*/) {}
virtual void OnCreatureEnterCombat(Creature* /*creature*/) {}
// called on creature evade
virtual void OnCreatureEvade(Creature * /*creature*/) {}
virtual void OnCreatureEvade(Creature* /*creature*/) {}
// called on creature death
virtual void OnCreatureDeath(Creature * /*creature*/) {}
virtual void OnCreatureDeath(Creature* /*creature*/) {}
// called on creature despawn
virtual void OnCreatureDespawn(Creature* /*creature*/) {}
// All-purpose data storage 64 bit
virtual uint64 GetData64(uint32 /*Data*/) const { return 0; }

View file

@ -75,7 +75,7 @@ bool WorldSession::CheckMailBox(ObjectGuid guid)
return false;
}
if (!(creature->GetCreatureInfo()->type_flags & CREATURE_TYPEFLAGS_SQUIRE))
if (!(creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_SQUIRE))
{
DEBUG_LOG("%s not have access to mailbox.", creature->GetGuidStr().c_str());
return false;

View file

@ -28,8 +28,8 @@
#include "Common.h"
#include "Platform/Define.h"
#include "Policies/ThreadingModel.h"
#include "ace/RW_Thread_Mutex.h"
#include "ace/Thread_Mutex.h"
#include <ace/RW_Thread_Mutex.h>
#include <ace/Thread_Mutex.h>
#include "DBCStructure.h"
#include "GridDefines.h"
@ -100,219 +100,219 @@ enum LevelRequirementVsMode
#define MIN_UNLOAD_DELAY 1 // immediate unload
class Map : public GridRefManager<NGridType>
class Map : public GridRefManager<NGridType>
{
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
friend class MapReference;
friend class ObjectGridLoader;
friend class ObjectWorldLoader;
protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
protected:
Map(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
public:
virtual ~Map();
public:
virtual ~Map();
// currently unused for normal maps
bool CanUnload(uint32 diff)
{
if (!m_unloadTimer) { return false; }
if (m_unloadTimer <= diff) { return true; }
m_unloadTimer -= diff;
return false;
}
// currently unused for normal maps
bool CanUnload(uint32 diff)
{
if (!m_unloadTimer) { return false; }
if (m_unloadTimer <= diff) { return true; }
m_unloadTimer -= diff;
return false;
}
virtual bool Add(Player*);
virtual void Remove(Player*, bool);
template<class T> void Add(T*);
template<class T> void Remove(T*, bool);
virtual bool Add(Player*);
virtual void Remove(Player*, bool);
template<class T> void Add(T*);
template<class T> void Remove(T*, bool);
static void DeleteFromWorld(Player* player); // player object will deleted at call
static void DeleteFromWorld(Player* player); // player object will deleted at call
virtual void Update(const uint32&);
virtual void Update(const uint32&);
void MessageBroadcast(Player const*, WorldPacket*, bool to_self);
void MessageBroadcast(WorldObject const*, WorldPacket*);
void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist);
void MessageBroadcast(Player const*, WorldPacket*, bool to_self);
void MessageBroadcast(WorldObject const*, WorldPacket*);
void MessageDistBroadcast(Player const*, WorldPacket*, float dist, bool to_self, bool own_team_only = false);
void MessageDistBroadcast(WorldObject const*, WorldPacket*, float dist);
float GetVisibilityDistance() const { return m_VisibleDistance; }
// function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
float GetVisibilityDistance() const { return m_VisibleDistance; }
// function for setting up visibility distance for maps on per-type/per-Id basis
virtual void InitVisibilityDistance();
void PlayerRelocation(Player*, float x, float y, float z, float angl);
void CreatureRelocation(Creature* creature, float x, float y, float z, float orientation);
void PlayerRelocation(Player*, float x, float y, float z, float angl);
void CreatureRelocation(Creature* creature, float x, float y, float z, float orientation);
template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor);
template<class T, class CONTAINER> void Visit(const Cell& cell, TypeContainerVisitor<T, CONTAINER>& visitor);
bool IsRemovalGrid(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return(!getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL);
}
bool IsRemovalGrid(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return(!getNGrid(p.x_coord, p.y_coord) || getNGrid(p.x_coord, p.y_coord)->GetGridState() == GRID_STATE_REMOVAL);
}
bool IsLoaded(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p);
}
bool IsLoaded(float x, float y) const
{
GridPair p = MaNGOS::ComputeGridPair(x, y);
return loaded(p);
}
bool GetUnloadLock(const GridPair& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(const GridPair& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
virtual void UnloadAll(bool pForce);
bool GetUnloadLock(const GridPair& p) const { return getNGrid(p.x_coord, p.y_coord)->getUnloadLock(); }
void SetUnloadLock(const GridPair& p, bool on) { getNGrid(p.x_coord, p.y_coord)->setUnloadExplicitLock(on); }
void LoadGrid(const Cell& cell, bool no_unload = false);
bool UnloadGrid(const uint32& x, const uint32& y, bool pForce);
virtual void UnloadAll(bool pForce);
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor));
}
void ResetGridExpiry(NGridType& grid, float factor = 1) const
{
grid.ResetTimeTracker((time_t)((float)i_gridExpiry * factor));
}
time_t GetGridExpiry(void) const { return i_gridExpiry; }
uint32 GetId(void) const { return i_id; }
time_t GetGridExpiry(void) const { return i_gridExpiry; }
uint32 GetId(void) const { return i_id; }
// some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height
// some calls like isInWater should not use vmaps due to processor power
// can return INVALID_HEIGHT if under z+2 z coord not found height
virtual void RemoveAllObjectsInRemoveList();
virtual void RemoveAllObjectsInRemoveList();
bool CreatureRespawnRelocation(Creature* c); // used only in CreatureRelocation and ObjectGridUnloader
bool CreatureRespawnRelocation(Creature* c); // used only in CreatureRelocation and ObjectGridUnloader
bool CheckGridIntegrity(Creature* c, bool moved) const;
bool CheckGridIntegrity(Creature* c, bool moved) const;
uint32 GetInstanceId() const { return i_InstanceId; }
virtual bool CanEnter(Player* player);
const char* GetMapName() const;
uint32 GetInstanceId() const { return i_InstanceId; }
virtual bool CanEnter(Player* player);
const char* GetMapName() const;
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
// _currently_ spawnmode == difficulty, but this can be changes later, so use appropriate spawnmode/difficult functions
// for simplify later code support
// regular difficulty = continent/dungeon normal/first raid normal difficulty
uint8 GetSpawnMode() const { return (i_spawnMode); }
Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const; // dependent from map difficulty
uint32 GetMaxResetDelay() const; // dependent from map difficulty
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
// have meaning only for instanced map (that have set real difficulty), NOT USE its for BaseMap
// _currently_ spawnmode == difficulty, but this can be changes later, so use appropriate spawnmode/difficult functions
// for simplify later code support
// regular difficulty = continent/dungeon normal/first raid normal difficulty
uint8 GetSpawnMode() const { return (i_spawnMode); }
Difficulty GetDifficulty() const { return Difficulty(GetSpawnMode()); }
bool IsRegularDifficulty() const { return GetDifficulty() == REGULAR_DIFFICULTY; }
uint32 GetMaxPlayers() const; // dependent from map difficulty
uint32 GetMaxResetDelay() const; // dependent from map difficulty
MapDifficultyEntry const* GetMapDifficulty() const; // dependent from map difficulty
bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); }
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); }
bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
bool Instanceable() const { return i_mapEntry && i_mapEntry->Instanceable(); }
// NOTE: this duplicate of Instanceable(), but Instanceable() can be changed when BG also will be instanceable
bool IsDungeon() const { return i_mapEntry && i_mapEntry->IsDungeon(); }
bool IsRaid() const { return i_mapEntry && i_mapEntry->IsRaid(); }
bool IsHeroic() const { return IsRaid() ? i_spawnMode >= RAID_DIFFICULTY_10MAN_HEROIC : i_spawnMode >= DUNGEON_DIFFICULTY_HEROIC; }
bool IsNonRaidDungeon() const { return i_mapEntry && i_mapEntry->IsNonRaidDungeon(); }
bool IsRaidOrHeroicDungeon() const { return IsRaid() || GetDifficulty() > DUNGEON_DIFFICULTY_NORMAL; }
bool IsBattleGround() const { return i_mapEntry && i_mapEntry->IsBattleGround(); }
bool IsBattleArena() const { return i_mapEntry && i_mapEntry->IsBattleArena(); }
bool IsBattleGroundOrArena() const { return i_mapEntry && i_mapEntry->IsBattleGroundOrArena(); }
// can't be NULL for loaded map
MapPersistentState* GetPersistentState() const { return m_persistentState; }
// can't be NULL for loaded map
MapPersistentState* GetPersistentState() const { return m_persistentState; }
void AddObjectToRemoveList(WorldObject* obj);
void AddObjectToRemoveList(WorldObject* obj);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void UpdateObjectVisibility(WorldObject* obj, Cell cell, CellPair cellpair);
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
void resetMarkedCells() { marked_cells.reset(); }
bool isCellMarked(uint32 pCellId) { return marked_cells.test(pCellId); }
void markCell(uint32 pCellId) { marked_cells.set(pCellId); }
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
bool HavePlayers() const { return !m_mapRefManager.isEmpty(); }
uint32 GetPlayersCountExceptGMs() const;
bool ActiveObjectsNearGrid(uint32 x, uint32 y) const;
/// Send a Packet to all players on a map
void SendToPlayers(WorldPacket const* data) const;
/// Send a Packet to all players in a zone. Return false if no player found
bool SendToPlayersInZone(WorldPacket const* data, uint32 zoneId) const;
/// Send a Packet to all players on a map
void SendToPlayers(WorldPacket const* data) const;
/// Send a Packet to all players in a zone. Return false if no player found
bool SendToPlayersInZone(WorldPacket const* data, uint32 zoneId) const;
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
typedef MapRefManager PlayerList;
PlayerList const& GetPlayers() const { return m_mapRefManager; }
// per-map script storage
enum ScriptExecutionParam
{
SCRIPT_EXEC_PARAM_NONE = 0x00, // Start regardless if already started
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE = 0x01, // Start Script only if not yet started (uniqueness identified by id and source)
SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET = 0x02, // Start Script only if not yet started (uniqueness identified by id and target)
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET = 0x03, // Start Script only if not yet started (uniqueness identified by id, source and target)
};
bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE);
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
// per-map script storage
enum ScriptExecutionParam
{
SCRIPT_EXEC_PARAM_NONE = 0x00, // Start regardless if already started
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE = 0x01, // Start Script only if not yet started (uniqueness identified by id and source)
SCRIPT_EXEC_PARAM_UNIQUE_BY_TARGET = 0x02, // Start Script only if not yet started (uniqueness identified by id and target)
SCRIPT_EXEC_PARAM_UNIQUE_BY_SOURCE_TARGET = 0x03, // Start Script only if not yet started (uniqueness identified by id, source and target)
};
bool ScriptsStart(ScriptMapMapName const& scripts, uint32 id, Object* source, Object* target, ScriptExecutionParam execParams = SCRIPT_EXEC_PARAM_NONE);
void ScriptCommandStart(ScriptInfo const& script, uint32 delay, Object* source, Object* target);
// must called with AddToWorld
void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld
void RemoveFromActive(WorldObject* obj);
// must called with AddToWorld
void AddToActive(WorldObject* obj);
// must called with RemoveFromWorld
void RemoveFromActive(WorldObject* obj);
Player* GetPlayer(ObjectGuid guid);
Creature* GetCreature(ObjectGuid guid);
Pet* GetPet(ObjectGuid guid);
Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle
GameObject* GetGameObject(ObjectGuid guid);
DynamicObject* GetDynamicObject(ObjectGuid guid);
Corpse* GetCorpse(ObjectGuid guid); // !!! find corpse can be not in world
Unit* GetUnit(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
Player* GetPlayer(ObjectGuid guid);
Creature* GetCreature(ObjectGuid guid);
Pet* GetPet(ObjectGuid guid);
Creature* GetAnyTypeCreature(ObjectGuid guid); // normal creature or pet or vehicle
GameObject* GetGameObject(ObjectGuid guid);
DynamicObject* GetDynamicObject(ObjectGuid guid);
Corpse* GetCorpse(ObjectGuid guid); // !!! find corpse can be not in world
Unit* GetUnit(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
WorldObject* GetWorldObject(ObjectGuid guid); // only use if sure that need objects at current map, specially for player case
typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; }
typedef TypeUnorderedMapContainer<AllMapStoredObjectTypes, ObjectGuid> MapStoredObjectTypesContainer;
MapStoredObjectTypesContainer& GetObjectsStore() { return m_objectsStore; }
void AddUpdateObject(Object* obj)
{
i_objectsToClientUpdate.insert(obj);
}
void AddUpdateObject(Object* obj)
{
i_objectsToClientUpdate.insert(obj);
}
void RemoveUpdateObject(Object* obj)
{
i_objectsToClientUpdate.erase(obj);
}
void RemoveUpdateObject(Object* obj)
{
i_objectsToClientUpdate.erase(obj);
}
// DynObjects currently
uint32 GenerateLocalLowGuid(HighGuid guidhigh);
// DynObjects currently
uint32 GenerateLocalLowGuid(HighGuid guidhigh);
// get corresponding TerrainData object for this particular map
const TerrainInfo* GetTerrain() const { return m_TerrainData; }
// get corresponding TerrainData object for this particular map
const TerrainInfo* GetTerrain() const { return m_TerrainData; }
void CreateInstanceData(bool load);
InstanceData* GetInstanceData() const { return i_data; }
virtual uint32 GetScriptId() const { return sScriptMgr.GetBoundScriptId(SCRIPTED_MAP, GetId()); }
void CreateInstanceData(bool load);
InstanceData* GetInstanceData() const { return i_data; }
virtual uint32 GetScriptId() const { return sScriptMgr.GetBoundScriptId(SCRIPTED_MAP, GetId()); }
void MonsterYellToMap(ObjectGuid guid, int32 textId, Language language, Unit const* target) const;
void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, Language language, Unit const* target, uint32 senderLowGuid = 0) const;
void PlayDirectSoundToMap(uint32 soundId, uint32 zoneId = 0) const;
void MonsterYellToMap(ObjectGuid guid, int32 textId, Language language, Unit const* target) const;
void MonsterYellToMap(CreatureInfo const* cinfo, int32 textId, Language language, Unit const* target, uint32 senderLowGuid = 0) const;
void PlayDirectSoundToMap(uint32 soundId, uint32 zoneId = 0) const;
// Dynamic VMaps
float GetHeight(uint32 phasemask, float x, float y, float z) const;
bool GetHeightInRange(uint32 phasemask, float x, float y, float& z, float maxSearchDist = 4.0f) const;
bool IsInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
bool GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float& destY, float& destZ, uint32 phasemask, float modifyDist) const;
// Dynamic VMaps
float GetHeight(uint32 phasemask, float x, float y, float z) const;
bool GetHeightInRange(uint32 phasemask, float x, float y, float& z, float maxSearchDist = 4.0f) const;
bool IsInLineOfSight(float x1, float y1, float z1, float x2, float y2, float z2, uint32 phasemask) const;
bool GetHitPosition(float srcX, float srcY, float srcZ, float& destX, float& destY, float& destZ, uint32 phasemask, float modifyDist) const;
// Object Model insertion/remove/test for dynamic vmaps use
void InsertGameObjectModel(const GameObjectModel& mdl);
void RemoveGameObjectModel(const GameObjectModel& mdl);
bool ContainsGameObjectModel(const GameObjectModel& mdl) const;
// Object Model insertion/remove/test for dynamic vmaps use
void InsertGameObjectModel(const GameObjectModel& mdl);
void RemoveGameObjectModel(const GameObjectModel& mdl);
bool ContainsGameObjectModel(const GameObjectModel& mdl) const;
// Get Holder for Creature Linking
CreatureLinkingHolder* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder; }
// Get Holder for Creature Linking
CreatureLinkingHolder* GetCreatureLinkingHolder() { return &m_creatureLinkingHolder; }
// Teleport all players in that map to choosed location
void TeleportAllPlayersTo(TeleportLocation loc);
// Teleport all players in that map to choosed location
void TeleportAllPlayersTo(TeleportLocation loc);
// WeatherSystem
WeatherSystem* GetWeatherSystem() const { return m_weatherSystem; }
/** Set the weather in a zone on this map
* @param zoneId set the weather for which zone
* @param type What weather to set
* @param grade how strong the weather should be
* @param permanently set the weather permanently?
*/
void SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently);
// WeatherSystem
WeatherSystem* GetWeatherSystem() const { return m_weatherSystem; }
/** Set the weather in a zone on this map
* @param zoneId set the weather for which zone
* @param type What weather to set
* @param grade how strong the weather should be
* @param permanently set the weather permanently?
*/
void SetWeather(uint32 zoneId, WeatherType type, float grade, bool permanently);
// Random on map generation
bool GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius);
bool GetReachableRandomPointOnGround(uint32 phaseMask, float& x, float& y, float& z, float radius);
bool GetRandomPointInTheAir(uint32 phaseMask, float& x, float& y, float& z, float radius);
bool GetRandomPointUnderWater(uint32 phaseMask, float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
// Random on map generation
bool GetReachableRandomPosition(Unit* unit, float& x, float& y, float& z, float radius);
bool GetReachableRandomPointOnGround(float& x, float& y, float& z, float radius);
bool GetRandomPointInTheAir(float& x, float& y, float& z, float radius);
bool GetRandomPointUnderWater(float& x, float& y, float& z, float radius, GridMapLiquidData& liquid_status);
private:
void LoadMapAndVMap(int gx, int gy);
@ -414,69 +414,69 @@ public:
class WorldMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {}
~WorldMap() {}
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
WorldMap(uint32 id, time_t expiry) : Map(id, expiry, 0, REGULAR_DIFFICULTY) {}
~WorldMap() {}
// can't be NULL for loaded map
WorldPersistentState* GetPersistanceState() const;
// can't be NULL for loaded map
WorldPersistentState* GetPersistanceState() const;
};
class DungeonMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
~DungeonMap();
bool Add(Player*) override;
void Remove(Player*, bool) override;
void Update(const uint32&) override;
bool Reset(InstanceResetMethod method);
void PermBindAllPlayers(Player* player);
void UnloadAll(bool pForce) override;
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
DungeonMap(uint32 id, time_t, uint32 InstanceId, uint8 SpawnMode);
~DungeonMap();
bool Add(Player*) override;
void Remove(Player*, bool) override;
void Update(const uint32&) override;
bool Reset(InstanceResetMethod method);
void PermBindAllPlayers(Player* player);
void UnloadAll(bool pForce) override;
void SendResetWarnings(uint32 timeLeft) const;
void SetResetSchedule(bool on);
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_INSTANCE, GetId()); }
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_INSTANCE, GetId()); }
// can't be NULL for loaded map
DungeonPersistentState* GetPersistanceState() const;
// can't be NULL for loaded map
DungeonPersistentState* GetPersistanceState() const;
virtual void InitVisibilityDistance() override;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
virtual void InitVisibilityDistance() override;
private:
bool m_resetAfterUnload;
bool m_unloadWhenEmpty;
};
class BattleGroundMap : public Map
{
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattleGroundMap();
private:
using Map::GetPersistentState; // hide in subclass for overwrite
public:
BattleGroundMap(uint32 id, time_t, uint32 InstanceId, uint8 spawnMode);
~BattleGroundMap();
void Update(const uint32&) override;
bool Add(Player*) override;
void Remove(Player*, bool) override;
bool CanEnter(Player* player) override;
void SetUnload();
void UnloadAll(bool pForce) override;
void Update(const uint32&) override;
bool Add(Player*) override;
void Remove(Player*, bool) override;
bool CanEnter(Player* player) override;
void SetUnload();
void UnloadAll(bool pForce) override;
virtual void InitVisibilityDistance() override;
BattleGround* GetBG() { return m_bg; }
void SetBG(BattleGround* bg) { m_bg = bg; }
virtual void InitVisibilityDistance() override;
BattleGround* GetBG() { return m_bg; }
void SetBG(BattleGround* bg) { m_bg = bg; }
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_BATTLEGROUND, GetId()); } //TODO bind BG scripts through script_binding, now these are broken!
uint32 GetScriptId() const override { return sScriptMgr.GetBoundScriptId(SCRIPTED_BATTLEGROUND, GetId()); } //TODO bind BG scripts through script_binding, now these are broken!
// can't be NULL for loaded map
BattleGroundPersistentState* GetPersistanceState() const;
// can't be NULL for loaded map
BattleGroundPersistentState* GetPersistanceState() const;
private:
BattleGround* m_bg;
private:
BattleGround* m_bg;
};
template<class T, class CONTAINER>

View file

@ -180,11 +180,11 @@ void WorldSession::HandleCreatureQueryOpcode(WorldPacket& recv_data)
data << subName;
data << ci->IconName; // "Directions" for guard, string for Icons 2.3.0
data << uint32(ci->type_flags); // flags
data << uint32(ci->CreatureTypeFlags); // flags
data << uint32(0); // unk
data << uint32(ci->type); // CreatureType.dbc
data << uint32(ci->family); // CreatureFamily.dbc
data << uint32(ci->rank); // Creature Rank (elite, boss, etc)
data << uint32(ci->Rank); // Creature Rank (elite, boss, etc)
data << uint32(ci->KillCredit[0]); // new in 3.1, kill credit
data << uint32(ci->KillCredit[1]); // new in 3.1, kill credit

File diff suppressed because it is too large Load diff

View file

@ -22,14 +22,14 @@
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef _SCRIPTMGR_H
#define _SCRIPTMGR_H
#ifndef MANGOS_H_SCRIPTMGR
#define MANGOS_H_SCRIPTMGR
#include "Common.h"
#include "Policies/Singleton.h"
#include "ObjectGuid.h"
#include "DBCEnums.h"
#include "ace/Atomic_Op.h"
#include <ace/Atomic_Op.h>
struct AreaTriggerEntry;
struct SpellEntry;
@ -49,28 +49,35 @@ class WorldObject;
enum ScriptedObjectType
{
SCRIPTED_UNIT = 0, //CreatureScript
SCRIPTED_GAMEOBJECT = 1, //GameObjectScript
SCRIPTED_ITEM = 2, //ItemScript
SCRIPTED_AREATRIGGER = 3, //AreaTriggerScript
SCRIPTED_SPELL = 4, //SpellScript
SCRIPTED_AURASPELL = 5, //AuraScript
SCRIPTED_MAPEVENT = 6, //MapEventScript
SCRIPTED_MAP = 7, //ZoneScript
SCRIPTED_BATTLEGROUND = 8, //BattleGroundScript
SCRIPTED_PVP_ZONE = 9, //OutdoorPvPScript
SCRIPTED_INSTANCE = 10, //InstanceScript
SCRIPTED_CONDITION = 11, //ConditionScript
SCRIPTED_ACHIEVEMENT = 12, //AchievementScript
SCRIPTED_UNIT = 0, //CreatureScript
SCRIPTED_GAMEOBJECT = 1, //GameObjectScript
SCRIPTED_ITEM = 2, //ItemScript
SCRIPTED_AREATRIGGER = 3, //AreaTriggerScript
SCRIPTED_SPELL = 4, //SpellScript
SCRIPTED_AURASPELL = 5, //AuraScript
SCRIPTED_MAPEVENT = 6, //MapEventScript
SCRIPTED_MAP = 7, //ZoneScript
SCRIPTED_BATTLEGROUND = 8, //BattleGroundScript
SCRIPTED_PVP_ZONE = 9, //OutdoorPvPScript
SCRIPTED_INSTANCE = 10, //InstanceScript
SCRIPTED_CONDITION = 11, //ConditionScript
SCRIPTED_ACHIEVEMENT = 12, //AchievementScript
SCRIPTED_MAX_TYPE
};
enum ScriptCommand // resSource, resTarget are the resulting Source/ Target after buddy search is done
enum ScriptImplementation
{
SCRIPT_FROM_DATABASE = 0,
SCRIPT_FROM_CORE = 1,
SCRIPT_FROM_ELUNA = 2,
};
enum DBScriptCommand // resSource, resTarget are the resulting Source/ Target after buddy search is done
{
SCRIPT_COMMAND_TALK = 0, // resSource = WorldObject, resTarget = Unit/none
// dataint = text entry from db_script_string -table. dataint2-4 optional for random selected texts.
SCRIPT_COMMAND_EMOTE = 1, // resSource = Unit, resTarget = Unit/none
// datalong1 = emote_id
// datalong1 = emote_id, dataint1-4 optional for random selected emotes
SCRIPT_COMMAND_FIELD_SET = 2, // source = any, datalong = field_id, datalong2 = value
SCRIPT_COMMAND_MOVE_TO = 3, // resSource = Creature, datalong2 = travel_speed*100, x/y/z
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL: teleport unit to position
@ -88,6 +95,7 @@ enum ScriptCommand // resSource, resTar
SCRIPT_COMMAND_REMOVE_AURA = 14, // resSource = Unit, datalong = spell_id
SCRIPT_COMMAND_CAST_SPELL = 15, // resSource = Unit, cast spell at resTarget = Unit
// datalong=spellid
// dataint1-4 optional for random selected spell
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL = cast triggered
SCRIPT_COMMAND_PLAY_SOUND = 16, // resSource = WorldObject, target=any/player, datalong (sound_id), datalong2 (bitmask: 0/1=target-player, 0/2=with distance dependent, 0/4=map wide, 0/8=zone wide; so 1|2 = 3 is target with distance dependent)
SCRIPT_COMMAND_CREATE_ITEM = 17, // source or target must be player, datalong = item entry, datalong2 = amount
@ -124,9 +132,25 @@ enum ScriptCommand // resSource, resTar
SCRIPT_COMMAND_XP_USER = 33, // source or target with Player, datalong = bool (0=off, 1=on)
SCRIPT_COMMAND_TERMINATE_COND = 34, // datalong = condition_id, datalong2 = if != 0 then quest_id of quest that will be failed for player's group if the script is terminated
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL terminate when condition is false ELSE terminate when condition is true
SCRIPT_COMMAND_SEND_AI_EVENT_AROUND = 35, // resSource = Creature, resTarget = Unit
// datalong = AIEventType
// datalong2 = radius
SCRIPT_COMMAND_TURN_TO = 36, // resSource = Unit, resTarget = Unit/none
SCRIPT_COMMAND_MOVE_DYNAMIC = 37, // resSource = Creature, resTarget Worldobject.
// datalong = 0: Move resSource towards resTarget
// datalong != 0: Move resSource to a random point between datalong2..datalong around resTarget.
// orientation != 0: Obtain a random point around resTarget in direction of orientation
// data_flags & SCRIPT_FLAG_COMMAND_ADDITIONAL Obtain a random point around resTarget in direction of resTarget->GetOrientation + orientation
// for resTarget == resSource and orientation == 0 this will mean resSource moving forward
SCRIPT_COMMAND_SEND_MAIL = 38, // resSource WorldObject, can be NULL, resTarget Player
// datalong: Send mailTemplateId from resSource (if provided) to player resTarget
// datalong2: AlternativeSenderEntry. Use as sender-Entry
// dataint1: Delay (>= 0) in Seconds
SCRIPT_COMMAND_CHANGE_ENTRY = 39, // resSource = Creature, datalong=creature entry
// dataint1 = entry
};
#define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK
#define MAX_TEXT_ID 4 // used for SCRIPT_COMMAND_TALK, SCRIPT_COMMAND_EMOTE, SCRIPT_COMMAND_CAST_SPELL, SCRIPT_COMMAND_TERMINATE_SCRIPT
enum ScriptInfoDataFlags
{
@ -347,6 +371,36 @@ struct ScriptInfo
uint32 failQuest; // datalong2
} terminateCond;
struct // SCRIPT_COMMAND_SEND_AI_EVENT_AROUND (35)
{
uint32 eventType; // datalong
uint32 radius; // datalong2
} sendAIEvent;
struct // SCRIPT_COMMAND_TURN_TO (36)
{
uint32 targetId; // datalong
uint32 empty1; // datalong2
} turnTo;
struct // SCRIPT_COMMAND_MOVE_DYNAMIC (37)
{
uint32 maxDist; // datalong
uint32 minDist; // datalong2
} moveDynamic;
struct // SCRIPT_COMMAND_SEND_MAIL (38)
{
uint32 mailTemplateId; // datalong
uint32 altSender; // datalong2;
} sendMail;
struct // SCRIPT_COMMAND_MORPH_TO_ENTRY_OR_MODEL (23)
{
uint32 creatureEntry; // datalong
uint32 empty1; // datalong2
} changeEntry;
struct
{
uint32 data[2];
@ -402,11 +456,14 @@ struct ScriptInfo
case SCRIPT_COMMAND_MOVE_TO:
case SCRIPT_COMMAND_TEMP_SUMMON_CREATURE:
case SCRIPT_COMMAND_CAST_SPELL:
case SCRIPT_COMMAND_PLAY_SOUND:
case SCRIPT_COMMAND_MOVEMENT:
case SCRIPT_COMMAND_MORPH_TO_ENTRY_OR_MODEL:
case SCRIPT_COMMAND_MOUNT_TO_ENTRY_OR_MODEL:
case SCRIPT_COMMAND_TERMINATE_SCRIPT:
case SCRIPT_COMMAND_TERMINATE_COND:
case SCRIPT_COMMAND_TURN_TO:
case SCRIPT_COMMAND_MOVE_DYNAMIC:
return true;
default:
return false;
@ -423,11 +480,26 @@ class ScriptAction
bool HandleScriptStep(); // return true IF AND ONLY IF the script should be terminated
const char* GetTableName() const { return m_table; }
uint32 GetId() const { return m_script->id; }
ObjectGuid GetSourceGuid() const { return m_sourceGuid; }
ObjectGuid GetTargetGuid() const { return m_targetGuid; }
ObjectGuid GetOwnerGuid() const { return m_ownerGuid; }
const char* GetTableName() const
{
return m_table;
}
uint32 GetId() const
{
return m_script->id;
}
ObjectGuid GetSourceGuid() const
{
return m_sourceGuid;
}
ObjectGuid GetTargetGuid() const
{
return m_targetGuid;
}
ObjectGuid GetOwnerGuid() const
{
return m_ownerGuid;
}
bool IsSameScript(const char* table, uint32 id, ObjectGuid sourceGuid, ObjectGuid targetGuid, ObjectGuid ownerGuid) const
{
@ -451,6 +523,7 @@ class ScriptAction
bool LogIfNotCreature(WorldObject* pWorldObject);
bool LogIfNotUnit(WorldObject* pWorldObject);
bool LogIfNotGameObject(WorldObject* pWorldObject);
bool LogIfNotPlayer(WorldObject* pWorldObject);
Player* GetPlayerTargetOrSourceAndLog(WorldObject* pSource, WorldObject* pTarget);
};
@ -482,6 +555,8 @@ class ScriptMgr
ScriptMgr();
~ScriptMgr();
std::string GenerateNameToId(ScriptedObjectType sot, uint32 id);
void LoadGameObjectScripts();
void LoadGameObjectTemplateScripts();
void LoadQuestEndScripts();
@ -496,11 +571,11 @@ class ScriptMgr
void LoadScriptNames();
void LoadScriptBinding();
void LoadAreaTriggerScripts();
void LoadEventIdScripts();
void LoadSpellIdScripts();
uint32 GetAreaTriggerScriptId(uint32 triggerId) const;
uint32 GetEventIdScriptId(uint32 eventId) const;
uint32 GetBoundScriptId(ScriptedObjectType entity, int32 entry);
bool ReloadScriptBinding();
const char* GetScriptName(uint32 id) const
{
@ -511,16 +586,17 @@ class ScriptMgr
{
return m_scriptNames.size();
}
uint32 GetBoundScriptId(ScriptedObjectType entity, int32 entry);
ScriptLoadResult LoadScriptLibrary(const char* libName);
void UnloadScriptLibrary();
bool IsScriptLibraryLoaded() const
{
#ifdef ENABLE_SD3
#ifdef ENABLE_SD3
return true;
#else
#else
return false;
#endif
#endif
}
uint32 IncreaseScheduledScriptsCount()
@ -561,10 +637,10 @@ class ScriptMgr
bool OnAreaTrigger(Player* pPlayer, AreaTriggerEntry const* atEntry);
bool OnNpcSpellClick(Player* pPlayer, Creature* pClickedCreature, uint32 spellId);
bool OnProcessEvent(uint32 eventId, Object* pSource, Object* pTarget, bool isStart);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Unit* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, GameObject* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectDummy(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Item* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectScriptEffect(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Creature* pTarget, ObjectGuid originalCasterGuid);
bool OnEffectScriptEffect(Unit* pCaster, uint32 spellId, SpellEffectIndex effIndex, Unit* pTarget, ObjectGuid originalCasterGuid);
bool OnAuraDummy(Aura const* pAura, bool apply);
private:
@ -579,6 +655,10 @@ class ScriptMgr
ScriptNameMap m_scriptNames;
#ifdef _DEBUG
// mutex allowing to reload the script binding table; TODO just do it AWAY from any map update, e.g. right after sessions update
ACE_RW_Thread_Mutex m_bindMutex;
#endif /* _DEBUG */
// atomic op counter for active scripts amount
ACE_Atomic_Op<ACE_Thread_Mutex, long> m_scheduledScripts;
};
@ -588,10 +668,8 @@ bool StartEvents_Event(Map* map, uint32 id, Object* source, Object* target, bool
#define sScriptMgr MaNGOS::Singleton<ScriptMgr>::Instance()
uint32 GetAreaTriggerScriptId(uint32 triggerId);
uint32 GetEventIdScriptId(uint32 eventId);
uint32 GetScriptId(const char* name);
char const* GetScriptName(uint32 id);
uint32 GetScriptIdsCount();
uint32 GetScriptId(const char* name);
char const* GetScriptName(uint32 id);
uint32 GetScriptIdsCount();
#endif

View file

@ -7654,7 +7654,7 @@ SpellCastResult Spell::CanOpenLock(SpellEffectIndex effIndex, uint32 lockId, Ski
reqSkillValue = lockInfo->Skill[j];
// castitem check: rogue using skeleton keys. the skill values should not be added in this case.
// MAX_SKILL_TYPE - skill value scales with caster level
// MAX_SKILL_TYPE - skill value Scales with caster level
if (skillId == MAX_SKILL_TYPE)
skillValue = m_CastItem || m_caster->GetTypeId() != TYPEID_PLAYER ? 0 : m_caster->getLevel() * 5;
else
@ -8223,10 +8223,10 @@ void Spell::GetSpellRangeAndRadius(SpellEffectEntry const* spellEffect, float& r
radius = 0.5f * (60000 - auraHolder->GetAuraDuration()) * 0.001f;
break;
}
case 66881: // Slime Pool (ToCrusader, Acidmaw & Dreadscale)
case 67638: // Slime Pool (ToCrusader, Acidmaw & Dreadscale) (Mode 1)
case 67639: // Slime Pool (ToCrusader, Acidmaw & Dreadscale) (Mode 2)
case 67640: // Slime Pool (ToCrusader, Acidmaw & Dreadscale) (Mode 3)
case 66881: // Slime Pool (ToCrusader, Acidmaw & DreadScale)
case 67638: // Slime Pool (ToCrusader, Acidmaw & DreadScale) (Mode 1)
case 67639: // Slime Pool (ToCrusader, Acidmaw & DreadScale) (Mode 2)
case 67640: // Slime Pool (ToCrusader, Acidmaw & DreadScale) (Mode 3)
if (SpellAuraHolder* auraHolder = m_caster->GetSpellAuraHolder(66882))
radius = 0.5f * (60000 - auraHolder->GetAuraDuration()) * 0.001f;
break;

File diff suppressed because it is too large Load diff

View file

@ -5030,7 +5030,7 @@ void Spell::EffectOpenLock(SpellEffectEntry const* effect)
return;
}
}
else if (goInfo->type == GAMEOBJECT_TYPE_FLAGSTAND)
else if (goInfo->type == GAMEOBJECT_CreatureTypeFlagsTAND)
{
// CanUseBattleGroundObject() already called in CheckCast()
// in battleground check

View file

@ -3031,7 +3031,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d
{
trigger_spell_id = 64442;
// need scale damage base at stack size
// need Scale damage base at stack size
if (SpellEntry const* trigEntry = sSpellStore.LookupEntry(trigger_spell_id))
basepoints[EFFECT_INDEX_0] = trigEntry->CalculateSimpleValue(EFFECT_INDEX_0) * triggeredByAura->GetStackAmount();
@ -3046,7 +3046,7 @@ SpellAuraProcResult Unit::HandleProcTriggerSpellAuraProc(Unit* pVictim, uint32 d
trigger_spell_id = 64569;
// need scale damage base at stack size
// need Scale damage base at stack size
if (SpellEntry const* trigEntry = sSpellStore.LookupEntry(trigger_spell_id))
basepoints[EFFECT_INDEX_0] = trigEntry->CalculateSimpleValue(EFFECT_INDEX_0) * triggeredByAura->GetStackAmount();

View file

@ -86,8 +86,8 @@ if(SCRIPT_LIB_ELUNA)
include_directories(${CMAKE_SOURCE_DIR}/dep/lualib)
endif()
if(SCRIPT_LIB_SD2)
include_directories(${CMAKE_SOURCE_DIR}/src/modules/SD2)
if(SCRIPT_LIB_SD3)
include_directories(${CMAKE_SOURCE_DIR}/src/modules/SD3)
endif()
if(SOAP)

View file

@ -18,8 +18,8 @@
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Build the mangos script library if enabled
if(SCRIPT_LIB_SD2)
add_subdirectory(SD2)
if(SCRIPT_LIB_SD3)
add_subdirectory(SD3)
endif()
# Build the Eluna library if enabled

View file

@ -0,0 +1,576 @@
# MaNGOS is a full featured server for World of Warcraft, supporting
# the following clients: 1.12.x, 2.4.3, 3.3.5a, 4.3.4a and 5.4.8
#
# Copyright (C) 2005-2016 MaNGOS project <http://getmangos.eu>
# Copyright (C) 2006-2013 ScriptDev2 project <http://www.scriptdev2.com>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
include(MacroMangosSourceGroup)
#Add PCH Files
set(mangosscript_PCH "${CMAKE_CURRENT_SOURCE_DIR}/precompiled.h")
if(PCH)
LIST(APPEND mangosscript_PCH "${CMAKE_CURRENT_SOURCE_DIR}/precompiled.cpp")
endif()
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/base
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src/shared
${CMAKE_SOURCE_DIR}/src/framework
${CMAKE_SOURCE_DIR}/src/game/Server
${CMAKE_SOURCE_DIR}/src/game/BattleGround
${CMAKE_SOURCE_DIR}/src/game/WorldHandlers
${CMAKE_SOURCE_DIR}/src/game/Object
${CMAKE_SOURCE_DIR}/src/game/References
${CMAKE_SOURCE_DIR}/src/game/MotionGenerators
${CMAKE_SOURCE_DIR}/src/game/vmap
${CMAKE_SOURCE_DIR}/src/shared
${CMAKE_SOURCE_DIR}/src/shared/Utilities
${CMAKE_SOURCE_DIR}/src/shared/Log
${CMAKE_SOURCE_DIR}/src/shared/DataStores
${CMAKE_SOURCE_DIR}/src/shared/Common
${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/src/shared
${ACE_INCLUDE_DIR}
${MYSQL_INCLUDE_DIR}
)
# Define the scriptdev3 library
set(mangosscript_LIB_SRCS ${mangosscript_PCH})
#Include Files
file(GLOB sources_include include/*.cpp include/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_include})
source_group("Include Files" FILES ${sources_include})
#System Files
file(GLOB sources_system system/*.cpp system/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_system})
source_group("System Files" FILES ${sources_system})
#Base Files
file(GLOB sources_base base/*.cpp base/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_base})
source_group("Base Files" FILES ${sources_base})
#Battleground Scripts
file(GLOB sources_battlegrounds scripts/battlegrounds/*.cpp scripts/battlegrounds/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_battlegrounds})
source_group("Battleground Scripts" FILES ${sources_battlegrounds})
#World Scripts
file(GLOB sources_world scripts/world/*.cpp scripts/world/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_world})
source_group("World Scripts" FILES ${sources_world})
#Eastern Kingdom Scripts
file(GLOB sources_eastern_kingdoms scripts/eastern_kingdoms/*.cpp scripts/eastern_kingdoms/*.h)
# --- Remove Azuremyst and BloodMyst Isle from classic
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
string(REGEX REPLACE "(eversong_woods.cpp|eversong_woods.h)" "" sources_eastern_kingdoms "${sources_eastern_kingdoms}")
string(REGEX REPLACE "(ghostlands.cpp|ghostlands.h)" "" sources_eastern_kingdoms "${sources_eastern_kingdoms}")
string(REGEX REPLACE "(isle_of_queldanas.cpp|isle_of_queldanas.h)" "" sources_eastern_kingdoms "${sources_eastern_kingdoms}")
endif()
LIST(APPEND mangosscript_LIB_SRCS ${sources_eastern_kingdoms})
source_group("Eastern Kingdoms Scripts" FILES ${sources_eastern_kingdoms})
#Kalimdor Scripts
set (GLOBIGNORE azuremyst_isle.cpp azuremyst_isle.h)
file(GLOB sources_kalimdor scripts/kalimdor/*.cpp scripts/kalimdor/*.h)
# --- Remove Azuremyst and BloodMyst Isle from classic
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
string(REGEX REPLACE "(azuremyst_isle.cpp|azuremyst_isle.h)" "" sources_kalimdor "${sources_kalimdor}")
string(REGEX REPLACE "(bloodmyst_isle.cpp|bloodmyst_isle.h)" "" sources_kalimdor "${sources_kalimdor}")
endif()
LIST(APPEND mangosscript_LIB_SRCS ${sources_kalimdor})
source_group("Kalimdor Scripts" FILES ${sources_kalimdor})
# --- NOT FOR ZERO ---
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Outlands Scripts
file(GLOB sources_outlands scripts/outland/*.cpp scripts/outland/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_outlands})
source_group("Outlands Scripts" FILES ${sources_outlands})
endif()
# --- END IF ---
# --- TWO / Three ---
if (("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Northrend Scripts
file(GLOB sources_northrend scripts/northrend/*.cpp scripts/northrend/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_northrend})
source_group("Northrend Scripts" FILES ${sources_northrend})
endif()
# --- END IF ---
#Instance: Blackrock Depths Scripts
file(GLOB sources_instance_ek_brd scripts/eastern_kingdoms/blackrock_mountain/blackrock_depths/*.cpp scripts/eastern_kingdoms/blackrock_mountain/blackrock_depths/*.h)
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
string(REGEX REPLACE "(boss_coren_direbrew.cpp|boss_coren_direbrew.h)" "" sources_instance_ek_brd "${sources_instance_ek_brd}")
endif()
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_brd})
source_group("Eastern Kingdoms Scripts\\Instances\\Blackrock Depths" FILES ${sources_instance_ek_brd})
#Instance: Blackrock Spire Scripts
file(GLOB sources_instance_ek_brs scripts/eastern_kingdoms/blackrock_mountain/blackrock_spire/*.cpp scripts/eastern_kingdoms/blackrock_mountain/blackrock_spire/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_brs})
source_group("Eastern Kingdoms Scripts\\Instances\\Blackrock Spire" FILES ${sources_instance_ek_brs})
#Instance: Deadmines Scripts
file(GLOB sources_instance_ek_tdm scripts/eastern_kingdoms/deadmines/*.cpp scripts/eastern_kingdoms/deadmines/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_tdm})
source_group("Eastern Kingdoms Scripts\\Instances\\Deadmines" FILES ${sources_instance_ek_tdm})
#Instance: Gnomeregan Scripts
file(GLOB sources_instance_ek_gno scripts/eastern_kingdoms/gnomeregan/*.cpp scripts/eastern_kingdoms/gnomeregan/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_gno})
source_group("Eastern Kingdoms Scripts\\Instances\\Gnomeregan" FILES ${sources_instance_ek_gno})
#Instance: Scarlet Monastery Scripts
file(GLOB sources_instance_ek_sm scripts/eastern_kingdoms/scarlet_monastery/*.cpp scripts/eastern_kingdoms/scarlet_monastery/*.h)
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
string(REGEX REPLACE "(boss_headless_horseman.cpp|boss_headless_horseman.h)" "" sources_instance_ek_sm "${sources_instance_ek_sm}")
endif()
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_sm})
source_group("Eastern Kingdoms Scripts\\Instances\\Scarlet Monastery" FILES ${sources_instance_ek_sm})
#Instance: Scholomance Scripts
file(GLOB sources_instance_ek_scholo scripts/eastern_kingdoms/scholomance/*.cpp scripts/eastern_kingdoms/scholomance/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_scholo})
source_group("Eastern Kingdoms Scripts\\Instances\\Scholomance" FILES ${sources_instance_ek_scholo})
#Instance: Uldaman Scripts
file(GLOB sources_instance_ek_uld scripts/eastern_kingdoms/uldaman/*.cpp scripts/eastern_kingdoms/uldaman/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_uld})
source_group("Eastern Kingdoms Scripts\\Instances\\Uldaman" FILES ${sources_instance_ek_uld})
#Instance: Shadowfang Keep Scripts
file(GLOB sources_instance_ek_sfk scripts/eastern_kingdoms/shadowfang_keep/*.cpp scripts/eastern_kingdoms/shadowfang_keep/*.h)
# --- Remove Hummel from classic
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
string(REGEX REPLACE "(boss_hummel.cpp|boss_hummel.h)" "" sources_instance_ek_sfk "${sources_instance_ek_sfk}")
endif()
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_sfk})
source_group("Eastern Kingdoms Scripts\\Instances\\Shadowfang Keep" FILES ${sources_instance_ek_sfk})
#Instance: Sunken Temple Scripts
file(GLOB sources_instance_ek_st scripts/eastern_kingdoms/sunken_temple/*.cpp scripts/eastern_kingdoms/sunken_temple/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_st})
source_group("Eastern Kingdoms Scripts\\Instances\\Sunken Temple" FILES ${sources_instance_ek_st})
#Instance: Stratholme Scripts
# --- ONLY FOR ZERO ---
IF("${MANGOS_EXP}" STREQUAL "CLASSIC")
file(GLOB sources_instance_ek_files scripts/eastern_kingdoms/stratholme/*.cpp scripts/eastern_kingdoms/stratholme/*.h)
string(REGEX REPLACE "(boss_order_of_silver_hand.cpp|boss_order_of_silver_hand.h)" "" sources_instance_ek_files "${sources_instance_ek_files}")
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_files})
source_group("Eastern Kingdoms Scripts\\Instances\\Stratholme" FILES ${sources_instance_ek_files})
endif()
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
file(GLOB sources_instance_ek_strat scripts/eastern_kingdoms/stratholme/*.cpp scripts/eastern_kingdoms/stratholme/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_strat})
source_group("Eastern Kingdoms Scripts\\Instances\\Stratholme" FILES ${sources_instance_ek_strat})
endif()
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Instance: Magisters Terrace Scripts
file(GLOB sources_instance_ek_mt scripts/eastern_kingdoms/magisters_terrace/*.cpp scripts/eastern_kingdoms/magisters_terrace/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ek_mt})
source_group("Eastern Kingdoms Scripts\\Instances\\Magisters Terrace" FILES ${sources_instance_ek_mt})
#Raid: Karazhan Scripts
file(GLOB sources_raid_ek_kara scripts/eastern_kingdoms/karazhan/*.cpp scripts/eastern_kingdoms/karazhan/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_kara})
source_group("Eastern Kingdoms Scripts\\Raids\\Karazhan" FILES ${sources_raid_ek_kara})
#Raid: Sunwell Plateau Scripts
file(GLOB sources_raid_ek_sp scripts/eastern_kingdoms/sunwell_plateau/*.cpp scripts/eastern_kingdoms/sunwell_plateau/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_sp})
source_group("Eastern Kingdoms Scripts\\Raids\\Sunwell Plateau" FILES ${sources_raid_ek_sp})
#Raid: Zul'Aman Scripts
file(GLOB sources_raid_ek_za scripts/eastern_kingdoms/zulaman/*.cpp scripts/eastern_kingdoms/zulaman/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_za})
source_group("Eastern Kingdoms Scripts\\Raids\\Zul'Aman" FILES ${sources_raid_ek_za})
endif()
# --- END IF ---
#Raid: Molten Core Scripts
file(GLOB sources_raid_ek_mc scripts/eastern_kingdoms/blackrock_mountain/molten_core/*.cpp scripts/eastern_kingdoms/blackrock_mountain/molten_core/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_mc})
source_group("Eastern Kingdoms Scripts\\Raids\\Molten Core" FILES ${sources_raid_ek_mc})
#Raid: Blackwing Lair Scripts
file(GLOB sources_raid_ek_bwl scripts/eastern_kingdoms/blackrock_mountain/blackwing_lair/*.cpp scripts/eastern_kingdoms/blackrock_mountain/blackwing_lair/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_bwl})
source_group("Eastern Kingdoms Scripts\\Raids\\Blackwing Lair" FILES ${sources_raid_ek_bwl})
# --- NOT TWO ---
IF(("${MANGOS_EXP}" STREQUAL "CLASSIC") OR ("${MANGOS_EXP}" STREQUAL "TBC"))
#Raid: Naxxramas Scripts
file(GLOB sources_raid_ek_naxx scripts/eastern_kingdoms/naxxramas/*.cpp scripts/eastern_kingdoms/naxxramas/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_naxx})
source_group("Eastern Kingdoms Scripts\\Raids\\Naxxramas" FILES ${sources_raid_ek_naxx})
endif()
# --- END IF ---
#Raid: Zul Gurub Scripts
file(GLOB sources_raid_ek_zg scripts/eastern_kingdoms/zulgurub/*.cpp scripts/eastern_kingdoms/zulgurub/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ek_zg})
source_group("Eastern Kingdoms Scripts\\Raids\\Zul Gurub" FILES ${sources_raid_ek_zg})
#Instance: Blackfathom Deeps Scripts
file(GLOB sources_instance_k_bdf scripts/kalimdor/blackfathom_deeps/*.cpp scripts/kalimdor/blackfathom_deeps/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_bdf})
source_group("Kalimdor Scripts\\Instances\\Blackfathom Deeps" FILES ${sources_instance_k_bdf})
#Instance: Dire Maul Scripts
file(GLOB sources_instance_k_dm scripts/kalimdor/dire_maul/*.cpp scripts/kalimdor/dire_maul/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_dm})
source_group("Kalimdor Scripts\\Instances\\Dire Maul" FILES ${sources_instance_k_dm})
#Instance: Maraudon Scripts
file(GLOB sources_instance_k_mara scripts/kalimdor/maraudon/*.cpp scripts/kalimdor/maraudon/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_mara})
source_group("Kalimdor Scripts\\Instances\\Maraudon Scripts" FILES ${sources_instance_k_mara})
#Instance: Razorfen Downs Scripts
file(GLOB sources_instance_k_rfd scripts/kalimdor/razorfen_downs/*.cpp scripts/kalimdor/razorfen_downs/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_rfd})
source_group("Kalimdor Scripts\\Instances\\Razorfen Downs" FILES ${sources_instance_k_rfd})
#Instance: Razorfen Kraul Scripts
file(GLOB sources_instance_k_rfk scripts/kalimdor/razorfen_kraul/*.cpp scripts/kalimdor/razorfen_kraul/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_rfk})
source_group("Kalimdor Scripts\\Instances\\Razorfen Kraul" FILES ${sources_instance_k_rfk})
#Instance: Wailing Caverns Scripts
file(GLOB sources_instance_k_wc scripts/kalimdor/wailing_caverns/*.cpp scripts/kalimdor/wailing_caverns/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_wc})
source_group("Kalimdor Scripts\\Instances\\Wailing Caverns" FILES ${sources_instance_k_wc})
# --- NOT FOR ZERO ---
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Instance: Caverns of Time - Black Morass
file(GLOB sources_instance_k_cot_bm scripts/kalimdor/caverns_of_time/dark_portal/*.cpp scripts/kalimdor/caverns_of_time/dark_portal/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_cot_bm})
source_group("Kalimdor Scripts\\Instances\\Caverns of Time\\Black Morass" FILES ${sources_instance_k_cot_bm})
#Instance: Caverns of Time - Old Hillsbrad
file(GLOB sources_instance_k_cot_oh scripts/kalimdor/caverns_of_time/old_hillsbrad/*.cpp scripts/kalimdor/caverns_of_time/old_hillsbrad/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_cot_oh})
source_group("Kalimdor Scripts\\Instances\\Caverns of Time\\Old Hillsbrad" FILES ${sources_instance_k_cot_oh})
endif()
# --- END IF ---
# --- TWO /THREE ONLY ---
if (("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Instance: Caverns of Time - Culling of Stratholme
file(GLOB sources_instance_k_cot_cos scripts/kalimdor/caverns_of_time/culling_of_stratholme/*.cpp scripts/kalimdor/caverns_of_time/culling_of_stratholme/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_cot_cos})
source_group("Kalimdor Scripts\\Instances\\Caverns of Time\\Culling of Stratholme" FILES ${sources_instance_k_cot_cos})
endif()
# --- END IF ---
#Instance: Zul Farrak Scripts
file(GLOB sources_instance_k_zf scripts/kalimdor/zulfarrak/*.cpp scripts/kalimdor/zulfarrak/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_zf})
source_group("Kalimdor Scripts\\Instances\\Zul Farrak" FILES ${sources_instance_k_zf})
# --- NOT FOR ZERO ---
#Raid: Caverns of Time - Mount Hyjal
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
file(GLOB sources_instance_k_cot_mh scripts/kalimdor/caverns_of_time/hyjal/*.cpp scripts/kalimdor/caverns_of_time/hyjal/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_k_cot_mh})
source_group("Kalimdor Scripts\\Raids\\Caverns of Time\\Mount Hyjal" FILES ${sources_instance_k_cot_mh})
endif()
# --- END IF ---
#Raid: Onyxias Lair Scripts
file(GLOB sources_raid_k_ony scripts/kalimdor/onyxias_lair/*.cpp scripts/kalimdor/onyxias_lair/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_k_ony})
source_group("Kalimdor Scripts\\Raids\\Onyxias Lair" FILES ${sources_raid_k_ony})
#Raid: Ruins of AQ Scripts
file(GLOB sources_raid_k_raq scripts/kalimdor/ruins_of_ahnqiraj/*.cpp scripts/kalimdor/ruins_of_ahnqiraj/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_k_raq})
source_group("Kalimdor Scripts\\Raids\\Ruins of AQ" FILES ${sources_raid_k_raq})
#Raid: Temple of AQ Scripts
file(GLOB sources_raid_k_taq scripts/kalimdor/temple_of_ahnqiraj/*.cpp scripts/kalimdor/temple_of_ahnqiraj/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_k_taq})
source_group("Kalimdor Scripts\\Raids\\Temple of AQ" FILES ${sources_raid_k_taq})
# --- NOT FOR ZERO ---
IF(("${MANGOS_EXP}" STREQUAL "TBC") OR ("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Instance: Auchindoun - Auchenai Crypts
file(GLOB sources_instance_ol_aac scripts/outland/auchindoun/auchenai_crypts/*.cpp scripts/outland/auchindoun/auchenai_crypts/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_aac})
source_group("Outlands Scripts\\Instances\\Auchindoun\\Auchenai Crypts" FILES ${sources_instance_ol_aac})
#Instance: Auchindoun - Mana Tombs
file(GLOB sources_instance_ol_amt scripts/outland/auchindoun/mana_tombs/*.cpp scripts/outland/auchindoun/mana_tombs/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_amt})
source_group("Outlands Scripts\\Instances\\Auchindoun\\Mana Tombs" FILES ${sources_instance_ol_amt})
#Instance: Auchindoun - Sethekk Halls
file(GLOB sources_instance_ol_ash scripts/outland/auchindoun/sethekk_halls/*.cpp scripts/outland/auchindoun/sethekk_halls/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_ash})
source_group("Outlands Scripts\\Instances\\Auchindoun\\Sethekk Halls" FILES ${sources_instance_ol_ash})
#Instance: Auchindoun - Shadow Labyrinth
file(GLOB sources_instance_ol_asl scripts/outland/auchindoun/shadow_labyrinth/*.cpp scripts/outland/auchindoun/shadow_labyrinth/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_asl})
source_group("Outlands Scripts\\Instances\\Auchindoun\\Shadow Labyrinth" FILES ${sources_instance_ol_asl})
#Instance: Coilfang Reservoir - Slave Pens
file(GLOB sources_instance_ol_csp scripts/outland/coilfang_reservoir/slave_pens/*.cpp scripts/outland/coilfang_reservoir/slave_pens/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_csp})
source_group("Outlands Scripts\\Instances\\Coilfang Reservoir\\Slave Pens" FILES ${sources_instance_ol_csp})
#Instance: Coilfang Reservoir - Steam Vaults
file(GLOB sources_instance_ol_cst scripts/outland/coilfang_reservoir/steam_vault/*.cpp scripts/outland/coilfang_reservoir/steam_vault/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_cst})
source_group("Outlands Scripts\\Instances\\Coilfang Reservoir\\Steam Vaults" FILES ${sources_instance_ol_cst})
#Instance: Coilfang Reservoir - Underbog
file(GLOB sources_instance_ol_cu scripts/outland/coilfang_reservoir/underbog/*.cpp scripts/outland/coilfang_reservoir/underbog/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_ol_cu})
source_group("Outlands Scripts\\Instances\\Coilfang Reservoir\\Underbog" FILES ${sources_instance_ol_cu})
#Instance: Hellfire Citadel - Blood Furnace
file(GLOB sources_raid_ol_hbf scripts/outland/hellfire_citadel/blood_furnace/*.cpp scripts/outland/hellfire_citadel/blood_furnace/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_hbf})
source_group("Outlands Scripts\\Instances\\Hellfire Citadel\\Blood Furnace" FILES ${sources_raid_ol_hbf})
#Instance: Hellfire Citadel - Hellfire Ramparts
file(GLOB sources_raid_ol_hhr scripts/outland/hellfire_citadel/hellfire_ramparts/*.cpp scripts/outland/hellfire_citadel/hellfire_ramparts/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_hhr})
source_group("Outlands Scripts\\Instances\\Hellfire Citadel\\Hellfire Ramparts" FILES ${sources_raid_ol_hhr})
#Instance: Hellfire Citadel - Shattered Halls
file(GLOB sources_raid_ol_hsh scripts/outland/hellfire_citadel/shattered_halls/*.cpp scripts/outland/hellfire_citadel/shattered_halls/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_hsh})
source_group("Outlands Scripts\\Instances\\Hellfire Citadel\\Shattered Halls" FILES ${sources_raid_ol_hsh})
#Instance: Tempest Keep - Arcatraz
file(GLOB sources_raid_ol_ta scripts/outland/tempest_keep/arcatraz/*.cpp scripts/outland/tempest_keep/arcatraz/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_ta})
source_group("Outlands Scripts\\Instances\\Tempest Keep\\Arcatraz" FILES ${sources_raid_ol_ta})
#Instance: Tempest Keep - Botanica
file(GLOB sources_raid_ol_tb scripts/outland/tempest_keep/botanica/*.cpp scripts/outland/tempest_keep/botanica/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_tb})
source_group("Outlands Scripts\\Instances\\Tempest Keep\\Botanica" FILES ${sources_raid_ol_tb})
#Instance: Tempest Keep - The Mechanar
file(GLOB sources_raid_ol_ttm scripts/outland/tempest_keep/the_mechanar/*.cpp scripts/outland/tempest_keep/the_mechanar/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_ttm})
source_group("Outlands Scripts\\Instances\\Tempest Keep\\The Mechanar" FILES ${sources_raid_ol_ttm})
#Raid: Hellfire Citadel - Magtheridons Lair
file(GLOB sources_raid_ol_hml scripts/outland/hellfire_citadel/magtheridons_lair/*.cpp scripts/outland/hellfire_citadel/magtheridons_lair/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_hml})
source_group("Outlands Scripts\\Raids\\Hellfire Citadel\\Magtheridons Lair" FILES ${sources_raid_ol_hml})
#Raid: Tempest Keep - The Eye
file(GLOB sources_raid_ol_tte scripts/outland/tempest_keep/the_eye/*.cpp scripts/outland/tempest_keep/the_eye/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_tte})
source_group("Outlands Scripts\\Raids\\Tempest Keep\\The Eye" FILES ${sources_raid_ol_tte})
#Raid: Coilfang Reservoir - Serpentshrine Cavern
file(GLOB sources_raid_ol_csc scripts/outland/coilfang_reservoir/serpent_shrine/*.cpp scripts/outland/coilfang_reservoir/serpent_shrine/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_csc})
source_group("Outlands Scripts\\Raids\\Coilfang Reservoir\\Serpentshrine Cavern" FILES ${sources_raid_ol_csc})
#Raid: Black Temple
file(GLOB sources_raid_ol_bt scripts/outland/black_temple/*.cpp scripts/outland/black_temple/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_bt})
source_group("Outlands Scripts\\Raids\\Black Temple" FILES ${sources_raid_ol_bt})
#Raid: Gruul's Lair
file(GLOB sources_raid_ol_gl scripts/outland/gruuls_lair/*.cpp scripts/outland/gruuls_lair/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_ol_gl})
source_group("Outlands Scripts\\Raids\\Gruul's Lair" FILES ${sources_raid_ol_gl})
endif()
# --- END IF ---
# --- TWO ONLY ---
if (("${MANGOS_EXP}" STREQUAL "WOTLK") OR ("${MANGOS_EXP}" STREQUAL "CATA"))
#Instance: Azjol Nerub
file(GLOB sources_instance_nr_aznj scripts/northrend/azjol-nerub/azjol-nerub/*.cpp scripts/northrend/azjol-nerub/azjol-nerub/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_aznj})
source_group("Northrend Scripts\\Instances\\Azjol Nerub" FILES ${sources_instance_nr_aznj})
#Instance: Ahn'Kahet
file(GLOB sources_instance_nr_ahnk scripts/northrend/azjol-nerub/ahnkahet/*.cpp scripts/northrend/azjol-nerub/ahnkahet/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_ahnk})
source_group("Northrend Scripts\\Instances\\Ahn'Kahet" FILES ${sources_instance_nr_ahnk})
#Instance: Trial of the Champion
file(GLOB sources_instance_nr_totch scripts/northrend/crusaders_coliseum/trial_of_the_champion/*.cpp scripts/northrend/crusaders_coliseum/trial_of_the_champion/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_totch})
source_group("Northrend Scripts\\Instances\\Trial of the Champion" FILES ${sources_instance_nr_totch})
#Instance: Drak'Tharon Keep
file(GLOB sources_instance_nr_dtk scripts/northrend/draktharon_keep/*.cpp scripts/northrend/draktharon_keep/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_dtk})
source_group("Northrend Scripts\\Instances\\Drak'Tharon Keep" FILES ${sources_instance_nr_dtk})
#Instance: Gundrak
file(GLOB sources_instance_nr_gdk scripts/northrend/gundrak/*.cpp scripts/northrend/gundrak/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_gdk})
source_group("Northrend Scripts\\Instances\\Gundrak" FILES ${sources_instance_nr_gdk})
#Instance: Frozen Halls: Forge of Souls
file(GLOB sources_instance_nr_fh_fos scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/*.cpp scripts/northrend/icecrown_citadel/frozen_halls/forge_of_souls/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_fh_fos})
source_group("Northrend Scripts\\Instances\\Forge of Souls" FILES ${sources_instance_nr_fh_fos})
#Instance: Frozen Halls: Halls of Reflection
file(GLOB sources_instance_nr_fh_hor scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/*.cpp scripts/northrend/icecrown_citadel/frozen_halls/halls_of_reflection/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_fh_hor})
source_group("Northrend Scripts\\Instances\\Halls of Reflection" FILES ${sources_instance_nr_fh_hor})
#Instance: Frozen Halls: Pit of Saron
file(GLOB sources_instance_nr_fh_pos scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/*.cpp scripts/northrend/icecrown_citadel/frozen_halls/pit_of_saron/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_fh_pos})
source_group("Northrend Scripts\\Instances\\Pit of Saron" FILES ${sources_instance_nr_fh_pos})
#Instance: The Nexus
file(GLOB sources_instance_nr_nex scripts/northrend/nexus/nexus/*.cpp scripts/northrend/nexus/nexus/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_nex})
source_group("Northrend Scripts\\Instances\\The Nexus" FILES ${sources_instance_nr_nex})
#Instance: The Oculus
file(GLOB sources_instance_nr_oculus scripts/northrend/nexus/oculus/*.cpp scripts/northrend/nexus/oculus/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_oculus})
source_group("Northrend Scripts\\Instances\\The Oculus" FILES ${sources_instance_nr_oculus})
#Instance: Halls of Lightning
file(GLOB sources_instance_nr_uld_hol scripts/northrend/ulduar/halls_of_lightning/*.cpp scripts/northrend/ulduar/halls_of_lightning/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_uld_hol})
source_group("Northrend Scripts\\Instances\\Halls of Lightning" FILES ${sources_instance_nr_uld_hol})
#Instance: Halls of Stone
file(GLOB sources_instance_nr_uld_hos scripts/northrend/ulduar/halls_of_stone/*.cpp scripts/northrend/ulduar/halls_of_stone/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_uld_hos})
source_group("Northrend Scripts\\Instances\\Halls of Stone" FILES ${sources_instance_nr_uld_hos})
#Instance: Utgarde Keep
file(GLOB sources_instance_nr_uk scripts/northrend/utgarde_keep/utgarde_keep/*.cpp scripts/northrend/utgarde_keep/utgarde_keep/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_uk})
source_group("Northrend Scripts\\Instances\\Utgarde Keep" FILES ${sources_instance_nr_uk})
#Instance: Utgarde Pinnacle
file(GLOB sources_instance_nr_up scripts/northrend/utgarde_keep/utgarde_pinnacle/*.cpp scripts/northrend/utgarde_keep/utgarde_pinnacle/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_up})
source_group("Northrend Scripts\\Instances\\Utgarde Pinnacle" FILES ${sources_instance_nr_up})
#Instance: Violet Hold
file(GLOB sources_instance_nr_vh scripts/northrend/violet_hold/*.cpp scripts/northrend/violet_hold/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_instance_nr_vh})
source_group("Northrend Scripts\\Instances\\Violet Hold" FILES ${sources_instance_nr_vh})
#Raid: Naxxramas
file(GLOB sources_raid_nr_naxx scripts/northrend/naxxramas/*.cpp scripts/northrend/naxxramas/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_naxx})
source_group("Northrend Scripts\\Raids\\Naxxramas" FILES ${sources_raid_nr_naxx})
#Raid: Vault of Archavon
file(GLOB sources_raid_nr_voa scripts/northrend/vault_of_archavon/*.cpp scripts/northrend/vault_of_archavon/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_voa})
source_group("Northrend Scripts\\Raids\\Vault of Archavon" FILES ${sources_raid_nr_voa})
#Raid: Obsidian Sanctum
file(GLOB sources_raid_nr_os scripts/northrend/obsidian_sanctum/*.cpp scripts/northrend/obsidian_sanctum/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_os})
source_group("Northrend Scripts\\Raids\\Obsidian Sanctum" FILES ${sources_raid_nr_os})
#Raid: Ruby Sanctum
file(GLOB sources_raid_nr_rs scripts/northrend/ruby_sanctum/*.cpp scripts/northrend/ruby_sanctum/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_rs})
source_group("Northrend Scripts\\Raids\\Ruby Sanctum" FILES ${sources_raid_nr_rs})
#Raid: Icecrown Citadel
file(GLOB sources_raid_nr_icc scripts/northrend/icecrown_citadel/icecrown_citadel/*.cpp scripts/northrend/icecrown_citadel/icecrown_citadel/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_icc})
source_group("Northrend Scripts\\Raids\\Icecrown Citadel" FILES ${sources_raid_nr_icc})
#Raid: Trial of the Crusader
file(GLOB sources_raid_nr_totc scripts/northrend/crusaders_coliseum/trial_of_the_crusader/*.cpp scripts/northrend/crusaders_coliseum/trial_of_the_crusader/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_totc})
source_group("Northrend Scripts\\Raids\\Trial of the Crusader" FILES ${sources_raid_nr_totc})
#Raid: Eye of Eternity
file(GLOB sources_raid_nr_eoe scripts/northrend/nexus/eye_of_eternity/*.cpp scripts/northrend/nexus/eye_of_eternity/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_eoe})
source_group("Northrend Scripts\\Raids\\Eye of Eternity" FILES ${sources_raid_nr_eoe})
#Raid: Ulduar
file(GLOB sources_raid_nr_uld scripts/northrend/ulduar/ulduar/*.cpp scripts/northrend/ulduar/ulduar/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_raid_nr_uld})
source_group("Northrend Scripts\\Raids\\Ulduar" FILES ${sources_raid_nr_uld})
#WorldScript: Scarlet Enclave
file(GLOB sources_world_scarlet_enclave scripts/eastern_kingdoms/scarlet_enclave/*.cpp scripts/eastern_kingdoms/scarlet_enclave/*.h)
LIST(APPEND mangosscript_LIB_SRCS ${sources_world_scarlet_enclave})
source_group("Eastern Kingdoms Scripts\\World\\Scarlet Enclave" FILES ${sources_world_scarlet_enclave})
endif()
# --- END IF ---
add_library(mangosscript STATIC ${mangosscript_LIB_SRCS})
# Generate PCH
if(PCH)
ADD_CXX_PCH(mangosscript ${mangosscript_PCH})
endif()
if(NOT ACE_USE_EXTERNAL)
add_dependencies(mangosscript ace)
endif()
if(UNIX)
set(mangosscript_LINK_FLAGS "-pthread")
if(APPLE)
set(mangosscript_LINK_FLAGS "-framework Carbon ${mangosscript_LINK_FLAGS}")
# Needed for the linking because of the missing symbols
set(mangosscript_LINK_FLAGS "-Wl,-undefined -Wl,dynamic_lookup ${mangosscript_LINK_FLAGS}")
endif()
if(APPLE)
set(mangosscript_PROPERTIES INSTALL_NAME_DIR ${LIBS_DIR})
else()
set(mangosscript_PROPERTIES INSTALL_RPATH ${LIBS_DIR})
endif()
# Run out of build tree
set(mangosscript_PROPERTIES
${mangosscript_PROPERTIES}
BUILD_WITH_INSTALL_RPATH OFF
)
set_target_properties(mangosscript PROPERTIES
LINK_FLAGS ${mangosscript_LINK_FLAGS}
${mangosscript_PROPERTIES}
)
endif()

View file

@ -0,0 +1,5 @@
# ScriptDev3
New EventAI engine for all MaNGOS cores. Developed from the old ScriptDev2.

View file

@ -0,0 +1,662 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/* ScriptData
SDName: EscortAI
SD%Complete: 100
SDComment:
SDCategory: Npc
EndScriptData */
#include "precompiled.h"
#include "escort_ai.h"
#include "system/system.h"
const float MAX_PLAYER_DISTANCE = 66.0f;
enum
{
POINT_LAST_POINT = 0xFFFFFF,
POINT_HOME = 0xFFFFFE
};
npc_escortAI::npc_escortAI(Creature* pCreature) : ScriptedAI(pCreature),
m_uiWPWaitTimer(2500),
m_uiPlayerCheckTimer(1000),
m_uiEscortState(STATE_ESCORT_NONE),
m_pQuestForEscort(NULL),
m_bIsRunning(false),
m_bCanInstantRespawn(false),
m_bCanReturnToStart(false)
{}
void npc_escortAI::GetAIInformation(ChatHandler& reader)
{
std::ostringstream oss;
oss << "EscortAI ";
if (m_playerGuid)
{
oss << "started for " << m_playerGuid.GetString() << " ";
}
if (m_pQuestForEscort)
{
oss << "started with quest " << m_pQuestForEscort->GetQuestId();
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
oss << "\nEscortFlags: Escorting" << (HasEscortState(STATE_ESCORT_RETURNING) ? ", Returning" : "") << (HasEscortState(STATE_ESCORT_PAUSED) ? ", Paused" : "");
if (CurrentWP != WaypointList.end())
{
oss << "\nNext Waypoint Id = " << CurrentWP->uiId << " Position: " << CurrentWP->fX << " " << CurrentWP->fY << " " << CurrentWP->fZ;
}
}
reader.PSendSysMessage(oss.str().c_str());
}
bool npc_escortAI::IsVisible(Unit* pWho) const
{
if (!pWho)
{
return false;
}
return m_creature->IsWithinDist(pWho, VISIBLE_RANGE) && pWho->IsVisibleForOrDetect(m_creature, m_creature, true);
}
void npc_escortAI::AttackStart(Unit* pWho)
{
if (!pWho)
{
return;
}
if (m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == POINT_MOTION_TYPE)
{
m_creature->GetMotionMaster()->MovementExpired();
}
if (IsCombatMovement())
{
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
}
void npc_escortAI::EnterCombat(Unit* pEnemy)
{
// Store combat start position
m_creature->SetCombatStartPosition(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
if (!pEnemy)
{
return;
}
Aggro(pEnemy);
}
void npc_escortAI::Aggro(Unit* /*pEnemy*/) {}
// see followerAI
bool npc_escortAI::AssistPlayerInCombat(Unit* pWho)
{
if (!pWho->getVictim())
{
return false;
}
// experimental (unknown) flag not present
if (!(m_creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_CAN_ASSIST))
{
return false;
}
// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
{
return false;
}
// victim of pWho is not a player
if (!pWho->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
{
return false;
}
// never attack friendly
if (m_creature->IsFriendlyTo(pWho))
{
return false;
}
// too far away and no free sight?
if (m_creature->IsWithinDistInMap(pWho, MAX_PLAYER_DISTANCE) && m_creature->IsWithinLOSInMap(pWho))
{
// already fighting someone?
if (!m_creature->getVictim())
{
AttackStart(pWho);
return true;
}
else
{
pWho->SetInCombatWith(m_creature);
m_creature->AddThreat(pWho);
return true;
}
}
return false;
}
void npc_escortAI::MoveInLineOfSight(Unit* pWho)
{
if (pWho->IsTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
{
// AssistPlayerInCombat can start attack, so return if true
if (HasEscortState(STATE_ESCORT_ESCORTING) && AssistPlayerInCombat(pWho))
{
return;
}
if (!m_creature->CanInitiateAttack())
{
return;
}
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
{
return;
}
if (m_creature->IsHostileTo(pWho))
{
float fAttackRadius = m_creature->GetAttackDistance(pWho);
if (m_creature->IsWithinDistInMap(pWho, fAttackRadius) && m_creature->IsWithinLOSInMap(pWho))
{
if (!m_creature->getVictim())
{
pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
AttackStart(pWho);
}
else if (m_creature->GetMap()->IsDungeon())
{
pWho->SetInCombatWith(m_creature);
m_creature->AddThreat(pWho);
}
}
}
}
}
void npc_escortAI::JustDied(Unit* /*pKiller*/)
{
if (!HasEscortState(STATE_ESCORT_ESCORTING) || !m_playerGuid || !m_pQuestForEscort)
{
return;
}
if (Player* pPlayer = GetPlayerForEscort())
{
if (Group* pGroup = pPlayer->GetGroup())
{
for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
{
if (Player* pMember = pRef->getSource())
{
if (pMember->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
{
pMember->FailQuest(m_pQuestForEscort->GetQuestId());
}
}
}
}
else
{
if (pPlayer->GetQuestStatus(m_pQuestForEscort->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
{
pPlayer->FailQuest(m_pQuestForEscort->GetQuestId());
}
}
}
}
void npc_escortAI::JustRespawned()
{
m_uiEscortState = STATE_ESCORT_NONE;
if (!IsCombatMovement())
{
SetCombatMovement(true);
}
// add a small delay before going to first waypoint, normal in near all cases
m_uiWPWaitTimer = 2500;
Reset();
}
void npc_escortAI::EnterEvadeMode()
{
m_creature->RemoveAllAurasOnEvade();
m_creature->DeleteThreatList();
m_creature->CombatStop(true);
m_creature->SetLootRecipient(NULL);
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
// We have left our path
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != POINT_MOTION_TYPE)
{
debug_log("SD3: EscortAI has left combat and is now returning to CombatStartPosition.");
AddEscortState(STATE_ESCORT_RETURNING);
float fPosX, fPosY, fPosZ;
m_creature->GetCombatStartPosition(fPosX, fPosY, fPosZ);
m_creature->GetMotionMaster()->MovePoint(POINT_LAST_POINT, fPosX, fPosY, fPosZ);
}
}
else
{
m_creature->GetMotionMaster()->MoveTargetedHome();
}
Reset();
}
bool npc_escortAI::IsPlayerOrGroupInRange()
{
if (Player* pPlayer = GetPlayerForEscort())
{
if (Group* pGroup = pPlayer->GetGroup())
{
for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
{
Player* pMember = pRef->getSource();
if (pMember && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
{
return true;
}
}
}
else
{
if (m_creature->IsWithinDistInMap(pPlayer, MAX_PLAYER_DISTANCE))
{
return true;
}
}
}
return false;
}
// Returns false, if npc is despawned
bool npc_escortAI::MoveToNextWaypoint()
{
// Do nothing if escorting is paused
if (HasEscortState(STATE_ESCORT_PAUSED))
{
return true;
}
// Final Waypoint reached (and final wait time waited)
if (CurrentWP == WaypointList.end())
{
debug_log("SD3: EscortAI reached end of waypoints");
if (m_bCanReturnToStart)
{
float fRetX, fRetY, fRetZ;
m_creature->GetRespawnCoord(fRetX, fRetY, fRetZ);
m_creature->GetMotionMaster()->MovePoint(POINT_HOME, fRetX, fRetY, fRetZ);
m_uiWPWaitTimer = 0;
debug_log("SD3: EscortAI are returning home to spawn location: %u, %f, %f, %f", POINT_HOME, fRetX, fRetY, fRetZ);
return true;
}
if (m_bCanInstantRespawn)
{
m_creature->SetDeathState(JUST_DIED);
m_creature->Respawn();
}
else
{
m_creature->ForcedDespawn();
}
return false;
}
m_creature->GetMotionMaster()->MovePoint(CurrentWP->uiId, CurrentWP->fX, CurrentWP->fY, CurrentWP->fZ);
debug_log("SD3: EscortAI start waypoint %u (%f, %f, %f).", CurrentWP->uiId, CurrentWP->fX, CurrentWP->fY, CurrentWP->fZ);
WaypointStart(CurrentWP->uiId);
m_uiWPWaitTimer = 0;
return true;
}
void npc_escortAI::UpdateAI(const uint32 uiDiff)
{
// Waypoint Updating
if (HasEscortState(STATE_ESCORT_ESCORTING) && !m_creature->getVictim() && m_uiWPWaitTimer && !HasEscortState(STATE_ESCORT_RETURNING))
{
if (m_uiWPWaitTimer <= uiDiff)
{
if (!MoveToNextWaypoint())
{
return;
}
}
else
{
m_uiWPWaitTimer -= uiDiff;
}
}
// Check if player or any member of his group is within range
if (HasEscortState(STATE_ESCORT_ESCORTING) && m_playerGuid && !m_creature->getVictim() && !HasEscortState(STATE_ESCORT_RETURNING))
{
if (m_uiPlayerCheckTimer < uiDiff)
{
if (!HasEscortState(STATE_ESCORT_PAUSED) && !IsPlayerOrGroupInRange())
{
debug_log("SD3: EscortAI failed because player/group was to far away or not found");
if (m_bCanInstantRespawn)
{
m_creature->SetDeathState(JUST_DIED);
m_creature->Respawn();
}
else
{
m_creature->ForcedDespawn();
}
return;
}
m_uiPlayerCheckTimer = 1000;
}
else
{
m_uiPlayerCheckTimer -= uiDiff;
}
}
UpdateEscortAI(uiDiff);
}
void npc_escortAI::UpdateEscortAI(const uint32 /*uiDiff*/)
{
// Check if we have a current target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
DoMeleeAttackIfReady();
}
void npc_escortAI::MovementInform(uint32 uiMoveType, uint32 uiPointId)
{
if (uiMoveType != POINT_MOTION_TYPE || !HasEscortState(STATE_ESCORT_ESCORTING))
{
return;
}
// Combat start position reached, continue waypoint movement
if (uiPointId == POINT_LAST_POINT)
{
debug_log("SD3: EscortAI has returned to original position before combat");
m_creature->SetWalk(!m_bIsRunning);
RemoveEscortState(STATE_ESCORT_RETURNING);
}
else if (uiPointId == POINT_HOME)
{
debug_log("SD3: EscortAI has returned to original home location and will continue from beginning of waypoint list.");
CurrentWP = WaypointList.begin();
m_uiWPWaitTimer = 0;
}
else
{
// Make sure that we are still on the right waypoint
if (CurrentWP->uiId != uiPointId)
{
script_error_log("EscortAI for Npc %u reached waypoint out of order %u, expected %u.", m_creature->GetEntry(), uiPointId, CurrentWP->uiId);
return;
}
debug_log("SD3: EscortAI waypoint %u reached.", CurrentWP->uiId);
// In case we were moving while in combat, we should evade back to this position
m_creature->SetCombatStartPosition(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
// Call WP function
WaypointReached(CurrentWP->uiId);
m_uiWPWaitTimer = CurrentWP->uiWaitTime;
++CurrentWP;
}
if (!m_uiWPWaitTimer)
{
// Continue WP Movement if Can
if (HasEscortState(STATE_ESCORT_ESCORTING) && !HasEscortState(STATE_ESCORT_PAUSED | STATE_ESCORT_RETURNING) && !m_creature->getVictim())
{
MoveToNextWaypoint();
}
else
{
m_uiWPWaitTimer = 1;
}
}
}
/*void npc_escortAI::AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs)
{
Escort_Waypoint t(id, x, y, z, WaitTimeMs);
WaypointList.push_back(t);
}*/
void npc_escortAI::FillPointMovementListForCreature()
{
std::vector<ScriptPointMove> const& pPointsEntries = pSystemMgr.GetPointMoveList(m_creature->GetEntry());
if (pPointsEntries.empty())
{
return;
}
std::vector<ScriptPointMove>::const_iterator itr;
for (itr = pPointsEntries.begin(); itr != pPointsEntries.end(); ++itr)
{
Escort_Waypoint pPoint(itr->uiPointId, itr->fX, itr->fY, itr->fZ, itr->uiWaitTime);
WaypointList.push_back(pPoint);
}
}
void npc_escortAI::SetCurrentWaypoint(uint32 uiPointId)
{
if (!(HasEscortState(STATE_ESCORT_PAUSED))) // Only when paused
{
return;
}
if (uiPointId == CurrentWP->uiId) // Already here
{
return;
}
bool bFoundWaypoint = false;
for (std::list<Escort_Waypoint>::iterator itr = WaypointList.begin(); itr != WaypointList.end(); ++itr)
{
if (itr->uiId == uiPointId)
{
CurrentWP = itr; // Set to found itr
bFoundWaypoint = true;
break;
}
}
if (!bFoundWaypoint)
{
debug_log("SD3: EscortAI current waypoint tried to set to id %u, but doesn't exist in WaypointList", uiPointId);
return;
}
m_uiWPWaitTimer = 1;
debug_log("SD3: EscortAI current waypoint set to id %u", CurrentWP->uiId);
}
void npc_escortAI::SetRun(bool bRun)
{
if (bRun)
{
if (!m_bIsRunning)
{
m_creature->SetWalk(false);
}
else
{
debug_log("SD3: EscortAI attempt to set run mode, but is already running.");
}
}
else
{
if (m_bIsRunning)
{
m_creature->SetWalk(true);
}
else
{
debug_log("SD3: EscortAI attempt to set walk mode, but is already walking.");
}
}
m_bIsRunning = bRun;
}
// TODO: get rid of this many variables passed in function.
void npc_escortAI::Start(bool bRun, const Player* pPlayer, const Quest* pQuest, bool bInstantRespawn, bool bCanLoopPath)
{
if (m_creature->getVictim())
{
script_error_log("EscortAI attempt to Start while in combat.");
return;
}
if (HasEscortState(STATE_ESCORT_ESCORTING))
{
script_error_log("EscortAI attempt to Start while already escorting.");
return;
}
if (!WaypointList.empty())
{
WaypointList.clear();
}
FillPointMovementListForCreature();
if (WaypointList.empty())
{
error_db_log("SD3: EscortAI Start with 0 waypoints (possible missing entry in script_waypoint).");
return;
}
// set variables
m_bIsRunning = bRun;
m_playerGuid = pPlayer ? pPlayer->GetObjectGuid() : ObjectGuid();
m_pQuestForEscort = pQuest;
m_bCanInstantRespawn = bInstantRespawn;
m_bCanReturnToStart = bCanLoopPath;
if (m_bCanReturnToStart && m_bCanInstantRespawn)
{
debug_log("SD3: EscortAI is set to return home after waypoint end and instant respawn at waypoint end. Creature will never despawn.");
}
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
m_creature->GetMotionMaster()->MovementExpired();
m_creature->GetMotionMaster()->MoveIdle();
debug_log("SD3: EscortAI start with WAYPOINT_MOTION_TYPE, changed to MoveIdle.");
}
// disable npcflags
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
debug_log("SD3: EscortAI started with " SIZEFMTD " waypoints. Run = %d, PlayerGuid = %s", WaypointList.size(), m_bIsRunning, m_playerGuid.GetString().c_str());
CurrentWP = WaypointList.begin();
// Set initial speed
m_creature->SetWalk(!m_bIsRunning);
AddEscortState(STATE_ESCORT_ESCORTING);
JustStartedEscort();
}
void npc_escortAI::SetEscortPaused(bool bPaused)
{
if (!HasEscortState(STATE_ESCORT_ESCORTING))
{
return;
}
if (bPaused)
{
AddEscortState(STATE_ESCORT_PAUSED);
}
else
{
RemoveEscortState(STATE_ESCORT_PAUSED);
}
}

View file

@ -0,0 +1,133 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_ESCORTAI_H
#define SC_ESCORTAI_H
// Remove this include, when EscortAI stores uint32 quest-id instead of Quest*
#include "ObjectMgr.h"
struct Escort_Waypoint
{
Escort_Waypoint(uint32 uiId, float fX, float fY, float fZ, uint32 uiWaitTime) :
uiId(uiId),
fX(fX),
fY(fY),
fZ(fZ),
uiWaitTime(uiWaitTime)
{}
uint32 uiId;
float fX;
float fY;
float fZ;
uint32 uiWaitTime;
};
enum EscortState
{
STATE_ESCORT_NONE = 0x000, // nothing in progress
STATE_ESCORT_ESCORTING = 0x001, // escort are in progress
STATE_ESCORT_RETURNING = 0x002, // escort is returning after being in combat
STATE_ESCORT_PAUSED = 0x004 // will not proceed with waypoints before state is removed
};
struct npc_escortAI : public ScriptedAI
{
public:
explicit npc_escortAI(Creature* pCreature);
~npc_escortAI() {}
void GetAIInformation(ChatHandler& reader) override;
virtual void Aggro(Unit*) override;
virtual void Reset() override {}
// CreatureAI functions
bool IsVisible(Unit*) const override;
void AttackStart(Unit*) override;
void EnterCombat(Unit*) override;
void MoveInLineOfSight(Unit*) override;
void JustDied(Unit*) override;
void JustRespawned() override;
void EnterEvadeMode() override;
void UpdateAI(const uint32) override; // the "internal" update, calls UpdateEscortAI()
virtual void UpdateEscortAI(const uint32); // used when it's needed to add code in update (abilities, scripted events, etc)
void MovementInform(uint32, uint32) override;
// EscortAI functions
// void AddWaypoint(uint32 id, float x, float y, float z, uint32 WaitTimeMs = 0);
virtual void WaypointReached(uint32 uiPointId) = 0;
virtual void WaypointStart(uint32 /*uiPointId*/) {}
void Start(bool bRun = false, const Player* pPlayer = NULL, const Quest* pQuest = NULL, bool bInstantRespawn = false, bool bCanLoopPath = false);
void SetRun(bool bRun = true);
void SetEscortPaused(bool uPaused);
bool HasEscortState(uint32 uiEscortState) { return (m_uiEscortState & uiEscortState); }
// update current point
void SetCurrentWaypoint(uint32 uiPointId);
protected:
Player* GetPlayerForEscort() { return m_creature->GetMap()->GetPlayer(m_playerGuid); }
virtual void JustStartedEscort() {}
private:
bool AssistPlayerInCombat(Unit* pWho);
bool IsPlayerOrGroupInRange();
bool MoveToNextWaypoint();
void FillPointMovementListForCreature();
void AddEscortState(uint32 uiEscortState) { m_uiEscortState |= uiEscortState; }
void RemoveEscortState(uint32 uiEscortState) { m_uiEscortState &= ~uiEscortState; }
ObjectGuid m_playerGuid;
uint32 m_uiWPWaitTimer;
uint32 m_uiPlayerCheckTimer;
uint32 m_uiEscortState;
const Quest* m_pQuestForEscort; // generally passed in Start() when regular escort script.
std::list<Escort_Waypoint> WaypointList;
std::list<Escort_Waypoint>::iterator CurrentWP;
bool m_bIsRunning; // all creatures are walking by default (has flag SPLINEFLAG_WALKMODE)
bool m_bCanInstantRespawn; // if creature should respawn instantly after escort over (if not, database respawntime are used)
bool m_bCanReturnToStart; // if creature can walk same path (loop) without despawn. Not for regular escort quests.
};
#endif

View file

@ -0,0 +1,458 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/* ScriptData
SDName: FollowerAI
SD%Complete: 60
SDComment: This AI is under development
SDCategory: Npc
EndScriptData */
#include "precompiled.h"
#include "follower_ai.h"
const float MAX_PLAYER_DISTANCE = 100.0f;
enum
{
POINT_COMBAT_START = 0xFFFFFF
};
FollowerAI::FollowerAI(Creature* pCreature) : ScriptedAI(pCreature),
m_uiUpdateFollowTimer(2500),
m_uiFollowState(STATE_FOLLOW_NONE),
m_pQuestForFollow(NULL)
{}
void FollowerAI::AttackStart(Unit* pWho)
{
if (!pWho)
{
return;
}
if (m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
if (IsCombatMovement())
{
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
}
// This part provides assistance to a player that are attacked by pWho, even if out of normal aggro range
// It will cause m_creature to attack pWho that are attacking _any_ player (which has been confirmed may happen also on offi)
bool FollowerAI::AssistPlayerInCombat(Unit* pWho)
{
if (!pWho->getVictim())
{
return false;
}
// experimental (unknown) flag not present
if (!(m_creature->GetCreatureInfo()->CreatureTypeFlags & CREATURE_TYPEFLAGS_CAN_ASSIST))
{
return false;
}
// unit state prevents (similar check is done in CanInitiateAttack which also include checking unit_flags. We skip those here)
if (m_creature->hasUnitState(UNIT_STAT_STUNNED | UNIT_STAT_DIED))
{
return false;
}
// victim of pWho is not a player
if (!pWho->getVictim()->GetCharmerOrOwnerPlayerOrPlayerItself())
{
return false;
}
// never attack friendly
if (m_creature->IsFriendlyTo(pWho))
{
return false;
}
// too far away and no free sight?
if (m_creature->IsWithinDistInMap(pWho, MAX_PLAYER_DISTANCE) && m_creature->IsWithinLOSInMap(pWho))
{
// already fighting someone?
if (!m_creature->getVictim())
{
AttackStart(pWho);
return true;
}
else
{
pWho->SetInCombatWith(m_creature);
m_creature->AddThreat(pWho);
return true;
}
}
return false;
}
void FollowerAI::MoveInLineOfSight(Unit* pWho)
{
if (pWho->IsTargetableForAttack() && pWho->isInAccessablePlaceFor(m_creature))
{
// AssistPlayerInCombat can start attack, so return if true
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && AssistPlayerInCombat(pWho))
{
return;
}
if (!m_creature->CanInitiateAttack())
{
return;
}
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
{
return;
}
if (m_creature->IsHostileTo(pWho))
{
float fAttackRadius = m_creature->GetAttackDistance(pWho);
if (m_creature->IsWithinDistInMap(pWho, fAttackRadius) && m_creature->IsWithinLOSInMap(pWho))
{
if (!m_creature->getVictim())
{
pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
AttackStart(pWho);
}
else if (m_creature->GetMap()->IsDungeon())
{
pWho->SetInCombatWith(m_creature);
m_creature->AddThreat(pWho);
}
}
}
}
}
void FollowerAI::JustDied(Unit* /*pKiller*/)
{
if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || !m_leaderGuid || !m_pQuestForFollow)
{
return;
}
// TODO: need a better check for quests with time limit.
if (Player* pPlayer = GetLeaderForFollower())
{
if (Group* pGroup = pPlayer->GetGroup())
{
for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
{
if (Player* pMember = pRef->getSource())
{
if (pMember->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
{
pMember->FailQuest(m_pQuestForFollow->GetQuestId());
}
}
}
}
else
{
if (pPlayer->GetQuestStatus(m_pQuestForFollow->GetQuestId()) == QUEST_STATUS_INCOMPLETE)
{
pPlayer->FailQuest(m_pQuestForFollow->GetQuestId());
}
}
}
}
void FollowerAI::JustRespawned()
{
m_uiFollowState = STATE_FOLLOW_NONE;
if (!IsCombatMovement())
{
SetCombatMovement(true);
}
Reset();
}
void FollowerAI::EnterEvadeMode()
{
m_creature->RemoveAllAurasOnEvade();
m_creature->DeleteThreatList();
m_creature->CombatStop(true);
m_creature->SetLootRecipient(NULL);
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
debug_log("SD3: FollowerAI left combat, returning to CombatStartPosition.");
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
float fPosX, fPosY, fPosZ;
m_creature->GetCombatStartPosition(fPosX, fPosY, fPosZ);
m_creature->GetMotionMaster()->MovePoint(POINT_COMBAT_START, fPosX, fPosY, fPosZ);
}
}
else
{
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == CHASE_MOTION_TYPE)
{
m_creature->GetMotionMaster()->MoveTargetedHome();
}
}
Reset();
}
void FollowerAI::UpdateAI(const uint32 uiDiff)
{
if (HasFollowState(STATE_FOLLOW_INPROGRESS) && !m_creature->getVictim())
{
if (m_uiUpdateFollowTimer < uiDiff)
{
if (HasFollowState(STATE_FOLLOW_COMPLETE) && !HasFollowState(STATE_FOLLOW_POSTEVENT))
{
debug_log("SD3: FollowerAI is set completed, despawns.");
m_creature->ForcedDespawn();
return;
}
bool bIsMaxRangeExceeded = true;
if (Player* pPlayer = GetLeaderForFollower())
{
if (HasFollowState(STATE_FOLLOW_RETURNING))
{
debug_log("SD3: FollowerAI is returning to leader.");
RemoveFollowState(STATE_FOLLOW_RETURNING);
m_creature->GetMotionMaster()->MoveFollow(pPlayer, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
return;
}
if (Group* pGroup = pPlayer->GetGroup())
{
for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
{
Player* pMember = pRef->getSource();
if (pMember && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
{
bIsMaxRangeExceeded = false;
break;
}
}
}
else
{
if (m_creature->IsWithinDistInMap(pPlayer, MAX_PLAYER_DISTANCE))
{
bIsMaxRangeExceeded = false;
}
}
}
if (bIsMaxRangeExceeded)
{
debug_log("SD3: FollowerAI failed because player/group was to far away or not found");
m_creature->ForcedDespawn();
return;
}
m_uiUpdateFollowTimer = 1000;
}
else
{
m_uiUpdateFollowTimer -= uiDiff;
}
}
UpdateFollowerAI(uiDiff);
}
void FollowerAI::UpdateFollowerAI(const uint32 /*uiDiff*/)
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
DoMeleeAttackIfReady();
}
void FollowerAI::MovementInform(uint32 uiMotionType, uint32 uiPointId)
{
if (uiMotionType != POINT_MOTION_TYPE || !HasFollowState(STATE_FOLLOW_INPROGRESS))
{
return;
}
if (uiPointId == POINT_COMBAT_START)
{
if (GetLeaderForFollower())
{
if (!HasFollowState(STATE_FOLLOW_PAUSED))
{
AddFollowState(STATE_FOLLOW_RETURNING);
}
}
else
{
m_creature->ForcedDespawn();
}
}
}
void FollowerAI::StartFollow(Player* pLeader, uint32 uiFactionForFollower, const Quest* pQuest)
{
if (m_creature->getVictim())
{
debug_log("SD3: FollowerAI attempt to StartFollow while in combat.");
return;
}
if (HasFollowState(STATE_FOLLOW_INPROGRESS))
{
script_error_log("FollowerAI attempt to StartFollow while already following.");
return;
}
// set variables
m_leaderGuid = pLeader->GetObjectGuid();
if (uiFactionForFollower)
{
m_creature->SetFactionTemporary(uiFactionForFollower, TEMPFACTION_RESTORE_RESPAWN);
}
m_pQuestForFollow = pQuest;
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == WAYPOINT_MOTION_TYPE)
{
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveIdle();
debug_log("SD3: FollowerAI start with WAYPOINT_MOTION_TYPE, set to MoveIdle.");
}
m_creature->SetUInt32Value(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_NONE);
AddFollowState(STATE_FOLLOW_INPROGRESS);
m_creature->GetMotionMaster()->MoveFollow(pLeader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
debug_log("SD3: FollowerAI start follow %s (Guid %s)", pLeader->GetName(), m_leaderGuid.GetString().c_str());
}
Player* FollowerAI::GetLeaderForFollower()
{
if (Player* pLeader = m_creature->GetMap()->GetPlayer(m_leaderGuid))
{
if (pLeader->IsAlive())
{
return pLeader;
}
else
{
if (Group* pGroup = pLeader->GetGroup())
{
for (GroupReference* pRef = pGroup->GetFirstMember(); pRef != NULL; pRef = pRef->next())
{
Player* pMember = pRef->getSource();
if (pMember && pMember->IsAlive() && m_creature->IsWithinDistInMap(pMember, MAX_PLAYER_DISTANCE))
{
debug_log("SD3: FollowerAI GetLeader changed and returned new leader.");
m_leaderGuid = pMember->GetObjectGuid();
return pMember;
}
}
}
}
}
debug_log("SD3: FollowerAI GetLeader can not find suitable leader.");
return NULL;
}
void FollowerAI::SetFollowComplete(bool bWithEndEvent)
{
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
{
m_creature->StopMoving();
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveIdle();
}
if (bWithEndEvent)
{
AddFollowState(STATE_FOLLOW_POSTEVENT);
}
else
{
if (HasFollowState(STATE_FOLLOW_POSTEVENT))
{
RemoveFollowState(STATE_FOLLOW_POSTEVENT);
}
}
AddFollowState(STATE_FOLLOW_COMPLETE);
}
void FollowerAI::SetFollowPaused(bool bPaused)
{
if (!HasFollowState(STATE_FOLLOW_INPROGRESS) || HasFollowState(STATE_FOLLOW_COMPLETE))
{
return;
}
if (bPaused)
{
AddFollowState(STATE_FOLLOW_PAUSED);
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() == FOLLOW_MOTION_TYPE)
{
m_creature->StopMoving();
m_creature->GetMotionMaster()->Clear();
m_creature->GetMotionMaster()->MoveIdle();
}
}
else
{
RemoveFollowState(STATE_FOLLOW_PAUSED);
if (Player* pLeader = GetLeaderForFollower())
{
m_creature->GetMotionMaster()->MoveFollow(pLeader, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
}
}

View file

@ -0,0 +1,87 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_FOLLOWERAI_H
#define SC_FOLLOWERAI_H
enum FollowState
{
STATE_FOLLOW_NONE = 0x000,
STATE_FOLLOW_INPROGRESS = 0x001, // must always have this state for any follow
STATE_FOLLOW_RETURNING = 0x002, // when returning to combat start after being in combat
STATE_FOLLOW_PAUSED = 0x004, // disables following
STATE_FOLLOW_COMPLETE = 0x008, // follow is completed and may end
STATE_FOLLOW_PREEVENT = 0x010, // not implemented (allow pre event to run, before follow is initiated)
STATE_FOLLOW_POSTEVENT = 0x020 // can be set at complete and allow post event to run
};
class FollowerAI : public ScriptedAI
{
public:
explicit FollowerAI(Creature* pCreature);
~FollowerAI() {}
// virtual void WaypointReached(uint32 uiPointId) = 0;
void MovementInform(uint32 uiMotionType, uint32 uiPointId) override;
void AttackStart(Unit*) override;
void MoveInLineOfSight(Unit*) override;
void EnterEvadeMode() override;
void JustDied(Unit*) override;
void JustRespawned() override;
void UpdateAI(const uint32) override; // the "internal" update, calls UpdateFollowerAI()
virtual void UpdateFollowerAI(const uint32); // used when it's needed to add code in update (abilities, scripted events, etc)
void StartFollow(Player* pPlayer, uint32 uiFactionForFollower = 0, const Quest* pQuest = NULL);
void SetFollowPaused(bool bPaused); // if special event require follow mode to hold/resume during the follow
void SetFollowComplete(bool bWithEndEvent = false);
bool HasFollowState(uint32 uiFollowState) { return (m_uiFollowState & uiFollowState); }
protected:
Player* GetLeaderForFollower();
private:
void AddFollowState(uint32 uiFollowState) { m_uiFollowState |= uiFollowState; }
void RemoveFollowState(uint32 uiFollowState) { m_uiFollowState &= ~uiFollowState; }
bool AssistPlayerInCombat(Unit* pWho);
ObjectGuid m_leaderGuid;
uint32 m_uiUpdateFollowTimer;
uint32 m_uiFollowState;
const Quest* m_pQuestForFollow; // normally we have a quest
};
#endif

View file

@ -0,0 +1,275 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/* ScriptData
SDName: Guard_AI
SD%Complete: 90
SDComment:
SDCategory: Guards
EndScriptData */
#include "precompiled.h"
#include "guard_ai.h"
// This script is for use within every single guard to save coding time
guardAI::guardAI(Creature* pCreature) : ScriptedAI(pCreature),
m_uiGlobalCooldown(0),
m_uiBuffTimer(0)
{}
void guardAI::Reset()
{
m_uiGlobalCooldown = 0;
m_uiBuffTimer = 0; // Rebuff as soon as we can
}
void guardAI::Aggro(Unit* pWho)
{
if (m_creature->GetEntry() == NPC_CENARION_INFANTRY)
{
switch (urand(0, 2))
{
case 0:
DoScriptText(SAY_GUARD_SIL_AGGRO1, m_creature, pWho);
break;
case 1:
DoScriptText(SAY_GUARD_SIL_AGGRO2, m_creature, pWho);
break;
case 2:
DoScriptText(SAY_GUARD_SIL_AGGRO3, m_creature, pWho);
break;
}
}
if (const SpellEntry* pSpellInfo = m_creature->ReachWithSpellAttack(pWho))
{
DoCastSpell(pWho, pSpellInfo);
}
}
void guardAI::JustDied(Unit* pKiller)
{
// Send Zone Under Attack message to the LocalDefense and WorldDefense Channels
if (Player* pPlayer = pKiller->GetCharmerOrOwnerPlayerOrPlayerItself())
{
m_creature->SendZoneUnderAttackMessage(pPlayer);
}
}
void guardAI::UpdateAI(const uint32 uiDiff)
{
// Always decrease our global cooldown first
if (m_uiGlobalCooldown > uiDiff)
{
m_uiGlobalCooldown -= uiDiff;
}
else
{
m_uiGlobalCooldown = 0;
}
// Buff timer (only buff when we are alive and not in combat
if (m_creature->IsAlive() && !m_creature->IsInCombat())
{
if (m_uiBuffTimer < uiDiff)
{
// Find a spell that targets friendly and applies an aura (these are generally buffs)
const SpellEntry* pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_AURA);
if (pSpellInfo && !m_uiGlobalCooldown)
{
// Cast the buff spell
DoCastSpell(m_creature, pSpellInfo);
// Set our global cooldown
m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
// Set our timer to 10 minutes before rebuff
m_uiBuffTimer = 600000;
} // Try again in 30 seconds
else
{
m_uiBuffTimer = 30000;
}
}
else
{
m_uiBuffTimer -= uiDiff;
}
}
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Make sure our attack is ready and we arn't currently casting
if (m_creature->isAttackReady() && !m_creature->IsNonMeleeSpellCasted(false))
{
// If we are within range melee the target
if (m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
{
bool bHealing = false;
const SpellEntry* pSpellInfo = NULL;
// Select a healing spell if less than 30% hp
if (m_creature->GetHealthPercent() < 30.0f)
{
pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
}
// No healing spell available, select a hostile spell
if (pSpellInfo)
{
bHealing = true;
}
else
{
pSpellInfo = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, 0, 0, SELECT_EFFECT_DONTCARE);
}
// 20% chance to replace our white hit with a spell
if (pSpellInfo && !urand(0, 4) && !m_uiGlobalCooldown)
{
// Cast the spell
if (bHealing)
{
DoCastSpell(m_creature, pSpellInfo);
}
else
{
DoCastSpell(m_creature->getVictim(), pSpellInfo);
}
// Set our global cooldown
m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
}
else
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
}
m_creature->resetAttackTimer();
}
}
else
{
// Only run this code if we arn't already casting
if (!m_creature->IsNonMeleeSpellCasted(false))
{
bool bHealing = false;
const SpellEntry* pSpellInfo = NULL;
// Select a healing spell if less than 30% hp ONLY 33% of the time
if (m_creature->GetHealthPercent() < 30.0f && !urand(0, 2))
{
pSpellInfo = SelectSpell(m_creature, -1, -1, SELECT_TARGET_ANY_FRIEND, 0, 0, 0, 0, SELECT_EFFECT_HEALING);
}
// No healing spell available, See if we can cast a ranged spell (Range must be greater than ATTACK_DISTANCE)
if (pSpellInfo)
{
bHealing = true;
}
else
{
pSpellInfo = SelectSpell(m_creature->getVictim(), -1, -1, SELECT_TARGET_ANY_ENEMY, 0, 0, ATTACK_DISTANCE, 0, SELECT_EFFECT_DONTCARE);
}
// Found a spell, check if we arn't on cooldown
if (pSpellInfo && !m_uiGlobalCooldown)
{
// If we are currently moving stop us and set the movement generator
if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != IDLE_MOTION_TYPE)
{
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveIdle();
}
// Cast spell
if (bHealing)
{
DoCastSpell(m_creature, pSpellInfo);
}
else
{
DoCastSpell(m_creature->getVictim(), pSpellInfo);
}
// Set our global cooldown
m_uiGlobalCooldown = GENERIC_CREATURE_COOLDOWN;
} // If no spells available and we arn't moving run to target
else if (m_creature->GetMotionMaster()->GetCurrentMovementGeneratorType() != CHASE_MOTION_TYPE)
{
// Cancel our current spell and then mutate new movement generator
m_creature->InterruptNonMeleeSpells(false);
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveChase(m_creature->getVictim());
}
}
}
}
void guardAI::DoReplyToTextEmote(uint32 uiTextEmote)
{
switch (uiTextEmote)
{
case TEXTEMOTE_KISS:
m_creature->HandleEmote(EMOTE_ONESHOT_BOW);
break;
case TEXTEMOTE_WAVE:
m_creature->HandleEmote(EMOTE_ONESHOT_WAVE);
break;
case TEXTEMOTE_SALUTE:
m_creature->HandleEmote(EMOTE_ONESHOT_SALUTE);
break;
case TEXTEMOTE_SHY:
m_creature->HandleEmote(EMOTE_ONESHOT_FLEX);
break;
case TEXTEMOTE_RUDE:
case TEXTEMOTE_CHICKEN:
m_creature->HandleEmote(EMOTE_ONESHOT_POINT);
break;
}
}
void guardAI_orgrimmar::ReceiveEmote(Player* pPlayer, uint32 uiTextEmote)
{
if (pPlayer->GetTeam() == HORDE)
{
DoReplyToTextEmote(uiTextEmote);
}
}
void guardAI_stormwind::ReceiveEmote(Player* pPlayer, uint32 uiTextEmote)
{
if (pPlayer->GetTeam() == ALLIANCE)
{
DoReplyToTextEmote(uiTextEmote);
}
}

View file

@ -0,0 +1,84 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_GUARDAI_H
#define SC_GUARDAI_H
enum
{
GENERIC_CREATURE_COOLDOWN = 5000,
SAY_GUARD_SIL_AGGRO1 = -1000198,
SAY_GUARD_SIL_AGGRO2 = -1000199,
SAY_GUARD_SIL_AGGRO3 = -1000200,
NPC_CENARION_INFANTRY = 15184
};
enum eShattrathGuard
{
SPELL_BANISHED_SHATTRATH_A = 36642,
SPELL_BANISHED_SHATTRATH_S = 36671,
SPELL_BANISH_TELEPORT = 36643,
SPELL_EXILE = 39533
};
struct guardAI : public ScriptedAI
{
public:
explicit guardAI(Creature* pCreature);
~guardAI() {}
uint32 m_uiGlobalCooldown; // This variable acts like the global cooldown that players have (1.5 seconds)
uint32 m_uiBuffTimer; // This variable keeps track of buffs
void Reset() override;
void Aggro(Unit* pWho) override;
void JustDied(Unit* /*pKiller*/) override;
void UpdateAI(const uint32 uiDiff) override;
// Commonly used for guards in main cities
void DoReplyToTextEmote(uint32 uiTextEmote);
};
struct guardAI_orgrimmar : public guardAI
{
guardAI_orgrimmar(Creature* pCreature) : guardAI(pCreature) {}
void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote) override;
};
struct guardAI_stormwind : public guardAI
{
guardAI_stormwind(Creature* pCreature) : guardAI(pCreature) {}
void ReceiveEmote(Player* pPlayer, uint32 uiTextEmote) override;
};
#endif

View file

@ -0,0 +1,172 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/* ScriptData
SDName: ScriptedPetAI
SD%Complete: 50
SDComment: Intended to be used with Guardian/Protector/Minipets. Little/no control over when pet enter/leave combat. Must be considered to be under development.
SDCategory: Npc
EndScriptData */
#include "precompiled.h"
#include "pet_ai.h"
ScriptedPetAI::ScriptedPetAI(Creature* pCreature) : CreatureAI(pCreature)
{}
bool ScriptedPetAI::IsVisible(Unit* pWho) const
{
return pWho && m_creature->IsWithinDist(pWho, VISIBLE_RANGE)
&& pWho->IsVisibleForOrDetect(m_creature, m_creature, true);
}
void ScriptedPetAI::MoveInLineOfSight(Unit* pWho)
{
if (m_creature->getVictim())
{
return;
}
if (!m_creature->GetCharmInfo() || !m_creature->GetCharmInfo()->HasReactState(REACT_AGGRESSIVE))
{
return;
}
if (m_creature->CanInitiateAttack() && pWho->IsTargetableForAttack() &&
m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
{
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
{
return;
}
if (m_creature->IsWithinDistInMap(pWho, m_creature->GetAttackDistance(pWho)) && m_creature->IsWithinLOSInMap(pWho))
{
pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
AttackStart(pWho);
}
}
}
void ScriptedPetAI::AttackStart(Unit* pWho)
{
if (pWho && m_creature->Attack(pWho, true))
{
m_creature->GetMotionMaster()->MoveChase(pWho);
}
}
void ScriptedPetAI::AttackedBy(Unit* pAttacker)
{
if (m_creature->getVictim())
{
return;
}
if (m_creature->GetCharmInfo() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE) &&
m_creature->CanReachWithMeleeAttack(pAttacker))
{
AttackStart(pAttacker);
}
}
void ScriptedPetAI::ResetPetCombat()
{
Unit* pOwner = m_creature->GetCharmerOrOwner();
if (pOwner && m_creature->GetCharmInfo() && m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
m_creature->GetMotionMaster()->MoveFollow(pOwner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
else
{
m_creature->GetMotionMaster()->Clear(false);
m_creature->GetMotionMaster()->MoveIdle();
}
m_creature->AttackStop();
debug_log("SD3: ScriptedPetAI reset pet combat and stop attack.");
Reset();
}
void ScriptedPetAI::UpdatePetAI(const uint32 /*uiDiff*/)
{
DoMeleeAttackIfReady();
}
void ScriptedPetAI::UpdateAI(const uint32 uiDiff)
{
if (!m_creature->IsAlive()) // should not be needed, IsAlive is checked in mangos before calling UpdateAI
{
return;
}
// UpdateAllies() is done in the generic PetAI in Mangos, but we can't do this from script side.
// Unclear what side effects this has, but is something to be resolved from Mangos.
if (m_creature->getVictim()) // in combat
{
if (!m_creature->getVictim()->IsTargetableForAttack())
{
// target no longer valid for pet, so either attack stops or new target are selected
// doesn't normally reach this, because of how petAi is designed in Mangos. CombatStop
// are called before this update diff, and then pet will already have no victim.
ResetPetCombat();
return;
}
// update when in combat
UpdatePetAI(uiDiff);
}
else if (m_creature->GetCharmInfo())
{
Unit* pOwner = m_creature->GetCharmerOrOwner();
if (!pOwner)
{
return;
}
if (pOwner->IsInCombat() && !m_creature->GetCharmInfo()->HasReactState(REACT_PASSIVE))
{
// Not correct in all cases.
// When mob initiate attack by spell, pet should not start attack before spell landed.
AttackStart(pOwner->getAttackerForHelper());
}
else if (m_creature->GetCharmInfo()->HasCommandState(COMMAND_FOLLOW))
{
// not following, so start follow
if (!m_creature->hasUnitState(UNIT_STAT_FOLLOW))
{
m_creature->GetMotionMaster()->MoveFollow(pOwner, PET_FOLLOW_DIST, PET_FOLLOW_ANGLE);
}
// update when not in combat
UpdatePetOOCAI(uiDiff);
}
}
}

View file

@ -0,0 +1,61 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_PET_H
#define SC_PET_H
// Using CreatureAI for now. Might change later and use PetAI (need to export for dll first)
class ScriptedPetAI : public CreatureAI
{
public:
explicit ScriptedPetAI(Creature* pCreature);
~ScriptedPetAI() {}
void MoveInLineOfSight(Unit* /*pWho*/) override;
void AttackStart(Unit* /*pWho*/) override;
void AttackedBy(Unit* /*pAttacker*/) override;
bool IsVisible(Unit* /*pWho*/) const override;
void KilledUnit(Unit* /*pVictim*/) override {}
void OwnerKilledUnit(Unit* /*pVictim*/) override {}
void UpdateAI(const uint32 uiDiff) override;
virtual void Reset() {}
virtual void UpdatePetAI(const uint32 uiDiff); // while in combat
virtual void UpdatePetOOCAI(const uint32 /*uiDiff*/) {} // when not in combat
protected:
void ResetPetCombat();
};
#endif

View file

@ -0,0 +1,26 @@
/**
* ScriptDev2 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "precompiled.h"

View file

@ -0,0 +1,42 @@
/**
* ScriptDev2 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_PRECOMPILED_H
#define SC_PRECOMPILED_H
#include "ScriptMgr.h"
#include "Object.h"
#include "Unit.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "GameObject.h"
#include "sc_creature.h"
#include "sc_gossip.h"
#include "sc_grid_searchers.h"
#include "sc_instance.h"
#include "SpellAuras.h"
#endif

View file

@ -0,0 +1,836 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "precompiled.h"
#include "Item.h"
#include "Spell.h"
#include "WorldPacket.h"
#include "ObjectMgr.h"
#include "Cell.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
// Spell summary for ScriptedAI::SelectSpell
struct TSpellSummary
{
uint8 Targets; // set of enum SelectTarget
uint8 Effects; // set of enum SelectEffect
}* SpellSummary;
ScriptedAI::ScriptedAI(Creature* pCreature) : CreatureAI(pCreature),
m_uiEvadeCheckCooldown(2500)
{}
/// This function shows if combat movement is enabled, overwrite for more info
void ScriptedAI::GetAIInformation(ChatHandler& reader)
{
reader.PSendSysMessage("ScriptedAI, combat movement is %s", reader.GetOnOffStr(IsCombatMovement()));
}
/// Return if the creature can "see" pWho
bool ScriptedAI::IsVisible(Unit* pWho) const
{
if (!pWho)
{
return false;
}
return m_creature->IsWithinDist(pWho, VISIBLE_RANGE) && pWho->IsVisibleForOrDetect(m_creature, m_creature, true);
}
/**
* This function triggers the creature attacking pWho, depending on conditions like:
* - Can the creature start an attack?
* - Is pWho hostile to the creature?
* - Can the creature reach pWho?
* - Is pWho in aggro-range?
* If the creature can attack pWho, it will if it has no victim.
* Inside dungeons, the creature will get into combat with pWho, even if it has already a victim
*/
void ScriptedAI::MoveInLineOfSight(Unit* pWho)
{
if (m_creature->CanInitiateAttack() && pWho->IsTargetableForAttack() &&
m_creature->IsHostileTo(pWho) && pWho->isInAccessablePlaceFor(m_creature))
{
if (!m_creature->CanFly() && m_creature->GetDistanceZ(pWho) > CREATURE_Z_ATTACK_RANGE)
{
return;
}
if (m_creature->IsWithinDistInMap(pWho, m_creature->GetAttackDistance(pWho)) && m_creature->IsWithinLOSInMap(pWho))
{
if (!m_creature->getVictim())
{
pWho->RemoveSpellsCausingAura(SPELL_AURA_MOD_STEALTH);
AttackStart(pWho);
}
else if (m_creature->GetMap()->IsDungeon())
{
pWho->SetInCombatWith(m_creature);
m_creature->AddThreat(pWho);
}
}
}
}
/**
* This function sets the TargetGuid for the creature if required
* Also it will handle the combat movement (chase movement), depending on SetCombatMovement(bool)
*/
void ScriptedAI::AttackStart(Unit* pWho)
{
#if defined (WOTLK) || defined (CATA)
if (!m_creature->CanInitiateAttack())
return;
#endif
if (pWho && m_creature->Attack(pWho, true)) // The Attack function also uses basic checks if pWho can be attacked
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
HandleMovementOnAttackStart(pWho);
}
}
/**
* This function only calls Aggro, which is to be used for scripting purposes
*/
void ScriptedAI::EnterCombat(Unit* pEnemy)
{
if (pEnemy)
{
Aggro(pEnemy);
}
}
/**
* Main update function, by default let the creature behave as expected by a mob (threat management and melee dmg)
* Always handle here threat-management with m_creature->SelectHostileTarget()
* Handle (if required) melee attack with DoMeleeAttackIfReady()
* This is usally overwritten to support timers for ie spells
*/
void ScriptedAI::UpdateAI(const uint32 /*uiDiff*/)
{
// Check if we have a current target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
DoMeleeAttackIfReady();
#if defined (WOTLK) || defined (CATA)
Unit* victim = m_creature->getVictim();
const SpellEntry* potentialSpell = m_creature->ReachWithSpellAttack(victim);
if (potentialSpell)
m_creature->CastSpell(victim, potentialSpell->Id, true);
#endif
}
/**
* This function cleans up the combat state if the creature evades
* It will:
* - Drop Auras
* - Drop all threat
* - Stop combat
* - Move the creature home
* - Clear tagging for loot
* - call Reset()
*/
void ScriptedAI::EnterEvadeMode()
{
m_creature->RemoveAllAurasOnEvade();
m_creature->DeleteThreatList();
m_creature->CombatStop(true);
if (m_creature->IsAlive())
{
m_creature->GetMotionMaster()->MoveTargetedHome();
}
m_creature->SetLootRecipient(NULL);
Reset();
}
/// This function calls Reset() to reset variables as expected
void ScriptedAI::JustRespawned()
{
Reset();
}
void ScriptedAI::DoStartMovement(Unit* pVictim, float fDistance, float fAngle)
{
if (pVictim)
{
m_creature->GetMotionMaster()->MoveChase(pVictim, fDistance, fAngle);
}
}
void ScriptedAI::DoStartNoMovement(Unit* pVictim)
{
if (!pVictim)
{
return;
}
m_creature->GetMotionMaster()->MoveIdle();
m_creature->StopMoving();
}
void ScriptedAI::DoStopAttack()
{
if (m_creature->getVictim())
{
m_creature->AttackStop();
}
}
void ScriptedAI::DoCast(Unit* pTarget, uint32 uiSpellId, bool bTriggered)
{
if (m_creature->IsNonMeleeSpellCasted(false) && !bTriggered)
{
return;
}
m_creature->CastSpell(pTarget, uiSpellId, bTriggered);
}
void ScriptedAI::DoCastSpell(Unit* pTarget, SpellEntry const* pSpellInfo, bool bTriggered)
{
if (m_creature->IsNonMeleeSpellCasted(false) && !bTriggered)
{
return;
}
m_creature->CastSpell(pTarget, pSpellInfo, bTriggered);
}
void ScriptedAI::DoPlaySoundToSet(WorldObject* pSource, uint32 uiSoundId)
{
if (!pSource)
{
return;
}
if (!GetSoundEntriesStore()->LookupEntry(uiSoundId))
{
script_error_log("Invalid soundId %u used in DoPlaySoundToSet (Source: TypeId %u, GUID %u)", uiSoundId, pSource->GetTypeId(), pSource->GetGUIDLow());
return;
}
pSource->PlayDirectSound(uiSoundId);
}
Creature* ScriptedAI::DoSpawnCreature(uint32 uiId, float fX, float fY, float fZ, float fAngle, uint32 uiType, uint32 uiDespawntime)
{
return m_creature->SummonCreature(uiId, m_creature->GetPositionX() + fX, m_creature->GetPositionY() + fY, m_creature->GetPositionZ() + fZ, fAngle, (TempSummonType)uiType, uiDespawntime);
}
SpellEntry const* ScriptedAI::SelectSpell(Unit* pTarget, int32 uiSchool, int32 iMechanic, SelectTarget selectTargets, uint32 uiPowerCostMin, uint32 uiPowerCostMax, float fRangeMin, float fRangeMax, SelectEffect selectEffects)
{
// No target so we can't cast
if (!pTarget)
{
return NULL;
}
// Silenced so we can't cast
if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
{
return NULL;
}
// Using the extended script system we first create a list of viable spells
SpellEntry const* apSpell[4];
memset(apSpell, 0, sizeof(SpellEntry*) * 4);
uint32 uiSpellCount = 0;
SpellEntry const* pTempSpell;
SpellRangeEntry const* pTempRange;
// Check if each spell is viable(set it to null if not)
for (uint8 i = 0; i < 4; ++i)
{
pTempSpell = GetSpellStore()->LookupEntry(m_creature->m_spells[i]);
// This spell doesn't exist
if (!pTempSpell)
{
continue;
}
// Targets and Effects checked first as most used restrictions
// Check the spell targets if specified
if (selectTargets && !(SpellSummary[m_creature->m_spells[i]].Targets & (1 << (selectTargets - 1))))
{
continue;
}
// Check the type of spell if we are looking for a specific spell type
if (selectEffects && !(SpellSummary[m_creature->m_spells[i]].Effects & (1 << (selectEffects - 1))))
{
continue;
}
// Check for school if specified
#if defined (TBC) || defined (WOTLK) || defined (CATA)
if (uiSchool >= 0 && pTempSpell->SchoolMask & uiSchool)
{ continue; }
#endif
// Check for spell mechanic if specified
#if defined (CATA)
if (iMechanic >= 0 && pTempSpell->GetMechanic() != (uint32)iMechanic)
#else
if (iMechanic >= 0 && pTempSpell->Mechanic != (uint32)iMechanic)
#endif
{
continue;
}
// Make sure that the spell uses the requested amount of power
#if defined (CATA)
if (uiPowerCostMin && pTempSpell->GetManaCost() < uiPowerCostMin)
#else
if (uiPowerCostMin && pTempSpell->manaCost < uiPowerCostMin)
#endif
{
continue;
}
#if defined (CATA)
if (uiPowerCostMax && pTempSpell->GetManaCost() > uiPowerCostMax)
#else
if (uiPowerCostMax && pTempSpell->manaCost > uiPowerCostMax)
#endif
{
continue;
}
// Continue if we don't have the mana to actually cast this spell
#if defined (CATA)
if (pTempSpell->GetManaCost() > m_creature->GetPower((Powers)pTempSpell->powerType))
#else
if (pTempSpell->manaCost > m_creature->GetPower((Powers)pTempSpell->powerType))
#endif
{
continue;
}
// Get the Range
pTempRange = GetSpellRangeStore()->LookupEntry(pTempSpell->rangeIndex);
// Spell has invalid range store so we can't use it
if (!pTempRange)
{
continue;
}
// Check if the spell meets our range requirements
if (fRangeMin && pTempRange->maxRange < fRangeMin)
{
continue;
}
if (fRangeMax && pTempRange->maxRange > fRangeMax)
{
continue;
}
// Check if our target is in range
if (m_creature->IsWithinDistInMap(pTarget, pTempRange->minRange) || !m_creature->IsWithinDistInMap(pTarget, pTempRange->maxRange))
{
continue;
}
// All good so lets add it to the spell list
apSpell[uiSpellCount] = pTempSpell;
++uiSpellCount;
}
// We got our usable spells so now lets randomly pick one
if (!uiSpellCount)
{
return NULL;
}
return apSpell[urand(0, uiSpellCount - 1)];
}
bool ScriptedAI::CanCast(Unit* pTarget, SpellEntry const* pSpellEntry, bool bTriggered)
{
// No target so we can't cast
if (!pTarget || !pSpellEntry)
{
return false;
}
// Silenced so we can't cast
if (!bTriggered && m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_SILENCED))
{
return false;
}
// Check for power
#if defined (CATA)
if (!bTriggered && m_creature->GetPower((Powers)pSpellEntry->powerType) < pSpellEntry->GetManaCost())
#else
if (!bTriggered && m_creature->GetPower((Powers)pSpellEntry->powerType) < pSpellEntry->manaCost)
#endif
{
return false;
}
SpellRangeEntry const* pTempRange = GetSpellRangeStore()->LookupEntry(pSpellEntry->rangeIndex);
// Spell has invalid range store so we can't use it
if (!pTempRange)
{
return false;
}
// Unit is out of range of this spell
if (!m_creature->IsInRange(pTarget, pTempRange->minRange, pTempRange->maxRange))
{
return false;
}
return true;
}
void FillSpellSummary()
{
SpellSummary = new TSpellSummary[GetSpellStore()->GetNumRows()];
SpellEntry const* pTempSpell;
for (uint32 i = 0; i < GetSpellStore()->GetNumRows(); ++i)
{
SpellSummary[i].Effects = 0;
SpellSummary[i].Targets = 0;
pTempSpell = GetSpellStore()->LookupEntry(i);
// This spell doesn't exist
if (!pTempSpell)
{
continue;
}
for (uint8 j = 0; j < 3; ++j)
{
#if defined (CATA)
SpellEffectEntry const* pSpellEffect = pTempSpell->GetSpellEffect(SpellEffectIndex(j));
if (!pSpellEffect)
continue;
#endif
// Spell targets self
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SELF)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SELF - 1);
}
// Spell targets a single enemy
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CHAIN_DAMAGE ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CURRENT_ENEMY_COORDINATES)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_ENEMY - 1);
}
// Spell targets AoE at enemy
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CASTER_COORDINATES ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_ENEMY - 1);
}
// Spell targets an enemy
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CHAIN_DAMAGE ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CURRENT_ENEMY_COORDINATES ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CASTER_COORDINATES ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_CHAIN_DAMAGE ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CURRENT_ENEMY_COORDINATES ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_INSTANT ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_ENEMY_IN_AREA_CHANNELED)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_ENEMY - 1);
}
// Spell targets a single friend(or self)
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SELF ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SINGLE_FRIEND ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SINGLE_PARTY)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_SINGLE_FRIEND - 1);
}
// Spell targets aoe friends
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_PARTY_AROUND_CASTER ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_AREAEFFECT_PARTY ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CASTER_COORDINATES)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_AOE_FRIEND - 1);
}
// Spell targets any friend(or self)
#if defined (CATA)
if (pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SELF ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SINGLE_FRIEND ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_SINGLE_PARTY ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_ALL_PARTY_AROUND_CASTER ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_AREAEFFECT_PARTY ||
pTempSpell->GetEffectImplicitTargetAByIndex(SpellEffectIndex(j)) == TARGET_CASTER_COORDINATES)
#else
if (pTempSpell->EffectImplicitTargetA[j] == TARGET_SELF ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_FRIEND ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_SINGLE_PARTY ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_ALL_PARTY_AROUND_CASTER ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_AREAEFFECT_PARTY ||
pTempSpell->EffectImplicitTargetA[j] == TARGET_CASTER_COORDINATES)
#endif
{
SpellSummary[i].Targets |= 1 << (SELECT_TARGET_ANY_FRIEND - 1);
}
// Make sure that this spell includes a damage effect
#if defined (CATA)
if (pSpellEffect->Effect == SPELL_EFFECT_SCHOOL_DAMAGE ||
pSpellEffect->Effect == SPELL_EFFECT_INSTAKILL ||
pSpellEffect->Effect == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
pSpellEffect->Effect == SPELL_EFFECT_HEALTH_LEECH)
#else
if (pTempSpell->Effect[j] == SPELL_EFFECT_SCHOOL_DAMAGE ||
pTempSpell->Effect[j] == SPELL_EFFECT_INSTAKILL ||
pTempSpell->Effect[j] == SPELL_EFFECT_ENVIRONMENTAL_DAMAGE ||
pTempSpell->Effect[j] == SPELL_EFFECT_HEALTH_LEECH)
#endif
{
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_DAMAGE - 1);
}
// Make sure that this spell includes a healing effect (or an apply aura with a periodic heal)
#if defined (CATA)
if (pSpellEffect->Effect == SPELL_EFFECT_HEAL ||
pSpellEffect->Effect == SPELL_EFFECT_HEAL_MAX_HEALTH ||
pSpellEffect->Effect == SPELL_EFFECT_HEAL_MECHANICAL ||
(pSpellEffect->Effect == SPELL_EFFECT_APPLY_AURA && pTempSpell->GetEffectApplyAuraNameByIndex(SpellEffectIndex(j)) == 8))
#else
if (pTempSpell->Effect[j] == SPELL_EFFECT_HEAL ||
pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MAX_HEALTH ||
pTempSpell->Effect[j] == SPELL_EFFECT_HEAL_MECHANICAL ||
(pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA && pTempSpell->EffectApplyAuraName[j] == 8))
#endif
{
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_HEALING - 1);
}
// Make sure that this spell applies an aura
#if defined (CATA)
if (pSpellEffect->Effect == SPELL_EFFECT_APPLY_AURA)
#else
if (pTempSpell->Effect[j] == SPELL_EFFECT_APPLY_AURA)
#endif
{
SpellSummary[i].Effects |= 1 << (SELECT_EFFECT_AURA - 1);
}
}
}
}
void ScriptedAI::DoResetThreat()
{
if (!m_creature->CanHaveThreatList() || m_creature->GetThreatManager().isThreatListEmpty())
{
script_error_log("DoResetThreat called for creature that either can not have threat list or has empty threat list (m_creature entry = %d)", m_creature->GetEntry());
return;
}
ThreatList const& tList = m_creature->GetThreatManager().getThreatList();
for (ThreatList::const_iterator itr = tList.begin(); itr != tList.end(); ++itr)
{
Unit* pUnit = m_creature->GetMap()->GetUnit((*itr)->getUnitGuid());
if (pUnit && m_creature->GetThreatManager().getThreat(pUnit))
{
m_creature->GetThreatManager().modifyThreatPercent(pUnit, -100);
}
}
}
void ScriptedAI::DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, float fO)
{
if (!pUnit)
{
return;
}
if (pUnit->GetTypeId() != TYPEID_PLAYER)
{
script_error_log("%s tried to teleport non-player (%s) to x: %f y:%f z: %f o: %f. Aborted.", m_creature->GetGuidStr().c_str(), pUnit->GetGuidStr().c_str(), fX, fY, fZ, fO);
return;
}
((Player*)pUnit)->TeleportTo(pUnit->GetMapId(), fX, fY, fZ, fO, TELE_TO_NOT_LEAVE_COMBAT);
}
Unit* ScriptedAI::DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff)
{
Unit* pUnit = NULL;
MaNGOS::MostHPMissingInRangeCheck u_check(m_creature, fRange, uiMinHPDiff);
MaNGOS::UnitLastSearcher<MaNGOS::MostHPMissingInRangeCheck> searcher(pUnit, u_check);
Cell::VisitGridObjects(m_creature, searcher, fRange);
return pUnit;
}
std::list<Creature*> ScriptedAI::DoFindFriendlyCC(float fRange)
{
std::list<Creature*> pList;
MaNGOS::FriendlyCCedInRangeCheck u_check(m_creature, fRange);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyCCedInRangeCheck> searcher(pList, u_check);
Cell::VisitGridObjects(m_creature, searcher, fRange);
return pList;
}
std::list<Creature*> ScriptedAI::DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId)
{
std::list<Creature*> pList;
MaNGOS::FriendlyMissingBuffInRangeCheck u_check(m_creature, fRange, uiSpellId);
MaNGOS::CreatureListSearcher<MaNGOS::FriendlyMissingBuffInRangeCheck> searcher(pList, u_check);
Cell::VisitGridObjects(m_creature, searcher, fRange);
return pList;
}
Player* ScriptedAI::GetPlayerAtMinimumRange(float fMinimumRange)
{
Player* pPlayer = NULL;
MaNGOS::AnyPlayerInObjectRangeCheck check(m_creature, fMinimumRange);
MaNGOS::PlayerSearcher<MaNGOS::AnyPlayerInObjectRangeCheck> searcher(pPlayer, check);
Cell::VisitWorldObjects(m_creature, searcher, fMinimumRange);
return pPlayer;
}
void ScriptedAI::SetEquipmentSlots(bool bLoadDefault, int32 iMainHand, int32 iOffHand, int32 iRanged)
{
if (bLoadDefault)
{
m_creature->LoadEquipment(m_creature->GetCreatureInfo()->EquipmentTemplateId, true);
return;
}
if (iMainHand >= 0)
{
m_creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_0, iMainHand);
}
if (iOffHand >= 0)
{
m_creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_1, iOffHand);
}
if (iRanged >= 0)
{
m_creature->SetVirtualItem(VIRTUAL_ITEM_SLOT_2, iRanged);
}
}
// Hacklike storage used for misc creatures that are expected to evade of outside of a certain area.
// It is assumed the information is found elswehere and can be handled by mangos. So far no luck finding such information/way to extract it.
enum
{
#if defined (CLASSIC)
NPC_BROODLORD = 12017
#endif
#if defined (TBC) || defined (WOTLK) || defined (CATA)
NPC_BROODLORD = 12017,
NPC_VOID_REAVER = 19516,
NPC_JAN_ALAI = 23578,
NPC_SARTHARION = 28860,
NPC_TALON_KING_IKISS = 18473,
NPC_KARGATH_BLADEFIST = 16808,
#endif
#if defined (WOTLK) || defined (CATA)
NPC_ANUBARAK = 29120,
NPC_SINDRAGOSA = 36853,
NPC_ZARITHRIAN = 39746,
#endif
};
bool ScriptedAI::EnterEvadeIfOutOfCombatArea(const uint32 uiDiff)
{
if (m_uiEvadeCheckCooldown < uiDiff)
{
m_uiEvadeCheckCooldown = 2500;
}
else
{
m_uiEvadeCheckCooldown -= uiDiff;
return false;
}
if (m_creature->IsInEvadeMode() || !m_creature->getVictim())
{
return false;
}
float fX = m_creature->GetPositionX();
float fY = m_creature->GetPositionY();
float fZ = m_creature->GetPositionZ();
switch (m_creature->GetEntry())
{
case NPC_BROODLORD: // broodlord (not move down stairs)
if (fZ > 448.60f)
{
return false;
}
break;
#if defined (TBC) || defined (WOTLK) || defined (CATA)
case NPC_VOID_REAVER: // void reaver (calculate from center of room)
if (m_creature->GetDistance2d(432.59f, 371.93f) < 105.0f)
{ return false; }
break;
case NPC_JAN_ALAI: // jan'alai (calculate by Z)
if (fZ > 12.0f)
{ return false; }
break;
case NPC_SARTHARION: // sartharion (calculate box)
if (fX > 3218.86f && fX < 3275.69f && fY < 572.40f && fY > 484.68f)
{ return false; }
break;
case NPC_TALON_KING_IKISS:
{
float fX, fY, fZ;
m_creature->GetRespawnCoord(fX, fY, fZ);
if (m_creature->GetDistance2d(fX, fY) < 70.0f)
{ return false; }
break;
}
case NPC_KARGATH_BLADEFIST:
if (fX < 255.0f && fX > 205.0f)
{ return false; }
break;
#endif
#if defined (WOTLK) || defined (CATA)
case NPC_ANUBARAK:
if (fY < 281.0f && fY > 228.0f)
return false;
break;
case NPC_SINDRAGOSA:
if (fX > 4314.0f)
return false;
break;
case NPC_ZARITHRIAN:
if (fZ > 87.0f)
return false;
break;
#endif
default:
script_error_log("EnterEvadeIfOutOfCombatArea used for creature entry %u, but does not have any definition.", m_creature->GetEntry());
return false;
}
EnterEvadeMode();
return true;
}
void Scripted_NoMovementAI::GetAIInformation(ChatHandler& reader)
{
reader.PSendSysMessage("Subclass of Scripted_NoMovementAI");
}
void Scripted_NoMovementAI::AttackStart(Unit* pWho)
{
#if defined (WOTLK) || defined (CATA)
if (!m_creature->CanInitiateAttack())
return;
#endif
if (pWho && m_creature->Attack(pWho, true))
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
DoStartNoMovement(pWho);
}
}

View file

@ -0,0 +1,262 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_CREATURE_H
#define SC_CREATURE_H
#include "Chat.h"
#include "DBCStores.h" // Mostly only used the Lookup acces, but a few cases really do use the DBC-Stores
// Spell targets used by SelectSpell
enum SelectTarget
{
SELECT_TARGET_DONTCARE = 0, // All target types allowed
SELECT_TARGET_SELF, // Only Self casting
SELECT_TARGET_SINGLE_ENEMY, // Only Single Enemy
SELECT_TARGET_AOE_ENEMY, // Only AoE Enemy
SELECT_TARGET_ANY_ENEMY, // AoE or Single Enemy
SELECT_TARGET_SINGLE_FRIEND, // Only Single Friend
SELECT_TARGET_AOE_FRIEND, // Only AoE Friend
SELECT_TARGET_ANY_FRIEND, // AoE or Single Friend
};
// Spell Effects used by SelectSpell
enum SelectEffect
{
SELECT_EFFECT_DONTCARE = 0, // All spell effects allowed
SELECT_EFFECT_DAMAGE, // Spell does damage
SELECT_EFFECT_HEALING, // Spell does healing
SELECT_EFFECT_AURA, // Spell applies an aura
};
enum SCEquip
{
EQUIP_NO_CHANGE = -1,
EQUIP_UNEQUIP = 0
};
/// Documentation of CreatureAI functions can be found in MaNGOS source
// Only list them here again to ensure that the interface between SD3 and the core is not changed unnoticed
struct ScriptedAI : public CreatureAI
{
public:
explicit ScriptedAI(Creature* pCreature);
~ScriptedAI() {}
// *************
// CreatureAI Functions
// *************
// == Information about AI ========================
// Get information about the AI
void GetAIInformation(ChatHandler& reader) override;
// == Reactions At =================================
// Called if IsVisible(Unit* pWho) is true at each relative pWho move
void MoveInLineOfSight(Unit* pWho) override;
// Called for reaction at enter to combat if not in combat yet (enemy can be NULL)
void EnterCombat(Unit* pEnemy) override;
// Called at stoping attack by any attacker
void EnterEvadeMode() override;
// Called when reached home after MoveTargetHome (in evade)
void JustReachedHome() override {}
// Called at any Heal received
void HealedBy(Unit* /*pHealer*/, uint32& /*uiHealedAmount*/) override {}
// Called at any Damage to any victim (before damage apply)
void DamageDeal(Unit* /*pDoneTo*/, uint32& /*uiDamage*/) override {}
// Called at any Damage from any attacker (before damage apply)
void DamageTaken(Unit* /*pDealer*/, uint32& /*uiDamage*/) override {}
// Called at creature death
void JustDied(Unit* /*pKiller*/) override {}
// Called when the corpse of this creature gets removed
void CorpseRemoved(uint32& /*uiRespawnDelay*/) override {}
// Called when a summoned creature is killed
void SummonedCreatureJustDied(Creature* /*pSummoned*/) override {}
// Called at creature killing another unit
void KilledUnit(Unit* /*pVictim*/) override {}
// Called when owner of m_creature (if m_creature is PROTECTOR_PET) kills a unit
void OwnerKilledUnit(Unit* /*pVictim*/) override {}
// Called when the creature successfully summons a creature
void JustSummoned(Creature* /*pSummoned*/) override {}
// Called when the creature successfully summons a gameobject
void JustSummoned(GameObject* /*pGo*/) override {}
// Called when a summoned creature gets TemporarySummon::UnSummon ed
void SummonedCreatureDespawn(Creature* /*pSummoned*/) override {}
// Called when hit by a spell
void SpellHit(Unit* /*pCaster*/, const SpellEntry* /*pSpell*/) override {}
// Called when spell hits creature's target
void SpellHitTarget(Unit* /*pTarget*/, const SpellEntry* /*pSpell*/) override {}
// Called when the creature is target of hostile action: swing, hostile spell landed, fear/etc)
/// This will by default result in reattacking, if the creature has no victim
void AttackedBy(Unit* pAttacker) override { CreatureAI::AttackedBy(pAttacker); }
// Called when creature is respawned (for reseting variables)
void JustRespawned() override;
// Called at waypoint reached or point movement finished
void MovementInform(uint32 /*uiMovementType*/, uint32 /*uiData*/) override {}
// Called if a temporary summoned of m_creature reach a move point
void SummonedMovementInform(Creature* /*pSummoned*/, uint32 /*uiMotionType*/, uint32 /*uiData*/) override {}
// Called at text emote receive from player
void ReceiveEmote(Player* /*pPlayer*/, uint32 /*uiEmote*/) override {}
// Called at each attack of m_creature by any victim
void AttackStart(Unit* pWho) override;
// Called at World update tick
void UpdateAI(const uint32) override;
// Called when an AI Event is received
void ReceiveAIEvent(AIEventType /*eventType*/, Creature* /*pSender*/, Unit* /*pInvoker*/, uint32 /*uiMiscValue*/) override {}
// == State checks =================================
// Check if unit is visible for MoveInLineOfSight
bool IsVisible(Unit* pWho) const override;
// Called when victim entered water and creature can not enter water
bool canReachByRangeAttack(Unit* pWho) override { return CreatureAI::canReachByRangeAttack(pWho); }
// *************
// Variables
// *************
// *************
// Pure virtual functions
// *************
/**
* This is a SD3 internal function, that every AI must implement
* Usally used to reset combat variables
* Called by default on creature evade and respawn
* In most scripts also called in the constructor of the AI
*/
void Reset() override {}
/// Called at creature EnterCombat with an enemy
/**
* This is a SD3 internal function
* Called by default on creature EnterCombat with an enemy
*/
virtual void Aggro(Unit* /*pWho*/) {}
// *************
// AI Helper Functions
// *************
// Start movement toward victim
void DoStartMovement(Unit* pVictim, float fDistance = 0, float fAngle = 0);
// Start no movement on victim
void DoStartNoMovement(Unit* pVictim);
// Stop attack of current victim
void DoStopAttack();
// Cast spell by Id
void DoCast(Unit* pTarget, uint32 uiSpellId, bool bTriggered = false);
// Cast spell by spell info
void DoCastSpell(Unit* pTarget, SpellEntry const* pSpellInfo, bool bTriggered = false);
// Plays a sound to all nearby players
void DoPlaySoundToSet(WorldObject* pSource, uint32 uiSoundId);
// Drops all threat to 0%. Does not remove enemies from the threat list
void DoResetThreat();
// Teleports a player without dropping threat (only teleports to same map)
void DoTeleportPlayer(Unit* pUnit, float fX, float fY, float fZ, float fO);
// Returns friendly unit with the most amount of hp missing from max hp
Unit* DoSelectLowestHpFriendly(float fRange, uint32 uiMinHPDiff = 1);
// Returns a list of friendly CC'd units within range
std::list<Creature*> DoFindFriendlyCC(float fRange);
// Returns a list of all friendly units missing a specific buff within range
std::list<Creature*> DoFindFriendlyMissingBuff(float fRange, uint32 uiSpellId);
// Return a player with at least minimumRange from m_creature
Player* GetPlayerAtMinimumRange(float fMinimumRange);
// Spawns a creature relative to m_creature
Creature* DoSpawnCreature(uint32 uiId, float fX, float fY, float fZ, float fAngle, uint32 uiType, uint32 uiDespawntime);
// Returns spells that meet the specified criteria from the creatures spell list
SpellEntry const* SelectSpell(Unit* pTarget, int32 uiSchool, int32 iMechanic, SelectTarget selectTargets, uint32 uiPowerCostMin, uint32 uiPowerCostMax, float fRangeMin, float fRangeMax, SelectEffect selectEffect);
// Checks if you can cast the specified spell
bool CanCast(Unit* pTarget, SpellEntry const* pSpell, bool bTriggered = false);
void SetEquipmentSlots(bool bLoadDefault, int32 iMainHand = EQUIP_NO_CHANGE, int32 iOffHand = EQUIP_NO_CHANGE, int32 iRanged = EQUIP_NO_CHANGE);
bool EnterEvadeIfOutOfCombatArea(const uint32 uiDiff);
// a wrapper for aggro list browsing
Unit *SelectAttackTarget(AttackingTarget type, uint32 position, uint32 spellId = 0, uint32 selectFlags = 0) { return m_creature->SelectAttackingTarget(type, position, spellId, selectFlags); }
private:
uint32 m_uiEvadeCheckCooldown;
};
struct Scripted_NoMovementAI : public ScriptedAI
{
Scripted_NoMovementAI(Creature* pCreature) : ScriptedAI(pCreature)
{
SetCombatMovement(false);
}
void GetAIInformation(ChatHandler& reader) override;
// Called at each attack of m_creature by any victim
void AttackStart(Unit* pWho) override;
};
#endif

View file

@ -0,0 +1,186 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_GOSSIP_H
#define SC_GOSSIP_H
#include "Player.h"
#include "GossipDef.h"
#include "QuestDef.h"
// Gossip Item Text
#define GOSSIP_TEXT_BROWSE_GOODS "I'd like to browse your goods."
#define GOSSIP_TEXT_TRAIN "Train me!"
#define GOSSIP_TEXT_BANK "The bank"
#define GOSSIP_TEXT_IRONFORGE_BANK "The bank of Ironforge"
#define GOSSIP_TEXT_STORMWIND_BANK "The bank of Stormwind"
#define GOSSIP_TEXT_WINDRIDER "The wind rider master"
#define GOSSIP_TEXT_GRYPHON "The gryphon master"
#define GOSSIP_TEXT_BATHANDLER "The bat handler"
#define GOSSIP_TEXT_HIPPOGRYPH "The hippogryph master"
#define GOSSIP_TEXT_ZEPPLINMASTER "The zeppelin master"
#define GOSSIP_TEXT_DEEPRUNTRAM "The Deeprun Tram"
#define GOSSIP_TEXT_FERRY "The Rut'theran Ferry"
#define GOSSIP_TEXT_FLIGHTMASTER "The flight master"
#define GOSSIP_TEXT_AUCTIONHOUSE "The auction house"
#define GOSSIP_TEXT_GUILDMASTER "The guild master"
#define GOSSIP_TEXT_INN "The inn"
#define GOSSIP_TEXT_MAILBOX "The mailbox"
#define GOSSIP_TEXT_STABLEMASTER "The stable master"
#define GOSSIP_TEXT_WEAPONMASTER "The weapon master"
#define GOSSIP_TEXT_OFFICERS "The officers' lounge"
#define GOSSIP_TEXT_BATTLEMASTER "The battlemaster"
#define GOSSIP_TEXT_BARBER "Barber"
#define GOSSIP_TEXT_CLASSTRAINER "A class trainer"
#define GOSSIP_TEXT_PROFTRAINER "A profession trainer"
#define GOSSIP_TEXT_LEXICON "Lexicon of Power"
#define GOSSIP_TEXT_ALTERACVALLEY "Alterac Valley"
#define GOSSIP_TEXT_ARATHIBASIN "Arathi Basin"
#define GOSSIP_TEXT_WARSONGULCH "Warsong Gulch"
#define GOSSIP_TEXT_ARENA "Arena"
#define GOSSIP_TEXT_EYEOFTHESTORM "Eye of The Storm"
#define GOSSIP_TEXT_STRANDOFANCIENT "Strand of the Ancients"
#define GOSSIP_TEXT_DEATH_KNIGHT "Death Knight"
#define GOSSIP_TEXT_DRUID "Druid"
#define GOSSIP_TEXT_HUNTER "Hunter"
#define GOSSIP_TEXT_PRIEST "Priest"
#define GOSSIP_TEXT_ROGUE "Rogue"
#define GOSSIP_TEXT_WARRIOR "Warrior"
#define GOSSIP_TEXT_PALADIN "Paladin"
#define GOSSIP_TEXT_SHAMAN "Shaman"
#define GOSSIP_TEXT_MAGE "Mage"
#define GOSSIP_TEXT_WARLOCK "Warlock"
#define GOSSIP_TEXT_ALCHEMY "Alchemy"
#define GOSSIP_TEXT_BLACKSMITHING "Blacksmithing"
#define GOSSIP_TEXT_COOKING "Cooking"
#define GOSSIP_TEXT_ENCHANTING "Enchanting"
#define GOSSIP_TEXT_ENGINEERING "Engineering"
#define GOSSIP_TEXT_FIRSTAID "First Aid"
#define GOSSIP_TEXT_HERBALISM "Herbalism"
#define GOSSIP_TEXT_LEATHERWORKING "Leatherworking"
#define GOSSIP_TEXT_TAILORING "Tailoring"
#define GOSSIP_TEXT_MINING "Mining"
#define GOSSIP_TEXT_FISHING "Fishing"
#define GOSSIP_TEXT_SKINNING "Skinning"
#define GOSSIP_TEXT_JEWELCRAFTING "Jewelcrafting"
#define GOSSIP_TEXT_INSCRIPTION "Inscription"
enum
{
// Skill defines
TRADESKILL_ALCHEMY = 1,
TRADESKILL_BLACKSMITHING = 2,
TRADESKILL_COOKING = 3,
TRADESKILL_ENCHANTING = 4,
TRADESKILL_ENGINEERING = 5,
TRADESKILL_FIRSTAID = 6,
TRADESKILL_HERBALISM = 7,
TRADESKILL_LEATHERWORKING = 8,
TRADESKILL_POISONS = 9,
TRADESKILL_TAILORING = 10,
TRADESKILL_MINING = 11,
TRADESKILL_FISHING = 12,
TRADESKILL_SKINNING = 13,
TRADESKILL_JEWLCRAFTING = 14,
TRADESKILL_INSCRIPTION = 15,
TRADESKILL_LEVEL_NONE = 0,
TRADESKILL_LEVEL_APPRENTICE = 1,
TRADESKILL_LEVEL_JOURNEYMAN = 2,
TRADESKILL_LEVEL_EXPERT = 3,
TRADESKILL_LEVEL_ARTISAN = 4,
TRADESKILL_LEVEL_MASTER = 5,
TRADESKILL_LEVEL_GRAND_MASTER = 6,
// Gossip defines
GOSSIP_ACTION_TRADE = 1,
GOSSIP_ACTION_TRAIN = 2,
GOSSIP_ACTION_TAXI = 3,
GOSSIP_ACTION_GUILD = 4,
GOSSIP_ACTION_BATTLE = 5,
GOSSIP_ACTION_BANK = 6,
GOSSIP_ACTION_INN = 7,
GOSSIP_ACTION_HEAL = 8,
GOSSIP_ACTION_TABARD = 9,
GOSSIP_ACTION_AUCTION = 10,
GOSSIP_ACTION_INN_INFO = 11,
GOSSIP_ACTION_UNLEARN = 12,
GOSSIP_ACTION_INFO_DEF = 1000,
GOSSIP_SENDER_MAIN = 1,
GOSSIP_SENDER_INN_INFO = 2,
GOSSIP_SENDER_INFO = 3,
GOSSIP_SENDER_SEC_PROFTRAIN = 4,
GOSSIP_SENDER_SEC_CLASSTRAIN = 5,
GOSSIP_SENDER_SEC_BATTLEINFO = 6,
GOSSIP_SENDER_SEC_BANK = 7,
GOSSIP_SENDER_SEC_INN = 8,
GOSSIP_SENDER_SEC_MAILBOX = 9,
GOSSIP_SENDER_SEC_STABLEMASTER = 10
};
extern uint32 GetSkillLevel(Player* pPlayer, uint32 uiSkill);
// Defined fuctions to use with player.
// This fuction add's a menu item,
// Icon Id
// Text
// Sender(this is to identify the current Menu with this item)
// Option id (identifies this Menu Item)
// Text to be displayed in pop up box
// Money value in pop up box
// Coded
#define ADD_GOSSIP_ITEM(uiIcon, chrText, uiSender, uiOptionId) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, chrText, uiSender, uiOptionId, "", 0)
#define ADD_GOSSIP_ITEM_ID(uiIcon, iTextId, uiSender, uiOptionId) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, iTextId, uiSender, uiOptionId, 0, 0)
#if defined (CLASSIC)
#define ADD_GOSSIP_ITEM_EXTENDED(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, uiBoxMoney, bCode) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, /*uiBoxMoney,*/ bCode)
#else
#define ADD_GOSSIP_ITEM_EXTENDED(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, uiBoxMoney, bCode) PlayerTalkClass->GetGossipMenu().AddMenuItem(uiIcon, chrText, uiSender, uiOptionId, chrBoxMessage, uiBoxMoney, bCode)
#endif
// This fuction Sends the current menu to show to client
// uiTextId - NPCTEXTID (uint32)
// guid - npc guid (ObjectGuid)
#define SEND_GOSSIP_MENU(uiTextId, guid) PlayerTalkClass->SendGossipMenu(uiTextId, guid)
// Closes the Menu
#define CLOSE_GOSSIP_MENU() PlayerTalkClass->CloseGossip()
// Fuctions to send NPC lists
// a - is always the npc guid (ObjectGuid)
#define SEND_VENDORLIST(a) GetSession()->SendListInventory(a)
#define SEND_TRAINERLIST(a) GetSession()->SendTrainerList(a)
#define SEND_BANKERLIST(a) GetSession()->SendShowBank(a)
#define SEND_TABARDLIST(a) GetSession()->SendTabardVendorActivate(a)
#define SEND_TAXILIST(a) GetSession()->SendTaxiStatus(a)
#endif

View file

@ -0,0 +1,74 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "precompiled.h"
#include "Cell.h"
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
// return closest GO in grid, with range from pSource
GameObject* GetClosestGameObjectWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
{
GameObject* pGo = NULL;
MaNGOS::NearestGameObjectEntryInObjectRangeCheck go_check(*pSource, uiEntry, fMaxSearchRange);
MaNGOS::GameObjectLastSearcher<MaNGOS::NearestGameObjectEntryInObjectRangeCheck> searcher(pGo, go_check);
Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
return pGo;
}
// return closest creature alive in grid, with range from pSource
Creature* GetClosestCreatureWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange, bool bOnlyAlive/*=true*/, bool bOnlyDead/*=false*/, bool bExcludeSelf/*=false*/)
{
Creature* pCreature = NULL;
MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck creature_check(*pSource, uiEntry, bOnlyAlive, bOnlyDead, fMaxSearchRange, bExcludeSelf);
MaNGOS::CreatureLastSearcher<MaNGOS::NearestCreatureEntryWithLiveStateInObjectRangeCheck> searcher(pCreature, creature_check);
Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
return pCreature;
}
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList , WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
{
MaNGOS::GameObjectEntryInPosRangeCheck check(*pSource, uiEntry, pSource->GetPositionX(), pSource->GetPositionY(), pSource->GetPositionZ(), fMaxSearchRange);
MaNGOS::GameObjectListSearcher<MaNGOS::GameObjectEntryInPosRangeCheck> searcher(lList, check);
Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
}
void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange)
{
MaNGOS::AllCreaturesOfEntryInRangeCheck check(pSource, uiEntry, fMaxSearchRange);
MaNGOS::CreatureListSearcher<MaNGOS::AllCreaturesOfEntryInRangeCheck> searcher(lList, check);
Cell::VisitGridObjects(pSource, searcher, fMaxSearchRange);
}

View file

@ -0,0 +1,64 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_GRIDSEARCH_H
#define SC_GRIDSEARCH_H
#include "Object.h"
class GameObject;
class Creature;
struct ObjectDistanceOrder : public std::binary_function<const WorldObject, const WorldObject, bool>
{
const Unit* m_pSource;
ObjectDistanceOrder(const Unit* pSource) : m_pSource(pSource) {}
bool operator()(const WorldObject* pLeft, const WorldObject* pRight) const
{
return m_pSource->GetDistanceOrder(pLeft, pRight);
}
};
struct ObjectDistanceOrderReversed : public std::binary_function<const WorldObject, const WorldObject, bool>
{
const Unit* m_pSource;
ObjectDistanceOrderReversed(const Unit* pSource) : m_pSource(pSource) {}
bool operator()(const WorldObject* pLeft, const WorldObject* pRight) const
{
return !m_pSource->GetDistanceOrder(pLeft, pRight);
}
};
GameObject* GetClosestGameObjectWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
Creature* GetClosestCreatureWithEntry(WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange, bool bOnlyAlive = true, bool bOnlyDead = false, bool bExcludeSelf = false);
void GetGameObjectListWithEntryInGrid(std::list<GameObject*>& lList , WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
void GetCreatureListWithEntryInGrid(std::list<Creature*>& lList, WorldObject* pSource, uint32 uiEntry, float fMaxSearchRange);
#endif

View file

@ -0,0 +1,434 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "precompiled.h"
/**
Function that uses a door or a button
@param guid The ObjectGuid of the Door/ Button that will be used
@param uiWithRestoreTime (in seconds) if == 0 autoCloseTime will be used (if not 0 by default in *_template)
@param bUseAlternativeState Use to alternative state
*/
void ScriptedInstance::DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTime, bool bUseAlternativeState)
{
if (!guid)
{
return;
}
if (GameObject* pGo = instance->GetGameObject(guid))
{
#if defined (CLASSIC) || defined (TBC)
if (pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON)
#endif
#if defined (WOTLK) || defined (CATA)
if (pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR || pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON || pGo->GetGoType() == GAMEOBJECT_TYPE_TRAPDOOR)
#endif
{
if (pGo->getLootState() == GO_READY)
{
pGo->UseDoorOrButton(uiWithRestoreTime, bUseAlternativeState);
}
else if (pGo->getLootState() == GO_ACTIVATED)
{
pGo->ResetDoorOrButton();
}
}
else
{
script_error_log("Script call DoUseDoorOrButton, but gameobject entry %u is type %u.", pGo->GetEntry(), pGo->GetGoType());
}
}
}
/// Function that uses a door or button that is stored in m_mGoEntryGuidStore
void ScriptedInstance::DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTime /*= 0*/, bool bUseAlternativeState /*= false*/)
{
EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry);
if (find != m_mGoEntryGuidStore.end())
{
DoUseDoorOrButton(find->second, uiWithRestoreTime, bUseAlternativeState);
}
else
// Output log, possible reason is not added GO to storage, or not yet loaded
{
debug_log("SD3: Script call DoUseDoorOrButton(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
}
/**
Function that respawns a despawned GameObject with given time
@param guid The ObjectGuid of the GO that will be respawned
@param uiTimeToDespawn (in seconds) Despawn the GO after this time, default is a minute
*/
void ScriptedInstance::DoRespawnGameObject(ObjectGuid guid, uint32 uiTimeToDespawn)
{
if (!guid)
{
return;
}
if (GameObject* pGo = instance->GetGameObject(guid))
{
// not expect any of these should ever be handled
if (pGo->GetGoType() == GAMEOBJECT_TYPE_FISHINGNODE || pGo->GetGoType() == GAMEOBJECT_TYPE_DOOR ||
#if defined (CLASSIC) || defined (TBC)
pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON || pGo->GetGoType() == GAMEOBJECT_TYPE_TRAP)
#endif
#if defined (WOTLK) || defined (CATA)
pGo->GetGoType() == GAMEOBJECT_TYPE_BUTTON)
#endif
{
return;
}
if (pGo->isSpawned())
{
return;
}
pGo->SetRespawnTime(uiTimeToDespawn);
pGo->Refresh();
}
}
/// Function that uses a door or button that is stored in m_mGoEntryGuidStore
void ScriptedInstance::DoToggleGameObjectFlags(uint32 uiEntry, uint32 uiGOflags, bool bApply)
{
EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry);
if (find != m_mGoEntryGuidStore.end())
{
DoToggleGameObjectFlags(find->second, uiGOflags, bApply);
}
else
// Output log, possible reason is not added GO to storage, or not yet loaded
{
debug_log("SD3: Script call ToogleTameObjectFlags (by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
}
/**
Function that toggles the GO-flags of a GameObject
@param guid The ObjectGuid of the GO that will be respawned
@param uiGOflags Which GO-flags to toggle
@param bApply should the GO-flags be applied or removed?
*/
void ScriptedInstance::DoToggleGameObjectFlags(ObjectGuid guid, uint32 uiGOflags, bool bApply)
{
if (!guid)
{
return;
}
if (GameObject* pGo = instance->GetGameObject(guid))
{
if (bApply)
{
pGo->SetFlag(GAMEOBJECT_FLAGS, uiGOflags);
}
else
{
pGo->RemoveFlag(GAMEOBJECT_FLAGS, uiGOflags);
}
}
}
/// Function that respawns a despawned GO that is stored in m_mGoEntryGuidStore
void ScriptedInstance::DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespawn)
{
EntryGuidMap::iterator find = m_mGoEntryGuidStore.find(uiEntry);
if (find != m_mGoEntryGuidStore.end())
{
DoRespawnGameObject(find->second, uiTimeToDespawn);
}
else
// Output log, possible reason is not added GO to storage, or not yet loaded;
{
debug_log("SD3: Script call DoRespawnGameObject(by Entry), but no gameobject of entry %u was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
}
/**
Helper function to update a world state for all players in the map
@param uiStateId The WorldState that will be set for all players in the map
@param uiStateData The Value to which the State will be set to
*/
void ScriptedInstance::DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData)
{
Map::PlayerList const& lPlayers = instance->GetPlayers();
if (!lPlayers.isEmpty())
{
for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
{
if (Player* pPlayer = itr->getSource())
{
pPlayer->SendUpdateWorldState(uiStateId, uiStateData);
}
}
}
else
{
debug_log("SD3: DoUpdateWorldState attempt send data but no players in map.");
}
}
/// Get the first found Player* (with requested properties) in the map. Can return NULL.
Player* ScriptedInstance::GetPlayerInMap(bool bOnlyAlive /*=false*/, bool bCanBeGamemaster /*=true*/)
{
Map::PlayerList const& lPlayers = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
{
Player* pPlayer = itr->getSource();
if (pPlayer && (!bOnlyAlive || pPlayer->IsAlive()) && (bCanBeGamemaster || !pPlayer->isGameMaster()))
{
return pPlayer;
}
}
return NULL;
}
/// Returns a pointer to a loaded GameObject that was stored in m_mGoEntryGuidStore. Can return NULL
GameObject* ScriptedInstance::GetSingleGameObjectFromStorage(uint32 uiEntry) const
{
EntryGuidMap::const_iterator find = m_mGoEntryGuidStore.find(uiEntry);
if (find != m_mGoEntryGuidStore.end())
{
return instance->GetGameObject(find->second);
}
// Output log, possible reason is not added GO to map, or not yet loaded;
script_error_log("Script requested gameobject with entry %u, but no gameobject of this entry was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
return NULL;
}
/// Returns a pointer to a loaded Creature that was stored in m_mGoEntryGuidStore. Can return NULL
Creature* ScriptedInstance::GetSingleCreatureFromStorage(uint32 uiEntry, bool bSkipDebugLog /*=false*/) const
{
EntryGuidMap::const_iterator find = m_mNpcEntryGuidStore.find(uiEntry);
if (find != m_mNpcEntryGuidStore.end())
{
return instance->GetCreature(find->second);
}
// Output log, possible reason is not added GO to map, or not yet loaded;
if (!bSkipDebugLog)
{
script_error_log("Script requested creature with entry %u, but no npc of this entry was created yet, or it was not stored by script for map %u.", uiEntry, instance->GetId());
}
return NULL;
}
#if defined (WOTLK) || defined (CATA)
/**
Helper function to start a timed achievement criteria for players in the map
@param criteriaType The Type that is required to complete the criteria, see enum AchievementCriteriaTypes in MaNGOS
@param uiTimedCriteriaMiscId The ID that identifies how the criteria is started
*/
void ScriptedInstance::DoStartTimedAchievement(AchievementCriteriaTypes criteriaType, uint32 uiTimedCriteriaMiscId)
{
Map::PlayerList const& lPlayers = instance->GetPlayers();
if (!lPlayers.isEmpty())
{
for (Map::PlayerList::const_iterator itr = lPlayers.begin(); itr != lPlayers.end(); ++itr)
{
if (Player* pPlayer = itr->getSource())
pPlayer->StartTimedAchievementCriteria(criteriaType, uiTimedCriteriaMiscId);
}
}
else
debug_log("SD3: DoStartTimedAchievement attempt start achievements but no players in map.");
}
#endif
/**
Constructor for DialogueHelper
@param pDialogueArray The static const array of DialogueEntry holding the information about the dialogue. This array MUST be terminated by {0,0,0}
*/
DialogueHelper::DialogueHelper(DialogueEntry const* pDialogueArray) :
m_pInstance(NULL),
m_pDialogueArray(pDialogueArray),
m_pCurrentEntry(NULL),
m_pDialogueTwoSideArray(NULL),
m_pCurrentEntryTwoSide(NULL),
m_uiTimer(0),
m_bIsFirstSide(true),
m_bCanSimulate(false)
{}
/**
Constructor for DialogueHelper (Two Sides)
@param pDialogueTwoSideArray The static const array of DialogueEntryTwoSide holding the information about the dialogue. This array MUST be terminated by {0,0,0,0,0}
*/
DialogueHelper::DialogueHelper(DialogueEntryTwoSide const* pDialogueTwoSideArray) :
m_pInstance(NULL),
m_pDialogueArray(NULL),
m_pCurrentEntry(NULL),
m_pDialogueTwoSideArray(pDialogueTwoSideArray),
m_pCurrentEntryTwoSide(NULL),
m_uiTimer(0),
m_bIsFirstSide(true),
m_bCanSimulate(false)
{}
/**
Function to start a (part of a) dialogue
@param iTextEntry The TextEntry of the dialogue that will be started (must be always the entry of first side)
*/
void DialogueHelper::StartNextDialogueText(int32 iTextEntry)
{
// Find iTextEntry
bool bFound = false;
if (m_pDialogueArray) // One Side
{
for (DialogueEntry const* pEntry = m_pDialogueArray; pEntry->iTextEntry; ++pEntry)
{
if (pEntry->iTextEntry == iTextEntry)
{
m_pCurrentEntry = pEntry;
bFound = true;
break;
}
}
}
else // Two Sides
{
for (DialogueEntryTwoSide const* pEntry = m_pDialogueTwoSideArray; pEntry->iTextEntry; ++pEntry)
{
if (pEntry->iTextEntry == iTextEntry)
{
m_pCurrentEntryTwoSide = pEntry;
bFound = true;
break;
}
}
}
if (!bFound)
{
script_error_log("Script call DialogueHelper::StartNextDialogueText, but textEntry %i is not in provided dialogue (on map id %u)", iTextEntry, m_pInstance ? m_pInstance->instance->GetId() : 0);
return;
}
DoNextDialogueStep();
}
/// Internal helper function to do the actual say of a DialogueEntry
void DialogueHelper::DoNextDialogueStep()
{
// Last Dialogue Entry done?
if ((m_pCurrentEntry && !m_pCurrentEntry->iTextEntry) || (m_pCurrentEntryTwoSide && !m_pCurrentEntryTwoSide->iTextEntry))
{
m_uiTimer = 0;
return;
}
// Get Text, SpeakerEntry and Timer
int32 iTextEntry = 0;
uint32 uiSpeakerEntry = 0;
if (m_pDialogueArray) // One Side
{
uiSpeakerEntry = m_pCurrentEntry->uiSayerEntry;
iTextEntry = m_pCurrentEntry->iTextEntry;
m_uiTimer = m_pCurrentEntry->uiTimer;
}
else // Two Sides
{
// Second Entries can be 0, if they are the entry from first side will be taken
uiSpeakerEntry = !m_bIsFirstSide && m_pCurrentEntryTwoSide->uiSayerEntryAlt ? m_pCurrentEntryTwoSide->uiSayerEntryAlt : m_pCurrentEntryTwoSide->uiSayerEntry;
iTextEntry = !m_bIsFirstSide && m_pCurrentEntryTwoSide->iTextEntryAlt ? m_pCurrentEntryTwoSide->iTextEntryAlt : m_pCurrentEntryTwoSide->iTextEntry;
m_uiTimer = m_pCurrentEntryTwoSide->uiTimer;
}
// Simulate Case
if (uiSpeakerEntry && iTextEntry < 0)
{
// Use Speaker if directly provided
Creature* pSpeaker = GetSpeakerByEntry(uiSpeakerEntry);
if (m_pInstance && !pSpeaker) // Get Speaker from instance
{
if (m_bCanSimulate) // Simulate case
{
m_pInstance->DoOrSimulateScriptTextForThisInstance(iTextEntry, uiSpeakerEntry);
}
else
{
pSpeaker = m_pInstance->GetSingleCreatureFromStorage(uiSpeakerEntry);
}
}
if (pSpeaker)
{
DoScriptText(iTextEntry, pSpeaker);
}
}
JustDidDialogueStep(m_pDialogueArray ? m_pCurrentEntry->iTextEntry : m_pCurrentEntryTwoSide->iTextEntry);
// Increment position
if (m_pDialogueArray)
{
++m_pCurrentEntry;
}
else
{
++m_pCurrentEntryTwoSide;
}
}
/// Call this function within any DialogueUpdate method. This is required for saying next steps in a dialogue
void DialogueHelper::DialogueUpdate(uint32 uiDiff)
{
if (m_uiTimer)
{
if (m_uiTimer <= uiDiff)
{
DoNextDialogueStep();
}
else
{
m_uiTimer -= uiDiff;
}
}
}

View file

@ -0,0 +1,159 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_INSTANCE_H
#define SC_INSTANCE_H
#include "InstanceData.h"
#include "Map.h"
enum EncounterState
{
NOT_STARTED = 0,
IN_PROGRESS = 1,
FAIL = 2,
DONE = 3,
SPECIAL = 4
};
#define OUT_SAVE_INST_DATA debug_log("SD3: Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_SAVE_INST_DATA_COMPLETE debug_log("SD3: Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_LOAD_INST_DATA(a) debug_log("SD3: Loading Instance Data for Instance %s (Map %d, Instance Id %d). Input is '%s'", instance->GetMapName(), instance->GetId(), instance->GetInstanceId(), a)
#define OUT_LOAD_INST_DATA_COMPLETE debug_log("SD3: Instance Data for Instance %s (Map %d, Instance Id: %d) is loaded.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_LOAD_INST_DATA_FAIL script_error_log("Unable to load Instance Data for Instance %s (Map %d, Instance Id: %d).", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
class ScriptedInstance : public InstanceData
{
public:
ScriptedInstance(Map* pMap) : InstanceData(pMap) {}
~ScriptedInstance() {}
// Default accessor functions
GameObject* GetSingleGameObjectFromStorage(uint32 uiEntry) const;
Creature* GetSingleCreatureFromStorage(uint32 uiEntry, bool bSkipDebugLog = false) const;
// Change active state of doors or buttons
void DoUseDoorOrButton(ObjectGuid guid, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false);
void DoUseDoorOrButton(uint32 uiEntry, uint32 uiWithRestoreTime = 0, bool bUseAlternativeState = false);
// Respawns a GO having negative spawntimesecs in gameobject-table
void DoRespawnGameObject(ObjectGuid guid, uint32 uiTimeToDespawn = MINUTE);
void DoRespawnGameObject(uint32 uiEntry, uint32 uiTimeToDespawn = MINUTE);
// Toggle the flags of a GO
void DoToggleGameObjectFlags(ObjectGuid guid, uint32 uiGOflags, bool bApply);
void DoToggleGameObjectFlags(uint32 uiEntry, uint32 uiGOflags, bool bApply);
// Sends world state update to all players in instance
void DoUpdateWorldState(uint32 uiStateId, uint32 uiStateData);
// Get a Player from map
Player* GetPlayerInMap(bool bOnlyAlive = false, bool bCanBeGamemaster = true);
/// Wrapper for simulating map-wide text in this instance. It is expected that the Creature is stored in m_mNpcEntryGuidStore if loaded.
void DoOrSimulateScriptTextForThisInstance(int32 iTextEntry, uint32 uiCreatureEntry)
{
// Prevent debug output in GetSingleCreatureFromStorage
DoOrSimulateScriptTextForMap(iTextEntry, uiCreatureEntry, instance, GetSingleCreatureFromStorage(uiCreatureEntry, true));
}
#if defined (WOTLK) || defined (CATA)
// Starts a timed achievement criteria for all players in instance
void DoStartTimedAchievement(AchievementCriteriaTypes criteriaType, uint32 uiTimedCriteriaMiscId);
#endif
protected:
// Storage for GO-Guids and NPC-Guids
typedef std::map<uint32, ObjectGuid> EntryGuidMap;
EntryGuidMap m_mGoEntryGuidStore; ///< Store unique GO-Guids by entry
EntryGuidMap m_mNpcEntryGuidStore; ///< Store unique NPC-Guids by entry
};
// Class for world maps (May need additional zone-wide functions later on)
class ScriptedMap : public ScriptedInstance
{
public:
ScriptedMap(Map* pMap) : ScriptedInstance(pMap) {}
};
/// A static const array of this structure must be handled to DialogueHelper
struct DialogueEntry
{
int32 iTextEntry; ///< To be said text entry
uint32 uiSayerEntry; ///< Entry of the mob who should say
uint32 uiTimer; ///< Time delay until next text of array is said (0 stops)
};
/// A static const array of this structure must be handled to DialogueHelper
struct DialogueEntryTwoSide
{
int32 iTextEntry; ///< To be said text entry (first side)
uint32 uiSayerEntry; ///< Entry of the mob who should say (first side)
int32 iTextEntryAlt; ///< To be said text entry (second side)
uint32 uiSayerEntryAlt; ///< Entry of the mob who should say (second side)
uint32 uiTimer; ///< Time delay until next text of array is said (0 stops)
};
/// Helper class handling a dialogue given as static const array of DialogueEntry or DialogueEntryTwoSide
class DialogueHelper
{
public:
// The array MUST be terminated by {0,0,0}
DialogueHelper(DialogueEntry const* pDialogueArray);
// The array MUST be terminated by {0,0,0,0,0}
DialogueHelper(DialogueEntryTwoSide const* aDialogueTwoSide);
/// Function to initialize the dialogue helper for instances. If not used with instances, GetSpeakerByEntry MUST be overwritten to obtain the speakers
void InitializeDialogueHelper(ScriptedInstance* pInstance, bool bCanSimulateText = false) { m_pInstance = pInstance; m_bCanSimulate = bCanSimulateText; }
/// Set if take first entries or second entries
void SetDialogueSide(bool bIsFirstSide) { m_bIsFirstSide = bIsFirstSide; }
void StartNextDialogueText(int32 iTextEntry);
void DialogueUpdate(uint32 uiDiff);
protected:
/// Will be called when a dialogue step was done
virtual void JustDidDialogueStep(int32 /*iEntry*/) {}
/// Will be called to get a speaker, MUST be implemented if not used in instances
virtual Creature* GetSpeakerByEntry(uint32 /*uiEntry*/) { return NULL; }
private:
void DoNextDialogueStep();
ScriptedInstance* m_pInstance;
DialogueEntry const* m_pDialogueArray;
DialogueEntry const* m_pCurrentEntry;
DialogueEntryTwoSide const* m_pDialogueTwoSideArray;
DialogueEntryTwoSide const* m_pCurrentEntryTwoSide;
uint32 m_uiTimer;
bool m_bIsFirstSide;
bool m_bCanSimulate;
};
#endif

View file

@ -0,0 +1,27 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#include "precompiled.h"

View file

@ -0,0 +1,46 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef SC_PRECOMPILED_H
#define SC_PRECOMPILED_H
#include "system/ScriptDevMgr.h"
#include "Object.h"
#include "Unit.h"
#include "Creature.h"
#include "CreatureAI.h"
#include "GameObject.h"
#include "sc_creature.h"
#include "sc_gossip.h"
#include "sc_grid_searchers.h"
#include "sc_instance.h"
#include "SpellAuras.h"
#include "World.h"
// sc_gossip.h: ADD_GOSSIP_ITEM_EXTENDED outcommented box-money (Required until professions are fixed)
// sc_creature.cpp: Used in ScriptedAI::SelectSpell, outcommented SchoolMask
#endif

View file

@ -0,0 +1,145 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Battleground
* SD%Complete: 100
* SDComment: Spirit guides in battlegrounds will revive all players every 30 sec.
* SDCategory: Battlegrounds
* EndScriptData
*/
#include "precompiled.h"
/**
* Script Info
*
* Spirit guides in battlegrounds resurrecting many players at once every 30
* seconds through a channeled spell, which gets autocasted the whole time.
*
* If a spirit guide despawns all players around him will get teleported to
* the next spirit guide.
*
* this script handles gossipHello and JustDied also allows autocast of the
* channeled spell.
*/
enum
{
SPELL_SPIRIT_HEAL_CHANNEL = 22011, // Spirit Heal Channel
SPELL_SPIRIT_HEAL = 22012, // Spirit Heal
#if defined (TBC) || defined (WOTLK) || defined (CATA)
SPELL_SPIRIT_HEAL_MANA = 44535, // in battlegrounds player get this no-mana-cost-buff
#endif
SPELL_WAITING_TO_RESURRECT = 2584 // players who cancel this aura don't want a resurrection
};
struct npc_spirit_guide : public CreatureScript
{
npc_spirit_guide() : CreatureScript("npc_spirit_guide") {}
bool OnGossipHello(Player* pPlayer, Creature* /*pCreature*/) override
{
pPlayer->CastSpell(pPlayer, SPELL_WAITING_TO_RESURRECT, true);
return true;
}
struct npc_spirit_guideAI : public ScriptedAI
{
npc_spirit_guideAI(Creature* pCreature) : ScriptedAI(pCreature)
{
pCreature->SetActiveObjectState(true);
Reset();
}
void UpdateAI(const uint32 /*uiDiff*/) override
{
// auto cast the whole time this spell
if (!m_creature->GetCurrentSpell(CURRENT_CHANNELED_SPELL))
{
m_creature->CastSpell(m_creature, SPELL_SPIRIT_HEAL_CHANNEL, false);
}
}
void CorpseRemoved(uint32&) override
{
// TODO: would be better to cast a dummy spell
Map* pMap = m_creature->GetMap();
if (!pMap || !pMap->IsBattleGround())
{
return;
}
Map::PlayerList const& PlayerList = pMap->GetPlayers();
for (Map::PlayerList::const_iterator itr = PlayerList.begin(); itr != PlayerList.end(); ++itr)
{
Player* pPlayer = itr->getSource();
if (!pPlayer || !pPlayer->IsWithinDistInMap(m_creature, 20.0f) || !pPlayer->HasAura(SPELL_WAITING_TO_RESURRECT))
{
continue;
}
// repop player again - now this node won't be counted and another node is searched
pPlayer->RepopAtGraveyard();
}
}
#if defined (TBC) || defined (WOTLK) || defined (CATA)
void SpellHitTarget(Unit* pUnit, const SpellEntry* pSpellEntry) override
{
if (pSpellEntry->Id == SPELL_SPIRIT_HEAL && pUnit->GetTypeId() == TYPEID_PLAYER
&& pUnit->HasAura(SPELL_WAITING_TO_RESURRECT))
{ pUnit->CastSpell(pUnit, SPELL_SPIRIT_HEAL_MANA, true); }
}
#endif
};
#if defined (TBC) || defined (WOTLK) || defined (CATA)
CreatureAI* GetAI(Creature* pCreature) override
{
return new npc_spirit_guideAI(pCreature);
}
#endif
};
void AddSC_battleground()
{
Script *s;
s = new npc_spirit_guide();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "npc_spirit_guide";
//pNewScript->GetAI = &GetAI_npc_spirit_guide;
//pNewScript->pGossipHello = &GossipHello_npc_spirit_guide;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,45 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Alterac_Mountains
* SD%Complete: 0
* SDComment: Placeholder
* SDCategory: Alterac Mountains
* EndScriptData
*/
/**
* ContentData
* EndContentData
*/
#include "precompiled.h"
void AddSC_alterac_mountains()
{
}

View file

@ -0,0 +1,326 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Arathi Highlands
* SD%Complete: 100
* SDComment: Quest support: 660, 665
* SDCategory: Arathi Highlands
* EndScriptData
*/
/**
* ContentData
* npc_professor_phizzlethorpe
* npc_kinelory
* EndContentData
*/
#include "precompiled.h"
#include "escort_ai.h"
/*######
## npc_professor_phizzlethorpe
######*/
enum
{
SAY_PROGRESS_1 = -1000264,
SAY_PROGRESS_2 = -1000265,
SAY_PROGRESS_3 = -1000266,
EMOTE_PROGRESS_4 = -1000267,
SAY_AGGRO = -1000268,
SAY_PROGRESS_5 = -1000269,
SAY_PROGRESS_6 = -1000270,
SAY_PROGRESS_7 = -1000271,
EMOTE_PROGRESS_8 = -1000272,
SAY_PROGRESS_9 = -1000273,
QUEST_SUNKEN_TREASURE = 665,
ENTRY_VENGEFUL_SURGE = 2776
};
struct npc_professor_phizzlethorpe : public CreatureScript
{
npc_professor_phizzlethorpe() : CreatureScript("npc_professor_phizzlethorpe") {}
struct npc_professor_phizzlethorpeAI : public npc_escortAI
{
npc_professor_phizzlethorpeAI(Creature* pCreature) : npc_escortAI(pCreature) { }
void WaypointReached(uint32 uiPointId) override
{
Player* pPlayer = GetPlayerForEscort();
if (!pPlayer)
{
return;
}
switch (uiPointId)
{
case 4:
DoScriptText(SAY_PROGRESS_2, m_creature, pPlayer);
break;
case 5:
DoScriptText(SAY_PROGRESS_3, m_creature, pPlayer);
break;
case 8:
DoScriptText(EMOTE_PROGRESS_4, m_creature);
break;
case 9:
m_creature->SummonCreature(ENTRY_VENGEFUL_SURGE, -2056.41f, -2144.01f, 20.59f, 5.70f, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 600000);
m_creature->SummonCreature(ENTRY_VENGEFUL_SURGE, -2050.17f, -2140.02f, 19.54f, 5.17f, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 600000);
break;
case 10:
DoScriptText(SAY_PROGRESS_5, m_creature, pPlayer);
break;
case 11:
DoScriptText(SAY_PROGRESS_6, m_creature, pPlayer);
SetRun();
break;
case 19:
DoScriptText(SAY_PROGRESS_7, m_creature, pPlayer);
break;
case 20:
DoScriptText(EMOTE_PROGRESS_8, m_creature);
DoScriptText(SAY_PROGRESS_9, m_creature, pPlayer);
pPlayer->GroupEventHappens(QUEST_SUNKEN_TREASURE, m_creature);
break;
}
}
void Aggro(Unit* /*pWho*/) override
{
DoScriptText(SAY_AGGRO, m_creature);
}
void JustSummoned(Creature* pSummoned) override
{
pSummoned->AI()->AttackStart(m_creature);
}
};
bool OnQuestAccept(Player* pPlayer, Creature* pCreature, const Quest* pQuest) override
{
if (pQuest->GetQuestId() == QUEST_SUNKEN_TREASURE)
{
pCreature->SetFactionTemporary(FACTION_ESCORT_N_NEUTRAL_PASSIVE, TEMPFACTION_RESTORE_RESPAWN);
DoScriptText(SAY_PROGRESS_1, pCreature, pPlayer);
if (npc_professor_phizzlethorpeAI* pEscortAI = dynamic_cast<npc_professor_phizzlethorpeAI*>(pCreature->AI()))
{
pEscortAI->Start(false, pPlayer, pQuest, true);
}
}
return true;
}
CreatureAI* GetAI(Creature* pCreature) override
{
return new npc_professor_phizzlethorpeAI(pCreature);
}
};
/*######
## npc_kinelory
######*/
enum
{
SAY_START = -1000948,
SAY_REACH_BOTTOM = -1000949,
SAY_AGGRO_KINELORY = -1000950,
SAY_AGGRO_JORELL = -1000951,
SAY_WATCH_BACK = -1000952,
EMOTE_BELONGINGS = -1000953,
SAY_DATA_FOUND = -1000954,
SAY_ESCAPE = -1000955,
SAY_FINISH = -1000956,
EMOTE_HAND_PACK = -1000957,
SPELL_REJUVENATION = 3627,
SPELL_BEAR_FORM = 4948,
NPC_JORELL = 2733,
NPC_QUAE = 2712,
QUEST_HINTS_NEW_PLAGUE = 660
};
struct npc_kinelory : public CreatureScript
{
npc_kinelory() : CreatureScript("npc_kinelory") {}
struct npc_kineloryAI : public npc_escortAI
{
npc_kineloryAI(Creature* pCreature) : npc_escortAI(pCreature) { }
uint32 m_uiBearFormTimer;
uint32 m_uiHealTimer;
void Reset() override
{
m_uiBearFormTimer = urand(5000, 7000);
m_uiHealTimer = urand(2000, 5000);
}
void WaypointReached(uint32 uiPointId) override
{
switch (uiPointId)
{
case 9:
DoScriptText(SAY_REACH_BOTTOM, m_creature);
break;
case 16:
DoScriptText(SAY_WATCH_BACK, m_creature);
DoScriptText(EMOTE_BELONGINGS, m_creature);
break;
case 17:
DoScriptText(SAY_DATA_FOUND, m_creature);
break;
case 18:
DoScriptText(SAY_ESCAPE, m_creature);
if (Player* pPlayer = GetPlayerForEscort())
{
m_creature->SetFacingToObject(pPlayer);
}
SetRun();
break;
case 33:
DoScriptText(SAY_FINISH, m_creature);
if (Creature* pQuae = GetClosestCreatureWithEntry(m_creature, NPC_QUAE, 10.0f))
{
DoScriptText(EMOTE_HAND_PACK, m_creature, pQuae);
m_creature->SetFacingToObject(pQuae);
}
break;
case 34:
if (Player* pPlayer = GetPlayerForEscort())
{
pPlayer->GroupEventHappens(QUEST_HINTS_NEW_PLAGUE, m_creature);
}
break;
}
}
void Aggro(Unit* pWho) override
{
if (pWho->GetEntry() == NPC_JORELL)
{
DoScriptText(SAY_AGGRO_JORELL, pWho, m_creature);
}
else if (roll_chance_i(10))
{
DoScriptText(SAY_AGGRO_KINELORY, m_creature);
}
}
void ReceiveAIEvent(AIEventType eventType, Creature* /*pSender*/, Unit* pInvoker, uint32 uiMiscValue) override
{
if (eventType == AI_EVENT_START_ESCORT && pInvoker->GetTypeId() == TYPEID_PLAYER)
{
DoScriptText(SAY_START, m_creature);
Start(false, (Player*)pInvoker, GetQuestTemplateStore(uiMiscValue), true);
}
}
void UpdateEscortAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
if (m_uiBearFormTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_BEAR_FORM) == CAST_OK)
{
m_uiBearFormTimer = urand(25000, 30000);
}
}
else
{
m_uiBearFormTimer -= uiDiff;
}
if (m_uiHealTimer < uiDiff)
{
if (Unit* pTarget = DoSelectLowestHpFriendly(40.0f))
{
if (DoCastSpellIfCan(pTarget, SPELL_REJUVENATION) == CAST_OK)
{
m_uiHealTimer = urand(15000, 25000);
}
}
}
else
{
m_uiHealTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new npc_kineloryAI(pCreature);
}
bool OnQuestAccept(Player* pPlayer, Creature* pCreature, const Quest* pQuest) override
{
if (pQuest->GetQuestId() == QUEST_HINTS_NEW_PLAGUE)
{
pCreature->AI()->SendAIEvent(AI_EVENT_START_ESCORT, pPlayer, pCreature, pQuest->GetQuestId());
return true;
}
return false;
}
};
void AddSC_arathi_highlands()
{
Script* s;
s = new npc_professor_phizzlethorpe();
s->RegisterSelf();
s = new npc_kinelory();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "npc_professor_phizzlethorpe";
//pNewScript->GetAI = &GetAI_npc_professor_phizzlethorpe;
//pNewScript->pQuestAcceptNPC = &QuestAccept_npc_professor_phizzlethorpe;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "npc_kinelory";
//pNewScript->GetAI = &GetAI_npc_kinelory;
//pNewScript->pQuestAcceptNPC = &QuestAccept_npc_kinelory;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,144 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef DEF_BRD_H
#define DEF_BRD_H
enum
{
MAX_ENCOUNTER = 7,
TYPE_SIGNAL = MAX_ENCOUNTER + 1,
MAX_RELIC_DOORS = 12,
MAX_DWARFS = 7,
TYPE_RING_OF_LAW = 1,
TYPE_VAULT = 2,
TYPE_BAR = 3,
TYPE_TOMB_OF_SEVEN = 4,
TYPE_LYCEUM = 5,
TYPE_IRON_HALL = 6,
TYPE_QUEST_JAIL_BREAK = 7,
NPC_EMPEROR = 9019,
NPC_PRINCESS = 8929,
NPC_PHALANX = 9502,
NPC_HATEREL = 9034,
NPC_ANGERREL = 9035,
NPC_VILEREL = 9036,
NPC_GLOOMREL = 9037,
NPC_SEETHREL = 9038,
NPC_DOOMREL = 9039,
NPC_DOPEREL = 9040,
NPC_MAGMUS = 9938,
NPC_WATCHER_DOOMGRIP = 9476,
NPC_WARBRINGER_CONST = 8905, // Four of them in Relict Vault are related to Doomgrip summon event
// Jail Break event related
NPC_OGRABISI = 9677,
NPC_SHILL = 9678,
NPC_CREST = 9680,
NPC_JAZ = 9681,
NPC_TOBIAS = 9679,
NPC_DUGHAL = 9022,
GO_ARENA_1 = 161525,
GO_ARENA_2 = 161522,
GO_ARENA_3 = 161524,
GO_ARENA_4 = 161523,
GO_SHADOW_LOCK = 161460,
GO_SHADOW_MECHANISM = 161461,
GO_SHADOW_GIANT_DOOR = 157923,
GO_SHADOW_DUMMY = 161516,
GO_BAR_KEG_SHOT = 170607,
GO_BAR_KEG_TRAP = 171941,
GO_BAR_DOOR = 170571,
GO_TOMB_ENTER = 170576,
GO_TOMB_EXIT = 170577,
GO_LYCEUM = 170558,
GO_GOLEM_ROOM_N = 170573,
GO_GOLEM_ROOM_S = 170574,
GO_THRONE_ROOM = 170575,
GO_SPECTRAL_CHALICE = 164869,
GO_CHEST_SEVEN = 169243,
GO_ARENA_SPOILS = 181074,
GO_SECRET_DOOR = 174553,
// Jail break event related
GO_JAIL_DOOR_SUPPLY = 170561,
GO_JAIL_SUPPLY_CRATE = 166872,
SPELL_STONED = 10255, // Aura of Warbringer Constructs in Relict Vault
FACTION_DWARF_HOSTILE = 754, // Hostile faction for the Tomb of the Seven dwarfs
};
enum ArenaNPCs
{
// Gladiators
NPC_LEFTY = 16049,
NPC_ROTFANG = 16050,
NPC_SNOKH = 16051,
NPC_MALGEN = 16052,
NPC_KORV = 16053,
NPC_REZZNIK = 16054,
NPC_VAJASHNI = 16055,
NPC_VOLIDA = 16058,
NPC_THELDREN = 16059,
// Ring mobs
NPC_WORM = 8925,
NPC_STINGER = 8926,
NPC_SCREECHER = 8927,
NPC_THUNDERSNOUT = 8928,
NPC_CREEPER = 8933,
NPC_BEETLE = 8932,
// Ring bosses
NPC_GOROSH = 9027,
NPC_GRIZZLE = 9028,
NPC_EVISCERATOR = 9029,
NPC_OKTHOR = 9030,
NPC_ANUBSHIAH = 9031,
NPC_HEDRUM = 9032
};
static const uint32 aArenaNPCs[] =
{
// Gladiators
NPC_LEFTY, NPC_ROTFANG, NPC_SNOKH, NPC_MALGEN, NPC_KORV, NPC_REZZNIK, NPC_VAJASHNI, NPC_VOLIDA, NPC_THELDREN,
// Ring mobs
NPC_WORM, NPC_STINGER, NPC_SCREECHER, NPC_THUNDERSNOUT, NPC_CREEPER, NPC_BEETLE,
// Ring bosses
NPC_GOROSH, NPC_GRIZZLE, NPC_EVISCERATOR, NPC_OKTHOR, NPC_ANUBSHIAH, NPC_HEDRUM
};
// Used to summon Watcher Doomgrip
static const float aVaultPositions[4] = {821.905f, -338.382f, -50.134f, 3.78736f};
// Tomb of the Seven dwarfs
static const uint32 aTombDwarfes[MAX_DWARFS] = {NPC_ANGERREL, NPC_SEETHREL, NPC_DOPEREL, NPC_GLOOMREL, NPC_VILEREL, NPC_HATEREL, NPC_DOOMREL};
#endif

View file

@ -0,0 +1,155 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Ambassador_Flamelash
* SD%Complete: 80
* SDComment: Texts missing, Add handling rather guesswork, Add spell Burning Spirit likely won't work
* SDCategory: Blackrock Depths
* EndScriptData
*/
#include "precompiled.h"
enum
{
SPELL_FIREBLAST = 15573,
SPELL_BURNING_SPIRIT = 13489,
SPELL_BURNING_SPIRIT_BUFF = 14744,
NPC_BURNING_SPIRIT = 9178,
};
struct boss_ambassador_flamelash : public CreatureScript
{
boss_ambassador_flamelash() : CreatureScript("boss_ambassador_flamelash") {}
struct boss_ambassador_flamelashAI : public ScriptedAI
{
boss_ambassador_flamelashAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
uint32 m_uiSpiritTimer;
int Rand;
int RandX;
int RandY;
void Reset() override
{
m_uiSpiritTimer = 12000;
}
void SummonSpirits()
{
float fX, fY, fZ;
m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 30.0f, fX, fY, fZ);
m_creature->SummonCreature(NPC_BURNING_SPIRIT, fX, fY, fZ, m_creature->GetAngle(fX, fY) + M_PI_F, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, 60000);
}
void Aggro(Unit* /*pWho*/) override
{
DoCastSpellIfCan(m_creature, SPELL_FIREBLAST);
}
void JustSummoned(Creature* pSummoned) override
{
pSummoned->GetMotionMaster()->MovePoint(1, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ());
}
void SummonedMovementInform(Creature* pSummoned, uint32 /*uiMotionType*/, uint32 uiPointId) override
{
if (uiPointId != 1)
{
return;
}
pSummoned->CastSpell(m_creature, SPELL_BURNING_SPIRIT, true);
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// m_uiSpiritTimer
if (m_uiSpiritTimer < uiDiff)
{
SummonSpirits();
SummonSpirits();
SummonSpirits();
SummonSpirits();
m_uiSpiritTimer = 20000;
}
else
{
m_uiSpiritTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_ambassador_flamelashAI(pCreature);
}
};
struct spell_boss_ambassador_flamelash : public SpellScript
{
spell_boss_ambassador_flamelash() : SpellScript("spell_boss_ambassador_flamelash") {}
bool EffectDummy(Unit* /*pCaster*/, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Object* pCreatureTarget, ObjectGuid /*originalCasterGuid*/) override
{
if (uiSpellId == SPELL_BURNING_SPIRIT && uiEffIndex == EFFECT_INDEX_1)
{
pCreatureTarget->ToCreature()->CastSpell(pCreatureTarget->ToCreature(), SPELL_BURNING_SPIRIT_BUFF, true);
return true;
}
return false;
}
};
void AddSC_boss_ambassador_flamelash()
{
Script *s;
s = new boss_ambassador_flamelash();
s->RegisterSelf();
s = new spell_boss_ambassador_flamelash();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_ambassador_flamelash";
//pNewScript->GetAI = &GetAI_boss_ambassador_flamelash;
//pNewScript->pEffectDummyNPC = &EffectDummyCreature_spell_boss_ambassador_flamelash;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,215 @@
/**
* ScriptDev3 is an extension for mangos-one providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos-one.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/* ScriptData
SDName: boss_coren_direbrew
SD%Complete: 75
SDComment: Some parts are not complete - requires additional research. Brewmaidens scripts handled in eventAI.
SDCategory: Blackrock Depths
EndScriptData */
#include "precompiled.h"
enum
{
SAY_AGGRO = -1230034,
// spells
SPELL_DIREBREW_DISARM = 47310,
SPELL_SUMMON_DIREBREW_MINION = 47375,
SPELL_DIREBREW_CHARGE = 47718,
SPELL_SUMMON_MOLE_MACHINE = 47691, // triggers 47690
// summoned auras
SPELL_PORT_TO_COREN = 52850,
// other summoned spells - currently not used in script
// SPELL_CHUCK_MUG = 50276,
// SPELL_BARRELED_AURA = 50278, // used by Ursula
// SPELL_HAS_BREW = 47331, // triggers 47344 - aura which asks for the second brew on item expire
// SPELL_SEND_FIRST_MUG = 47333, // triggers 47345
// SPELL_SEND_SECOND_MUG = 47339, // triggers 47340 - spell triggered by 47344
// SPELL_BREWMAIDEN_DESPAWN_AURA = 48186, // purpose unk
// npcs
NPC_DIREBREW_MINION = 26776,
NPC_ILSA_DIREBREW = 26764,
NPC_URSULA_DIREBREW = 26822,
// other
FACTION_HOSTILE = 736,
QUEST_INSULT_COREN = 12062,
MAX_DIREBREW_MINIONS = 3,
};
struct boss_coren_direbrew : public CreatureScript
{
boss_coren_direbrew() : CreatureScript("boss_coren_direbrew") {}
struct boss_coren_direbrewAI : public ScriptedAI
{
boss_coren_direbrewAI(Creature* pCreature) : ScriptedAI(pCreature) { Reset(); }
uint32 m_uiDisarmTimer;
uint32 m_uiChargeTimer;
uint32 m_uiSummonTimer;
uint8 m_uiPhase;
void Reset() override
{
m_uiDisarmTimer = 10000;
m_uiChargeTimer = 5000;
m_uiSummonTimer = 15000;
m_uiPhase = 0;
}
void Aggro(Unit* /*pWho*/) override
{
// Spawn 3 minions on aggro
for (uint8 i = 0; i < MAX_DIREBREW_MINIONS; ++i)
{
DoCastSpellIfCan(m_creature, SPELL_SUMMON_DIREBREW_MINION, CAST_TRIGGERED);
}
}
void JustSummoned(Creature* pSummoned) override
{
switch (pSummoned->GetEntry())
{
case NPC_ILSA_DIREBREW:
case NPC_URSULA_DIREBREW:
pSummoned->CastSpell(m_creature, SPELL_PORT_TO_COREN, true);
break;
}
if (m_creature->getVictim())
{
pSummoned->AI()->AttackStart(m_creature->getVictim());
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Spawn Ilsa
if (m_creature->GetHealthPercent() < 66.0f && m_uiPhase == 0)
{
float fX, fY, fZ;
m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 10, fX, fY, fZ);
m_creature->SummonCreature(NPC_ILSA_DIREBREW, fX, fY, fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
m_uiPhase = 1;
}
// Spawn Ursula
if (m_creature->GetHealthPercent() < 33.0f && m_uiPhase == 1)
{
float fX, fY, fZ;
m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 10, fX, fY, fZ);
m_creature->SummonCreature(NPC_URSULA_DIREBREW, fX, fY, fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0);
m_uiPhase = 2;
}
if (m_uiDisarmTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_DIREBREW_DISARM) == CAST_OK)
{
m_uiDisarmTimer = 15000;
}
}
else
{
m_uiDisarmTimer -= uiDiff;
}
if (m_uiChargeTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_DIREBREW_CHARGE, SELECT_FLAG_NOT_IN_MELEE_RANGE))
{
if (DoCastSpellIfCan(pTarget, SPELL_DIREBREW_CHARGE) == CAST_OK)
{
m_uiChargeTimer = urand(5000, 10000);
}
}
}
else
{
m_uiChargeTimer -= uiDiff;
}
if (m_uiSummonTimer < uiDiff)
{
for (uint8 i = 0; i < MAX_DIREBREW_MINIONS; ++i)
{
DoCastSpellIfCan(m_creature, SPELL_SUMMON_DIREBREW_MINION, CAST_TRIGGERED);
}
m_uiSummonTimer = 15000;
}
else
{
m_uiSummonTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_coren_direbrewAI(pCreature);
}
bool OnQuestRewarded(Player* pPlayer, Creature* pCreature, Quest const* pQuest) override
{
if (pQuest->GetQuestId() == QUEST_INSULT_COREN)
{
DoScriptText(SAY_AGGRO, pCreature, pPlayer);
pCreature->SetFactionTemporary(FACTION_HOSTILE, TEMPFACTION_RESTORE_REACH_HOME | TEMPFACTION_RESTORE_RESPAWN);
pCreature->AI()->AttackStart(pPlayer);
}
return true;
}
};
void AddSC_boss_coren_direbrew()
{
Script* s;
s = new boss_coren_direbrew();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_coren_direbrew";
//pNewScript->GetAI = &GetAI_boss_coren_direbrew;
//pNewScript->pQuestRewardedNPC = &QuestRewarded_npc_coren_direbrew;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,308 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Emperor_Dagran_Thaurissan
* SD%Complete: 90
* SDComment: With script for Moira
* SDCategory: Blackrock Depths
* EndScriptData
*/
#include "precompiled.h"
#include "blackrock_depths.h"
enum eEmperor
{
FACTION_NEUTRAL = 734,
SAY_AGGRO = -1230001,
SAY_SLAY = -1230002,
SPELL_HANDOFTHAURISSAN = 17492,
SPELL_AVATAROFFLAME = 15636
};
struct boss_emperor_dagran_thaurissan : public CreatureScript
{
boss_emperor_dagran_thaurissan() : CreatureScript("boss_emperor_dagran_thaurissan") {}
struct boss_emperor_dagran_thaurissanAI : public ScriptedAI
{
boss_emperor_dagran_thaurissanAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiHandOfThaurissan_Timer;
uint32 m_uiAvatarOfFlame_Timer;
// uint32 m_uiCounter;
void Reset() override
{
m_uiHandOfThaurissan_Timer = 4000;
m_uiAvatarOfFlame_Timer = 25000;
// m_uiCounter = 0;
}
void Aggro(Unit* /*pWho*/) override
{
DoScriptText(SAY_AGGRO, m_creature);
m_creature->CallForHelp(VISIBLE_RANGE);
}
void JustDied(Unit* /*pVictim*/) override
{
if (!m_pInstance)
{
return;
}
if (Creature* pPrincess = m_pInstance->GetSingleCreatureFromStorage(NPC_PRINCESS))
{
if (pPrincess->IsAlive())
{
pPrincess->SetFactionTemporary(FACTION_NEUTRAL, TEMPFACTION_NONE);
pPrincess->AI()->EnterEvadeMode();
}
}
}
void KilledUnit(Unit* /*pVictim*/) override
{
DoScriptText(SAY_SLAY, m_creature);
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
if (m_uiHandOfThaurissan_Timer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
DoCastSpellIfCan(pTarget, SPELL_HANDOFTHAURISSAN);
}
// 3 Hands of Thaurissan will be casted
// if (m_uiCounter < 3)
//{
// m_uiHandOfThaurissan_Timer = 1000;
// ++m_uiCounter;
//}
// else
//{
m_uiHandOfThaurissan_Timer = 5000;
// m_uiCounter = 0;
//}
}
else
{
m_uiHandOfThaurissan_Timer -= uiDiff;
}
// AvatarOfFlame_Timer
if (m_uiAvatarOfFlame_Timer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_AVATAROFFLAME);
m_uiAvatarOfFlame_Timer = 18000;
}
else
{
m_uiAvatarOfFlame_Timer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_emperor_dagran_thaurissanAI(pCreature);
}
};
/*######
## boss_moira_bronzebeard
######*/
enum ePrincess
{
SPELL_HEAL = 15586,
SPELL_RENEW = 10929,
SPELL_SHIELD = 10901,
SPELL_MINDBLAST = 15587,
SPELL_SHADOWWORDPAIN = 15654,
SPELL_SMITE = 10934,
SPELL_SHADOW_BOLT = 15537,
SPELL_OPEN_PORTAL = 13912
};
struct boss_moira_bronzebeard : public CreatureScript
{
boss_moira_bronzebeard() : CreatureScript("boss_moira_bronzebeard") {}
struct boss_moira_bronzebeardAI : public ScriptedAI
{
boss_moira_bronzebeardAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiHeal_Timer;
uint32 m_uiMindBlast_Timer;
uint32 m_uiShadowWordPain_Timer;
uint32 m_uiSmite_Timer;
void Reset() override
{
m_uiHeal_Timer = 12000; // These times are probably wrong
m_uiMindBlast_Timer = 16000;
m_uiShadowWordPain_Timer = 2000;
m_uiSmite_Timer = 8000;
}
void AttackStart(Unit* pWho) override
{
if (m_creature->Attack(pWho, false))
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
m_creature->GetMotionMaster()->MoveChase(pWho, 25.0f);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
if (Creature* pEmperor = m_pInstance->GetSingleCreatureFromStorage(NPC_EMPEROR))
{
// if evade, then check if he is alive. If not, start make portal
if (!pEmperor->IsAlive())
{
m_creature->CastSpell(m_creature, SPELL_OPEN_PORTAL, false);
}
}
}
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// MindBlast_Timer
if (m_uiMindBlast_Timer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_MINDBLAST);
m_uiMindBlast_Timer = 14000;
}
else
{
m_uiMindBlast_Timer -= uiDiff;
}
// ShadowWordPain_Timer
if (m_uiShadowWordPain_Timer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOWWORDPAIN);
m_uiShadowWordPain_Timer = 18000;
}
else
{
m_uiShadowWordPain_Timer -= uiDiff;
}
// Smite_Timer
if (m_uiSmite_Timer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_SMITE);
m_uiSmite_Timer = 10000;
}
else
{
m_uiSmite_Timer -= uiDiff;
}
// Heal_Timer
if (m_uiHeal_Timer < uiDiff)
{
if (Creature* pEmperor = m_pInstance->GetSingleCreatureFromStorage(NPC_EMPEROR))
{
if (pEmperor->IsAlive() && pEmperor->GetHealthPercent() != 100.0f)
{
DoCastSpellIfCan(pEmperor, SPELL_HEAL);
}
}
m_uiHeal_Timer = 10000;
}
else
{
m_uiHeal_Timer -= uiDiff;
}
// No meele?
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_moira_bronzebeardAI(pCreature);
}
};
void AddSC_boss_draganthaurissan()
{
Script *s;
s = new boss_emperor_dagran_thaurissan();
s->RegisterSelf();
s = new boss_moira_bronzebeard();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_emperor_dagran_thaurissan";
//pNewScript->GetAI = &GetAI_boss_emperor_dagran_thaurissan;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_moira_bronzebeard";
//pNewScript->GetAI = &GetAI_boss_moira_bronzebeard;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,173 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_General_Angerforge
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackrock Depths
* EndScriptData
*/
#include "precompiled.h"
enum
{
SPELL_MIGHTYBLOW = 14099,
SPELL_HAMSTRING = 9080,
SPELL_CLEAVE = 20691,
NPC_ANVILRAGE_RESERVIST = 8901,
NPC_ANVILRAGE_MEDIC = 8894,
};
struct boss_general_angerforge : public CreatureScript
{
boss_general_angerforge() : CreatureScript("boss_general_angerforge") {}
struct boss_general_angerforgeAI : public ScriptedAI
{
boss_general_angerforgeAI(Creature* pCreature) : ScriptedAI(pCreature) { }
uint32 m_uiMightyBlowTimer;
uint32 m_uiHamStringTimer;
uint32 m_uiCleaveTimer;
uint32 m_uiAddsTimer;
bool m_bSummonedMedics;
void Reset() override
{
m_uiMightyBlowTimer = 8000;
m_uiHamStringTimer = 12000;
m_uiCleaveTimer = 16000;
m_uiAddsTimer = 0;
m_bSummonedMedics = false;
}
void SummonAdd(uint32 uiEntry)
{
float fX, fY, fZ;
m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 20.0f, fX, fY, fZ);
m_creature->SummonCreature(uiEntry, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, 60000);
}
void JustSummoned(Creature* pSummoned) override
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
pSummoned->AI()->AttackStart(pTarget);
}
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// MightyBlow_Timer
if (m_uiMightyBlowTimer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_MIGHTYBLOW);
m_uiMightyBlowTimer = 18000;
}
else
{
m_uiMightyBlowTimer -= uiDiff;
}
// HamString_Timer
if (m_uiHamStringTimer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_HAMSTRING);
m_uiHamStringTimer = 15000;
}
else
{
m_uiHamStringTimer -= uiDiff;
}
// Cleave_Timer
if (m_uiCleaveTimer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
m_uiCleaveTimer = 9000;
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// Adds_Timer
if (m_creature->GetHealthPercent() < 21.0f)
{
if (m_uiAddsTimer < uiDiff)
{
// summon 3 Adds every 25s
SummonAdd(NPC_ANVILRAGE_RESERVIST);
SummonAdd(NPC_ANVILRAGE_RESERVIST);
SummonAdd(NPC_ANVILRAGE_RESERVIST);
m_uiAddsTimer = 25000;
}
else
{
m_uiAddsTimer -= uiDiff;
}
}
// Summon Medics
if (!m_bSummonedMedics && m_creature->GetHealthPercent() < 21.0f)
{
SummonAdd(NPC_ANVILRAGE_MEDIC);
SummonAdd(NPC_ANVILRAGE_MEDIC);
m_bSummonedMedics = true;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_general_angerforgeAI(pCreature);
}
};
void AddSC_boss_general_angerforge()
{
Script *s;
s = new boss_general_angerforge();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_general_angerforge";
//pNewScript->GetAI = &GetAI_boss_general_angerforge;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,147 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_High_Interrogator_Gerstahn
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackrock Depths
* EndScriptData
*/
#include "precompiled.h"
enum
{
SPELL_SHADOWWORDPAIN = 14032,
SPELL_MANABURN = 14033,
SPELL_PSYCHICSCREAM = 13704,
SPELL_SHADOWSHIELD = 12040
};
struct boss_high_interrogator_gerstahn : public CreatureScript
{
boss_high_interrogator_gerstahn() : CreatureScript("boss_high_interrogator_gerstahn") {}
struct boss_high_interrogator_gerstahnAI : public ScriptedAI
{
boss_high_interrogator_gerstahnAI(Creature* pCreature) : ScriptedAI(pCreature) { }
uint32 m_uiShadowWordPainTimer;
uint32 m_uiManaBurnTimer;
uint32 m_uiPsychicScreamTimer;
uint32 m_uiShadowShieldTimer;
void Reset() override
{
m_uiShadowWordPainTimer = 4000;
m_uiManaBurnTimer = 14000;
m_uiPsychicScreamTimer = 32000;
m_uiShadowShieldTimer = 8000;
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// ShadowWordPain_Timer
if (m_uiShadowWordPainTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
DoCastSpellIfCan(pTarget, SPELL_SHADOWWORDPAIN);
}
m_uiShadowWordPainTimer = 7000;
}
else
{
m_uiShadowWordPainTimer -= uiDiff;
}
// ManaBurn_Timer
if (m_uiManaBurnTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_MANABURN, SELECT_FLAG_POWER_MANA))
{
DoCastSpellIfCan(pTarget, SPELL_MANABURN);
}
m_uiManaBurnTimer = 10000;
}
else
{
m_uiManaBurnTimer -= uiDiff;
}
// PsychicScream_Timer
if (m_uiPsychicScreamTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_PSYCHICSCREAM);
m_uiPsychicScreamTimer = 30000;
}
else
{
m_uiPsychicScreamTimer -= uiDiff;
}
// ShadowShield_Timer
if (m_uiShadowShieldTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_SHADOWSHIELD);
m_uiShadowShieldTimer = 25000;
}
else
{
m_uiShadowShieldTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_high_interrogator_gerstahnAI(pCreature);
}
};
void AddSC_boss_high_interrogator_gerstahn()
{
Script *s;
s = new boss_high_interrogator_gerstahn();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_high_interrogator_gerstahn";
//pNewScript->GetAI = &GetAI_boss_high_interrogator_gerstahn;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,501 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Instance_Blackrock_Depths
* SD%Complete: 80
* SDComment: None
* SDCategory: Blackrock Depths
* EndScriptData
*/
#include "precompiled.h"
#include "blackrock_depths.h"
struct is_blackrock_depths : public InstanceScript
{
is_blackrock_depths() : InstanceScript("instance_blackrock_depths") {}
class instance_blackrock_depths : public ScriptedInstance
{
public:
instance_blackrock_depths(Map* pMap) : ScriptedInstance(pMap),
m_uiBarAleCount(0),
m_uiCofferDoorsOpened(0),
m_uiDwarfFightTimer(0),
m_uiArenaCenterAT(0),
m_uiDwarfRound(0)
{
Initialize();
}
~instance_blackrock_depths() {}
void Initialize() override
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
void OnCreatureCreate(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
case NPC_EMPEROR:
case NPC_PRINCESS:
case NPC_PHALANX:
case NPC_HATEREL:
case NPC_ANGERREL:
case NPC_VILEREL:
case NPC_GLOOMREL:
case NPC_SEETHREL:
case NPC_DOOMREL:
case NPC_DOPEREL:
case NPC_SHILL:
case NPC_CREST:
case NPC_JAZ:
case NPC_TOBIAS:
case NPC_DUGHAL:
m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid();
break;
case NPC_WARBRINGER_CONST:
// Golems not in the Relict Vault?
if (std::abs(pCreature->GetPositionZ() - aVaultPositions[2]) > 1.0f || !pCreature->IsWithinDist2d(aVaultPositions[0], aVaultPositions[1], 20.0f))
{
break;
}
// Golems in Relict Vault need to have a stoned aura, set manually to prevent reapply when reached home
pCreature->CastSpell(pCreature, SPELL_STONED, true);
// Store the Relict Vault Golems into m_sVaultNpcGuids
case NPC_WATCHER_DOOMGRIP:
m_sVaultNpcGuids.insert(pCreature->GetObjectGuid());
break;
}
}
void OnCreatureEnterCombat(Creature* pCreature) override
{
if (pCreature->GetEntry() == NPC_MAGMUS)
{
SetData(TYPE_IRON_HALL, IN_PROGRESS);
}
}
void OnCreatureDeath(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
case NPC_WARBRINGER_CONST:
case NPC_WATCHER_DOOMGRIP:
if (GetData(TYPE_VAULT) == IN_PROGRESS)
{
m_sVaultNpcGuids.erase(pCreature->GetObjectGuid());
// If all event npcs dead then set event to done
if (m_sVaultNpcGuids.empty())
{
SetData(TYPE_VAULT, DONE);
}
}
break;
case NPC_OGRABISI:
case NPC_SHILL:
case NPC_CREST:
case NPC_JAZ:
if (GetData(TYPE_QUEST_JAIL_BREAK) == IN_PROGRESS)
{
SetData(TYPE_QUEST_JAIL_BREAK, SPECIAL);
}
break;
// Handle Tomb of the Seven dwarf death event
case NPC_HATEREL:
case NPC_ANGERREL:
case NPC_VILEREL:
case NPC_GLOOMREL:
case NPC_SEETHREL:
case NPC_DOPEREL:
// Only handle the event when event is in progress
if (GetData(TYPE_TOMB_OF_SEVEN) != IN_PROGRESS)
{
return;
}
// Call the next dwarf only if it's the last one which joined the fight
if (pCreature->GetEntry() == aTombDwarfes[m_uiDwarfRound - 1])
{
DoCallNextDwarf();
}
break;
case NPC_DOOMREL:
SetData(TYPE_TOMB_OF_SEVEN, DONE);
break;
case NPC_MAGMUS:
SetData(TYPE_IRON_HALL, DONE);
break;
}
}
void OnCreatureEvade(Creature* pCreature) override
{
if (GetData(TYPE_RING_OF_LAW) == IN_PROGRESS || GetData(TYPE_RING_OF_LAW) == SPECIAL)
{
for (uint8 i = 0; i < countof(aArenaNPCs); ++i)
{
if (pCreature->GetEntry() == aArenaNPCs[i])
{
SetData(TYPE_RING_OF_LAW, FAIL);
return;
}
}
}
switch (pCreature->GetEntry())
{
// Handle Tomb of the Seven reset in case of wipe
case NPC_HATEREL:
case NPC_ANGERREL:
case NPC_VILEREL:
case NPC_GLOOMREL:
case NPC_SEETHREL:
case NPC_DOPEREL:
case NPC_DOOMREL:
SetData(TYPE_TOMB_OF_SEVEN, FAIL);
break;
case NPC_MAGMUS:
SetData(TYPE_IRON_HALL, FAIL);
break;
}
}
void OnObjectCreate(GameObject* pGo) override
{
switch (pGo->GetEntry())
{
case GO_ARENA_1:
case GO_ARENA_2:
case GO_ARENA_3:
case GO_ARENA_4:
case GO_SHADOW_LOCK:
case GO_SHADOW_MECHANISM:
case GO_SHADOW_GIANT_DOOR:
case GO_SHADOW_DUMMY:
case GO_BAR_KEG_SHOT:
case GO_BAR_KEG_TRAP:
case GO_BAR_DOOR:
case GO_TOMB_ENTER:
case GO_TOMB_EXIT:
case GO_LYCEUM:
case GO_GOLEM_ROOM_N:
case GO_GOLEM_ROOM_S:
case GO_THRONE_ROOM:
case GO_SPECTRAL_CHALICE:
case GO_CHEST_SEVEN:
case GO_ARENA_SPOILS:
case GO_SECRET_DOOR:
case GO_JAIL_DOOR_SUPPLY:
case GO_JAIL_SUPPLY_CRATE:
break;
default:
return;
}
m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid();
}
void SetData(uint32 uiType, uint32 uiData) override
{
switch (uiType)
{
case TYPE_RING_OF_LAW:
// If finished the arena event after theldren fight
if (uiData == DONE && m_auiEncounter[0] == SPECIAL)
{
DoRespawnGameObject(GO_ARENA_SPOILS, HOUR);
}
m_auiEncounter[0] = uiData;
break;
case TYPE_VAULT:
if (uiData == SPECIAL)
{
++m_uiCofferDoorsOpened;
if (m_uiCofferDoorsOpened == MAX_RELIC_DOORS)
{
SetData(TYPE_VAULT, IN_PROGRESS);
Creature* pConstruct = NULL;
// Activate vault constructs
for (GuidSet::const_iterator itr = m_sVaultNpcGuids.begin(); itr != m_sVaultNpcGuids.end(); ++itr)
{
pConstruct = instance->GetCreature(*itr);
if (pConstruct)
{
pConstruct->RemoveAurasDueToSpell(SPELL_STONED);
}
}
if (!pConstruct)
{
return;
}
// Summon doomgrip
pConstruct->SummonCreature(NPC_WATCHER_DOOMGRIP, aVaultPositions[0], aVaultPositions[1], aVaultPositions[2], aVaultPositions[3], TEMPSUMMON_DEAD_DESPAWN, 0);
}
// No need to store in this case
return;
}
if (uiData == DONE)
{
DoUseDoorOrButton(GO_SECRET_DOOR);
}
m_auiEncounter[1] = uiData;
break;
case TYPE_BAR:
if (uiData == SPECIAL)
{
++m_uiBarAleCount;
}
else
{
m_auiEncounter[2] = uiData;
}
break;
case TYPE_TOMB_OF_SEVEN:
// Don't set the same data twice
if (uiData == m_auiEncounter[3])
{
break;
}
// Combat door
DoUseDoorOrButton(GO_TOMB_ENTER);
// Start the event
if (uiData == IN_PROGRESS)
{
DoCallNextDwarf();
}
if (uiData == FAIL)
{
// Reset dwarfes
for (uint8 i = 0; i < MAX_DWARFS; ++i)
{
if (Creature* pDwarf = GetSingleCreatureFromStorage(aTombDwarfes[i]))
{
if (!pDwarf->IsAlive())
{
pDwarf->Respawn();
}
}
}
m_uiDwarfRound = 0;
m_uiDwarfFightTimer = 0;
}
if (uiData == DONE)
{
DoRespawnGameObject(GO_CHEST_SEVEN, HOUR);
DoUseDoorOrButton(GO_TOMB_EXIT);
}
m_auiEncounter[3] = uiData;
break;
case TYPE_LYCEUM:
if (uiData == DONE)
{
DoUseDoorOrButton(GO_GOLEM_ROOM_N);
DoUseDoorOrButton(GO_GOLEM_ROOM_S);
}
m_auiEncounter[4] = uiData;
break;
case TYPE_IRON_HALL:
switch (uiData)
{
case IN_PROGRESS:
DoUseDoorOrButton(GO_GOLEM_ROOM_N);
DoUseDoorOrButton(GO_GOLEM_ROOM_S);
break;
case FAIL:
DoUseDoorOrButton(GO_GOLEM_ROOM_N);
DoUseDoorOrButton(GO_GOLEM_ROOM_S);
break;
case DONE:
DoUseDoorOrButton(GO_GOLEM_ROOM_N);
DoUseDoorOrButton(GO_GOLEM_ROOM_S);
DoUseDoorOrButton(GO_THRONE_ROOM);
break;
}
m_auiEncounter[5] = uiData;
break;
case TYPE_QUEST_JAIL_BREAK:
m_auiEncounter[6] = uiData;
return;
case TYPE_SIGNAL:
if (AreaTriggerEntry const *at = sAreaTriggerStore.LookupEntry(uiData))
m_uiArenaCenterAT = uiData;
return;
}
if (uiData == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
<< m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " " << m_auiEncounter[6];
m_strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 uiType) const override
{
switch (uiType)
{
case TYPE_RING_OF_LAW:
return m_auiEncounter[0];
case TYPE_VAULT:
return m_auiEncounter[1];
case TYPE_BAR:
if (m_auiEncounter[2] == IN_PROGRESS && m_uiBarAleCount == 3)
{
return SPECIAL;
}
else
{
return m_auiEncounter[2];
}
case TYPE_TOMB_OF_SEVEN:
return m_auiEncounter[3];
case TYPE_LYCEUM:
return m_auiEncounter[4];
case TYPE_IRON_HALL:
return m_auiEncounter[5];
case TYPE_QUEST_JAIL_BREAK:
return m_auiEncounter[6];
case TYPE_SIGNAL:
return m_uiArenaCenterAT;
default:
return 0;
}
}
const char* Save() const override { return m_strInstData.c_str(); }
void Load(const char* chrIn) override
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
{
m_auiEncounter[i] = NOT_STARTED;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 uiDiff) override
{
if (m_uiDwarfFightTimer)
{
if (m_uiDwarfFightTimer <= uiDiff)
{
if (m_uiDwarfRound < MAX_DWARFS)
{
DoCallNextDwarf();
m_uiDwarfFightTimer = 30000;
}
else
{
m_uiDwarfFightTimer = 0;
}
}
else
{
m_uiDwarfFightTimer -= uiDiff;
}
}
}
private:
void DoCallNextDwarf()
{
if (Creature* pDwarf = GetSingleCreatureFromStorage(aTombDwarfes[m_uiDwarfRound]))
{
if (Player* pPlayer = GetPlayerInMap())
{
pDwarf->SetFactionTemporary(FACTION_DWARF_HOSTILE, TEMPFACTION_RESTORE_RESPAWN | TEMPFACTION_RESTORE_REACH_HOME);
pDwarf->AI()->AttackStart(pPlayer);
}
}
m_uiDwarfFightTimer = 30000;
++m_uiDwarfRound;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string m_strInstData;
uint32 m_uiBarAleCount;
uint8 m_uiCofferDoorsOpened;
uint32 m_uiDwarfFightTimer;
uint32 m_uiArenaCenterAT;
uint8 m_uiDwarfRound;
float m_fArenaCenterX, m_fArenaCenterY, m_fArenaCenterZ;
GuidSet m_sVaultNpcGuids;
};
InstanceData* GetInstanceData(Map* pMap) override
{
return new instance_blackrock_depths(pMap);
}
};
void AddSC_instance_blackrock_depths()
{
Script* s;
s = new is_blackrock_depths();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "instance_blackrock_depths";
//pNewScript->GetInstanceData = &GetInstanceData_instance_blackrock_depths;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,141 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef DEF_BLACKROCK_SPIRE_H
#define DEF_BLACKROCK_SPIRE_H
enum
{
MAX_ENCOUNTER = 6,
MAX_ROOMS = 7,
DO_ACTIVATE_RUNES = 0,
DO_SORT_MOBS = 1,
DO_EMBERSEER_EVENT = 2,
DO_FLAMEWREATH_EVENT = 3,
TYPE_ROOM_EVENT = 0,
TYPE_EMBERSEER = 1,
TYPE_FLAMEWREATH = 2, // Only summon once per instance
TYPE_STADIUM = 3,
TYPE_DRAKKISATH = 4,
TYPE_VALTHALAK = 5, // Only summon once per instance
NPC_SCARSHIELD_INFILTRATOR = 10299,
NPC_BLACKHAND_SUMMONER = 9818,
NPC_BLACKHAND_VETERAN = 9819,
NPC_PYROGUARD_EMBERSEER = 9816,
NPC_SOLAKAR_FLAMEWREATH = 10264,
NPC_BLACKHAND_INCARCERATOR = 10316,
NPC_LORD_VICTOR_NEFARIUS = 10162,
NPC_REND_BLACKHAND = 10429,
NPC_GYTH = 10339,
NPC_DRAKKISATH = 10363,
NPC_CHROMATIC_WHELP = 10442, // related to Gyth arena event
NPC_CHROMATIC_DRAGON = 10447,
NPC_BLACKHAND_HANDLER = 10742,
// Doors
GO_EMBERSEER_IN = 175244,
GO_DOORS = 175705,
GO_EMBERSEER_OUT = 175153,
GO_FATHER_FLAME = 175245,
GO_GYTH_ENTRY_DOOR = 164726,
GO_GYTH_COMBAT_DOOR = 175185,
GO_GYTH_EXIT_DOOR = 175186,
GO_DRAKKISATH_DOOR_1 = 175946,
GO_DRAKKISATH_DOOR_2 = 175947,
#if defined (TBC) || defined (WOTLK) || defined (CATA)
// upper spire entrance
GO_DRAGONSPINE = 164725,
GO_BRAZIER_1 = 175528,
GO_BRAZIER_2 = 175529,
GO_BRAZIER_3 = 175530,
GO_BRAZIER_4 = 175531,
GO_BRAZIER_5 = 175532,
GO_BRAZIER_6 = 175533,
#endif
GO_ROOM_7_RUNE = 175194,
GO_ROOM_3_RUNE = 175195,
GO_ROOM_6_RUNE = 175196,
GO_ROOM_1_RUNE = 175197,
GO_ROOM_5_RUNE = 175198,
GO_ROOM_2_RUNE = 175199,
GO_ROOM_4_RUNE = 175200,
GO_ROOKERY_EGG = 175124,
GO_EMBERSEER_RUNE_1 = 175266,
GO_EMBERSEER_RUNE_2 = 175267,
GO_EMBERSEER_RUNE_3 = 175268,
GO_EMBERSEER_RUNE_4 = 175269,
GO_EMBERSEER_RUNE_5 = 175270,
GO_EMBERSEER_RUNE_6 = 175271,
GO_EMBERSEER_RUNE_7 = 175272,
#if defined (TBC) || defined (WOTLK) || defined (CATA)
ITEM_SEAL_OF_ASCENSION = 12344,
#endif
MAX_STADIUM_WAVES = 7,
MAX_STADIUM_MOBS_PER_WAVE = 5,
FACTION_BLACK_DRAGON = 103,
SPELL_ENCAGE_EMBERSEER = 15281, // cast by Blackhand Incarcerator
};
struct SpawnLocation
{
float m_fX, m_fY, m_fZ, m_fO;
};
static const SpawnLocation aStadiumLocs[7] =
{
{210.00f, -420.30f, 110.94f, 3.14f}, // dragons summon location
{210.14f, -397.54f, 111.1f, 0.0f}, // Gyth summon location
{163.62f, -420.33f, 110.47f, 0.0f}, // center of the stadium location (for movement)
{164.63f, -444.04f, 121.97f, 3.22f}, // Lord Nefarius summon position
{161.01f, -443.73f, 121.97f, 6.26f}, // Rend summon position
{164.64f, -443.30f, 121.97f, 1.61f}, // Nefarius move position
{165.74f, -466.46f, 116.80f, 0.0f}, // Rend move position
};
// Stadium event description
static const uint32 aStadiumEventNpcs[MAX_STADIUM_WAVES][5] =
{
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, 0},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, 0},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, NPC_BLACKHAND_HANDLER, 0},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, NPC_BLACKHAND_HANDLER, 0},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, NPC_BLACKHAND_HANDLER},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, NPC_CHROMATIC_DRAGON, NPC_BLACKHAND_HANDLER},
{NPC_CHROMATIC_WHELP, NPC_CHROMATIC_WHELP, NPC_CHROMATIC_DRAGON, NPC_CHROMATIC_DRAGON, NPC_BLACKHAND_HANDLER},
};
#endif

View file

@ -0,0 +1,180 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Gyth
* SD%Complete: 100
* SDComment: Timers may need adjustments
* SDCategory: Blackrock Spire
* EndScriptData
*/
#include "precompiled.h"
#include "blackrock_spire.h"
enum
{
SAY_NEFARIUS_BUFF_GYTH = -1229017,
EMOTE_KNOCKED_OFF = -1229019,
SPELL_CHROMATIC_CHAOS = 16337, // casted by Nefarius at 50%
SPELL_REND_MOUNTS = 16167,
SPELL_SUMMON_REND = 16328,
SPELL_CORROSIVE_ACID = 16359,
SPELL_FREEZE = 16350,
SPELL_FLAME_BREATH = 16390,
SPELL_KNOCK_AWAY = 10101,
};
struct boss_gyth : public CreatureScript
{
boss_gyth() : CreatureScript("boss_gyth") {}
struct boss_gythAI : public ScriptedAI
{
boss_gythAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 uiCorrosiveAcidTimer;
uint32 uiFreezeTimer;
uint32 uiFlamebreathTimer;
bool m_bSummonedRend;
bool m_bHasChromaticChaos;
void Reset() override
{
uiCorrosiveAcidTimer = 8000;
uiFreezeTimer = 11000;
uiFlamebreathTimer = 4000;
m_bSummonedRend = false;
m_bHasChromaticChaos = false;
DoCastSpellIfCan(m_creature, SPELL_REND_MOUNTS);
}
void JustSummoned(Creature* pSummoned) override
{
DoScriptText(EMOTE_KNOCKED_OFF, pSummoned);
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Chromatic Chaos at 50%
if (!m_bHasChromaticChaos && m_creature->GetHealthPercent() < 50.0f)
{
if (m_pInstance)
{
if (Creature* pNefarius = m_pInstance->GetSingleCreatureFromStorage(NPC_LORD_VICTOR_NEFARIUS))
{
pNefarius->CastSpell(m_creature, SPELL_CHROMATIC_CHAOS, true);
DoScriptText(SAY_NEFARIUS_BUFF_GYTH, pNefarius);
m_bHasChromaticChaos = true;
}
}
}
// CorrosiveAcid_Timer
if (uiCorrosiveAcidTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_CORROSIVE_ACID) == CAST_OK)
{
uiCorrosiveAcidTimer = 7000;
}
}
else
{
uiCorrosiveAcidTimer -= uiDiff;
}
// Freeze_Timer
if (uiFreezeTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FREEZE) == CAST_OK)
{
uiFreezeTimer = 16000;
}
}
else
{
uiFreezeTimer -= uiDiff;
}
// Flamebreath_Timer
if (uiFlamebreathTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FLAME_BREATH) == CAST_OK)
{
uiFlamebreathTimer = 10500;
}
}
else
{
uiFlamebreathTimer -= uiDiff;
}
// Summon Rend
if (!m_bSummonedRend && m_creature->GetHealthPercent() < 11.0f)
{
if (DoCastSpellIfCan(m_creature, SPELL_SUMMON_REND) == CAST_OK)
{
m_creature->RemoveAurasDueToSpell(SPELL_REND_MOUNTS);
m_bSummonedRend = true;
}
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_gythAI(pCreature);
}
};
void AddSC_boss_gyth()
{
Script *s;
s = new boss_gyth();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_gyth";
//pNewScript->GetAI = &GetAI_boss_gyth;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,173 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Overlord_Wyrmthalak
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackrock Spire
* EndScriptData
*/
#include "precompiled.h"
enum
{
SPELL_BLASTWAVE = 11130,
SPELL_SHOUT = 23511,
SPELL_CLEAVE = 20691,
SPELL_KNOCKAWAY = 20686,
NPC_SPIRESTONE_WARLORD = 9216,
NPC_SMOLDERTHORN_BERSERKER = 9268
};
const float afLocations[2][4] =
{
{ -39.355381f, -513.456482f, 88.472046f, 4.679872f},
{ -49.875881f, -511.896942f, 88.195160f, 4.613114f}
};
struct boss_overlordwyrmthalak : public CreatureScript
{
boss_overlordwyrmthalak() : CreatureScript("boss_overlord_wyrmthalak") {}
struct boss_overlordwyrmthalakAI : public ScriptedAI
{
boss_overlordwyrmthalakAI(Creature* pCreature) : ScriptedAI(pCreature) { }
uint32 m_uiBlastWaveTimer;
uint32 m_uiShoutTimer;
uint32 m_uiCleaveTimer;
uint32 m_uiKnockawayTimer;
bool m_bSummoned;
void Reset() override
{
m_uiBlastWaveTimer = 20000;
m_uiShoutTimer = 2000;
m_uiCleaveTimer = 6000;
m_uiKnockawayTimer = 12000;
m_bSummoned = false;
}
void JustSummoned(Creature* pSummoned) override
{
if (pSummoned->GetEntry() != NPC_SPIRESTONE_WARLORD && pSummoned->GetEntry() != NPC_SMOLDERTHORN_BERSERKER)
{
return;
}
if (m_creature->getVictim())
{
Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0);
pSummoned->AI()->AttackStart(pTarget ? pTarget : m_creature->getVictim());
}
}
void UpdateAI(const uint32 uiDiff) override
{
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// BlastWave
if (m_uiBlastWaveTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_BLASTWAVE);
m_uiBlastWaveTimer = 20000;
}
else
{
m_uiBlastWaveTimer -= uiDiff;
}
// Shout
if (m_uiShoutTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_SHOUT);
m_uiShoutTimer = 10000;
}
else
{
m_uiShoutTimer -= uiDiff;
}
// Cleave
if (m_uiCleaveTimer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE);
m_uiCleaveTimer = 7000;
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// Knockaway
if (m_uiKnockawayTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_KNOCKAWAY);
m_uiKnockawayTimer = 14000;
}
else
{
m_uiKnockawayTimer -= uiDiff;
}
// Summon two Beserks
if (!m_bSummoned && m_creature->GetHealthPercent() < 51.0f)
{
m_creature->SummonCreature(NPC_SPIRESTONE_WARLORD, afLocations[0][0], afLocations[0][1], afLocations[0][2], afLocations[0][3], TEMPSUMMON_TIMED_DESPAWN, 300000);
m_creature->SummonCreature(NPC_SMOLDERTHORN_BERSERKER, afLocations[1][0], afLocations[1][1], afLocations[1][2], afLocations[1][3], TEMPSUMMON_TIMED_DESPAWN, 300000);
m_bSummoned = true;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_overlordwyrmthalakAI(pCreature);
}
};
void AddSC_boss_overlordwyrmthalak()
{
Script *s;
s = new boss_overlordwyrmthalak();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_overlord_wyrmthalak";
//pNewScript->GetAI = &GetAI_boss_overlordwyrmthalak;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,263 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Pyroguard_Emberseer
* SD%Complete: 90
* SDComment: Dummy spells used during the transformation may need further research
* SDCategory: Blackrock Spire
* EndScriptData
*/
#include "precompiled.h"
#include "blackrock_spire.h"
enum
{
// Intro emote/say
EMOTE_NEAR = -1229001,
EMOTE_FULL = -1229002,
SAY_FREE = -1229003,
MAX_GROWING_STACKS = 20,
// Intro spells
SPELL_FIRE_SHIELD = 13376, // not sure what's the purpose of this
SPELL_DESPAWN_EMBERSEER = 16078, // not sure what's the purpose of this
SPELL_FREEZE_ANIM = 16245, // not sure what's the purpose of this
SPELL_FULL_STRENGHT = 16047,
SPELL_GROWING = 16049, // stacking aura
SPELL_BONUS_DAMAGE = 16534, // triggered on full grow
SPELL_TRANSFORM = 16052,
// Combat spells
SPELL_FIRENOVA = 23462,
SPELL_FLAMEBUFFET = 23341,
SPELL_PYROBLAST = 20228 // guesswork, but best fitting in spells-area, was 17274 (has mana cost)
};
struct boss_pyroguard_emberseer : public CreatureScript
{
boss_pyroguard_emberseer() : CreatureScript("boss_pyroguard_emberseer") {}
struct boss_pyroguard_emberseerAI : public ScriptedAI
{
boss_pyroguard_emberseerAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = pCreature->GetInstanceData();
}
InstanceData* m_pInstance;
uint32 m_uiEncageTimer;
uint32 m_uiFireNovaTimer;
uint32 m_uiFlameBuffetTimer;
uint32 m_uiPyroBlastTimer;
uint8 m_uiGrowingStacks;
void Reset() override
{
m_uiEncageTimer = 10000;
m_uiFireNovaTimer = 6000;
m_uiFlameBuffetTimer = 3000;
m_uiPyroBlastTimer = 14000;
m_uiGrowingStacks = 0;
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_EMBERSEER, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_EMBERSEER, FAIL);
}
}
void ReceiveAIEvent(AIEventType type, Creature* pSender, Unit* /*pInvoker*/, uint32 /*uiMiscValue*/) override
{
if (type == AI_EVENT_CUSTOM_A && pSender == m_creature) //defined in the spell
DoHandleEmberseerGrowing();
}
void UpdateAI(const uint32 uiDiff) override
{
// Cast Encage spell on OOC timer
if (m_uiEncageTimer)
{
if (m_uiEncageTimer <= uiDiff)
{
if (!m_pInstance)
{
script_error_log("Instance Blackrock Spire: ERROR Failed to load instance data for this instace.");
return;
}
m_pInstance->SetData64(NPC_PYROGUARD_EMBERSEER, m_creature->GetObjectGuid());
m_uiEncageTimer = 0;
}
else
{
m_uiEncageTimer -= uiDiff;
}
}
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// FireNova Timer
if (m_uiFireNovaTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FIRENOVA) == CAST_OK)
{
m_uiFireNovaTimer = 6000;
}
}
else
{
m_uiFireNovaTimer -= uiDiff;
}
// FlameBuffet Timer
if (m_uiFlameBuffetTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FLAMEBUFFET) == CAST_OK)
{
m_uiFlameBuffetTimer = 14000;
}
}
else
{
m_uiFlameBuffetTimer -= uiDiff;
}
// PyroBlast Timer
if (m_uiPyroBlastTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_PYROBLAST) == CAST_OK)
{
m_uiPyroBlastTimer = 15000;
}
}
}
else
{
m_uiPyroBlastTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
private:
// Wrapper to handle the transformation
void DoHandleEmberseerGrowing()
{
++m_uiGrowingStacks;
if (m_uiGrowingStacks == MAX_GROWING_STACKS * 0.5f)
{
DoScriptText(EMOTE_NEAR, m_creature);
}
else if (m_uiGrowingStacks == MAX_GROWING_STACKS)
{
DoScriptText(EMOTE_FULL, m_creature);
DoScriptText(SAY_FREE, m_creature);
// Note: the spell order needs further research
DoCastSpellIfCan(m_creature, SPELL_FULL_STRENGHT, CAST_TRIGGERED);
DoCastSpellIfCan(m_creature, SPELL_BONUS_DAMAGE, CAST_TRIGGERED);
DoCastSpellIfCan(m_creature, SPELL_TRANSFORM, CAST_TRIGGERED);
// activate all runes
if (m_pInstance)
{
m_pInstance->SetData(MAX_ENCOUNTER, DO_ACTIVATE_RUNES);
// Redundant check: if for some reason the event isn't set in progress until this point - avoid using the altar again when the boss is fully grown
m_pInstance->SetData(TYPE_EMBERSEER, IN_PROGRESS);
}
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_pyroguard_emberseerAI(pCreature);
}
};
struct spell_emberseer_growing : public SpellScript
{
spell_emberseer_growing() : SpellScript("spell_emberseer_growing") {}
bool EffectDummy(Unit* /*pCaster*/, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Object* pCreatureTarget, ObjectGuid /*originalCasterGuid*/) override
{
// always check spellid and effectindex
if (uiSpellId == SPELL_GROWING && uiEffIndex == EFFECT_INDEX_0)
{
if (CreatureAI* pEmberseerAI = pCreatureTarget->ToCreature()->AI())
{
pEmberseerAI->SendAIEvent(AI_EVENT_CUSTOM_A, pCreatureTarget->ToCreature(), pCreatureTarget->ToCreature(), 0);
}
return true;
}
return false;
}
};
void AddSC_boss_pyroguard_emberseer()
{
Script *s;
s = new boss_pyroguard_emberseer();
s->RegisterSelf();
s = new spell_emberseer_growing();
s->RegisterSelf();
//Script* pNewScript;
//pNewScript = new Script;
//pNewScript->Name = "boss_pyroguard_emberseer";
//pNewScript->GetAI = &GetAI_boss_pyroguard_emberseer;
//pNewScript->pEffectDummyNPC = &EffectDummyCreature_pyroguard_emberseer;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,86 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
#ifndef DEF_BLACKWING_LAIR
#define DEF_BLACKWING_LAIR
enum
{
MAX_ENCOUNTER = 8,
TYPE_RAZORGORE = 0,
TYPE_VAELASTRASZ = 1,
TYPE_LASHLAYER = 2,
TYPE_FIREMAW = 3,
TYPE_EBONROC = 4,
TYPE_FLAMEGOR = 5,
TYPE_CHROMAGGUS = 6,
TYPE_NEFARIAN = 7,
DATA_DRAGON_EGG = 1, // track the used eggs
NPC_RAZORGORE = 12435,
NPC_VAELASTRASZ = 13020,
NPC_LASHLAYER = 12017,
NPC_FIREMAW = 11983,
NPC_EBONROC = 14601,
NPC_FLAMEGOR = 11981,
NPC_CHROMAGGUS = 14020,
NPC_NEFARIAN = 11583,
NPC_LORD_VICTOR_NEFARIUS = 10162,
NPC_BLACKWING_TECHNICIAN = 13996, // Flees at Vael intro event
// Razorgore event related
NPC_GRETHOK_CONTROLLER = 12557,
NPC_BLACKWING_ORB_TRIGGER = 14449,
NPC_NEFARIANS_TROOPS = 14459,
NPC_MONSTER_GENERATOR = 12434,
NPC_BLACKWING_LEGIONNAIRE = 12416, // one spawn per turn
NPC_BLACKWING_MAGE = 12420, // one spawn per turn
NPC_DRAGONSPAWN = 12422, // two spawns per turn
GO_DOOR_RAZORGORE_ENTER = 176964,
GO_DOOR_RAZORGORE_EXIT = 176965,
GO_DOOR_NEFARIAN = 176966,
// GO_DOOR_CHROMAGGUS_ENTER = 179115,
// GO_DOOR_CHROMAGGUS_SIDE = 179116,
GO_DOOR_CHROMAGGUS_EXIT = 179117,
GO_DOOR_VAELASTRASZ = 179364,
GO_DOOR_LASHLAYER = 179365,
GO_ORB_OF_DOMINATION = 177808, // trigger 19832 on Razorgore
GO_BLACK_DRAGON_EGG = 177807,
GO_DRAKONID_BONES = 179804,
EMOTE_ORB_SHUT_OFF = -1469035,
EMOTE_TROOPS_FLEE = -1469033, // emote by Nefarian's Troops npc
MAX_EGGS_DEFENDERS = 4,
};
// Coords used to spawn Nefarius at the throne
static const float aNefariusSpawnLoc[4] = { -7466.16f, -1040.80f, 412.053f, 2.14675f};
#endif

View file

@ -0,0 +1,188 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Broodlord_Lashlayer
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SAY_AGGRO = -1469000,
SAY_LEASH = -1469001,
SPELL_CLEAVE = 26350,
SPELL_BLAST_WAVE = 23331,
SPELL_MORTAL_STRIKE = 24573,
SPELL_KNOCK_AWAY = 25778
};
struct boss_broodlord : public CreatureScript
{
boss_broodlord() : CreatureScript("boss_broodlord") {}
struct boss_broodlordAI : public ScriptedAI
{
boss_broodlordAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiCleaveTimer;
uint32 m_uiBlastWaveTimer;
uint32 m_uiMortalStrikeTimer;
uint32 m_uiKnockAwayTimer;
void Reset() override
{
m_uiCleaveTimer = 8000; // These times are probably wrong
m_uiBlastWaveTimer = 12000;
m_uiMortalStrikeTimer = 20000;
m_uiKnockAwayTimer = 30000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LASHLAYER, IN_PROGRESS);
}
DoScriptText(SAY_AGGRO, m_creature);
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LASHLAYER, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LASHLAYER, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Cleave Timer
if (m_uiCleaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
{
m_uiCleaveTimer = 7000;
}
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// Blast Wave
if (m_uiBlastWaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_BLAST_WAVE) == CAST_OK)
{
m_uiBlastWaveTimer = urand(8000, 16000);
}
}
else
{
m_uiBlastWaveTimer -= uiDiff;
}
// Mortal Strike Timer
if (m_uiMortalStrikeTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MORTAL_STRIKE) == CAST_OK)
{
m_uiMortalStrikeTimer = urand(25000, 35000);
}
}
else
{
m_uiMortalStrikeTimer -= uiDiff;
}
if (m_uiKnockAwayTimer < uiDiff)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_KNOCK_AWAY);
// Drop 50% aggro - TODO should be scriptedEffect?
if (m_creature->GetThreatManager().getThreat(m_creature->getVictim()))
{
m_creature->GetThreatManager().modifyThreatPercent(m_creature->getVictim(), -50);
}
m_uiKnockAwayTimer = urand(15000, 30000);
}
else
{
m_uiKnockAwayTimer -= uiDiff;
}
DoMeleeAttackIfReady();
if (EnterEvadeIfOutOfCombatArea(uiDiff))
{
DoScriptText(SAY_LEASH, m_creature);
}
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_broodlordAI(pCreature);
}
};
void AddSC_boss_broodlord()
{
Script* s;
s = new boss_broodlord();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_broodlord";
//pNewScript->GetAI = &GetAI_boss_broodlord;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,312 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Chromaggus
* SD%Complete: 90
* SDComment: Chromatic Mutation disabled due to lack of core support
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
EMOTE_GENERIC_FRENZY_KILL = -1000001,
EMOTE_SHIMMER = -1469003,
// These spells are actually called elemental shield
// What they do is decrease all damage by 75% then they increase
// One school of damage by 1100%
SPELL_FIRE_VULNERABILITY = 22277,
SPELL_FROST_VULNERABILITY = 22278,
SPELL_SHADOW_VULNERABILITY = 22279,
SPELL_NATURE_VULNERABILITY = 22280,
SPELL_ARCANE_VULNERABILITY = 22281,
MAX_BREATHS = 5,
SPELL_INCINERATE = 23308, // Incinerate 23308,23309
SPELL_TIME_LAPSE = 23310, // Time lapse 23310, 23311(old threat mod that was removed in 2.01)
SPELL_CORROSIVE_ACID = 23313, // Corrosive Acid 23313, 23314
SPELL_IGNITE_FLESH = 23315, // Ignite Flesh 23315,23316
SPELL_FROST_BURN = 23187, // Frost burn 23187, 23189
// Brood Affliction 23173 - Scripted Spell that cycles through all targets within 100 yards and has a chance to cast one of the afflictions on them
// Since Scripted spells arn't coded I'll just write a function that does the same thing
SPELL_BROODAF_BLUE = 23153, // Blue affliction 23153
SPELL_BROODAF_BLACK = 23154, // Black affliction 23154
SPELL_BROODAF_RED = 23155, // Red affliction 23155 (23168 on death)
SPELL_BROODAF_BRONZE = 23170, // Bronze Affliction 23170
SPELL_BROODAF_GREEN = 23169, // Brood Affliction Green 23169
SPELL_CHROMATIC_MUT_1 = 23174, // Spell cast on player if they get all 5 debuffs
SPELL_FRENZY = 28371, // The frenzy spell may be wrong
SPELL_ENRAGE = 28747
};
static const uint32 aPossibleBreaths[MAX_BREATHS] = {SPELL_INCINERATE, SPELL_TIME_LAPSE, SPELL_CORROSIVE_ACID, SPELL_IGNITE_FLESH, SPELL_FROST_BURN};
struct boss_chromaggus : public CreatureScript
{
boss_chromaggus() : CreatureScript("boss_chromaggus") {}
struct boss_chromaggusAI : public ScriptedAI
{
boss_chromaggusAI(Creature* pCreature) : ScriptedAI(pCreature)
{
// Select the 2 different breaths that we are going to use until despawned
// 5 possiblities for the first breath, 4 for the second, 20 total possiblites
// select two different numbers between 0..MAX_BREATHS-1
uint8 uiPos1 = urand(0, MAX_BREATHS - 1);
uint8 uiPos2 = (uiPos1 + urand(1, MAX_BREATHS - 1)) % MAX_BREATHS;
m_uiBreathOneSpell = aPossibleBreaths[uiPos1];
m_uiBreathTwoSpell = aPossibleBreaths[uiPos2];
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiBreathOneSpell;
uint32 m_uiBreathTwoSpell;
uint32 m_uiCurrentVulnerabilitySpell;
uint32 m_uiShimmerTimer;
uint32 m_uiBreathOneTimer;
uint32 m_uiBreathTwoTimer;
uint32 m_uiAfflictionTimer;
uint32 m_uiFrenzyTimer;
bool m_bEnraged;
void Reset() override
{
m_uiCurrentVulnerabilitySpell = 0; // We use this to store our last vulnerability spell so we can remove it later
m_uiShimmerTimer = 0; // Time till we change vurlnerabilites
m_uiBreathOneTimer = 30000; // First breath is 30 seconds
m_uiBreathTwoTimer = 60000; // Second is 1 minute so that we can alternate
m_uiAfflictionTimer = 10000; // This is special - 5 seconds means that we cast this on 1 pPlayer every 5 sconds
m_uiFrenzyTimer = 15000;
m_bEnraged = false;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_CHROMAGGUS, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_CHROMAGGUS, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_CHROMAGGUS, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Shimmer Timer Timer
if (m_uiShimmerTimer < uiDiff)
{
// Remove old vulnerability spell
if (m_uiCurrentVulnerabilitySpell)
{
m_creature->RemoveAurasDueToSpell(m_uiCurrentVulnerabilitySpell);
}
// Cast new random vurlnabilty on self
uint32 aSpellId[] = { SPELL_FIRE_VULNERABILITY, SPELL_FROST_VULNERABILITY, SPELL_SHADOW_VULNERABILITY, SPELL_NATURE_VULNERABILITY, SPELL_ARCANE_VULNERABILITY };
uint32 uiSpell = aSpellId[urand(0, 4)];
if (DoCastSpellIfCan(m_creature, uiSpell) == CAST_OK)
{
m_uiCurrentVulnerabilitySpell = uiSpell;
DoScriptText(EMOTE_SHIMMER, m_creature);
m_uiShimmerTimer = 45000;
}
}
else
{
m_uiShimmerTimer -= uiDiff;
}
// Breath One Timer
if (m_uiBreathOneTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, m_uiBreathOneSpell) == CAST_OK)
{
m_uiBreathOneTimer = 60000;
}
}
else
{
m_uiBreathOneTimer -= uiDiff;
}
// Breath Two Timer
if (m_uiBreathTwoTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, m_uiBreathTwoSpell) == CAST_OK)
{
m_uiBreathTwoTimer = 60000;
}
}
else
{
m_uiBreathTwoTimer -= uiDiff;
}
// Affliction Timer
if (m_uiAfflictionTimer < uiDiff)
{
uint32 m_uiSpellAfflict = 0;
switch (urand(0, 4))
{
case 0:
m_uiSpellAfflict = SPELL_BROODAF_BLUE;
break;
case 1:
m_uiSpellAfflict = SPELL_BROODAF_BLACK;
break;
case 2:
m_uiSpellAfflict = SPELL_BROODAF_RED;
break;
case 3:
m_uiSpellAfflict = SPELL_BROODAF_BRONZE;
break;
case 4:
m_uiSpellAfflict = SPELL_BROODAF_GREEN;
break;
}
GuidVector vGuids;
m_creature->FillGuidsListFromThreatList(vGuids);
for (GuidVector::const_iterator i = vGuids.begin(); i != vGuids.end(); ++i)
{
Unit* pUnit = m_creature->GetMap()->GetUnit(*i);
if (pUnit)
{
// Cast affliction
DoCastSpellIfCan(pUnit, m_uiSpellAfflict, CAST_TRIGGERED);
// Chromatic mutation if target is effected by all afflictions
if (pUnit->HasAura(SPELL_BROODAF_BLUE, EFFECT_INDEX_0)
&& pUnit->HasAura(SPELL_BROODAF_BLACK, EFFECT_INDEX_0)
&& pUnit->HasAura(SPELL_BROODAF_RED, EFFECT_INDEX_0)
&& pUnit->HasAura(SPELL_BROODAF_BRONZE, EFFECT_INDEX_0)
&& pUnit->HasAura(SPELL_BROODAF_GREEN, EFFECT_INDEX_0))
{
// target->RemoveAllAuras();
// DoCastSpellIfCan(target,SPELL_CHROMATIC_MUT_1);
// Chromatic mutation is causing issues
// Assuming it is caused by a lack of core support for Charm
// So instead we instant kill our target
// WORKAROUND
if (pUnit->GetTypeId() == TYPEID_PLAYER)
{
m_creature->CastSpell(pUnit, 5, false);
}
}
}
}
m_uiAfflictionTimer = 10000;
}
else
{
m_uiAfflictionTimer -= uiDiff;
}
// Frenzy Timer
if (m_uiFrenzyTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
{
DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
m_uiFrenzyTimer = urand(10000, 15000);
}
}
else
{
m_uiFrenzyTimer -= uiDiff;
}
// Enrage if not already enraged and below 20%
if (!m_bEnraged && m_creature->GetHealthPercent() < 20.0f)
{
DoCastSpellIfCan(m_creature, SPELL_ENRAGE);
m_bEnraged = true;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_chromaggusAI(pCreature);
}
};
void AddSC_boss_chromaggus()
{
Script* s;
s = new boss_chromaggus();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_chromaggus";
//pNewScript->GetAI = &GetAI_boss_chromaggus;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,176 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Ebonroc
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SPELL_SHADOW_FLAME = 22539,
SPELL_WING_BUFFET = 18500,
SPELL_SHADOW_OF_EBONROC = 23340,
SPELL_THRASH = 3391
};
struct boss_ebonroc : public CreatureScript
{
boss_ebonroc() : CreatureScript("boss_ebonroc") {}
struct boss_ebonrocAI : public ScriptedAI
{
boss_ebonrocAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiShadowFlameTimer;
uint32 m_uiWingBuffetTimer;
uint32 m_uiShadowOfEbonrocTimer;
uint32 m_uiTrashTimer;
void Reset() override
{
m_uiShadowFlameTimer = 15000; // These times are probably wrong
m_uiWingBuffetTimer = 30000;
m_uiShadowOfEbonrocTimer = 45000;
m_uiTrashTimer = 25000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_EBONROC, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_EBONROC, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_EBONROC, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Shadow Flame Timer
if (m_uiShadowFlameTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOW_FLAME) == CAST_OK)
{
m_uiShadowFlameTimer = urand(12000, 15000);
}
}
else
{
m_uiShadowFlameTimer -= uiDiff;
}
// Wing Buffet Timer
if (m_uiWingBuffetTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_WING_BUFFET) == CAST_OK)
{
m_uiWingBuffetTimer = 25000;
}
}
else
{
m_uiWingBuffetTimer -= uiDiff;
}
// Shadow of Ebonroc Timer
if (m_uiShadowOfEbonrocTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_SHADOW_OF_EBONROC) == CAST_OK)
{
m_uiShadowOfEbonrocTimer = urand(25000, 35000);
}
}
else
{
m_uiShadowOfEbonrocTimer -= uiDiff;
}
// Thrash Timer
if (m_uiTrashTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_THRASH) == CAST_OK)
{
m_uiTrashTimer = 20000;
}
}
else
{
m_uiTrashTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_ebonrocAI(pCreature);
}
};
void AddSC_boss_ebonroc()
{
Script* s;
s = new boss_ebonroc();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_ebonroc";
//pNewScript->GetAI = &GetAI_boss_ebonroc;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,181 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Firemaw
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SPELL_SHADOW_FLAME = 22539,
SPELL_WING_BUFFET = 23339,
SPELL_FLAME_BUFFET = 23341,
SPELL_THRASH = 3391
};
struct boss_firemaw : public CreatureScript
{
boss_firemaw() : CreatureScript("boss_firemaw") {}
struct boss_firemawAI : public ScriptedAI
{
boss_firemawAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiShadowFlameTimer;
uint32 m_uiWingBuffetTimer;
uint32 m_uiFlameBuffetTimer;
uint32 m_uiTrashTimer;
void Reset() override
{
m_uiShadowFlameTimer = 30000; // These times are probably wrong
m_uiWingBuffetTimer = 24000;
m_uiFlameBuffetTimer = 5000;
m_uiTrashTimer = 25000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FIREMAW, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FIREMAW, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FIREMAW, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Shadow Flame Timer
if (m_uiShadowFlameTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOW_FLAME) == CAST_OK)
{
m_uiShadowFlameTimer = urand(15000, 18000);
}
}
else
{
m_uiShadowFlameTimer -= uiDiff;
}
// Wing Buffet Timer
if (m_uiWingBuffetTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_WING_BUFFET) == CAST_OK)
{
if (m_creature->GetThreatManager().getThreat(m_creature->getVictim()))
{
m_creature->GetThreatManager().modifyThreatPercent(m_creature->getVictim(), -75);
}
m_uiWingBuffetTimer = 25000;
}
}
else
{
m_uiWingBuffetTimer -= uiDiff;
}
// Flame Buffet Timer
if (m_uiFlameBuffetTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FLAME_BUFFET) == CAST_OK)
{
m_uiFlameBuffetTimer = 5000;
}
}
else
{
m_uiFlameBuffetTimer -= uiDiff;
}
// Thrash Timer
if (m_uiTrashTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_THRASH) == CAST_OK)
{
m_uiTrashTimer = 20000;
}
}
else
{
m_uiTrashTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_firemawAI(pCreature);
}
};
void AddSC_boss_firemaw()
{
Script* s;
s = new boss_firemaw();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_firemaw";
//pNewScript->GetAI = &GetAI_boss_firemaw;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,184 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Flamegor
* SD%Complete: 100
* SDComment: None
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
EMOTE_GENERIC_FRENZY = -1000002,
SPELL_SHADOW_FLAME = 22539,
SPELL_WING_BUFFET = 23339,
SPELL_FRENZY = 23342, // This spell periodically triggers fire nova
SPELL_THRASH = 3391
};
struct boss_flamegor : public CreatureScript
{
boss_flamegor() : CreatureScript("boss_flamegor") {}
struct boss_flamegorAI : public ScriptedAI
{
boss_flamegorAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiShadowFlameTimer;
uint32 m_uiWingBuffetTimer;
uint32 m_uiFrenzyTimer;
uint32 m_uiTrashTimer;
void Reset() override
{
m_uiShadowFlameTimer = 21000; // These times are probably wrong
m_uiWingBuffetTimer = 35000;
m_uiFrenzyTimer = 10000;
m_uiTrashTimer = 25000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FLAMEGOR, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FLAMEGOR, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_FLAMEGOR, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Shadow Flame Timer
if (m_uiShadowFlameTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOW_FLAME) == CAST_OK)
{
m_uiShadowFlameTimer = urand(15000, 22000);
}
}
else
{
m_uiShadowFlameTimer -= uiDiff;
}
// Wing Buffet Timer
if (m_uiWingBuffetTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_WING_BUFFET) == CAST_OK)
{
if (m_creature->GetThreatManager().getThreat(m_creature->getVictim()))
{
m_creature->GetThreatManager().modifyThreatPercent(m_creature->getVictim(), -75);
}
m_uiWingBuffetTimer = 25000;
}
}
else
{
m_uiWingBuffetTimer -= uiDiff;
}
// Frenzy Timer
if (m_uiFrenzyTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
{
DoScriptText(EMOTE_GENERIC_FRENZY, m_creature);
m_uiFrenzyTimer = urand(8000, 10000);
}
}
else
{
m_uiFrenzyTimer -= uiDiff;
}
// Thrash Timer
if (m_uiTrashTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_THRASH) == CAST_OK)
{
m_uiTrashTimer = 20000;
}
}
else
{
m_uiTrashTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_flamegorAI(pCreature);
}
};
void AddSC_boss_flamegor()
{
Script* s;
s = new boss_flamegor();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_flamegor";
//pNewScript->GetAI = &GetAI_boss_flamegor;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,331 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Nefarian
* SD%Complete: 80
* SDComment: Some issues with class calls effecting more than one class
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
#include "TemporarySummon.h"
enum
{
SAY_XHEALTH = -1469008, // at 5% hp
SAY_AGGRO = -1469009,
SAY_RAISE_SKELETONS = -1469010,
SAY_SLAY = -1469011,
SAY_DEATH = -1469012,
SAY_MAGE = -1469013,
SAY_WARRIOR = -1469014,
SAY_DRUID = -1469015,
SAY_PRIEST = -1469016,
SAY_PALADIN = -1469017,
SAY_SHAMAN = -1469018,
SAY_WARLOCK = -1469019,
SAY_HUNTER = -1469020,
SAY_ROGUE = -1469021,
SAY_DEATH_KNIGHT = -1469031, // spell unk for the moment
SPELL_SHADOWFLAME_INITIAL = 22992, // old spell id 22972 -> wrong
SPELL_SHADOWFLAME = 22539,
SPELL_BELLOWING_ROAR = 22686,
SPELL_VEIL_OF_SHADOW = 22687, // old spell id 7068 -> wrong
SPELL_CLEAVE = 20691,
SPELL_TAIL_LASH = 23364,
// SPELL_BONE_CONTRUST = 23363, // 23362, 23361 Missing from DBC!
SPELL_MAGE = 23410, // wild magic
SPELL_WARRIOR = 23397, // beserk
SPELL_DRUID = 23398, // cat form
SPELL_PRIEST = 23401, // corrupted healing
SPELL_PALADIN = 23418, // syphon blessing
SPELL_SHAMAN = 23425, // totems
SPELL_WARLOCK = 23427, // infernals -> should trigger 23426
SPELL_HUNTER = 23436, // bow broke
SPELL_ROGUE = 23414, // Paralise
};
struct boss_nefarian : public CreatureScript
{
boss_nefarian() : CreatureScript("boss_nefarian") {}
struct boss_nefarianAI : public ScriptedAI
{
boss_nefarianAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiShadowFlameTimer;
uint32 m_uiBellowingRoarTimer;
uint32 m_uiVeilOfShadowTimer;
uint32 m_uiCleaveTimer;
uint32 m_uiTailLashTimer;
uint32 m_uiClassCallTimer;
bool m_bPhase3;
bool m_bHasEndYell;
void Reset() override
{
m_uiShadowFlameTimer = 12000; // These times are probably wrong
m_uiBellowingRoarTimer = 30000;
m_uiVeilOfShadowTimer = 15000;
m_uiCleaveTimer = 7000;
m_uiTailLashTimer = 10000;
m_uiClassCallTimer = 35000; // 35-40 seconds
m_bPhase3 = false;
m_bHasEndYell = false;
}
void KilledUnit(Unit* pVictim) override
{
if (urand(0, 4))
{
return;
}
DoScriptText(SAY_SLAY, m_creature, pVictim);
}
void JustDied(Unit* /*pKiller*/) override
{
DoScriptText(SAY_DEATH, m_creature);
if (m_pInstance)
{
m_pInstance->SetData(TYPE_NEFARIAN, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_NEFARIAN, FAIL);
// Cleanup encounter
if (m_creature->IsTemporarySummon())
{
TemporarySummon* pTemporary = (TemporarySummon*)m_creature;
if (Creature* pNefarius = m_creature->GetMap()->GetCreature(pTemporary->GetSummonerGuid()))
{
pNefarius->AI()->EnterEvadeMode();
}
}
m_creature->ForcedDespawn();
}
}
void Aggro(Unit* /*pWho*/) override
{
DoScriptText(SAY_AGGRO, m_creature);
// Remove flying in case Nefarian aggroes before his combat point was reached
if (m_creature->IsLevitating())
{
m_creature->SetByteValue(UNIT_FIELD_BYTES_1, 3, 0);
m_creature->SetLevitate(false);
}
DoCastSpellIfCan(m_creature, SPELL_SHADOWFLAME_INITIAL);
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// ShadowFlame_Timer
if (m_uiShadowFlameTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOWFLAME) == CAST_OK)
{
m_uiShadowFlameTimer = 12000;
}
}
else
{
m_uiShadowFlameTimer -= uiDiff;
}
// BellowingRoar_Timer
if (m_uiBellowingRoarTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_BELLOWING_ROAR) == CAST_OK)
{
m_uiBellowingRoarTimer = 30000;
}
}
else
{
m_uiBellowingRoarTimer -= uiDiff;
}
// VeilOfShadow_Timer
if (m_uiVeilOfShadowTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_VEIL_OF_SHADOW) == CAST_OK)
{
m_uiVeilOfShadowTimer = 15000;
}
}
else
{
m_uiVeilOfShadowTimer -= uiDiff;
}
// Cleave_Timer
if (m_uiCleaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
{
m_uiCleaveTimer = 7000;
}
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// TailLash_Timer
if (m_uiTailLashTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_TAIL_LASH) == CAST_OK)
{
m_uiTailLashTimer = 10000;
}
}
else
{
m_uiTailLashTimer -= uiDiff;
}
// ClassCall_Timer
if (m_uiClassCallTimer < uiDiff)
{
// Cast a random class call
// On official it is based on what classes are currently on the hostil list
// but we can't do that yet so just randomly call one
switch (urand(0, 8))
{
case 0:
DoScriptText(SAY_MAGE, m_creature);
DoCastSpellIfCan(m_creature, SPELL_MAGE);
break;
case 1:
DoScriptText(SAY_WARRIOR, m_creature);
DoCastSpellIfCan(m_creature, SPELL_WARRIOR);
break;
case 2:
DoScriptText(SAY_DRUID, m_creature);
DoCastSpellIfCan(m_creature, SPELL_DRUID);
break;
case 3:
DoScriptText(SAY_PRIEST, m_creature);
DoCastSpellIfCan(m_creature, SPELL_PRIEST);
break;
case 4:
DoScriptText(SAY_PALADIN, m_creature);
DoCastSpellIfCan(m_creature, SPELL_PALADIN);
break;
case 5:
DoScriptText(SAY_SHAMAN, m_creature);
DoCastSpellIfCan(m_creature, SPELL_SHAMAN);
break;
case 6:
DoScriptText(SAY_WARLOCK, m_creature);
DoCastSpellIfCan(m_creature, SPELL_WARLOCK);
break;
case 7:
DoScriptText(SAY_HUNTER, m_creature);
DoCastSpellIfCan(m_creature, SPELL_HUNTER);
break;
case 8:
DoScriptText(SAY_ROGUE, m_creature);
DoCastSpellIfCan(m_creature, SPELL_ROGUE);
break;
}
m_uiClassCallTimer = urand(35000, 40000);
}
else
{
m_uiClassCallTimer -= uiDiff;
}
// Phase3 begins when we are below X health
if (!m_bPhase3 && m_creature->GetHealthPercent() < 20.0f)
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_NEFARIAN, SPECIAL);
}
m_bPhase3 = true;
DoScriptText(SAY_RAISE_SKELETONS, m_creature);
}
// 5% hp yell
if (!m_bHasEndYell && m_creature->GetHealthPercent() < 5.0f)
{
m_bHasEndYell = true;
DoScriptText(SAY_XHEALTH, m_creature);
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_nefarianAI(pCreature);
}
};
void AddSC_boss_nefarian()
{
Script* s;
s = new boss_nefarian();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_nefarian";
//pNewScript->GetAI = &GetAI_boss_nefarian;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,310 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Razorgore
* SD%Complete: 95
* SDComment: Timers may be improved.
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SAY_EGGS_BROKEN_1 = -1469022,
SAY_EGGS_BROKEN_2 = -1469023,
SAY_EGGS_BROKEN_3 = -1469024,
SAY_DEATH = -1469025,
SPELL_POSSESS = 23014, // visual effect and increase the damage taken
SPELL_DESTROY_EGG = 19873,
SPELL_EXPLODE_ORB = 20037, // used if attacked without destroying the eggs - triggers 20038
SPELL_CLEAVE = 19632,
SPELL_WARSTOMP = 24375,
SPELL_FIREBALL_VOLLEY = 22425,
SPELL_CONFLAGRATION = 23023,
};
struct boss_razorgore : public CreatureScript
{
boss_razorgore() : CreatureScript("boss_razorgore") {}
struct boss_razorgoreAI : public ScriptedAI
{
boss_razorgoreAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
Reset();
}
ScriptedInstance* m_pInstance;
uint32 m_uiIntroVisualTimer;
uint32 m_uiCleaveTimer;
uint32 m_uiWarStompTimer;
uint32 m_uiFireballVolleyTimer;
uint32 m_uiConflagrationTimer;
bool m_bEggsExploded;
void Reset() override
{
m_uiIntroVisualTimer = 5000;
m_bEggsExploded = false;
m_uiCleaveTimer = urand(4000, 8000);
m_uiWarStompTimer = 30000;
m_uiConflagrationTimer = urand(10000, 15000);
m_uiFireballVolleyTimer = urand(15000, 20000);
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
// Don't set instance data unless all eggs are destroyed
if (m_pInstance->GetData(TYPE_RAZORGORE) != SPECIAL)
{
return;
}
m_pInstance->SetData(TYPE_RAZORGORE, DONE);
}
DoScriptText(SAY_DEATH, m_creature);
}
void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) override
{
if (uiDamage < m_creature->GetHealth())
{
return;
}
if (!m_pInstance)
{
return;
}
// Don't allow any accident
if (m_bEggsExploded)
{
uiDamage = 0;
return;
}
// Boss explodes everything and resets - this happens if not all eggs are destroyed
if (m_pInstance->GetData(TYPE_RAZORGORE) == IN_PROGRESS)
{
uiDamage = 0;
m_bEggsExploded = true;
m_pInstance->SetData(TYPE_RAZORGORE, FAIL);
DoCastSpellIfCan(m_creature, SPELL_EXPLODE_ORB, CAST_TRIGGERED);
m_creature->ForcedDespawn();
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_RAZORGORE, FAIL);
}
}
void JustSummoned(Creature* pSummoned) override
{
// Defenders should attack the players and the boss
pSummoned->SetInCombatWithZone();
pSummoned->AI()->AttackStart(m_creature);
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
// Set visual only on OOC timer
if (m_uiIntroVisualTimer)
{
if (m_uiIntroVisualTimer <= uiDiff)
{
if (!m_pInstance)
{
script_error_log("Instance Blackwing Lair: ERROR Failed to load instance data for this instace.");
return;
}
if (Creature* pOrbTrigger = m_pInstance->GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER))
{
pOrbTrigger->CastSpell(m_creature, SPELL_POSSESS, false);
}
m_uiIntroVisualTimer = 0;
}
else
{
m_uiIntroVisualTimer -= uiDiff;
}
}
return;
}
// Cleave
if (m_uiCleaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
{
m_uiCleaveTimer = urand(4000, 8000);
}
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// War Stomp
if (m_uiWarStompTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_WARSTOMP) == CAST_OK)
{
m_uiWarStompTimer = 30000;
}
}
else
{
m_uiWarStompTimer -= uiDiff;
}
// Fireball Volley
if (m_uiFireballVolleyTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FIREBALL_VOLLEY) == CAST_OK)
{
m_uiFireballVolleyTimer = urand(15000, 20000);
}
}
else
{
m_uiFireballVolleyTimer -= uiDiff;
}
// Conflagration
if (m_uiConflagrationTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_CONFLAGRATION) == CAST_OK)
{
m_uiConflagrationTimer = urand(15000, 25000);
}
}
else
{
m_uiConflagrationTimer -= uiDiff;
}
/* This is obsolete code, not working anymore, keep as reference, should be handled in core though
* // Aura Check. If the gamer is affected by confliguration we attack a random gamer.
* if (m_creature->getVictim()->HasAura(SPELL_CONFLAGRATION, EFFECT_INDEX_0))
* {
* if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
* m_creature->TauntApply(pTarget);
* }
*/
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_razorgoreAI(pCreature);
}
};
struct spell_go_black_dragon_egg : public SpellScript
{
spell_go_black_dragon_egg() : SpellScript("spell_go_black_dragon_egg") {}
bool EffectDummy(Unit* pCaster, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Object* pGOTarget, ObjectGuid /*originalCasterGuid*/) override
{
if (uiSpellId == SPELL_DESTROY_EGG && uiEffIndex == EFFECT_INDEX_1)
{
if (!pGOTarget->ToGameObject()->isSpawned())
{
return true;
}
if (ScriptedInstance* pInstance = (ScriptedInstance*)pGOTarget->ToGameObject()->GetInstanceData())
{
if (urand(0, 1))
{
switch (urand(0, 2))
{
case 0:
DoScriptText(SAY_EGGS_BROKEN_1, pCaster);
break;
case 1:
DoScriptText(SAY_EGGS_BROKEN_2, pCaster);
break;
case 2:
DoScriptText(SAY_EGGS_BROKEN_3, pCaster);
break;
}
}
// Store the eggs which are destroyed, in order to count them for the second phase
pInstance->SetData64(DATA_DRAGON_EGG, pGOTarget->GetObjectGuid().GetRawValue());
}
return true;
}
return false;
}
};
void AddSC_boss_razorgore()
{
Script* s;
s = new boss_razorgore();
s->RegisterSelf();
s = new spell_go_black_dragon_egg();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_razorgore";
//pNewScript->GetAI = &GetAI_boss_razorgore;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "go_black_dragon_egg";
//pNewScript->pEffectDummyGO = &EffectDummyGameObj_go_black_dragon_egg;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,472 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Vaelastrasz
* SD%Complete: 75
* SDComment: Burning Adrenaline not correctly implemented in core
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SAY_LINE_1 = -1469026,
SAY_LINE_2 = -1469027,
SAY_LINE_3 = -1469028,
SAY_HALFLIFE = -1469029,
SAY_KILLTARGET = -1469030,
SAY_NEFARIUS_CORRUPT_1 = -1469006, // When he corrupts Vaelastrasz
SAY_NEFARIUS_CORRUPT_2 = -1469032,
SAY_TECHNICIAN_RUN = -1469034,
SPELL_ESSENCE_OF_THE_RED = 23513,
SPELL_FLAME_BREATH = 23461,
SPELL_FIRE_NOVA = 23462,
SPELL_TAIL_SWEEP = 15847,
SPELL_BURNING_ADRENALINE = 23620,
SPELL_CLEAVE = 20684, // Chain cleave is most likely named something different and contains a dummy effect
SPELL_NEFARIUS_CORRUPTION = 23642,
GOSSIP_ITEM_VAEL_1 = -3469003,
GOSSIP_ITEM_VAEL_2 = -3469004,
// Vael Gossip texts might be 7156 and 7256; At the moment are missing from DB
// For the moment add the default values
GOSSIP_TEXT_VAEL_1 = 384,
GOSSIP_TEXT_VAEL_2 = 384,
FACTION_HOSTILE = 14,
AREATRIGGER_VAEL_INTRO = 3626,
};
struct boss_vaelastrasz : public CreatureScript
{
boss_vaelastrasz() : CreatureScript("boss_vaelastrasz") {}
struct boss_vaelastraszAI : public ScriptedAI
{
boss_vaelastraszAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
// Set stand state to dead before the intro event
m_creature->SetStandState(UNIT_STAND_STATE_DEAD);
}
ScriptedInstance* m_pInstance;
ObjectGuid m_nefariusGuid;
uint32 m_uiIntroTimer;
uint8 m_uiIntroPhase;
ObjectGuid m_playerGuid;
uint32 m_uiSpeechTimer;
uint8 m_uiSpeechNum;
uint32 m_uiCleaveTimer;
uint32 m_uiFlameBreathTimer;
uint32 m_uiFireNovaTimer;
uint32 m_uiBurningAdrenalineCasterTimer;
uint32 m_uiBurningAdrenalineTankTimer;
uint32 m_uiTailSweepTimer;
bool m_bHasYelled;
void Reset() override
{
m_playerGuid.Clear();
m_uiIntroTimer = 0;
m_uiIntroPhase = 0;
m_uiSpeechTimer = 0;
m_uiSpeechNum = 0;
m_uiCleaveTimer = 8000; // These times are probably wrong
m_uiFlameBreathTimer = 11000;
m_uiBurningAdrenalineCasterTimer = 15000;
m_uiBurningAdrenalineTankTimer = 45000;
m_uiFireNovaTimer = 5000;
m_uiTailSweepTimer = 20000;
m_bHasYelled = false;
// Creature should have only 1/3 of hp
m_creature->SetHealth(uint32(m_creature->GetMaxHealth()*0.3f));
}
void BeginIntro()
{
// Start Intro delayed
m_uiIntroTimer = 1000;
if (m_pInstance)
{
m_pInstance->SetData(TYPE_VAELASTRASZ, SPECIAL);
}
}
void BeginSpeech(Player* pTarget)
{
// Stand up and begin speach
m_playerGuid = pTarget->GetObjectGuid();
// 10 seconds
DoScriptText(SAY_LINE_1, m_creature);
// Make boss stand
m_creature->SetStandState(UNIT_STAND_STATE_STAND);
m_uiSpeechTimer = 10000;
m_uiSpeechNum = 0;
}
void KilledUnit(Unit* pVictim) override
{
if (urand(0, 4))
{
return;
}
DoScriptText(SAY_KILLTARGET, m_creature, pVictim);
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_VAELASTRASZ, IN_PROGRESS);
}
// Buff players on aggro
DoCastSpellIfCan(m_creature, SPELL_ESSENCE_OF_THE_RED);
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_VAELASTRASZ, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_VAELASTRASZ, FAIL);
}
}
void JustSummoned(Creature* pSummoned) override
{
if (pSummoned->GetEntry() == NPC_LORD_VICTOR_NEFARIUS)
{
// Set not selectable, so players won't interact with it
pSummoned->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_nefariusGuid = pSummoned->GetObjectGuid();
}
}
void ReceiveAIEvent(AIEventType eventType, Creature* pSender, Unit* pInvoker, uint32 /*uiMiscValue*/) override
{
if (eventType == AI_EVENT_START_EVENT && pSender == m_creature && pInvoker->GetTypeId() == TYPEID_PLAYER)
{
BeginIntro();
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (m_uiIntroTimer)
{
if (m_uiIntroTimer <= uiDiff)
{
switch (m_uiIntroPhase)
{
case 0:
m_creature->SummonCreature(NPC_LORD_VICTOR_NEFARIUS, aNefariusSpawnLoc[0], aNefariusSpawnLoc[1], aNefariusSpawnLoc[2], aNefariusSpawnLoc[3], TEMPSUMMON_TIMED_DESPAWN, 25000);
m_uiIntroTimer = 1000;
break;
case 1:
if (Creature* pNefarius = m_creature->GetMap()->GetCreature(m_nefariusGuid))
{
pNefarius->CastSpell(m_creature, SPELL_NEFARIUS_CORRUPTION, true);
DoScriptText(SAY_NEFARIUS_CORRUPT_1, pNefarius);
}
m_uiIntroTimer = 16000;
break;
case 2:
if (Creature* pNefarius = m_creature->GetMap()->GetCreature(m_nefariusGuid))
{
DoScriptText(SAY_NEFARIUS_CORRUPT_2, pNefarius);
}
// Set npc flags now
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_QUESTGIVER);
m_uiIntroTimer = 0;
break;
}
++m_uiIntroPhase;
}
else
{
m_uiIntroTimer -= uiDiff;
}
}
// Speech
if (m_uiSpeechTimer)
{
if (m_uiSpeechTimer <= uiDiff)
{
switch (m_uiSpeechNum)
{
case 0:
// 16 seconds till next line
DoScriptText(SAY_LINE_2, m_creature);
m_uiSpeechTimer = 16000;
++m_uiSpeechNum;
break;
case 1:
// This one is actually 16 seconds but we only go to 10 seconds because he starts attacking after he says "I must fight this!"
DoScriptText(SAY_LINE_3, m_creature);
m_uiSpeechTimer = 10000;
++m_uiSpeechNum;
break;
case 2:
m_creature->SetFactionTemporary(FACTION_HOSTILE, TEMPFACTION_RESTORE_RESPAWN);
if (m_playerGuid)
{
if (Player* pPlayer = m_creature->GetMap()->GetPlayer(m_playerGuid))
{
AttackStart(pPlayer);
}
}
m_uiSpeechTimer = 0;
break;
}
}
else
{
m_uiSpeechTimer -= uiDiff;
}
}
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Yell if hp lower than 15%
if (m_creature->GetHealthPercent() < 15.0f && !m_bHasYelled)
{
DoScriptText(SAY_HALFLIFE, m_creature);
m_bHasYelled = true;
}
// Cleave Timer
if (m_uiCleaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_CLEAVE) == CAST_OK)
{
m_uiCleaveTimer = 15000;
}
}
else
{
m_uiCleaveTimer -= uiDiff;
}
// Flame Breath Timer
if (m_uiFlameBreathTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_FLAME_BREATH) == CAST_OK)
{
m_uiFlameBreathTimer = urand(4000, 8000);
}
}
else
{
m_uiFlameBreathTimer -= uiDiff;
}
// Burning Adrenaline Caster Timer
if (m_uiBurningAdrenalineCasterTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_BURNING_ADRENALINE, SELECT_FLAG_PLAYER | SELECT_FLAG_POWER_MANA))
{
pTarget->CastSpell(pTarget, SPELL_BURNING_ADRENALINE, true, NULL, NULL, m_creature->GetObjectGuid());
m_uiBurningAdrenalineCasterTimer = 15000;
}
}
else
{
m_uiBurningAdrenalineCasterTimer -= uiDiff;
}
// Burning Adrenaline Tank Timer
if (m_uiBurningAdrenalineTankTimer < uiDiff)
{
// have the victim cast the spell on himself otherwise the third effect aura will be applied
// to Vael instead of the player
m_creature->getVictim()->CastSpell(m_creature->getVictim(), SPELL_BURNING_ADRENALINE, true, NULL, NULL, m_creature->GetObjectGuid());
m_uiBurningAdrenalineTankTimer = 45000;
}
else
{
m_uiBurningAdrenalineTankTimer -= uiDiff;
}
// Fire Nova Timer
if (m_uiFireNovaTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FIRE_NOVA) == CAST_OK)
{
m_uiFireNovaTimer = 5000;
}
}
else
{
m_uiFireNovaTimer -= uiDiff;
}
// Tail Sweep Timer
if (m_uiTailSweepTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_TAIL_SWEEP) == CAST_OK)
{
m_uiTailSweepTimer = 20000;
}
}
else
{
m_uiTailSweepTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) override
{
pPlayer->PlayerTalkClass->ClearMenus();
switch (uiAction)
{
case GOSSIP_ACTION_INFO_DEF + 1:
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VAEL_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_VAEL_2, pCreature->GetObjectGuid());
break;
case GOSSIP_ACTION_INFO_DEF + 2:
pPlayer->CLOSE_GOSSIP_MENU();
if (boss_vaelastraszAI* pVaelAI = dynamic_cast<boss_vaelastraszAI*>(pCreature->AI()))
{
pVaelAI->BeginSpeech(pPlayer);
}
break;
}
return true;
}
bool OnGossipHello(Player* pPlayer, Creature* pCreature) override
{
if (pCreature->IsQuestGiver())
{
pPlayer->PrepareQuestMenu(pCreature->GetObjectGuid());
}
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_VAEL_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_VAEL_1, pCreature->GetObjectGuid());
return true;
}
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_vaelastraszAI(pCreature);
}
};
struct at_vaelastrasz : public AreaTriggerScript
{
at_vaelastrasz() : AreaTriggerScript("at_vaelastrasz") {}
bool OnTrigger(Player* pPlayer, AreaTriggerEntry const* pAt) override
{
if (pAt->id == AREATRIGGER_VAEL_INTRO)
{
if (pPlayer->isGameMaster() || pPlayer->IsDead())
{
return false;
}
if (ScriptedInstance* pInstance = (ScriptedInstance*)pPlayer->GetInstanceData())
{
// Handle intro event
if (pInstance->GetData(TYPE_VAELASTRASZ) == NOT_STARTED)
{
if (Creature* pVaelastrasz = pInstance->GetSingleCreatureFromStorage(NPC_VAELASTRASZ))
if (CreatureAI* pVaelAI = pVaelastrasz->AI())
{
pVaelAI->SendAIEvent(AI_EVENT_START_EVENT, pPlayer, pVaelastrasz);
}
}
// ToDo: make goblins flee
}
}
return false;
}
};
void AddSC_boss_vaelastrasz()
{
Script* s;
s = new boss_vaelastrasz();
s->RegisterSelf();
s = new at_vaelastrasz();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_vaelastrasz";
//pNewScript->GetAI = &GetAI_boss_vaelastrasz;
//pNewScript->pGossipHello = &GossipHello_boss_vaelastrasz;
//pNewScript->pGossipSelect = &GossipSelect_boss_vaelastrasz;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "at_vaelastrasz";
//pNewScript->pAreaTrigger = &AreaTrigger_at_vaelastrasz;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,477 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Victor_Nefarius
* SD%Complete: 90
* SDComment: Small adjustments needed; Timers
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
enum
{
SAY_GAMESBEGIN_1 = -1469004,
SAY_GAMESBEGIN_2 = -1469005,
SAY_NEFARIAN_INTRO = -1469007,
GOSSIP_ITEM_NEFARIUS_1 = -3469000,
GOSSIP_ITEM_NEFARIUS_2 = -3469001,
GOSSIP_ITEM_NEFARIUS_3 = -3469002,
GOSSIP_TEXT_NEFARIUS_1 = 7134,
GOSSIP_TEXT_NEFARIUS_2 = 7198,
GOSSIP_TEXT_NEFARIUS_3 = 7199,
MAX_DRAKES = 5,
MAX_DRAKE_SUMMONS = 42,
NPC_BRONZE_DRAKANOID = 14263,
NPC_BLUE_DRAKANOID = 14261,
NPC_RED_DRAKANOID = 14264,
NPC_GREEN_DRAKANOID = 14262,
NPC_BLACK_DRAKANOID = 14265,
NPC_CHROMATIC_DRAKANOID = 14302,
SPELL_NEFARIUS_BARRIER = 22663, // immunity in phase 1
SPELL_SHADOWBLINK_INTRO = 22664,
SPELL_SHADOWBOLT_VOLLEY = 22665,
SPELL_SILENCE = 22666,
SPELL_SHADOW_COMMAND = 22667,
SPELL_SHADOWBOLT = 22677,
SPELL_FEAR = 22678,
SPELL_SHADOWBLINK = 22681, // triggers a random from spells (22668 - 22676)
SPELL_SUMMON_DRAKONID_BONES = 23363,
MAP_ID_BWL = 469,
FACTION_BLACK_DRAGON = 103
};
static const DialogueEntry aIntroDialogue[] =
{
{SAY_GAMESBEGIN_1, NPC_LORD_VICTOR_NEFARIUS, 4000},
{SAY_GAMESBEGIN_2, NPC_LORD_VICTOR_NEFARIUS, 5000},
{SPELL_SHADOWBLINK, 0, 0},
{0, 0, 0},
};
struct SpawnLocation
{
float m_fX, m_fY, m_fZ;
};
static const SpawnLocation aNefarianLocs[4] =
{
{ -7599.32f, -1191.72f, 475.545f}, // opening where red/blue/black darknid spawner appear (ori 3.05433)
{ -7526.27f, -1135.04f, 473.445f}, // same as above, closest to door (ori 5.75959)
{ -7498.177f, -1273.277f, 481.649f}, // nefarian spawn location (ori 1.798)
{ -7502.002f, -1256.503f, 476.758f}, // nefarian fly to this position
};
static const uint32 aPossibleDrake[MAX_DRAKES] = {NPC_BRONZE_DRAKANOID, NPC_BLUE_DRAKANOID, NPC_RED_DRAKANOID, NPC_GREEN_DRAKANOID, NPC_BLACK_DRAKANOID};
// This script is complicated
// Instead of morphing Victor Nefarius we will have him control phase 1
// And then have him spawn "Nefarian" for phase 2
// When phase 2 starts Victor Nefarius will go invisible and stop attacking
// If Nefarian reched home because nef killed the players then nef will trigger this guy to EnterEvadeMode
// and allow players to start the event over
// If nefarian dies then he will kill himself then he will be despawned in Nefarian script
// To prevent players from doing the event twice
// Dev note: Lord Victor Nefarius should despawn completely, then ~5 seconds later Nefarian should appear.
struct boss_victor_nefarius : public CreatureScript
{
boss_victor_nefarius() : CreatureScript("boss_victor_nefarius") {}
struct boss_victor_nefariusAI : public ScriptedAI, private DialogueHelper
{
boss_victor_nefariusAI(Creature* pCreature) : ScriptedAI(pCreature),
DialogueHelper(aIntroDialogue)
{
// Select the 2 different drakes that we are going to use until despawned
// 5 possiblities for the first drake, 4 for the second, 20 total possiblites
// select two different numbers between 0..MAX_DRAKES-1
uint8 uiPos1 = urand(0, MAX_DRAKES - 1);
uint8 uiPos2 = (uiPos1 + urand(1, MAX_DRAKES - 1)) % MAX_DRAKES;
m_uiDrakeTypeOne = aPossibleDrake[uiPos1];
m_uiDrakeTypeTwo = aPossibleDrake[uiPos2];
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
InitializeDialogueHelper(m_pInstance);
}
ScriptedInstance* m_pInstance;
uint32 m_uiSpawnedAdds;
uint32 m_uiAddSpawnTimer;
uint32 m_uiShadowBoltTimer;
uint32 m_uiFearTimer;
uint32 m_uiDrakeTypeOne;
uint32 m_uiDrakeTypeTwo;
uint32 m_uiShadowboltVolleyTimer;
uint32 m_uiSilenceTimer;
uint32 m_uiShadowCommandTimer;
uint32 m_uiShadowBlinkTimer;
void Reset() override
{
m_uiSpawnedAdds = 0;
m_uiAddSpawnTimer = 10000;
m_uiShadowBoltTimer = 3000;
m_uiFearTimer = 8000;
m_uiShadowboltVolleyTimer = 13000;
m_uiSilenceTimer = 23000;
m_uiShadowCommandTimer = 30000;
m_uiShadowBlinkTimer = 40000;
// set gossip flag to begin the event
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
// Make visible if needed
if (m_creature->GetVisibility() != VISIBILITY_ON)
{
m_creature->SetVisibility(VISIBILITY_ON);
}
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_NEFARIAN, IN_PROGRESS);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_NEFARIAN, FAIL);
}
}
void AttackStart(Unit* pWho) override
{
if (m_creature->Attack(pWho, false))
{
m_creature->AddThreat(pWho);
m_creature->SetInCombatWith(pWho);
pWho->SetInCombatWith(m_creature);
// Only range attack - ToDo: research the distance
m_creature->GetMotionMaster()->MoveChase(pWho, 30.0f);
}
}
void JustSummoned(Creature* pSummoned) override
{
if (pSummoned->GetEntry() == NPC_NEFARIAN)
{
pSummoned->SetWalk(false);
// see boss_onyxia (also note the removal of this in boss_nefarian)
#if defined (CLASSIC) || defined (TBC)
pSummoned->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND);
#endif
#if defined (WOTLK) || defined (CATA)
pSummoned->SetByteValue(UNIT_FIELD_BYTES_1, 3, UNIT_BYTE1_FLAG_ALWAYS_STAND | UNIT_BYTE1_FLAG_FLY_ANIM);
#endif
pSummoned->SetLevitate(true);
// Let Nefarian fly towards combat area
pSummoned->GetMotionMaster()->MovePoint(1, aNefarianLocs[3].m_fX, aNefarianLocs[3].m_fY, aNefarianLocs[3].m_fZ);
DoScriptText(SAY_NEFARIAN_INTRO, pSummoned);
}
else
{
++m_uiSpawnedAdds;
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
pSummoned->AI()->AttackStart(pTarget);
}
}
}
void SummonedMovementInform(Creature* pSummoned, uint32 uiMotionType, uint32 uiPointId) override
{
// If Nefarian has reached combat area, let him attack
if (pSummoned->GetEntry() == NPC_NEFARIAN && uiMotionType == POINT_MOTION_TYPE && uiPointId == 1)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
pSummoned->AI()->AttackStart(pTarget);
}
}
}
void SummonedCreatureJustDied(Creature* pSummoned) override
{
// Despawn self when Nefarian is killed
if (pSummoned->GetEntry() == NPC_NEFARIAN)
{
m_creature->ForcedDespawn();
}
else
{
pSummoned->CastSpell(pSummoned, SPELL_SUMMON_DRAKONID_BONES, true);
}
}
void JustDidDialogueStep(int32 iEntry) override
{
// Start combat after the dialogue is finished
if (iEntry == SPELL_SHADOWBLINK)
{
m_creature->SetStandState(UNIT_STAND_STATE_STAND);
m_creature->SetFactionTemporary(FACTION_BLACK_DRAGON, TEMPFACTION_RESTORE_REACH_HOME);
DoCastSpellIfCan(m_creature, SPELL_NEFARIUS_BARRIER, CAST_TRIGGERED);
DoCastSpellIfCan(m_creature, SPELL_SHADOWBLINK_INTRO, CAST_TRIGGERED);
m_creature->SetInCombatWithZone();
}
}
void DoStartIntro()
{
StartNextDialogueText(SAY_GAMESBEGIN_1);
}
void UpdateAI(const uint32 uiDiff) override
{
DialogueUpdate(uiDiff);
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Only do this if we haven't spawned nef yet
if (m_uiSpawnedAdds < MAX_DRAKE_SUMMONS)
{
// Shadowbolt Timer
if (m_uiShadowBoltTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_SHADOWBOLT) == CAST_OK)
{
m_uiShadowBoltTimer = urand(2000, 4000);
}
}
}
else
{
m_uiShadowBoltTimer -= uiDiff;
}
// Fear Timer
if (m_uiFearTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
{
if (DoCastSpellIfCan(pTarget, SPELL_FEAR) == CAST_OK)
{
m_uiFearTimer = urand(10000, 20000);
}
}
}
else
{
m_uiFearTimer -= uiDiff;
}
// Shadowbolt Volley
if (m_uiShadowboltVolleyTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOWBOLT_VOLLEY) == CAST_OK)
{
m_uiShadowboltVolleyTimer = urand(19000, 28000);
}
}
else
{
m_uiShadowboltVolleyTimer -= uiDiff;
}
// Silence
if (m_uiSilenceTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_SILENCE) == CAST_OK)
{
m_uiSilenceTimer = urand(14000, 23000);
}
}
}
else
{
m_uiSilenceTimer -= uiDiff;
}
// Shadow Command
if (m_uiShadowCommandTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
{
if (DoCastSpellIfCan(pTarget, SPELL_SHADOW_COMMAND) == CAST_OK)
{
m_uiShadowCommandTimer = urand(24000, 30000);
}
}
}
else
{
m_uiShadowCommandTimer -= uiDiff;
}
// ShadowBlink
if (m_uiShadowBlinkTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHADOWBLINK) == CAST_OK)
{
m_uiShadowBlinkTimer = urand(30000, 40000);
}
}
else
{
m_uiShadowBlinkTimer -= uiDiff;
}
// Add spawning mechanism
if (m_uiAddSpawnTimer < uiDiff)
{
// Spawn 2 random types of creatures at the 2 locations
uint32 uiCreatureId = 0;
// 1 in 3 chance it will be a chromatic
uiCreatureId = urand(0, 2) ? m_uiDrakeTypeOne : uint32(NPC_CHROMATIC_DRAKANOID);
m_creature->SummonCreature(uiCreatureId, aNefarianLocs[0].m_fX, aNefarianLocs[0].m_fY, aNefarianLocs[0].m_fZ, 5.000f, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 30000);
// 1 in 3 chance it will be a chromatic
uiCreatureId = urand(0, 2) ? m_uiDrakeTypeTwo : uint32(NPC_CHROMATIC_DRAKANOID);
m_creature->SummonCreature(uiCreatureId, aNefarianLocs[1].m_fX, aNefarianLocs[1].m_fY, aNefarianLocs[1].m_fZ, 5.000, TEMPSUMMON_TIMED_OOC_OR_CORPSE_DESPAWN, 30000);
// Begin phase 2 by spawning Nefarian
if (m_uiSpawnedAdds >= MAX_DRAKE_SUMMONS)
{
// Inturrupt any spell casting
m_creature->InterruptNonMeleeSpells(false);
// Make super invis
if (m_creature->GetVisibility() != VISIBILITY_OFF)
{
m_creature->SetVisibility(VISIBILITY_OFF);
}
// Spawn Nefarian
// Summon as active, to be able to work proper!
m_creature->SummonCreature(NPC_NEFARIAN, aNefarianLocs[2].m_fX, aNefarianLocs[2].m_fY, aNefarianLocs[2].m_fZ, 0, TEMPSUMMON_DEAD_DESPAWN, 0, true);
}
m_uiAddSpawnTimer = 4000;
}
else
{
m_uiAddSpawnTimer -= uiDiff;
}
}
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
// Check the map id because the same creature entry is involved in other scripted event in other instance
return pCreature->GetMapId() == MAP_ID_BWL ? new boss_victor_nefariusAI(pCreature) : NULL;
}
bool OnGossipHello(Player* pPlayer, Creature* pCreature) override
{
if (pCreature->GetMapId() != MAP_ID_BWL)
{
return true;
}
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NEFARIUS_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_NEFARIUS_1, pCreature->GetObjectGuid());
return true;
}
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*uiSender*/, uint32 uiAction) override
{
pPlayer->PlayerTalkClass->ClearMenus();
if (pCreature->GetMapId() != MAP_ID_BWL)
{
return true;
}
switch (uiAction)
{
case GOSSIP_ACTION_INFO_DEF + 1:
pCreature->HandleEmote(EMOTE_ONESHOT_TALK);
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NEFARIUS_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_NEFARIUS_2, pCreature->GetObjectGuid());
break;
case GOSSIP_ACTION_INFO_DEF + 2:
pCreature->HandleEmote(EMOTE_ONESHOT_TALK);
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_NEFARIUS_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
pPlayer->SEND_GOSSIP_MENU(GOSSIP_TEXT_NEFARIUS_3, pCreature->GetObjectGuid());
break;
case GOSSIP_ACTION_INFO_DEF + 3:
pCreature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
pPlayer->CLOSE_GOSSIP_MENU();
// Start the intro event
if (boss_victor_nefariusAI* pBossAI = dynamic_cast<boss_victor_nefariusAI*>(pCreature->AI()))
{
pBossAI->DoStartIntro();
}
break;
}
return true;
}
};
void AddSC_boss_victor_nefarius()
{
Script* s;
s = new boss_victor_nefarius();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_victor_nefarius";
//pNewScript->GetAI = &GetAI_boss_victor_nefarius;
//pNewScript->pGossipHello = &GossipHello_boss_victor_nefarius;
//pNewScript->pGossipSelect = &GossipSelect_boss_victor_nefarius;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,478 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Instance_Blackwing_Lair
* SD%Complete: 90
* SDComment: None
* SDCategory: Blackwing Lair
* EndScriptData
*/
#include "precompiled.h"
#include "blackwing_lair.h"
static const uint32 aRazorgoreSpawns[MAX_EGGS_DEFENDERS] = { NPC_BLACKWING_LEGIONNAIRE, NPC_BLACKWING_MAGE, NPC_DRAGONSPAWN, NPC_DRAGONSPAWN };
struct is_blackwing_lair : public InstanceScript
{
is_blackwing_lair() : InstanceScript("instance_blackwing_lair") {}
class instance_blackwing_lair : public ScriptedInstance
{
public:
instance_blackwing_lair(Map* pMap) : ScriptedInstance(pMap),
m_uiResetTimer(0),
m_uiDefenseTimer(0)
{
Initialize();
}
~instance_blackwing_lair() {}
void Initialize() override
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
}
bool IsEncounterInProgress() const override
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
{
return true;
}
}
return false;
}
void OnCreatureCreate(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
case NPC_BLACKWING_TECHNICIAN:
// Sort creatures so we can get only the ones near Vaelastrasz
if (pCreature->IsWithinDist2d(aNefariusSpawnLoc[0], aNefariusSpawnLoc[1], 50.0f))
{
m_lTechnicianGuids.push_back(pCreature->GetObjectGuid());
}
break;
case NPC_MONSTER_GENERATOR:
m_vGeneratorGuids.push_back(pCreature->GetObjectGuid());
break;
case NPC_BLACKWING_LEGIONNAIRE:
case NPC_BLACKWING_MAGE:
case NPC_DRAGONSPAWN:
m_lDefendersGuids.push_back(pCreature->GetObjectGuid());
break;
case NPC_RAZORGORE:
case NPC_NEFARIANS_TROOPS:
case NPC_BLACKWING_ORB_TRIGGER:
case NPC_VAELASTRASZ:
case NPC_LORD_VICTOR_NEFARIUS:
m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid();
break;
}
}
void OnObjectCreate(GameObject* pGo) override
{
switch (pGo->GetEntry())
{
case GO_DOOR_RAZORGORE_ENTER:
case GO_ORB_OF_DOMINATION:
case GO_DOOR_NEFARIAN:
break;
case GO_DOOR_RAZORGORE_EXIT:
if (m_auiEncounter[TYPE_RAZORGORE] == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_DOOR_CHROMAGGUS_EXIT:
if (m_auiEncounter[TYPE_CHROMAGGUS] == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_DOOR_VAELASTRASZ:
if (m_auiEncounter[TYPE_VAELASTRASZ] == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_DOOR_LASHLAYER:
if (m_auiEncounter[TYPE_LASHLAYER] == DONE)
{
pGo->SetGoState(GO_STATE_ACTIVE);
}
break;
case GO_BLACK_DRAGON_EGG:
m_lDragonEggsGuids.push_back(pGo->GetObjectGuid());
return;
case GO_DRAKONID_BONES:
m_lDrakonidBonesGuids.push_back(pGo->GetObjectGuid());
return;
default:
return;
}
m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid();
}
void OnCreatureEnterCombat(Creature* pCreature) override
{
if (pCreature->GetEntry() == NPC_GRETHOK_CONTROLLER)
{
SetData(TYPE_RAZORGORE, IN_PROGRESS);
m_uiDefenseTimer = 40000;
}
}
void OnCreatureDeath(Creature* pCreature) override
{
if (pCreature->GetEntry() == NPC_GRETHOK_CONTROLLER)
{
// Allow orb to be used
DoToggleGameObjectFlags(GO_ORB_OF_DOMINATION, GO_FLAG_NO_INTERACT, false);
if (Creature* pOrbTrigger = GetSingleCreatureFromStorage(NPC_BLACKWING_ORB_TRIGGER))
{
pOrbTrigger->InterruptNonMeleeSpells(false);
}
}
}
void SetData(uint32 uiType, uint32 uiData) override
{
switch (uiType)
{
case TYPE_RAZORGORE:
m_auiEncounter[uiType] = uiData;
if (uiData != SPECIAL)
{
DoUseDoorOrButton(GO_DOOR_RAZORGORE_ENTER);
}
if (uiData == DONE)
{
DoUseDoorOrButton(GO_DOOR_RAZORGORE_EXIT);
}
else if (uiData == FAIL)
{
m_uiResetTimer = 30000;
// Reset the Orb of Domination and the eggs
DoToggleGameObjectFlags(GO_ORB_OF_DOMINATION, GO_FLAG_NO_INTERACT, true);
// Reset defenders
for (GuidList::const_iterator itr = m_lDefendersGuids.begin(); itr != m_lDefendersGuids.end(); ++itr)
{
if (Creature* pDefender = instance->GetCreature(*itr))
{
pDefender->ForcedDespawn();
}
}
m_lUsedEggsGuids.clear();
m_lDefendersGuids.clear();
}
break;
case TYPE_VAELASTRASZ:
m_auiEncounter[uiType] = uiData;
// Prevent the players from running back to the first room; use if the encounter is not special
if (uiData != SPECIAL)
{
DoUseDoorOrButton(GO_DOOR_RAZORGORE_EXIT);
}
if (uiData == DONE)
{
DoUseDoorOrButton(GO_DOOR_VAELASTRASZ);
}
break;
case TYPE_LASHLAYER:
m_auiEncounter[uiType] = uiData;
if (uiData == DONE)
{
DoUseDoorOrButton(GO_DOOR_LASHLAYER);
}
break;
case TYPE_FIREMAW:
case TYPE_EBONROC:
case TYPE_FLAMEGOR:
m_auiEncounter[uiType] = uiData;
break;
case TYPE_CHROMAGGUS:
m_auiEncounter[uiType] = uiData;
if (uiData == DONE)
{
DoUseDoorOrButton(GO_DOOR_CHROMAGGUS_EXIT);
}
break;
case TYPE_NEFARIAN:
// Don't store the same thing twice
if (m_auiEncounter[uiType] == uiData)
{
break;
}
if (uiData == SPECIAL)
{
// handle missing spell 23362
Creature* pNefarius = GetSingleCreatureFromStorage(NPC_LORD_VICTOR_NEFARIUS);
if (!pNefarius)
{
break;
}
for (GuidList::const_iterator itr = m_lDrakonidBonesGuids.begin(); itr != m_lDrakonidBonesGuids.end(); ++itr)
{
// The Go script will handle the missing spell 23361
if (GameObject* pGo = instance->GetGameObject(*itr))
{
pGo->Use(pNefarius);
}
}
// Don't store special data
break;
}
m_auiEncounter[uiType] = uiData;
DoUseDoorOrButton(GO_DOOR_NEFARIAN);
// Cleanup the drakonid bones
if (uiData == FAIL)
{
for (GuidList::const_iterator itr = m_lDrakonidBonesGuids.begin(); itr != m_lDrakonidBonesGuids.end(); ++itr)
{
if (GameObject* pGo = instance->GetGameObject(*itr))
{
pGo->SetLootState(GO_JUST_DEACTIVATED);
}
}
m_lDrakonidBonesGuids.clear();
}
break;
}
if (uiData == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
<< m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " "
<< m_auiEncounter[6] << " " << m_auiEncounter[7];
m_strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 uiType) const override
{
if (uiType < MAX_ENCOUNTER)
{
return m_auiEncounter[uiType];
}
return 0;
}
void SetData64(uint32 uiData, uint64 uiGuid) override
{
if (uiData == DATA_DRAGON_EGG)
{
if (GameObject* pEgg = instance->GetGameObject(ObjectGuid(uiGuid)))
{
m_lUsedEggsGuids.push_back(pEgg->GetObjectGuid());
}
// If all eggs are destroyed, then allow Razorgore to be attacked
if (m_lUsedEggsGuids.size() == m_lDragonEggsGuids.size())
{
SetData(TYPE_RAZORGORE, SPECIAL);
DoToggleGameObjectFlags(GO_ORB_OF_DOMINATION, GO_FLAG_NO_INTERACT, true);
// Emote for the start of the second phase
if (Creature* pTrigger = GetSingleCreatureFromStorage(NPC_NEFARIANS_TROOPS))
{
DoScriptText(EMOTE_ORB_SHUT_OFF, pTrigger);
DoScriptText(EMOTE_TROOPS_FLEE, pTrigger);
}
// Break mind control and set max health
if (Creature* pRazorgore = GetSingleCreatureFromStorage(NPC_RAZORGORE))
{
pRazorgore->RemoveAllAuras();
pRazorgore->SetHealth(pRazorgore->GetMaxHealth());
}
// All defenders evade and despawn
for (GuidList::const_iterator itr = m_lDefendersGuids.begin(); itr != m_lDefendersGuids.end(); ++itr)
{
if (Creature* pDefender = instance->GetCreature(*itr))
{
pDefender->AI()->EnterEvadeMode();
pDefender->ForcedDespawn(10000);
}
}
}
}
}
const char* Save() const override { return m_strInstData.c_str(); }
void Load(const char* chrIn) override
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
{
m_auiEncounter[i] = NOT_STARTED;
}
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 uiDiff) override
{
// Reset Razorgore in case of wipe
if (m_uiResetTimer)
{
if (m_uiResetTimer <= uiDiff)
{
// Respawn Razorgore
if (Creature* pRazorgore = GetSingleCreatureFromStorage(NPC_RAZORGORE))
{
if (!pRazorgore->IsAlive())
{
pRazorgore->Respawn();
}
}
// Respawn the Dragon Eggs
for (GuidList::const_iterator itr = m_lDragonEggsGuids.begin(); itr != m_lDragonEggsGuids.end(); ++itr)
{
if (GameObject* pEgg = instance->GetGameObject(*itr))
{
if (!pEgg->isSpawned())
{
pEgg->Respawn();
}
}
}
m_uiResetTimer = 0;
}
else
{
m_uiResetTimer -= uiDiff;
}
}
if (GetData(TYPE_RAZORGORE) != IN_PROGRESS)
{
return;
}
if (m_uiDefenseTimer < uiDiff)
{
// Allow Razorgore to spawn the defenders
Creature* pRazorgore = GetSingleCreatureFromStorage(NPC_RAZORGORE);
if (!pRazorgore)
{
return;
}
// Randomize generators
std::random_shuffle(m_vGeneratorGuids.begin(), m_vGeneratorGuids.end());
// Spawn the defenders
for (uint8 i = 0; i < MAX_EGGS_DEFENDERS; ++i)
{
Creature* pGenerator = instance->GetCreature(m_vGeneratorGuids[i]);
if (!pGenerator)
{
return;
}
pRazorgore->SummonCreature(aRazorgoreSpawns[i], pGenerator->GetPositionX(), pGenerator->GetPositionY(), pGenerator->GetPositionZ(), pGenerator->GetOrientation(), TEMPSUMMON_DEAD_DESPAWN, 0);
}
m_uiDefenseTimer = 20000;
}
else
{
m_uiDefenseTimer -= uiDiff;
}
}
protected:
std::string m_strInstData;
uint32 m_auiEncounter[MAX_ENCOUNTER];
uint32 m_uiResetTimer;
uint32 m_uiDefenseTimer;
GuidList m_lTechnicianGuids;
GuidList m_lDragonEggsGuids;
GuidList m_lDrakonidBonesGuids;
GuidList m_lDefendersGuids;
GuidList m_lUsedEggsGuids;
GuidVector m_vGeneratorGuids;
};
InstanceData* GetInstanceData(Map* pMap) override
{
return new instance_blackwing_lair(pMap);
}
};
void AddSC_instance_blackwing_lair()
{
Script* s;
s = new is_blackwing_lair();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "instance_blackwing_lair";
//pNewScript->GetInstanceData = &GetInstanceData_instance_blackwing_lair;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,184 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Baron_Geddon
* SD%Complete: 90
* SDComment: Armaggedon is not working properly (core issue)
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
EMOTE_SERVICE = -1409000,
SPELL_INFERNO = 19695,
SPELL_IGNITE_MANA = 19659,
SPELL_LIVING_BOMB = 20475,
SPELL_ARMAGEDDON = 20478
};
struct boss_baron_geddon : public CreatureScript
{
boss_baron_geddon() : CreatureScript("boss_baron_geddon") {}
struct boss_baron_geddonAI : public ScriptedAI
{
boss_baron_geddonAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
bool m_bIsArmageddon;
uint32 m_uiInfernoTimer;
uint32 m_uiIgniteManaTimer;
uint32 m_uiLivingBombTimer;
void Reset() override
{
m_bIsArmageddon = false;
m_uiInfernoTimer = 45000;
m_uiIgniteManaTimer = 30000;
m_uiLivingBombTimer = 35000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEDDON, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEDDON, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEDDON, NOT_STARTED);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
if (m_bIsArmageddon) // Do nothing untill armageddon triggers
{
return;
}
// If we are <2% hp cast Armageddom
if (m_creature->GetHealthPercent() <= 2.0f && !m_bIsArmageddon)
{
if (DoCastSpellIfCan(m_creature, SPELL_ARMAGEDDON, CAST_INTERRUPT_PREVIOUS) == CAST_OK)
{
DoScriptText(EMOTE_SERVICE, m_creature);
m_bIsArmageddon = true;
return;
}
}
// Inferno_Timer
if (m_uiInfernoTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_INFERNO) == CAST_OK)
{
m_uiInfernoTimer = 45000;
}
}
else
{
m_uiInfernoTimer -= uiDiff;
}
// Ignite Mana Timer
if (m_uiIgniteManaTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_IGNITE_MANA) == CAST_OK)
{
m_uiIgniteManaTimer = 30000;
}
}
else
{
m_uiIgniteManaTimer -= uiDiff;
}
// Living Bomb Timer
if (m_uiLivingBombTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_LIVING_BOMB) == CAST_OK)
{
m_uiLivingBombTimer = 35000;
}
}
}
else
{
m_uiLivingBombTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_baron_geddonAI(pCreature);
}
};
void AddSC_boss_baron_geddon()
{
Script* s;
s = new boss_baron_geddon();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_baron_geddon";
//pNewScript->GetAI = &GetAI_boss_baron_geddon;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,313 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Garr
* SD%Complete: 50
* SDComment: Garr's enrage is missing
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
// Garr spells
SPELL_ANTIMAGICPULSE = 19492,
SPELL_MAGMASHACKLES = 19496,
SPELL_ERUPTION_TRIGGER = 20482, // target script, dispel and permanent immune to banish anywhere on map
SPELL_ENRAGE_TRIGGER = 19515, // target script, effect dummy anywhere on map
// Add spells
SPELL_ERUPTION = 19497,
SPELL_MASSIVE_ERUPTION = 20483, // TODO possible on death
SPELL_IMMOLATE = 20294,
};
struct boss_garr : public CreatureScript
{
boss_garr() : CreatureScript("boss_garr") {}
struct boss_garrAI : public ScriptedAI
{
boss_garrAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiAntiMagicPulseTimer;
uint32 m_uiMagmaShacklesTimer;
uint32 m_uiExplodeAddTimer;
bool m_bHasFreed;
void Reset() override
{
m_uiAntiMagicPulseTimer = 25 * IN_MILLISECONDS;
m_uiMagmaShacklesTimer = 15 * IN_MILLISECONDS;
m_uiExplodeAddTimer = 60 * IN_MILLISECONDS;
m_bHasFreed = false;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GARR, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GARR, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GARR, FAIL);
}
}
void DamageTaken(Unit* /*damager*/, uint32 &damage) override
{
if (!m_bHasFreed && m_creature->HealthBelowPctDamaged(50, damage))
{
m_pInstance->SetData(TYPE_DO_FREE_GARR_ADDS, 0);
m_bHasFreed = true;
}
}
void ReceiveAIEvent(AIEventType type, Creature* pSender, Unit* /*pInvoker*/, uint32 /*uiData*/) override
{
if (type == AI_EVENT_CUSTOM_B && pSender == m_creature)
{
if (Creature* spawn = m_creature->SummonCreature(NPC_FIRESWORN, m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), m_creature->GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, true))
spawn->SetOwnerGuid(ObjectGuid()); // trying to prevent despawn of the summon at Garr death
m_uiExplodeAddTimer = 25 * IN_MILLISECONDS;
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// AntiMagicPulse_Timer
if (m_uiAntiMagicPulseTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_ANTIMAGICPULSE) == CAST_OK)
{
m_uiAntiMagicPulseTimer = urand(10 * IN_MILLISECONDS, 15 * IN_MILLISECONDS);
}
}
else
{
m_uiAntiMagicPulseTimer -= uiDiff;
}
// MagmaShackles_Timer
if (m_uiMagmaShacklesTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_MAGMASHACKLES) == CAST_OK)
{
m_uiMagmaShacklesTimer = urand(8 * IN_MILLISECONDS, 12 * IN_MILLISECONDS);
}
}
else
{
m_uiMagmaShacklesTimer -= uiDiff;
}
// Explode an add
if (m_uiExplodeAddTimer < uiDiff)
{
if (urand(0, 1)) // 50% chance to explode, is it too much?
{
ObjectGuid guid = m_pInstance->GetGuid(NPC_FIRESWORN);
if (Creature* firesworn = m_pInstance->instance->GetCreature(guid))
SendAIEvent(AI_EVENT_CUSTOM_A, firesworn, firesworn, SPELL_MASSIVE_ERUPTION); // this is an instant explosion with no SPELL_ERUPTION_TRIGGER
}
m_uiExplodeAddTimer = 15 * IN_MILLISECONDS;
}
else m_uiExplodeAddTimer -= uiDiff;
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_garrAI(pCreature);
}
};
struct mob_firesworn : public CreatureScript
{
mob_firesworn() : CreatureScript("mob_firesworn") {}
struct mob_fireswornAI : public ScriptedAI
{
mob_fireswornAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiImmolateTimer;
uint32 m_uiSeparationCheckTimer;
bool m_bExploding;
void Reset() override
{
m_uiImmolateTimer = urand(4 * IN_MILLISECONDS, 8 * IN_MILLISECONDS); // These times are probably wrong
m_uiSeparationCheckTimer = 5 * IN_MILLISECONDS;
m_bExploding = false;
}
void DamageTaken(Unit* /*pDealer*/, uint32& uiDamage) override
{
if (!m_bExploding && m_creature->HealthBelowPctDamaged(10, uiDamage))
{
ReceiveAIEvent(AI_EVENT_CUSTOM_A, m_creature, m_creature, SPELL_ERUPTION);
uiDamage = 0;
}
}
void ReceiveAIEvent(AIEventType type, Creature* /*pSender*/, Unit* pInvoker, uint32 uiData) override
{
if (type == AI_EVENT_CUSTOM_A && pInvoker == m_creature)
{
m_creature->CastSpell(m_creature, uiData, true);
m_creature->ForcedDespawn(100);
m_bExploding = true;
}
}
#if defined (WOTLK) || defined (CATA)
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
if (Creature* pGarr = m_pInstance->GetSingleCreatureFromStorage(NPC_GARR))
pGarr->CastSpell(pGarr, SPELL_GARR_ENRAGE, true, NULL, NULL, m_creature->GetObjectGuid());
}
}
#endif
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim() || m_bExploding)
{
return;
}
if (m_uiSeparationCheckTimer < uiDiff)
{
#if defined (WOTLK) || defined (CATA)
if (!m_pInstance)
return;
#endif
// Distance guesswork, but should be ok
Creature* pGarr = m_pInstance->GetSingleCreatureFromStorage(NPC_GARR);
if (pGarr && pGarr->IsAlive() && !m_creature->IsWithinDist2d(pGarr->GetPositionX(), pGarr->GetPositionY(), 50.0f))
{
DoCastSpellIfCan(m_creature, SPELL_SEPARATION_ANXIETY, CAST_TRIGGERED);
}
m_uiSeparationCheckTimer = 5000;
}
else
{
m_uiSeparationCheckTimer -= uiDiff;
}
#if defined (WOTLK) || defined (CATA)
// Cast Erruption and let them die
if (m_creature->GetHealthPercent() <= 10.0f)
{
DoCastSpellIfCan(m_creature->getVictim(), SPELL_ERUPTION);
m_creature->SetDeathState(JUST_DIED);
m_creature->RemoveCorpse();
}
#endif
// Immolate_Timer
if (m_uiImmolateTimer < uiDiff)
{
if (Unit* pTarget = SelectAttackTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_IMMOLATE))
{
if (DoCastSpellIfCan(pTarget, SPELL_IMMOLATE, CAST_TRIGGERED) == CAST_OK)
{
m_uiImmolateTimer = urand(5 * IN_MILLISECONDS, 10 * IN_MILLISECONDS);
}
}
}
else
{
m_uiImmolateTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new mob_fireswornAI(pCreature);
}
};
void AddSC_boss_garr()
{
Script* s;
s = new boss_garr();
s->RegisterSelf();
s = new mob_firesworn();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_garr";
//pNewScript->GetAI = &GetAI_boss_garr;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "mob_firesworn";
//pNewScript->GetAI = &GetAI_mob_firesworn;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,170 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Gehennas
* SD%Complete: 90
* SDComment: None
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
SPELL_SHADOW_BOLT = 19728, // 19729 exists too, but can be reflected
SPELL_RAIN_OF_FIRE = 19717,
SPELL_GEHENNAS_CURSE = 19716
};
struct boss_gehennas : public CreatureScript
{
boss_gehennas() : CreatureScript("boss_gehennas") {}
struct boss_gehennasAI : public ScriptedAI
{
boss_gehennasAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiShadowBoltTimer;
uint32 m_uiRainOfFireTimer;
uint32 m_uiGehennasCurseTimer;
void Reset() override
{
m_uiShadowBoltTimer = 6000;
m_uiRainOfFireTimer = 10000;
m_uiGehennasCurseTimer = 12000;
}
void Aggro(Unit* /*pwho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEHENNAS, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEHENNAS, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GEHENNAS, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// ShadowBolt Timer
if (m_uiShadowBoltTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
{
if (DoCastSpellIfCan(pTarget, SPELL_SHADOW_BOLT) == CAST_OK)
{
m_uiShadowBoltTimer = 7000;
}
}
else // In case someone attempts soloing, we don't need to scan for targets every tick
{
m_uiShadowBoltTimer = 7000;
}
}
else
{
m_uiShadowBoltTimer -= uiDiff;
}
// Rain of Fire Timer
if (m_uiRainOfFireTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_RAIN_OF_FIRE) == CAST_OK)
{
m_uiRainOfFireTimer = urand(4000, 12000);
}
}
}
else
{
m_uiRainOfFireTimer -= uiDiff;
}
// GehennasCurse Timer
if (m_uiGehennasCurseTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_GEHENNAS_CURSE) == CAST_OK)
{
m_uiGehennasCurseTimer = 30000;
}
}
else
{
m_uiGehennasCurseTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_gehennasAI(pCreature);
}
};
void AddSC_boss_gehennas()
{
Script* s;
s = new boss_gehennas();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_gehennas";
//pNewScript->GetAI = &GetAI_boss_gehennas;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,258 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Golemagg
* SD%Complete: 80
* SDComment: Rager need to be tied to boss (Despawn on boss-death)
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
SPELL_MAGMA_SPLASH = 13879,
SPELL_PYROBLAST = 20228,
SPELL_EARTHQUAKE = 19798,
SPELL_ENRAGE = 19953,
SPELL_GOLEMAGG_TRUST = 20553,
// Core Rager
EMOTE_LOW_HP = -1409002,
SPELL_MANGLE = 19820
};
struct boss_golemagg : public CreatureScript
{
boss_golemagg() : CreatureScript("boss_golemagg") {}
struct boss_golemaggAI : public ScriptedAI
{
boss_golemaggAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
#if defined (WOTLK) || defined (CATA)
DoCastSpellIfCan(m_creature, SPELL_MAGMA_SPLASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
#endif
}
ScriptedInstance* m_pInstance;
uint32 m_uiPyroblastTimer;
uint32 m_uiEarthquakeTimer;
uint32 m_uiBuffTimer;
bool m_bEnraged;
void Reset() override
{
m_uiPyroblastTimer = 7 * IN_MILLISECONDS;
m_uiEarthquakeTimer = 3 * IN_MILLISECONDS;
m_uiBuffTimer = 1.5 * IN_MILLISECONDS;
m_bEnraged = false;
m_creature->CastSpell(m_creature, SPELL_MAGMA_SPLASH, true);
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GOLEMAGG, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GOLEMAGG, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_GOLEMAGG, FAIL);
}
#if defined (WOTLK) || defined (CATA)
DoCastSpellIfCan(m_creature, SPELL_MAGMA_SPLASH, CAST_TRIGGERED | CAST_AURA_NOT_PRESENT);
#endif
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Pyroblast
if (m_uiPyroblastTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_PYROBLAST) == CAST_OK)
{
m_uiPyroblastTimer = 7 * IN_MILLISECONDS;
}
}
}
else
{
m_uiPyroblastTimer -= uiDiff;
}
// Enrage
if (!m_bEnraged && m_creature->GetHealthPercent() < 10.0f)
{
if (DoCastSpellIfCan(m_creature, SPELL_ENRAGE) == CAST_OK)
{
m_bEnraged = true;
}
}
// Earthquake
if (m_bEnraged)
{
if (m_uiEarthquakeTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_EARTHQUAKE) == CAST_OK)
{
m_uiEarthquakeTimer = 3 * IN_MILLISECONDS;
}
}
else
{
m_uiEarthquakeTimer -= uiDiff;
}
}
// Golemagg's Trust
if (m_uiBuffTimer < uiDiff)
{
DoCastSpellIfCan(m_creature, SPELL_GOLEMAGG_TRUST);
m_uiBuffTimer = 1.5 * IN_MILLISECONDS;
}
else
{
m_uiBuffTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_golemaggAI(pCreature);
}
};
struct mob_core_rager : public CreatureScript
{
mob_core_rager() : CreatureScript("mob_core_rager") {}
struct mob_core_ragerAI : public ScriptedAI
{
mob_core_ragerAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiMangleTimer;
void Reset() override
{
m_uiMangleTimer = 7 * IN_MILLISECONDS; // These times are probably wrong
}
void DamageTaken(Unit* /*pDoneBy*/, uint32& uiDamage) override
{
if (m_creature->GetHealthPercent() < 50.0f)
{
if (m_pInstance && m_pInstance->GetData(TYPE_GOLEMAGG) != DONE)
{
DoScriptText(EMOTE_LOW_HP, m_creature);
m_creature->SetHealth(m_creature->GetMaxHealth());
uiDamage = 0;
}
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Mangle
if (m_uiMangleTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_MANGLE) == CAST_OK)
{
m_uiMangleTimer = 10 * IN_MILLISECONDS;
}
}
else
{
m_uiMangleTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new mob_core_ragerAI(pCreature);
}
};
void AddSC_boss_golemagg()
{
Script* s;
s = new boss_golemagg();
s->RegisterSelf();
s = new mob_core_rager();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_golemagg";
//pNewScript->GetAI = &GetAI_boss_golemagg;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "mob_core_rager";
//pNewScript->GetAI = &GetAI_mob_core_rager;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,164 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Lucifron
* SD%Complete: 100
* SDComment: None
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
SPELL_IMPENDINGDOOM = 19702,
SPELL_LUCIFRONCURSE = 19703,
SPELL_SHADOWSHOCK = 19460
};
struct boss_lucifron : public CreatureScript
{
boss_lucifron() : CreatureScript("boss_lucifron") {}
struct boss_lucifronAI : public ScriptedAI
{
boss_lucifronAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
Reset();
}
ScriptedInstance* m_pInstance;
uint32 m_uiImpendingDoomTimer;
uint32 m_uiLucifronCurseTimer;
uint32 m_uiShadowShockTimer;
void Reset() override
{
m_uiImpendingDoomTimer = 10000;
m_uiLucifronCurseTimer = 20000;
m_uiShadowShockTimer = 6000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LUCIFRON, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LUCIFRON, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_LUCIFRON, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Impending doom timer
if (m_uiImpendingDoomTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_IMPENDINGDOOM) == CAST_OK)
{
m_uiImpendingDoomTimer = 20000;
}
}
else
{
m_uiImpendingDoomTimer -= uiDiff;
}
// Lucifron's curse timer
if (m_uiLucifronCurseTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_LUCIFRONCURSE) == CAST_OK)
{
m_uiLucifronCurseTimer = 20000;
}
}
else
{
m_uiLucifronCurseTimer -= uiDiff;
}
// Shadowshock
if (m_uiShadowShockTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_SHADOWSHOCK) == CAST_OK)
{
m_uiShadowShockTimer = 6000;
}
}
}
else
{
m_uiShadowShockTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_lucifronAI(pCreature);
}
};
void AddSC_boss_lucifron()
{
Script* s;
s = new boss_lucifron();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_lucifron";
//pNewScript->GetAI = &GetAI_boss_lucifron;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,170 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Magmadar
* SD%Complete: 75
* SDComment: Lava bomb needs still core support
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
EMOTE_GENERIC_FRENZY_KILL = -1000001,
SPELL_FRENZY = 19451,
SPELL_MAGMASPIT = 19449, // This is actually a buff he gives himself
SPELL_PANIC = 19408,
SPELL_LAVABOMB = 19411, // This calls a dummy server side effect that isn't implemented yet
SPELL_LAVABOMB_ALT = 19428
};
struct boss_magmadar : public CreatureScript
{
boss_magmadar() : CreatureScript("boss_magmadar") {}
struct boss_magmadarAI : public ScriptedAI
{
boss_magmadarAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiFrenzyTimer;
uint32 m_uiPanicTimer;
uint32 m_uiLavabombTimer;
void Reset() override
{
m_uiFrenzyTimer = 30000;
m_uiPanicTimer = 7000;
m_uiLavabombTimer = 12000;
}
void Aggro(Unit* /*pWho*/) override
{
DoCastSpellIfCan(m_creature, SPELL_MAGMASPIT, true);
if (m_pInstance)
{
m_pInstance->SetData(TYPE_MAGMADAR, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_MAGMADAR, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_MAGMADAR, NOT_STARTED);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Frenzy_Timer
if (m_uiFrenzyTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_FRENZY) == CAST_OK)
{
DoScriptText(EMOTE_GENERIC_FRENZY_KILL, m_creature);
m_uiFrenzyTimer = 15000;
}
}
else
{
m_uiFrenzyTimer -= uiDiff;
}
// Panic_Timer
if (m_uiPanicTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_PANIC) == CAST_OK)
{
m_uiPanicTimer = 30000;
}
}
else
{
m_uiPanicTimer -= uiDiff;
}
// Lavabomb_Timer
if (m_uiLavabombTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_LAVABOMB) == CAST_OK)
{
m_uiLavabombTimer = 12000;
}
}
}
else
{
m_uiLavabombTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_magmadarAI(pCreature);
}
};
void AddSC_boss_magmadar()
{
Script* s;
s = new boss_magmadar();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_magmadar";
//pNewScript->GetAI = &GetAI_boss_magmadar;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,560 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Majordomo_Executus
* SD%Complete: 95
* SDComment: Minor weaknesses
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
#include "TemporarySummon.h"
enum
{
SAY_AGGRO = -1409003,
SAY_SLAY = -1409005,
SAY_SPECIAL = -1409006, // Use unknown
SAY_LAST_ADD = -1409019, // When only one add remaining
SAY_DEFEAT_1 = -1409007,
SAY_DEFEAT_2 = -1409020,
SAY_DEFEAT_3 = -1409021,
SAY_SUMMON_0 = -1409023,
SAY_SUMMON_1 = -1409024,
SAY_SUMMON_MAJ = -1409008,
SAY_ARRIVAL1_RAG = -1409009,
SAY_ARRIVAL2_MAJ = -1409010,
SAY_ARRIVAL3_RAG = -1409011,
SAY_ARRIVAL4_MAJ = -1409022,
GOSSIP_ITEM_SUMMON_1 = -3409000,
GOSSIP_ITEM_SUMMON_2 = -3409001,
GOSSIP_ITEM_SUMMON_3 = -3409002,
TEXT_ID_SUMMON_1 = 4995,
TEXT_ID_SUMMON_2 = 5011,
TEXT_ID_SUMMON_3 = 5012,
SPELL_MAGIC_REFLECTION = 20619,
SPELL_DAMAGE_REFLECTION = 21075,
SPELL_BLASTWAVE = 20229,
SPELL_AEGIS = 20620,
SPELL_TELEPORT = 20618,
SPELL_TELEPORT_SELF = 19484,
SPELL_SUMMON_RAGNAROS = 19774,
SPELL_ELEMENTAL_FIRE = 19773,
SPELL_RAGNA_EMERGE = 20568,
};
struct boss_majordomo : public CreatureScript
{
boss_majordomo() : CreatureScript("boss_majordomo") {}
struct boss_majordomoAI : public ScriptedAI
{
boss_majordomoAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
m_bHasEncounterFinished = false;
}
ScriptedInstance* m_pInstance;
uint32 m_uiMagicReflectionTimer;
uint32 m_uiDamageReflectionTimer;
uint32 m_uiBlastwaveTimer;
uint32 m_uiTeleportTimer;
uint32 m_uiAegisTimer;
uint32 m_uiSpeechTimer;
ObjectGuid m_ragnarosGuid;
bool m_bHasEncounterFinished;
uint8 m_uiAddsKilled;
uint8 m_uiSpeech;
GuidList m_luiMajordomoAddsGUIDs;
void Reset() override
{
m_uiMagicReflectionTimer = 30000; // Damage reflection first so we alternate
m_uiDamageReflectionTimer = 15000;
m_uiBlastwaveTimer = 10000;
m_uiTeleportTimer = 20000;
m_uiAegisTimer = 5000;
m_uiSpeechTimer = 1000;
m_uiAddsKilled = 0;
m_uiSpeech = 0;
}
void KilledUnit(Unit* /*pVictim*/) override
{
if (urand(0, 4))
{
return;
}
DoScriptText(SAY_SLAY, m_creature);
}
void Aggro(Unit* pWho) override
{
if (pWho->GetTypeId() == TYPEID_UNIT && pWho->GetEntry() == NPC_RAGNAROS)
{
return;
}
DoScriptText(SAY_AGGRO, m_creature);
if (m_pInstance)
{
m_pInstance->SetData(TYPE_MAJORDOMO, IN_PROGRESS);
}
}
void JustReachedHome() override
{
if (!m_bHasEncounterFinished) // Normal reached home, FAIL
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_MAJORDOMO, FAIL);
}
}
else // Finished the encounter, DONE
{
// Exit combat
m_creature->RemoveAllAurasOnEvade();
m_creature->DeleteThreatList();
m_creature->CombatStop(true);
m_creature->SetLootRecipient(NULL);
// Set friendly
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
m_creature->SetFactionTemporary(FACTION_MAJORDOMO_FRIENDLY, TEMPFACTION_RESTORE_RESPAWN);
// Reset orientation
m_creature->SetFacingTo(m_aMajordomoLocations[0].m_fO);
// Start his speech
m_uiSpeechTimer = 1; // At next tick
m_uiSpeech = 1;
m_pInstance->SetData(TYPE_MAJORDOMO, DONE);
}
}
void StartSummonEvent(Player* pPlayer)
{
m_creature->RemoveFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
// Prevent possible exploits with double summoning
if (m_creature->GetMap()->GetCreature(m_ragnarosGuid))
{
return;
}
DoScriptText(SAY_SUMMON_0, m_creature, pPlayer);
m_uiSpeechTimer = 5000;
m_uiSpeech = 10;
}
void JustRespawned() override
{
// Encounter finished, need special treatment
if (m_bHasEncounterFinished)
{
// This needs to be set to be able to resummon Ragnaros
m_creature->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
// Relocate here
debug_log("[SD3]: boss_majordomo_executus: Relocate to Ragnaros' Lair on respawn");
m_creature->GetMap()->CreatureRelocation(m_creature, m_aMajordomoLocations[1].m_fX, m_aMajordomoLocations[1].m_fY, m_aMajordomoLocations[1].m_fZ, m_aMajordomoLocations[1].m_fO);
m_creature->SetActiveObjectState(false);
}
}
void JustSummoned(Creature* pSummoned) override
{
if (pSummoned->GetEntry() == NPC_FLAMEWAKER_HEALER || pSummoned->GetEntry() == NPC_FLAMEWAKER_ELITE)
{
m_luiMajordomoAddsGUIDs.push_back(pSummoned->GetObjectGuid());
pSummoned->SetRespawnDelay(2 * HOUR);
}
else if (pSummoned->GetEntry() == NPC_RAGNAROS)
{
m_ragnarosGuid = pSummoned->GetObjectGuid();
pSummoned->CastSpell(pSummoned, SPELL_RAGNA_EMERGE, false);
}
}
void JustDied(Unit* pKiller) override
{
if (pKiller->GetTypeId() == TYPEID_UNIT && pKiller->GetEntry() == NPC_RAGNAROS)
{
DoScriptText(SAY_ARRIVAL4_MAJ, m_creature);
}
}
void CorpseRemoved(uint32& uiRespawnDelay) override
{
uiRespawnDelay = urand(2 * HOUR, 3 * HOUR);
if (m_bHasEncounterFinished)
{
// Needed for proper respawn handling
debug_log("[SD3]: boss_majordomo_executus: Set active");
m_creature->SetActiveObjectState(true);
}
}
void SummonedCreatureJustDied(Creature* pSummoned) override
{
if (pSummoned->GetEntry() == NPC_FLAMEWAKER_HEALER || pSummoned->GetEntry() == NPC_FLAMEWAKER_ELITE)
{
m_uiAddsKilled += 1;
// Yell if only one Add alive
if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size() - 1)
{
DoScriptText(SAY_LAST_ADD, m_creature);
}
// All adds are killed, retreat
else if (m_uiAddsKilled == m_luiMajordomoAddsGUIDs.size())
{
m_bHasEncounterFinished = true;
m_creature->GetMotionMaster()->MoveTargetedHome();
}
}
}
// Unsummon Majordomo adds
void UnsummonMajordomoAdds()
{
for (GuidList::const_iterator itr = m_luiMajordomoAddsGUIDs.begin(); itr != m_luiMajordomoAddsGUIDs.end(); ++itr)
{
if (Creature* pAdd = m_creature->GetMap()->GetCreature(*itr))
if (pAdd->IsTemporarySummon())
{
((TemporarySummon*)pAdd)->UnSummon();
}
}
m_luiMajordomoAddsGUIDs.clear();
}
void DamageTaken(Unit* /*pDealer*/, uint32& uiDamage) override
{
if (uiDamage > m_creature->GetHealth())
{
uiDamage = 0;
DoCastSpellIfCan(m_creature, SPELL_AEGIS, CAST_TRIGGERED);
}
}
void UpdateAI(const uint32 uiDiff) override
{
// Handling of his combat-end speech and Ragnaros summoning
if (m_uiSpeech)
{
if (m_uiSpeechTimer < uiDiff)
{
switch (m_uiSpeech)
{
// Majordomo retreat event
case 1:
DoScriptText(SAY_DEFEAT_1, m_creature);
m_uiSpeechTimer = 7500;
++m_uiSpeech;
break;
case 2:
DoScriptText(SAY_DEFEAT_2, m_creature);
m_uiSpeechTimer = 8000;
++m_uiSpeech;
break;
case 3:
DoScriptText(SAY_DEFEAT_3, m_creature);
m_uiSpeechTimer = 21500;
++m_uiSpeech;
break;
case 4:
DoCastSpellIfCan(m_creature, SPELL_TELEPORT_SELF);
// TODO - when should they be unsummoned?
// TODO - also unclear how this should be handled, as of range issues
m_uiSpeechTimer = 900;
++m_uiSpeech;
break;
case 5:
// Majordomo is away now, remove his adds
UnsummonMajordomoAdds();
m_uiSpeech = 0;
break;
// Ragnaros Summon Event
case 10:
DoScriptText(SAY_SUMMON_1, m_creature);
++m_uiSpeech;
m_uiSpeechTimer = 1000;
break;
case 11:
DoCastSpellIfCan(m_creature, SPELL_SUMMON_RAGNAROS);
// TODO - Move along, this expects to be handled with mmaps
m_creature->GetMotionMaster()->MovePoint(1, 831.079590f, -816.023193f, -229.023270f);
++m_uiSpeech;
m_uiSpeechTimer = 7000;
break;
case 12:
// Reset orientation
if (GameObject* pLavaSteam = m_pInstance->GetSingleGameObjectFromStorage(GO_LAVA_STEAM))
{
m_creature->SetFacingToObject(pLavaSteam);
}
m_uiSpeechTimer = 4500;
++m_uiSpeech;
break;
case 13:
DoScriptText(SAY_SUMMON_MAJ, m_creature);
++m_uiSpeech;
m_uiSpeechTimer = 8000;
break;
case 14:
// Summon Ragnaros
if (m_pInstance)
if (GameObject* pGo = m_pInstance->GetSingleGameObjectFromStorage(GO_LAVA_STEAM))
{
m_creature->SummonCreature(NPC_RAGNAROS, pGo->GetPositionX(), pGo->GetPositionY(), pGo->GetPositionZ(), fmod(m_creature->GetOrientation() + M_PI, 2 * M_PI), TEMPSUMMON_TIMED_OOC_OR_DEAD_DESPAWN, 2 * HOUR * IN_MILLISECONDS);
}
++m_uiSpeech;
m_uiSpeechTimer = 8700;
break;
case 15:
if (Creature* pRagnaros = m_creature->GetMap()->GetCreature(m_ragnarosGuid))
{
DoScriptText(SAY_ARRIVAL1_RAG, pRagnaros);
}
++m_uiSpeech;
m_uiSpeechTimer = 11700;
break;
case 16:
DoScriptText(SAY_ARRIVAL2_MAJ, m_creature);
++m_uiSpeech;
m_uiSpeechTimer = 8700;
break;
case 17:
if (Creature* pRagnaros = m_creature->GetMap()->GetCreature(m_ragnarosGuid))
{
DoScriptText(SAY_ARRIVAL3_RAG, pRagnaros);
}
++m_uiSpeech;
m_uiSpeechTimer = 16500;
break;
case 18:
if (Creature* pRagnaros = m_creature->GetMap()->GetCreature(m_ragnarosGuid))
{
pRagnaros->CastSpell(m_creature, SPELL_ELEMENTAL_FIRE, false);
}
// Rest of summoning speech is handled by Ragnaros, as Majordomo will be dead
m_uiSpeech = 0;
break;
}
}
else
{
m_uiSpeechTimer -= uiDiff;
}
}
// When encounter finished, no need to do anything anymore (important for moving home after victory)
if (m_bHasEncounterFinished)
{
return;
}
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Cast Ageis to heal self
if (m_uiAegisTimer <= uiDiff)
{
m_uiAegisTimer = 0;
}
else
{
m_uiAegisTimer -= uiDiff;
}
if (m_creature->GetHealthPercent() < 90.0f && !m_uiAegisTimer)
{
DoCastSpellIfCan(m_creature, SPELL_AEGIS);
m_uiAegisTimer = 10000;
}
// Magic Reflection Timer
if (m_uiMagicReflectionTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_MAGIC_REFLECTION) == CAST_OK)
{
m_uiMagicReflectionTimer = 30000;
}
}
else
{
m_uiMagicReflectionTimer -= uiDiff;
}
// Damage Reflection Timer
if (m_uiDamageReflectionTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_DAMAGE_REFLECTION) == CAST_OK)
{
m_uiDamageReflectionTimer = 30000;
}
}
else
{
m_uiDamageReflectionTimer -= uiDiff;
}
// Teleports the target to the heated rock in the center of the area
if (m_uiTeleportTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 1))
{
if (DoCastSpellIfCan(pTarget, SPELL_TELEPORT) == CAST_OK)
{
m_uiTeleportTimer = 20000;
}
}
}
else
{
m_uiTeleportTimer -= uiDiff;
}
// Blastwave Timer
if (m_uiBlastwaveTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_BLASTWAVE) == CAST_OK)
{
m_uiBlastwaveTimer = 10000;
}
}
else
{
m_uiBlastwaveTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_majordomoAI(pCreature);
}
bool OnGossipHello(Player* pPlayer, Creature* pCreature) override
{
if (InstanceData* pInstance = pCreature->GetInstanceData())
{
if (pInstance->GetData(TYPE_RAGNAROS) == NOT_STARTED || pInstance->GetData(TYPE_RAGNAROS) == FAIL)
{
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SUMMON_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 1);
pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SUMMON_1, pCreature->GetObjectGuid());
}
}
return true;
}
bool OnGossipSelect(Player* pPlayer, Creature* pCreature, uint32 /*sender*/, uint32 uiAction) override
{
pPlayer->PlayerTalkClass->ClearMenus();
switch (uiAction)
{
case GOSSIP_ACTION_INFO_DEF + 1:
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SUMMON_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 2);
pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SUMMON_2, pCreature->GetObjectGuid());
break;
case GOSSIP_ACTION_INFO_DEF + 2:
pPlayer->ADD_GOSSIP_ITEM_ID(GOSSIP_ICON_CHAT, GOSSIP_ITEM_SUMMON_3, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF + 3);
pPlayer->SEND_GOSSIP_MENU(TEXT_ID_SUMMON_3, pCreature->GetObjectGuid());
break;
case GOSSIP_ACTION_INFO_DEF + 3:
pPlayer->CLOSE_GOSSIP_MENU();
if (boss_majordomoAI* pMajoAI = dynamic_cast<boss_majordomoAI*>(pCreature->AI()))
{
pMajoAI->StartSummonEvent(pPlayer);
}
break;
}
return true;
}
};
struct spell_boss_majordomo : public SpellScript
{
spell_boss_majordomo() : SpellScript("spell_boss_majordomo") {}
bool EffectDummy(Unit* /*pCaster*/, uint32 uiSpellId, SpellEffectIndex uiEffIndex, Object* pCreatureTarget, ObjectGuid /*originalCasterGuid*/) override
{
if (uiSpellId != SPELL_TELEPORT_SELF || uiEffIndex != EFFECT_INDEX_0)
{
return false;
}
pCreatureTarget->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP); //TODO is here ToCreature() needed?
pCreatureTarget->ToCreature()->NearTeleportTo(m_aMajordomoLocations[1].m_fX, m_aMajordomoLocations[1].m_fY, m_aMajordomoLocations[1].m_fZ, m_aMajordomoLocations[1].m_fO, true);
// TODO - some visibility update?
return true;
}
};
void AddSC_boss_majordomo()
{
Script* s;
s = new boss_majordomo();
s->RegisterSelf();
s = new spell_boss_majordomo();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_majordomo";
//pNewScript->pEffectDummyNPC = &EffectDummyCreature_spell_boss_majordomo;
//pNewScript->pGossipHello = &GossipHello_boss_majordomo;
//pNewScript->pGossipSelect = &GossipSelect_boss_majordomo;
//pNewScript->GetAI = &GetAI_boss_majordomo;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,409 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Ragnaros
* SD%Complete: 70
* SDComment: Melee/Range Combat behavior is not correct(any enemy in melee range, not only getVictim), Some abilities are missing
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
/**
* Notes:
*
* There have been quite some bugs about his spells, keep this as reference until all are resolved.
*
* Missing features (based on wowwiki)
* Lava Burst - this spell is handled by Go 178088 which is summoned by spells 21886, 21900 - 21907
*/
enum
{
SAY_ARRIVAL5_RAG = -1409012,
SAY_REINFORCEMENTS_1 = -1409013,
SAY_REINFORCEMENTS_2 = -1409014,
SAY_HAMMER = -1409015,
SAY_WRATH = -1409016,
SAY_KILL = -1409017,
SAY_MAGMABURST = -1409018,
SPELL_WRATH_OF_RAGNAROS = 20566,
SPELL_ELEMENTAL_FIRE = 20564,
SPELL_MAGMA_BLAST = 20565, // Ranged attack if nobody is in melee range
SPELL_MELT_WEAPON = 21387,
SPELL_RAGNA_SUBMERGE = 21107, // Stealth aura
SPELL_RAGNA_EMERGE = 20568, // Emerge from lava
SPELL_ELEMENTAL_FIRE_KILL = 19773,
SPELL_MIGHT_OF_RAGNAROS = 21154,
SPELL_INTENSE_HEAT = 21155,
MAX_ADDS_IN_SUBMERGE = 8,
NPC_SON_OF_FLAME = 12143,
NPC_FLAME_OF_RAGNAROS = 13148,
};
struct boss_ragnaros : public CreatureScript
{
boss_ragnaros() : CreatureScript("boss_ragnaros") {}
struct boss_ragnarosAI : public Scripted_NoMovementAI
{
boss_ragnarosAI(Creature* pCreature) : Scripted_NoMovementAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
m_uiEnterCombatTimer = 0;
m_bHasAggroYelled = false;
}
ScriptedInstance* m_pInstance;
uint32 m_uiEnterCombatTimer;
uint32 m_uiWrathOfRagnarosTimer;
uint32 m_uiHammerTimer;
uint32 m_uiMagmaBlastTimer;
uint32 m_uiElementalFireTimer;
uint32 m_uiSubmergeTimer;
uint32 m_uiAttackTimer;
uint32 m_uiAddCount;
bool m_bHasAggroYelled;
bool m_bHasYelledMagmaBurst;
bool m_bHasSubmergedOnce;
bool m_bIsSubmerged;
void Reset() override
{
m_uiWrathOfRagnarosTimer = 30000; // TODO Research more, according to wowwiki 25s, but timers up to 34s confirmed
m_uiHammerTimer = 11000; // TODO wowwiki states 20-30s timer, but ~11s confirmed
m_uiMagmaBlastTimer = 2000;
m_uiElementalFireTimer = 3000;
m_uiSubmergeTimer = 3 * MINUTE * IN_MILLISECONDS;
m_uiAttackTimer = 90 * IN_MILLISECONDS;
m_uiAddCount = 0;
m_bHasYelledMagmaBurst = false;
m_bHasSubmergedOnce = false;
m_bIsSubmerged = false;
}
void KilledUnit(Unit* pVictim) override
{
if (pVictim->GetTypeId() != TYPEID_PLAYER)
{
return;
}
if (urand(0, 3))
{
return;
}
DoScriptText(SAY_KILL, m_creature);
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_RAGNAROS, DONE);
}
}
void Aggro(Unit* pWho) override
{
if (pWho->GetTypeId() == TYPEID_UNIT && pWho->GetEntry() == NPC_MAJORDOMO)
{
return;
}
DoCastSpellIfCan(m_creature, SPELL_MELT_WEAPON);
if (m_pInstance)
{
m_pInstance->SetData(TYPE_RAGNAROS, IN_PROGRESS);
}
}
void EnterEvadeMode() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_RAGNAROS, FAIL);
}
// Reset flag if had been submerged
if (m_creature->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE))
{
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
}
ScriptedAI::EnterEvadeMode();
}
void SummonedCreatureJustDied(Creature* pSummmoned) override
{
// If all Sons of Flame are dead, trigger emerge
if (pSummmoned->GetEntry() == NPC_SON_OF_FLAME)
{
m_uiAddCount--;
// If last add killed then emerge soonish
if (m_uiAddCount == 0)
{
m_uiAttackTimer = std::min(m_uiAttackTimer, (uint32)1000);
}
}
}
void JustSummoned(Creature* pSummoned) override
{
if (pSummoned->GetEntry() == NPC_SON_OF_FLAME)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
pSummoned->AI()->AttackStart(pTarget);
}
++m_uiAddCount;
}
else if (pSummoned->GetEntry() == NPC_FLAME_OF_RAGNAROS)
{
pSummoned->CastSpell(pSummoned, SPELL_INTENSE_HEAT, true, NULL, NULL, m_creature->GetObjectGuid());
}
}
void SpellHitTarget(Unit* pTarget, const SpellEntry* pSpell) override
{
// As Majordomo is now killed, the last timer (until attacking) must be handled with ragnaros script
if (pSpell->Id == SPELL_ELEMENTAL_FIRE_KILL && pTarget->GetTypeId() == TYPEID_UNIT && pTarget->GetEntry() == NPC_MAJORDOMO)
{
m_uiEnterCombatTimer = 10000;
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (m_uiEnterCombatTimer)
{
if (m_uiEnterCombatTimer <= uiDiff)
{
if (!m_bHasAggroYelled)
{
m_uiEnterCombatTimer = 3000;
m_bHasAggroYelled = true;
DoScriptText(SAY_ARRIVAL5_RAG, m_creature);
}
else
{
m_uiEnterCombatTimer = 0;
// If we don't remove this passive flag, he will be unattackable after evading, this way he will enter combat
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PASSIVE);
if (m_pInstance)
{
if (Player* pPlayer = m_pInstance->GetPlayerInMap(true, false))
{
m_creature->AI()->AttackStart(pPlayer);
return;
}
}
}
}
else
{
m_uiEnterCombatTimer -= uiDiff;
}
}
// Return since we have no target
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
if (m_bIsSubmerged)
{
// Timer to check when Ragnaros should emerge (is set to soonish, when last add is killed)
if (m_uiAttackTimer < uiDiff)
{
// Become emerged again
DoCastSpellIfCan(m_creature, SPELL_RAGNA_EMERGE);
m_creature->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
m_uiSubmergeTimer = 3 * MINUTE * IN_MILLISECONDS;
m_uiMagmaBlastTimer = 3000; // Delay the magma blast after emerge
m_bIsSubmerged = false;
}
else
{
m_uiAttackTimer -= uiDiff;
}
// Do nothing while submerged
return;
}
// Wrath Of Ragnaros Timer
if (m_uiWrathOfRagnarosTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_WRATH_OF_RAGNAROS) == CAST_OK)
{
DoScriptText(SAY_WRATH, m_creature);
m_uiWrathOfRagnarosTimer = 30000;
}
}
else
{
m_uiWrathOfRagnarosTimer -= uiDiff;
}
// Elemental Fire Timer
if (m_uiElementalFireTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_ELEMENTAL_FIRE) == CAST_OK)
{
m_uiElementalFireTimer = urand(10000, 14000);
}
}
else
{
m_uiElementalFireTimer -= uiDiff;
}
// Hammer of Ragnaros
if (m_uiHammerTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0, SPELL_MIGHT_OF_RAGNAROS, SELECT_FLAG_POWER_MANA))
{
if (DoCastSpellIfCan(pTarget, SPELL_MIGHT_OF_RAGNAROS) == CAST_OK)
{
DoScriptText(SAY_HAMMER, m_creature);
m_uiHammerTimer = 11000;
}
}
else
{
m_uiHammerTimer = 11000;
}
}
else
{
m_uiHammerTimer -= uiDiff;
}
// Submerge Timer
if (m_uiSubmergeTimer < uiDiff)
{
// Submerge and attack again after 90 secs
DoCastSpellIfCan(m_creature, SPELL_RAGNA_SUBMERGE, CAST_INTERRUPT_PREVIOUS);
m_creature->HandleEmote(EMOTE_ONESHOT_SUBMERGE);
m_bIsSubmerged = true;
m_uiAttackTimer = 90 * IN_MILLISECONDS;
m_creature->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
// Say dependend if first time or not
DoScriptText(!m_bHasSubmergedOnce ? SAY_REINFORCEMENTS_1 : SAY_REINFORCEMENTS_2, m_creature);
m_bHasSubmergedOnce = true;
// Summon 8 elementals at random points around the boss
float fX, fY, fZ;
for (uint8 i = 0; i < MAX_ADDS_IN_SUBMERGE; ++i)
{
m_creature->GetRandomPoint(m_creature->GetPositionX(), m_creature->GetPositionY(), m_creature->GetPositionZ(), 30.0f, fX, fY, fZ);
m_creature->SummonCreature(NPC_SON_OF_FLAME, fX, fY, fZ, 0.0f, TEMPSUMMON_TIMED_OOC_DESPAWN, 1000);
}
return;
}
else
{
m_uiSubmergeTimer -= uiDiff;
}
// TODO this actually should select _any_ enemy in melee range, not only the tank
// Range check for melee target, if nobody is found in range, then cast magma blast on random
// If we are within range melee the target
if (m_creature->IsNonMeleeSpellCasted(false) || !m_creature->getVictim())
{
return;
}
if (m_creature->CanReachWithMeleeAttack(m_creature->getVictim()))
{
// Make sure our attack is ready
if (m_creature->isAttackReady())
{
m_creature->AttackerStateUpdate(m_creature->getVictim());
m_creature->resetAttackTimer();
m_bHasYelledMagmaBurst = false;
}
}
else
{
// Magma Burst Timer
if (m_uiMagmaBlastTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_MAGMA_BLAST) == CAST_OK)
{
if (!m_bHasYelledMagmaBurst)
{
DoScriptText(SAY_MAGMABURST, m_creature);
m_bHasYelledMagmaBurst = true;
}
m_uiMagmaBlastTimer = 1000; // Spamm this!
}
}
}
else
{
m_uiMagmaBlastTimer -= uiDiff;
}
}
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_ragnarosAI(pCreature);
}
};
void AddSC_boss_ragnaros()
{
Script* s;
s = new boss_ragnaros();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_ragnaros";
//pNewScript->GetAI = &GetAI_boss_ragnaros;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,202 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Shazzrah
* SD%Complete: 75
* SDComment: Teleport NYI (need core support, remove hack here when implemented)
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
SPELL_ARCANE_EXPLOSION = 19712,
SPELL_SHAZZRAH_CURSE = 19713,
SPELL_MAGIC_GROUNDING = 19714,
SPELL_COUNTERSPELL = 19715,
SPELL_GATE_OF_SHAZZRAH = 23138 // effect spell: 23139
};
struct boss_shazzrah : public CreatureScript
{
boss_shazzrah() : CreatureScript("boss_shazzrah") {}
struct boss_shazzrahAI : public ScriptedAI
{
boss_shazzrahAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiArcaneExplosionTimer;
uint32 m_uiShazzrahCurseTimer;
uint32 m_uiMagicGroundingTimer;
uint32 m_uiCounterspellTimer;
uint32 m_uiBlinkTimer;
void Reset() override
{
m_uiArcaneExplosionTimer = 6000;
m_uiShazzrahCurseTimer = 10000;
m_uiMagicGroundingTimer = 24000;
m_uiCounterspellTimer = 15000;
m_uiBlinkTimer = 30000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SHAZZRAH, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SHAZZRAH, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SHAZZRAH, NOT_STARTED);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Arcane Explosion Timer
if (m_uiArcaneExplosionTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_ARCANE_EXPLOSION) == CAST_OK)
{
m_uiArcaneExplosionTimer = urand(5000, 9000);
}
}
else
{
m_uiArcaneExplosionTimer -= uiDiff;
}
// Shazzrah Curse Timer
if (m_uiShazzrahCurseTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_SHAZZRAH_CURSE) == CAST_OK)
{
m_uiShazzrahCurseTimer = 20000;
}
}
else
{
m_uiShazzrahCurseTimer -= uiDiff;
}
// Magic Grounding Timer
if (m_uiMagicGroundingTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_MAGIC_GROUNDING) == CAST_OK)
{
m_uiMagicGroundingTimer = 35000;
}
}
else
{
m_uiMagicGroundingTimer -= uiDiff;
}
// Counterspell Timer
if (m_uiCounterspellTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_COUNTERSPELL) == CAST_OK)
{
m_uiCounterspellTimer = urand(16000, 20000);
}
}
else
{
m_uiCounterspellTimer -= uiDiff;
}
// Blink Timer
if (m_uiBlinkTimer < uiDiff)
{
// Teleporting him to a random gamer and casting Arcane Explosion after that.
if (DoCastSpellIfCan(m_creature, SPELL_GATE_OF_SHAZZRAH) == CAST_OK)
{
// manual, until added effect of dummy properly -- TODO REMOVE HACK
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
m_creature->NearTeleportTo(pTarget->GetPositionX(), pTarget->GetPositionY(), pTarget->GetPositionZ(), m_creature->GetOrientation());
}
DoResetThreat();
DoCastSpellIfCan(m_creature, SPELL_ARCANE_EXPLOSION, CAST_TRIGGERED);
m_uiBlinkTimer = 45000;
}
}
else
{
m_uiBlinkTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_shazzrahAI(pCreature);
}
};
void AddSC_boss_shazzrah()
{
Script* s;
s = new boss_shazzrah();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_shazzrah";
//pNewScript->GetAI = &GetAI_boss_shazzrah;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,310 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Boss_Sulfuron_Harbringer
* SD%Complete: 80
* SDComment: Spells Dark strike and Flamespear need confirmation
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
enum
{
SPELL_DARK_STRIKE = 19777, // Wowhead Linked to add - need confirmation!
SPELL_DEMORALIZING_SHOUT = 19778,
SPELL_INSPIRE = 19779,
SPELL_HAND_OF_RAGNAROS = 19780,
SPELL_FLAMESPEAR = 19781,
// Adds Spells
SPELL_HEAL = 19775,
SPELL_SHADOWWORD_PAIN = 19776,
SPELL_IMMOLATE = 20294
};
struct boss_sulfuron : public CreatureScript
{
boss_sulfuron() : CreatureScript("boss_sulfuron") {}
struct boss_sulfuronAI : public ScriptedAI
{
boss_sulfuronAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
ScriptedInstance* m_pInstance;
uint32 m_uiDarkstrikeTimer;
uint32 m_uiDemoralizingShoutTimer;
uint32 m_uiInspireTimer;
uint32 m_uiKnockdownTimer;
uint32 m_uiFlamespearTimer;
void Reset() override
{
m_uiDarkstrikeTimer = 10000;
m_uiDemoralizingShoutTimer = 15000;
m_uiInspireTimer = 3000;
m_uiKnockdownTimer = 6000;
m_uiFlamespearTimer = 2000;
}
void Aggro(Unit* /*pWho*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SULFURON, IN_PROGRESS);
}
}
void JustDied(Unit* /*pKiller*/) override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SULFURON, DONE);
}
}
void JustReachedHome() override
{
if (m_pInstance)
{
m_pInstance->SetData(TYPE_SULFURON, FAIL);
}
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Demoralizing Shout Timer
if (m_uiDemoralizingShoutTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_DEMORALIZING_SHOUT) == CAST_OK)
{
m_uiDemoralizingShoutTimer = urand(15000, 20000);
}
}
else
{
m_uiDemoralizingShoutTimer -= uiDiff;
}
// Inspire Timer
if (m_uiInspireTimer < uiDiff)
{
Creature* pTarget = NULL;
std::list<Creature*> pList = DoFindFriendlyMissingBuff(45.0f, SPELL_INSPIRE);
if (!pList.empty())
{
std::list<Creature*>::iterator i = pList.begin();
advance(i, (rand() % pList.size()));
pTarget = (*i);
}
if (!pTarget)
{
pTarget = m_creature;
}
if (DoCastSpellIfCan(pTarget, SPELL_INSPIRE) == CAST_OK)
{
m_uiInspireTimer = 10000;
}
}
else
{
m_uiInspireTimer -= uiDiff;
}
// Hand of Ragnaros Timer
if (m_uiKnockdownTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature, SPELL_HAND_OF_RAGNAROS) == CAST_OK)
{
m_uiKnockdownTimer = urand(12000, 15000);
}
}
else
{
m_uiKnockdownTimer -= uiDiff;
}
// Flamespear Timer
if (m_uiFlamespearTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_FLAMESPEAR) == CAST_OK)
{
m_uiFlamespearTimer = urand(12000, 16000);
}
}
}
else
{
m_uiFlamespearTimer -= uiDiff;
}
// Dark Strike Timer
if (m_uiDarkstrikeTimer < uiDiff)
{
if (DoCastSpellIfCan(m_creature->getVictim(), SPELL_DARK_STRIKE) == CAST_OK)
{
m_uiDarkstrikeTimer = urand(15000, 18000);
}
}
else
{
m_uiDarkstrikeTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new boss_sulfuronAI(pCreature);
}
};
struct mob_flamewaker_priest : public CreatureScript
{
mob_flamewaker_priest() : CreatureScript("mob_flamewaker_priest") {}
struct mob_flamewaker_priestAI : public ScriptedAI
{
mob_flamewaker_priestAI(Creature* pCreature) : ScriptedAI(pCreature)
{
m_pInstance = (ScriptedInstance*)pCreature->GetInstanceData();
}
uint32 m_uiHealTimer;
uint32 m_uiShadowWordPainTimer;
uint32 m_uiImmolateTimer;
ScriptedInstance* m_pInstance;
void Reset() override
{
m_uiHealTimer = urand(15000, 30000);
m_uiShadowWordPainTimer = 2000;
m_uiImmolateTimer = 8000;
}
void UpdateAI(const uint32 uiDiff) override
{
if (!m_creature->SelectHostileTarget() || !m_creature->getVictim())
{
return;
}
// Casting Heal to Sulfuron or other Guards.
if (m_uiHealTimer < uiDiff)
{
if (Unit* pUnit = DoSelectLowestHpFriendly(60.0f, 1))
{
if (DoCastSpellIfCan(pUnit, SPELL_HEAL) == CAST_OK)
{
m_uiHealTimer = urand(15000, 20000);
}
}
}
else
{
m_uiHealTimer -= uiDiff;
}
// ShadowWord Pain Timer
if (m_uiShadowWordPainTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_SHADOWWORD_PAIN) == CAST_OK)
{
m_uiShadowWordPainTimer = urand(18000, 26000);
}
}
}
else
{
m_uiShadowWordPainTimer -= uiDiff;
}
// Immolate Timer
if (m_uiImmolateTimer < uiDiff)
{
if (Unit* pTarget = m_creature->SelectAttackingTarget(ATTACKING_TARGET_RANDOM, 0))
{
if (DoCastSpellIfCan(pTarget, SPELL_IMMOLATE) == CAST_OK)
{
m_uiImmolateTimer = urand(15000, 25000);
}
}
}
else
{
m_uiImmolateTimer -= uiDiff;
}
DoMeleeAttackIfReady();
}
};
CreatureAI* GetAI(Creature* pCreature) override
{
return new mob_flamewaker_priestAI(pCreature);
}
};
void AddSC_boss_sulfuron()
{
Script* s;
s = new boss_sulfuron();
s->RegisterSelf();
s = new mob_flamewaker_priest();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "boss_sulfuron";
//pNewScript->GetAI = &GetAI_boss_sulfuron;
//pNewScript->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "mob_flamewaker_priest";
//pNewScript->GetAI = &GetAI_mob_flamewaker_priest;
//pNewScript->RegisterSelf();
}

View file

@ -0,0 +1,502 @@
/**
* ScriptDev3 is an extension for mangos providing enhanced features for
* area triggers, creatures, game objects, instances, items, and spells beyond
* the default database scripting in mangos.
*
* Copyright (C) 2006-2013 ScriptDev2 <http://www.scriptdev2.com/>
* Copyright (C) 2014-2016 MaNGOS <https://getmangos.eu>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* World of Warcraft, and all World of Warcraft or Warcraft art, images,
* and lore are copyrighted by Blizzard Entertainment, Inc.
*/
/**
* ScriptData
* SDName: Instance_Molten_Core
* SD%Complete: 25
* SDComment: Majordomos and Ragnaros Event missing
* SDCategory: Molten Core
* EndScriptData
*/
#include "precompiled.h"
#include "molten_core.h"
static sSpawnLocation m_aBosspawnLocs[MAX_MAJORDOMO_ADDS] =
{
{NPC_FLAMEWAKER_ELITE, 737.945f, -1156.48f, -118.945f, 4.46804f},
{NPC_FLAMEWAKER_ELITE, 752.520f, -1191.02f, -118.218f, 2.49582f},
{NPC_FLAMEWAKER_ELITE, 752.953f, -1163.94f, -118.869f, 3.70010f},
{NPC_FLAMEWAKER_ELITE, 738.814f, -1197.40f, -118.018f, 1.83260f},
{NPC_FLAMEWAKER_HEALER, 746.939f, -1194.87f, -118.016f, 2.21657f},
{NPC_FLAMEWAKER_HEALER, 747.132f, -1158.87f, -118.897f, 4.03171f},
{NPC_FLAMEWAKER_HEALER, 757.116f, -1170.12f, -118.793f, 3.40339f},
{NPC_FLAMEWAKER_HEALER, 755.910f, -1184.46f, -118.449f, 2.80998f}
};
struct is_molten_core : public InstanceScript
{
is_molten_core() : InstanceScript("instance_molten_core") {}
class instance_molten_core : public ScriptedInstance
{
public:
instance_molten_core(Map* pMap) : ScriptedInstance(pMap)
{
Initialize();
}
~instance_molten_core() {}
void Initialize() override
{
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
memset(&m_auiRuneState, 0, sizeof(m_auiRuneState));
}
bool IsEncounterInProgress() const override
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
{
return true;
}
}
return false;
}
void OnCreatureCreate(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
// Bosses
case NPC_GARR:
case NPC_SULFURON:
case NPC_MAJORDOMO:
m_mNpcEntryGuidStore[pCreature->GetEntry()] = pCreature->GetObjectGuid();
break;
case NPC_FIRESWORN:
m_sFireswornGUID.insert(pCreature->GetObjectGuid());
break;
case NPC_LAVA_SURGER:
if (GetData(TYPE_GARR) == DONE)
pCreature->ForcedDespawn(500);
break;
}
}
void OnCreatureDeath(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
case NPC_FIRESWORN:
m_sFireswornGUID.erase(pCreature->GetObjectGuid());
if (Creature* pGarr = GetSingleCreatureFromStorage(NPC_GARR))
{
if (pGarr->IsAlive())
{
pGarr->CastSpell(pGarr, SPELL_GARR_ENRAGE, true);
pGarr->CastSpell(pGarr, SPELL_GARR_ARMOR_DEBUFF, true);
if (!m_sFireswornGUID.size())
pGarr->AI()->ReceiveAIEvent(AI_EVENT_CUSTOM_B, pGarr, pGarr, 0);
}
}
break;
default:
break;
}
}
void OnCreatureDespawn(Creature* pCreature) override
{
switch (pCreature->GetEntry())
{
case NPC_FIRESWORN:
OnCreatureDeath(pCreature);
break;
default:
break;
}
}
void OnObjectCreate(GameObject* pGo) override
{
switch (pGo->GetEntry())
{
// Runes
case GO_RUNE_KRESS:
case GO_RUNE_MOHN:
case GO_RUNE_BLAZ:
case GO_RUNE_MAZJ:
case GO_RUNE_ZETH:
case GO_RUNE_THERI:
case GO_RUNE_KORO:
if (sRuneEncounters const *rstr = GetRuneStructForTrapEntry(pGo->GetGOInfo()->button.linkedTrapId))
{
switch (m_auiRuneState[rstr->getRuneType()])
{
case DONE:
pGo->SetGoState(GO_STATE_READY);
break;
default:
pGo->SetGoState(GO_STATE_ACTIVE);
break;
}
}
// no break here!
// Majordomo event chest
case GO_CACHE_OF_THE_FIRE_LORD:
// Ragnaros GOs
case GO_LAVA_STEAM:
case GO_LAVA_SPLASH:
m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid();
break;
// rune traps: just change state
case GO_RUNE_KRESS_TRAP:
case GO_RUNE_MOHN_TRAP:
case GO_RUNE_BLAZ_TRAP:
case GO_RUNE_MAZJ_TRAP:
case GO_RUNE_ZETH_TRAP:
case GO_RUNE_THERI_TRAP:
case GO_RUNE_KORO_TRAP:
if (sRuneEncounters const *rstr = GetRuneStructForTrapEntry(pGo->GetEntry()))
{
switch (m_auiRuneState[rstr->getRuneType()])
{
case DONE:
pGo->SetLootState(GO_JUST_DEACTIVATED); //TODO fix GameObject::Use for traps
// no break here!
case NOT_STARTED:
pGo->SetGoState(GO_STATE_ACTIVE);
default:
break;
}
}
m_mGoEntryGuidStore[pGo->GetEntry()] = pGo->GetObjectGuid();
break;
}
}
void OnPlayerEnter(Player* pPlayer) override
{
// Summon Majordomo if can
DoSpawnMajordomoIfCan(true);
}
void SetData(uint32 uiType, uint32 uiData) override
{
bool save = (uiData == DONE);
switch (uiType)
{
case TYPE_MAJORDOMO:
if (uiData == DONE)
{
DoRespawnGameObject(GO_CACHE_OF_THE_FIRE_LORD, HOUR);
}
// no break here!
case TYPE_LUCIFRON:
m_auiEncounter[uiType] = uiData;
break;
case TYPE_MAGMADAR:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_KRESS); }
#endif
break;
case TYPE_GEHENNAS:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_MOHN); }
#endif
break;
case TYPE_GARR:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_BLAZ); }
#endif
break;
case TYPE_SHAZZRAH:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_MAZJ); }
#endif
break;
case TYPE_GEDDON:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_ZETH); }
#endif
break;
case TYPE_GOLEMAGG:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_THERI); }
#endif
break;
case TYPE_SULFURON:
case TYPE_RAGNAROS:
m_auiEncounter[uiType] = uiData;
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{ DoUseDoorOrButton(GO_RUNE_KORO); }
#endif
break;
case TYPE_FLAME_DOSED:
if (sRuneEncounters const *rstr = GetRuneStructForTrapEntry(uiData))
{
m_auiRuneState[rstr->getRuneType()] = DONE;
save = true;
if (GameObject *trap = GetSingleGameObjectFromStorage(rstr->m_uiTrapEntry))
{
trap->SetGoState(GO_STATE_ACTIVE);
trap->SetLootState(GO_JUST_DEACTIVATED); //TODO fix GameObject::Use for traps
}
if (GameObject *rune = GetSingleGameObjectFromStorage(rstr->m_uiRuneEntry))
rune->SetGoState(GO_STATE_READY);
DoSpawnMajordomoIfCan(false);
}
break;
case TYPE_DO_FREE_GARR_ADDS:
for (std::set<ObjectGuid>::const_iterator it = m_sFireswornGUID.begin(); it != m_sFireswornGUID.end(); ++it)
{
ObjectGuid guid = *it;
int32 bp0 = 0;
if (Creature* firesworn = instance->GetCreature(guid))
if (firesworn->IsAlive())
firesworn->CastCustomSpell(firesworn, SPELL_SEPARATION_ANXIETY, &bp0, NULL, NULL, true);
}
return;
}
// Check if Majordomo can be summoned
#if defined (CLASSIC) || defined (TBC)
if (uiType < MAX_ENCOUNTER && uiData == DONE) // a boss just killed
{
if (sRuneEncounters const *rstr = GetRuneStructForBoss(uiType))
{
m_auiRuneState[rstr->getRuneType()] = SPECIAL;
if (GameObject *trap = GetSingleGameObjectFromStorage(rstr->m_uiTrapEntry))
trap->SetGoState(GO_STATE_READY);
}
}
#endif
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
{
DoSpawnMajordomoIfCan(false);
}
#endif
#if defined (CLASSIC) || defined (TBC) || defined(WOTLK)
if (save)
#endif
#if defined (WOTLK) || defined (CATA)
if (uiData == DONE)
#endif
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << " " << m_auiEncounter[1] << " " << m_auiEncounter[2] << " "
<< m_auiEncounter[3] << " " << m_auiEncounter[4] << " " << m_auiEncounter[5] << " "
<< m_auiEncounter[6] << " " << m_auiEncounter[7] << " " << m_auiEncounter[8] << " "
<< m_auiEncounter[9] << " " << m_auiRuneState[0] << " " << m_auiRuneState[1] << " "
<< m_auiRuneState[2] << " " << m_auiRuneState[3] << " " << m_auiRuneState[4] << " "
<< m_auiRuneState[5] << " " << m_auiRuneState[6];
m_strInstData = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 uiType) const override
{
if (uiType < MAX_ENCOUNTER)
{
return m_auiEncounter[uiType];
}
else if (sRuneEncounters const *rstr = GetRuneStructForTrapEntry(uiType))
return m_auiRuneState[rstr->getRuneType()];
return 0;
}
uint64 GetData64(uint32 uiType) const override
{
switch (uiType)
{
case NPC_FIRESWORN:
{
Creature* garr = GetSingleCreatureFromStorage(NPC_GARR);
for (std::set<ObjectGuid>::const_iterator it = m_sFireswornGUID.begin(); it != m_sFireswornGUID.end(); ++it)
{
ObjectGuid guid = *it;
if (Creature* firesworn = instance->GetCreature(guid))
if (firesworn->IsAlive() && firesworn->IsWithinDistInMap(garr, 20.0f, false))
return guid.GetRawValue();
}
break;
}
default:
break;
}
return 0;
}
const char* Save() const override { return m_strInstData.c_str(); }
void Load(const char* chrIn) override
{
if (!chrIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(chrIn);
std::istringstream loadStream(chrIn);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7]
>> m_auiEncounter[8] >> m_auiEncounter[9] >> m_auiRuneState[0] >> m_auiRuneState[1]
>> m_auiRuneState[2] >> m_auiRuneState[3] >> m_auiRuneState[4] >> m_auiRuneState[5]
>> m_auiRuneState[6];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
{
m_auiEncounter[i] = NOT_STARTED;
}
}
OUT_LOAD_INST_DATA_COMPLETE;
}
protected:
void DoSpawnMajordomoIfCan(bool bByPlayerEnter)
{
// If both Majordomo and Ragnaros events are finished, return
if (m_auiEncounter[TYPE_MAJORDOMO] == DONE && m_auiEncounter[TYPE_RAGNAROS] == DONE)
{
return;
}
// If already spawned return
if (GetSingleCreatureFromStorage(NPC_MAJORDOMO, true))
{
return;
}
// Check if all rune bosses are done
for (uint8 i = TYPE_MAGMADAR; i < TYPE_MAJORDOMO; ++i)
{
#if defined (CLASSIC) || defined (TBC) || defined(WOTLK)
if (m_auiEncounter[i] != SPECIAL)
#endif
#if defined (WOTLK) || defined (CATA)
if (m_auiEncounter[i] != DONE)
#endif
{
return;
}
}
Player* pPlayer = GetPlayerInMap();
if (!pPlayer)
{
return;
}
// Summon Majordomo
// If Majordomo encounter isn't done, summon at encounter place, else near Ragnaros
uint8 uiSummonPos = m_auiEncounter[TYPE_MAJORDOMO] == DONE ? 1 : 0;
if (Creature* pMajordomo = pPlayer->SummonCreature(m_aMajordomoLocations[uiSummonPos].m_uiEntry, m_aMajordomoLocations[uiSummonPos].m_fX, m_aMajordomoLocations[uiSummonPos].m_fY, m_aMajordomoLocations[uiSummonPos].m_fZ, m_aMajordomoLocations[uiSummonPos].m_fO, TEMPSUMMON_MANUAL_DESPAWN, 2 * HOUR * IN_MILLISECONDS))
{
if (uiSummonPos) // Majordomo encounter already done, set faction
{
pMajordomo->SetFactionTemporary(FACTION_MAJORDOMO_FRIENDLY, TEMPFACTION_RESTORE_RESPAWN);
pMajordomo->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE);
pMajordomo->SetFlag(UNIT_NPC_FLAGS, UNIT_NPC_FLAG_GOSSIP);
}
else // Else yell and summon adds
{
if (!bByPlayerEnter)
{
DoScriptText(SAY_MAJORDOMO_SPAWN, pMajordomo);
}
for (uint8 i = 0; i < MAX_MAJORDOMO_ADDS; ++i)
{
pMajordomo->SummonCreature(m_aBosspawnLocs[i].m_uiEntry, m_aBosspawnLocs[i].m_fX, m_aBosspawnLocs[i].m_fY, m_aBosspawnLocs[i].m_fZ, m_aBosspawnLocs[i].m_fO, TEMPSUMMON_MANUAL_DESPAWN, DAY * IN_MILLISECONDS);
}
}
}
}
sRuneEncounters const *GetRuneStructForBoss(uint32 uiType) const
{
for (int i = 0; i < MAX_MOLTEN_RUNES; ++i)
if (m_aMoltenCoreRunes[i].m_bossType == uiType)
return &m_aMoltenCoreRunes[i];
return NULL;
}
sRuneEncounters const *GetRuneStructForTrapEntry(uint32 entry) const
{
for (int i = 0; i < MAX_MOLTEN_RUNES; ++i)
if (m_aMoltenCoreRunes[i].m_uiTrapEntry == entry)
return &m_aMoltenCoreRunes[i];
return NULL;
}
std::string m_strInstData;
uint32 m_auiEncounter[MAX_ENCOUNTER];
uint32 m_auiRuneState[MAX_MOLTEN_RUNES];
std::set<ObjectGuid> m_sFireswornGUID;
};
InstanceData* GetInstanceData(Map* pMap) override
{
return new instance_molten_core(pMap);
}
};
void AddSC_instance_molten_core()
{
Script* s;
s = new is_molten_core();
s->RegisterSelf();
//pNewScript = new Script;
//pNewScript->Name = "instance_molten_core";
//pNewScript->GetInstanceData = &GetInstance_instance_molten_core;
//pNewScript->RegisterSelf();
}

Some files were not shown because too many files have changed in this diff Show more