mirror of
https://github.com/mangosfour/server.git
synced 2025-12-14 07:37:01 +00:00
[SD3] first commit with SD3 inplace - not complete yet
This commit is contained in:
parent
35415eb738
commit
afc2df2f7d
603 changed files with 222771 additions and 1729 deletions
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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()),
|
||||
|
|
|
|||
|
|
@ -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*/)
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ enum GridMapLiquidStatus
|
|||
|
||||
struct GridMapLiquidData
|
||||
{
|
||||
uint32 type_flags;
|
||||
uint32 CreatureTypeFlags;
|
||||
uint32 entry;
|
||||
float level;
|
||||
float depth_level;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
576
src/modules/SD3/CMakeLists.txt
Normal file
576
src/modules/SD3/CMakeLists.txt
Normal 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()
|
||||
5
src/modules/SD3/README.md
Normal file
5
src/modules/SD3/README.md
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# ScriptDev3
|
||||
|
||||
New EventAI engine for all MaNGOS cores. Developed from the old ScriptDev2.
|
||||
|
||||
|
||||
662
src/modules/SD3/base/escort_ai.cpp
Normal file
662
src/modules/SD3/base/escort_ai.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
133
src/modules/SD3/base/escort_ai.h
Normal file
133
src/modules/SD3/base/escort_ai.h
Normal 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
|
||||
458
src/modules/SD3/base/follower_ai.cpp
Normal file
458
src/modules/SD3/base/follower_ai.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
87
src/modules/SD3/base/follower_ai.h
Normal file
87
src/modules/SD3/base/follower_ai.h
Normal 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
|
||||
275
src/modules/SD3/base/guard_ai.cpp
Normal file
275
src/modules/SD3/base/guard_ai.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
84
src/modules/SD3/base/guard_ai.h
Normal file
84
src/modules/SD3/base/guard_ai.h
Normal 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
|
||||
172
src/modules/SD3/base/pet_ai.cpp
Normal file
172
src/modules/SD3/base/pet_ai.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
61
src/modules/SD3/base/pet_ai.h
Normal file
61
src/modules/SD3/base/pet_ai.h
Normal 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
|
||||
26
src/modules/SD3/include/precompiled.cpp
Normal file
26
src/modules/SD3/include/precompiled.cpp
Normal 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"
|
||||
42
src/modules/SD3/include/precompiled.h
Normal file
42
src/modules/SD3/include/precompiled.h
Normal 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
|
||||
836
src/modules/SD3/include/sc_creature.cpp
Normal file
836
src/modules/SD3/include/sc_creature.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
262
src/modules/SD3/include/sc_creature.h
Normal file
262
src/modules/SD3/include/sc_creature.h
Normal 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
|
||||
186
src/modules/SD3/include/sc_gossip.h
Normal file
186
src/modules/SD3/include/sc_gossip.h
Normal 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
|
||||
74
src/modules/SD3/include/sc_grid_searchers.cpp
Normal file
74
src/modules/SD3/include/sc_grid_searchers.cpp
Normal 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);
|
||||
}
|
||||
64
src/modules/SD3/include/sc_grid_searchers.h
Normal file
64
src/modules/SD3/include/sc_grid_searchers.h
Normal 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
|
||||
434
src/modules/SD3/include/sc_instance.cpp
Normal file
434
src/modules/SD3/include/sc_instance.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
159
src/modules/SD3/include/sc_instance.h
Normal file
159
src/modules/SD3/include/sc_instance.h
Normal 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
|
||||
27
src/modules/SD3/precompiled.cpp
Normal file
27
src/modules/SD3/precompiled.cpp
Normal 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"
|
||||
46
src/modules/SD3/precompiled.h
Normal file
46
src/modules/SD3/precompiled.h
Normal 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
|
||||
145
src/modules/SD3/scripts/battlegrounds/battleground.cpp
Normal file
145
src/modules/SD3/scripts/battlegrounds/battleground.cpp
Normal 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();
|
||||
}
|
||||
|
|
@ -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()
|
||||
{
|
||||
}
|
||||
326
src/modules/SD3/scripts/eastern_kingdoms/arathi_highlands.cpp
Normal file
326
src/modules/SD3/scripts/eastern_kingdoms/arathi_highlands.cpp
Normal 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();
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
|
|
@ -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
Loading…
Add table
Add a link
Reference in a new issue