Merge commit 'dbaf88566be7083408fb8324d7886dc3e0a45cc0' into 4.3.4

Conflicts:
	.gitattributes
	CONTRIBUTING.md
	sql/updates/world/2015_05_11_04_world.sql
	sql/updates/world/2015_05_27_00_world.sql
	sql/updates/world/2015_05_27_01_world.sql
	sql/updates/world/2015_06_06_01_world_335.sql
	src/server/game/Battlegrounds/Zones/BattlegroundSA.cpp
	src/server/game/Entities/Creature/Creature.cpp
	src/server/game/Entities/Creature/Creature.h
	src/server/game/Entities/Object/ObjectGuid.h
	src/server/game/Entities/Player/Player.cpp
	src/server/game/Entities/Player/Player.h
	src/server/game/Entities/Unit/Unit.cpp
	src/server/game/Entities/Unit/Unit.h
	src/server/game/Spells/Auras/SpellAuras.cpp
	src/server/game/Spells/Spell.cpp
	src/server/game/Spells/SpellMgr.cpp
	src/server/scripts/Commands/cs_modify.cpp
	src/server/scripts/Kalimdor/zone_moonglade.cpp
	src/server/scripts/Spells/spell_hunter.cpp
	src/server/scripts/Spells/spell_item.cpp
	src/server/scripts/Spells/spell_rogue.cpp
This commit is contained in:
Carbenium committed 2015-07-22 02:09:32 +02:00
commit 6dfaec3d97
119 files changed
+3776 -2162

No files matched your search

+1
View File
@@ -17,3 +17,4 @@ endif()
# -Wno-narrowing needed to suppress a warning in g3d
# -Wno-deprecated-register is needed to suppress 185 gsoap warnings on Unix systems.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wno-narrowing -Wno-deprecated-register")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DDEBUG=1")
-2
View File
@@ -7,8 +7,6 @@ else()
MESSAGE(STATUS "Detected 32-bit platform")
endif()
include("${CMAKE_SOURCE_DIR}/cmake/platform/settings.cmake")
if(WIN32)
include("${CMAKE_SOURCE_DIR}/cmake/platform/win/settings.cmake")
elseif(UNIX)
-5
View File
@@ -1,5 +0,0 @@
# set installation prefix
if( PREFIX )
set(CMAKE_INSTALL_PREFIX "${PREFIX}")
endif()
+38 -6
View File
@@ -46,11 +46,25 @@ using namespace boost::program_options;
# define _TRINITY_REALM_CONFIG "authserver.conf"
#endif
#ifdef _WIN32
#include "ServiceWin32.h"
char serviceName[] = "authserver";
char serviceLongName[] = "TrinityCore auth service";
char serviceDescription[] = "TrinityCore World of Warcraft emulator auth service";
/*
* -1 - not in service mode
* 0 - stopped
* 1 - running
* 2 - paused
*/
int m_ServiceStatus = -1;
#endif
bool StartDB();
void StopDB();
void SignalHandler(const boost::system::error_code& error, int signalNumber);
void KeepDatabaseAliveHandler(const boost::system::error_code& error);
variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile);
variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService);
boost::asio::io_service _ioService;
boost::asio::deadline_timer _dbPingTimer(_ioService);
@@ -60,11 +74,21 @@ LoginDatabaseWorkerPool LoginDatabase;
int main(int argc, char** argv)
{
std::string configFile = _TRINITY_REALM_CONFIG;
auto vm = GetConsoleArguments(argc, argv, configFile);
std::string configService;
auto vm = GetConsoleArguments(argc, argv, configFile, configService);
// exit if help is enabled
if (vm.count("help"))
return 0;
#ifdef _WIN32
if (configService.compare("install") == 0)
return WinServiceInstall() == true ? 0 : 1;
else if (configService.compare("uninstall") == 0)
return WinServiceUninstall() == true ? 0 : 1;
else if (configService.compare("run") == 0)
WinServiceRun();
#endif
std::string configError;
if (!sConfigMgr->LoadInitial(configFile, configError))
{
@@ -189,26 +213,34 @@ void KeepDatabaseAliveHandler(const boost::system::error_code& error)
}
}
variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile)
variables_map GetConsoleArguments(int argc, char** argv, std::string& configFile, std::string& configService)
{
options_description all("Allowed options");
all.add_options()
("help,h", "print usage message")
("config,c", value<std::string>(&configFile)->default_value(_TRINITY_REALM_CONFIG), "use <arg> as configuration file")
;
#ifdef _WIN32
options_description win("Windows platform specific options");
win.add_options()
("service,s", value<std::string>(&configService)->default_value(""), "Windows service options: [install | uninstall]")
;
all.add(win);
#endif
variables_map variablesMap;
try
{
store(command_line_parser(argc, argv).options(all).allow_unregistered().run(), variablesMap);
notify(variablesMap);
}
catch (std::exception& e) {
catch (std::exception& e)
{
std::cerr << e.what() << "\n";
}
if (variablesMap.count("help")) {
if (variablesMap.count("help"))
std::cout << all << "\n";
}
return variablesMap;
}
+4 -3
View File
@@ -22,6 +22,7 @@
#include "Player.h"
#include "Spell.h"
#include "ObjectAccessor.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "Creature.h"
#include "Util.h"
@@ -146,15 +147,15 @@ void PetAI::UpdateAI(uint32 diff)
if (!spellInfo)
continue;
if (me->GetCharmInfo() && me->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(spellInfo))
if (me->GetCharmInfo() && me->GetSpellHistory()->HasGlobalCooldown(spellInfo))
continue;
if (spellInfo->IsPositive())
{
if (spellInfo->CanBeUsedInCombat())
{
// check spell cooldown
if (me->HasSpellCooldown(spellInfo->Id))
// check spell cooldown & school lock
if (!me->GetSpellHistory()->IsReady(spellInfo))
continue;
// Check if we're in combat or commanded to attack
+1 -1
View File
@@ -128,7 +128,7 @@ class UnitAI
virtual void InitializeAI() { if (!me->isDead()) Reset(); }
virtual void Reset() { };
virtual void Reset() { }
// Called when unit is charmed
virtual void OnCharmed(bool apply) = 0;
+3 -3
View File
@@ -811,6 +811,7 @@ class RBACData
* @return Success or failure (with reason) to grant the permission
*
* Example Usage:
* @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->GrantRole(permissionId) == RBAC_IN_DENIED_LIST)
@@ -834,6 +835,7 @@ class RBACData
* @return Success or failure (with reason) to deny the permission
*
* Example Usage:
* @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->DenyRole(permissionId) == RBAC_ID_DOES_NOT_EXISTS)
@@ -858,6 +860,7 @@ class RBACData
* @return Success or failure (with reason) to remove the permission
*
* Example Usage:
* @code
* // previously defined "RBACData* rbac" with proper initialization
* uint32 permissionId = 2;
* if (rbac->RevokeRole(permissionId) == RBAC_OK)
@@ -948,9 +951,6 @@ class RBACData
*
* Given a list of permissions, gets all the inherited permissions
* @param permissions The list of permissions to expand
*
* @return new list of permissions containing original permissions and
* all other pemissions that are linked to the original ones
*/
void ExpandPermissions(RBACPermissionContainer& permissions);
@@ -890,7 +890,8 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
// (after what time the ratings aren't taken into account when making teams) then
// the discard time is current_time - time_to_discard, teams that joined after that, will have their ratings taken into account
// else leave the discard time on 0, this way all ratings will be discarded
uint32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
// this has to be signed value - when the server starts, this value would be negative and thus overflow
int32 discardTime = getMSTime() - sBattlegroundMgr->GetRatingDiscardTimer();
// we need to find 2 teams which will play next game
GroupsQueueType::iterator itr_teams[BG_TEAMS_COUNT];
@@ -906,7 +907,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
// if group match conditions, then add it to pool
if (!(*itr2)->IsInvitedToBGInstanceGUID
&& (((*itr2)->ArenaMatchmakerRating >= arenaMinRating && (*itr2)->ArenaMatchmakerRating <= arenaMaxRating)
|| (*itr2)->JoinTime < discardTime))
|| (int32)(*itr2)->JoinTime < discardTime))
{
itr_teams[found++] = itr2;
team = i;
@@ -924,7 +925,7 @@ void BattlegroundQueue::BattlegroundQueueUpdate(uint32 /*diff*/, BattlegroundTyp
{
if (!(*itr3)->IsInvitedToBGInstanceGUID
&& (((*itr3)->ArenaMatchmakerRating >= arenaMinRating && (*itr3)->ArenaMatchmakerRating <= arenaMaxRating)
|| (*itr3)->JoinTime < discardTime)
|| (int32)(*itr3)->JoinTime < discardTime)
&& (*itr_teams[0])->ArenaTeamId != (*itr3)->ArenaTeamId)
{
itr_teams[found++] = itr3;
@@ -106,7 +106,7 @@ class BattlegroundQueue
class SelectionPool
{
public:
SelectionPool(): PlayerCount(0) { };
SelectionPool(): PlayerCount(0) { }
void Init();
bool AddGroup(GroupQueueInfo* ginfo, uint32 desiredCount);
bool KickGroup(uint32 size);
@@ -99,7 +99,7 @@ bool BattlegroundSA::ResetObjs()
for (uint8 i = BG_SA_MAXNPC; i < BG_SA_MAXNPC + BG_SA_MAX_GY; i++)
DelCreature(i);
for (uint8 i = 0; i < 6; i++)
for (uint8 i = 0; i < MAX_GATES; ++i)
GateStatus[i] = BG_SA_GATE_OK;
if (!AddCreature(BG_SA_NpcEntries[BG_SA_NPC_KANRETHAD], BG_SA_NPC_KANRETHAD, BG_SA_NpcSpawnlocs[BG_SA_NPC_KANRETHAD]))
@@ -179,9 +179,6 @@ bool BattlegroundSA::ResetObjs()
GetBGObject(BG_SA_TITAN_RELIC)->SetFaction(atF);
GetBGObject(BG_SA_TITAN_RELIC)->Refresh();
for (uint8 i = 0; i <= 5; i++)
GateStatus[i] = BG_SA_GATE_OK;
TotalTime = 0;
ShipsStarted = false;
@@ -221,6 +218,8 @@ bool BattlegroundSA::ResetObjs()
GetBGObject(i)->SetFaction(atF);
}
UpdateObjectInteractionFlags();
for (uint8 i = BG_SA_BOMB; i < BG_SA_MAXOBJ; i++)
{
if (!AddObject(i, BG_SA_ObjEntries[BG_SA_BOMB], BG_SA_ObjSpawnlocs[i], 0, 0, 0, 0, RESPAWN_ONE_DAY))
@@ -481,28 +480,7 @@ void BattlegroundSA::AddPlayer(Player* player)
SendTransportInit(player);
if (!ShipsStarted)
{
if (player->GetTeamId() == Attackers)
{
//player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
else
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
}
else
{
if (player->GetTeamId() == Attackers)
player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
else
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
}
TeleportToEntrancePosition(player);
}
void BattlegroundSA::RemovePlayer(Player* /*player*/, ObjectGuid /*guid*/, uint32 /*team*/) { }
@@ -533,25 +511,33 @@ void BattlegroundSA::TeleportPlayers()
player->ResetAllPowers();
player->CombatStopWithPets(true);
for (BattlegroundPlayerMap::const_iterator itr = GetPlayers().begin(); itr != GetPlayers().end(); ++itr)
if (Player* p = ObjectAccessor::FindPlayer(itr->first))
p->CastSpell(p, SPELL_PREPARATION, true);
player->CastSpell(player, SPELL_PREPARATION, true);
if (player->GetTeamId() == Attackers)
{
//player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
else
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
TeleportToEntrancePosition(player);
}
}
}
void BattlegroundSA::TeleportToEntrancePosition(Player* player)
{
if (player->GetTeamId() == Attackers)
{
if (!ShipsStarted)
{
player->AddUnitMovementFlag(MOVEMENTFLAG_ONTRANSPORT);
if (urand(0, 1))
player->TeleportTo(607, 2682.936f, -830.368f, 15.0f, 2.895f, 0);
else
player->TeleportTo(607, 2577.003f, 980.261f, 15.0f, 0.807f, 0);
}
else
player->TeleportTo(607, 1600.381f, -106.263f, 8.8745f, 3.78f, 0);
}
else
player->TeleportTo(607, 1209.7f, -65.16f, 70.1f, 0.0f, 0);
}
void BattlegroundSA::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject* invoker /*= NULL*/)
{
if (GameObject* go = obj->ToGameObject())
@@ -628,6 +614,8 @@ void BattlegroundSA::ProcessEvent(WorldObject* obj, uint32 eventId, WorldObject*
}
}
}
UpdateObjectInteractionFlags();
}
else
break;
@@ -711,7 +699,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
safeloc = BG_SA_GYEntries[BG_SA_DEFENDER_LAST_GY];
closest = sWorldSafeLocsStore.LookupEntry(safeloc);
nearest = std::sqrt((closest->x - x)*(closest->x - x) + (closest->y - y)*(closest->y - y) + (closest->z - z)*(closest->z - z));
nearest = player->GetExactDistSq(closest->x, closest->y, closest->z);
for (uint8 i = BG_SA_RIGHT_CAPTURABLE_GY; i < BG_SA_MAX_GY; i++)
{
@@ -719,7 +707,7 @@ WorldSafeLocsEntry const* BattlegroundSA::GetClosestGraveYard(Player* player)
continue;
ret = sWorldSafeLocsStore.LookupEntry(BG_SA_GYEntries[i]);
dist = std::sqrt((ret->x - x)*(ret->x - x) + (ret->y - y)*(ret->y - y) + (ret->z - z)*(ret->z - z));
dist = player->GetExactDistSq(ret->x, ret->y, ret->z);
if (dist < nearest)
{
closest = ret;
@@ -738,23 +726,66 @@ void BattlegroundSA::SendTime()
UpdateWorldState(BG_SA_TIMER_SEC_DECS, ((end_of_round%60000)%10000)/1000);
}
bool BattlegroundSA::CanInteractWithObject(uint32 objectId)
{
switch (objectId)
{
case BG_SA_TITAN_RELIC:
if (GateStatus[BG_SA_ANCIENT_GATE] != BG_SA_GATE_DESTROYED || GateStatus[BG_SA_YELLOW_GATE] != BG_SA_GATE_DESTROYED)
return false;
// no break
case BG_SA_CENTRAL_FLAG:
if (GateStatus[BG_SA_RED_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_PURPLE_GATE] != BG_SA_GATE_DESTROYED)
return false;
// no break
case BG_SA_LEFT_FLAG:
case BG_SA_RIGHT_FLAG:
if (GateStatus[BG_SA_GREEN_GATE] != BG_SA_GATE_DESTROYED && GateStatus[BG_SA_BLUE_GATE] != BG_SA_GATE_DESTROYED)
return false;
break;
default:
ASSERT(false);
break;
}
return true;
}
void BattlegroundSA::UpdateObjectInteractionFlags(uint32 objectId)
{
if (GameObject* go = GetBGObject(objectId))
{
if (CanInteractWithObject(objectId))
go->RemoveFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
else
go->SetFlag(GAMEOBJECT_FLAGS, GO_FLAG_NOT_SELECTABLE);
}
}
void BattlegroundSA::UpdateObjectInteractionFlags()
{
for (uint8 i = BG_SA_CENTRAL_FLAG; i <= BG_SA_LEFT_FLAG; ++i)
UpdateObjectInteractionFlags(i);
UpdateObjectInteractionFlags(BG_SA_TITAN_RELIC);
}
void BattlegroundSA::EventPlayerClickedOnFlag(Player* source, GameObject* go)
{
switch (go->GetEntry())
{
case 191307:
case 191308:
if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)
if (CanInteractWithObject(BG_SA_LEFT_FLAG))
CaptureGraveyard(BG_SA_LEFT_CAPTURABLE_GY, source);
break;
case 191305:
case 191306:
if (GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED)
if (CanInteractWithObject(BG_SA_RIGHT_FLAG))
CaptureGraveyard(BG_SA_RIGHT_CAPTURABLE_GY, source);
break;
case 191310:
case 191309:
if ((GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED) && (GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED))
if (CanInteractWithObject(BG_SA_CENTRAL_FLAG))
CaptureGraveyard(BG_SA_CENTRAL_CAPTURABLE_GY, source);
break;
default:
@@ -856,10 +887,7 @@ void BattlegroundSA::TitanRelicActivated(Player* clicker)
if (!clicker)
return;
if (GateStatus[BG_SA_ANCIENT_GATE] == BG_SA_GATE_DESTROYED &&
GateStatus[BG_SA_YELLOW_GATE] == BG_SA_GATE_DESTROYED &&
(GateStatus[BG_SA_PURPLE_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_RED_GATE] == BG_SA_GATE_DESTROYED) &&
(GateStatus[BG_SA_GREEN_GATE] == BG_SA_GATE_DESTROYED || GateStatus[BG_SA_BLUE_GATE] == BG_SA_GATE_DESTROYED))
if (CanInteractWithObject(BG_SA_TITAN_RELIC))
{
if (clicker->GetTeamId() == Attackers)
{
@@ -620,6 +620,7 @@ class BattlegroundSA : public Battleground
* -Teleport all players to good location
*/
void TeleportPlayers();
void TeleportToEntrancePosition(Player* player);
/**
* \brief Called on start and between the two round
* -Update faction of all vehicle
@@ -627,6 +628,11 @@ class BattlegroundSA : public Battleground
void OverrideGunFaction();
/// Set selectable or not demolisher, called on battle start, when boats arrive to dock
void DemolisherStartState(bool start);
/// Checks if a player can interact with the given object
bool CanInteractWithObject(uint32 objectId);
/// Updates interaction flags of specific objects
void UpdateObjectInteractionFlags(uint32 objectId);
void UpdateObjectInteractionFlags();
/**
* \brief Called when a gate is destroy
* -Give honor to player witch destroy it
+1 -1
View File
@@ -184,7 +184,7 @@ class Channel
void DeVoice(ObjectGuid guid1, ObjectGuid guid2);
void JoinNotify(ObjectGuid guid); // invisible notify
void LeaveNotify(ObjectGuid guid); // invisible notify
void SetOwnership(bool ownership) { _ownership = ownership; };
void SetOwnership(bool ownership) { _ownership = ownership; }
static void CleanOldChannelsInDB();
private:
+3 -3
View File
@@ -704,8 +704,8 @@ void LoadDBCStores(const std::string& dataPath)
for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
{
if (pathLength[entry->path] < entry->index + 1)
pathLength[entry->path] = entry->index + 1;
if (pathLength[entry->PathID] < entry->NodeIndex + 1)
pathLength[entry->PathID] = entry->NodeIndex + 1;
}
// Set path length
sTaxiPathNodesByPath.resize(pathCount); // 0 and some other indexes not used
@@ -714,7 +714,7 @@ void LoadDBCStores(const std::string& dataPath)
// fill data
for (uint32 i = 1; i < sTaxiPathNodeStore.GetNumRows(); ++i)
if (TaxiPathNodeEntry const* entry = sTaxiPathNodeStore.LookupEntry(i))
sTaxiPathNodesByPath[entry->path].set(entry->index, entry);
sTaxiPathNodesByPath[entry->PathID].set(entry->NodeIndex, entry);
// Initialize global taxinodes mask
// include existed nodes that have at least single not spell base (scripted) path
+11 -22
View File
@@ -30,13 +30,7 @@
#include <vector>
// Structures using to access raw DBC data and required packing to portability
// 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__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct AchievementEntry
{
@@ -2230,17 +2224,17 @@ struct TaxiPathEntry
struct TaxiPathNodeEntry
{
// 0 m_ID
uint32 path; // 1 m_PathID
uint32 index; // 2 m_NodeIndex
uint32 mapid; // 3 m_ContinentID
float x; // 4 m_LocX
float y; // 5 m_LocY
float z; // 6 m_LocZ
uint32 actionFlag; // 7 m_flags
uint32 delay; // 8 m_delay
uint32 arrivalEventID; // 9 m_arrivalEventID
uint32 departureEventID; // 10 m_departureEventID
// 0 ID
uint32 PathID; // 1
uint32 NodeIndex; // 2
uint32 MapID; // 3
float LocX; // 4
float LocY; // 5
float LocZ; // 6
uint32 Flags; // 7
uint32 Delay; // 8
uint32 ArrivalEventID; // 9
uint32 DepartureEventID; // 10
};
struct TotemCategoryEntry
@@ -2492,12 +2486,7 @@ struct WorldStateUI
};
*/
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
struct VectorArray
{
@@ -408,6 +408,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_RANDOM_COOLDOWN;
else if (dungeons.empty())
joinData.result = LFG_JOIN_NOT_MEET_REQS;
else if (player->HasAura(9454)) // check Freeze debuff
joinData.result = LFG_JOIN_NOT_MEET_REQS;
else if (grp)
{
if (grp->GetMembersCount() > MAXGROUPSIZE)
@@ -427,6 +429,8 @@ void LFGMgr::JoinLfg(Player* player, uint8 roles, LfgDungeonSet& dungeons, const
joinData.result = LFG_JOIN_PARTY_RANDOM_COOLDOWN;
else if (plrg->InBattleground() || plrg->InArena() || plrg->InBattlegroundQueue())
joinData.result = LFG_JOIN_USING_BG_SYSTEM;
else if (plrg->HasAura(9454)) // check Freeze debuff
joinData.result = LFG_JOIN_PARTY_NOT_MEET_REQS;
++memberCount;
players.insert(plrg->GetGUID());
}
@@ -1283,6 +1287,8 @@ void LFGMgr::TeleportPlayer(Player* player, bool out, bool fromOpcode /*= false*
error = LFG_TELEPORTERROR_IN_VEHICLE;
else if (player->GetCharmGUID())
error = LFG_TELEPORTERROR_CHARMING;
else if (player->HasAura(9454)) // check Freeze debuff
error = LFG_TELEPORTERROR_INVALID_LOCATION;
else if (player->GetMapId() != uint32(dungeon->map)) // Do not teleport players in dungeon to the entrance
{
uint32 mapid = dungeon->map;
@@ -150,8 +150,6 @@ m_originalEntry(0), m_homePosition(), m_transportHomePosition(), m_creatureInfo(
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
m_spells[i] = 0;
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
DisableReputationGain = false;
m_SightDistance = sWorld->getFloatConfig(CONFIG_SIGHT_MONSTER);
@@ -1390,9 +1388,6 @@ bool Creature::CanStartAttack(Unit const* who, bool force) const
if (IsCivilian())
return false;
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_NPC))
return false;
// Do not attack non-combat pets
if (who->GetTypeId() == TYPEID_UNIT && who->GetCreatureType() == CREATURE_TYPE_NON_COMBAT_PET)
return false;
@@ -2167,83 +2162,6 @@ void Creature::SetInCombatWithZone()
}
}
void Creature::_AddCreatureSpellCooldown(uint32 spell_id, time_t end_time)
{
m_CreatureSpellCooldowns[spell_id] = end_time;
}
void Creature::_AddCreatureCategoryCooldown(uint32 category, time_t apply_time)
{
m_CreatureCategoryCooldowns[category] = apply_time;
}
void Creature::AddCreatureSpellCooldown(uint32 spellid)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellid);
if (!spellInfo)
return;
uint32 cooldown = spellInfo->GetRecoveryTime();
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellid, SPELLMOD_COOLDOWN, cooldown);
if (cooldown)
_AddCreatureSpellCooldown(spellid, time(NULL) + cooldown/IN_MILLISECONDS);
if (spellInfo->GetCategory())
_AddCreatureCategoryCooldown(spellInfo->GetCategory(), time(NULL));
}
bool Creature::HasCategoryCooldown(uint32 spell_id) const
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
if (!spellInfo)
return false;
CreatureSpellCooldowns::const_iterator itr = m_CreatureCategoryCooldowns.find(spellInfo->GetCategory());
return(itr != m_CreatureCategoryCooldowns.end() && time_t(itr->second + (spellInfo->CategoryRecoveryTime / IN_MILLISECONDS)) > time(NULL));
}
uint32 Creature::GetCreatureSpellCooldownDelay(uint32 spellId) const
{
CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.find(spellId);
time_t t = time(NULL);
return uint32(itr != m_CreatureSpellCooldowns.end() && itr->second > t ? itr->second - t : 0);
}
bool Creature::HasSpellCooldown(uint32 spell_id) const
{
CreatureSpellCooldowns::const_iterator itr = m_CreatureSpellCooldowns.find(spell_id);
return (itr != m_CreatureSpellCooldowns.end() && itr->second > time(NULL)) || HasCategoryCooldown(spell_id);
}
void Creature::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
{
time_t curTime = time(NULL);
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
{
if (m_spells[i] == 0)
continue;
uint32 unSpellId = m_spells[i];
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(unSpellId);
// Not send cooldown for this spells
if (spellInfo->IsCooldownStartedOnEvent())
continue;
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
continue;
if ((idSchoolMask & spellInfo->GetSchoolMask()) && GetCreatureSpellCooldownDelay(unSpellId) < unTimeMs)
{
_AddCreatureSpellCooldown(unSpellId, curTime + unTimeMs/IN_MILLISECONDS);
if (UnitAI* ai = GetAI())
ai->SpellInterrupted(unSpellId, unTimeMs);
}
}
}
bool Creature::HasSpell(uint32 spellID) const
{
uint8 i;
@@ -174,12 +174,7 @@ struct CreatureTemplate
// Benchmarked: Faster than std::map (insert/find)
typedef std::unordered_map<uint32, CreatureTemplate> CreatureTemplateContainer;
// 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__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
// Defines base stats for creatures (used to calculate HP/mana/armor/attackpower/rangedattackpower/all damage).
struct CreatureBaseStats
@@ -314,12 +309,7 @@ enum ChatType
CHAT_TYPE_END = 255
};
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
// `creature_addon` table
struct CreatureAddon
@@ -422,8 +412,6 @@ struct TrainerSpellData
TrainerSpell const* Find(uint32 spell_id) const;
};
typedef std::map<uint32, time_t> CreatureSpellCooldowns;
// max different by z coordinate for creature aggro reaction
#define CREATURE_Z_ATTACK_RANGE 3
@@ -289,6 +289,16 @@ bool GameObject::Create(uint32 guidlow, uint32 name_id, Map* map, uint32 /*phase
SetGoAnimProgress(animprogress);
break;
}
if (GameObjectAddon const* addon = sObjectMgr->GetGameObjectAddon(guidlow))
{
if (addon->InvisibilityValue)
{
m_invisibility.AddFlag(addon->invisibilityType);
m_invisibility.AddValue(addon->invisibilityType, addon->InvisibilityValue);
}
}
LastUsedScriptID = GetGOInfo()->ScriptId;
AIM_Initialize();
@@ -585,6 +585,15 @@ struct GameObjectLocale
StringVector CastBarCaption;
};
// `gameobject_addon` table
struct GameObjectAddon
{
InvisibilityType invisibilityType;
uint32 InvisibilityValue;
};
typedef std::unordered_map<ObjectGuid::LowType, GameObjectAddon> GameObjectAddonContainer;
// client side GO show states
enum GOState
{
-2
View File
@@ -208,8 +208,6 @@ enum ItemUpdateState
ITEM_REMOVED = 3
};
#define MAX_ITEM_SPELLS 5
bool ItemCanGoIntoBag(ItemTemplate const* proto, ItemTemplate const* pBagProto);
class Item : public Object
-146
View File
@@ -1194,61 +1194,6 @@ bool Object::PrintIndexError(uint32 index, bool set) const
return false;
}
bool Position::operator==(Position const &a)
{
return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
G3D::fuzzyEq(a.m_positionY, m_positionY) &&
G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
G3D::fuzzyEq(a.m_orientation, m_orientation));
}
bool Position::HasInLine(WorldObject const* target, float width) const
{
if (!HasInArc(float(M_PI), target))
return false;
width += target->GetObjectSize();
float angle = GetRelativeAngle(target);
return std::fabs(std::sin(angle)) * GetExactDist2d(target->GetPositionX(), target->GetPositionY()) < width;
}
std::string Position::ToString() const
{
std::stringstream sstr;
sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation;
return sstr.str();
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
float x, y, z, o;
buf >> x >> y >> z >> o;
streamer.m_pos->Relocate(x, y, z, o);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
float x, y, z;
streamer.m_pos->GetPosition(x, y, z);
buf << x << y << z;
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
float x, y, z;
buf >> x >> y >> z;
streamer.m_pos->Relocate(x, y, z);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
float x, y, z, o;
streamer.m_pos->GetPosition(x, y, z, o);
buf << x << y << z << o;
return buf;
}
void MovementInfo::OutDebug()
{
TC_LOG_DEBUG("misc", "MOVEMENT INFO");
@@ -1614,92 +1559,6 @@ bool WorldObject::IsInRange3d(float x, float y, float z, float minRange, float m
return distsq < maxdist * maxdist;
}
void Position::RelocateOffset(const Position & offset)
{
m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI)));
m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation()));
m_positionZ = GetPositionZ() + offset.GetPositionZ();
SetOrientation(GetOrientation() + offset.GetOrientation());
}
void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const
{
float dx = endPos.GetPositionX() - GetPositionX();
float dy = endPos.GetPositionY() - GetPositionY();
retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation());
retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation());
retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ();
retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation());
}
Position Position::GetPositionWithOffset(Position const& offset) const
{
Position ret(*this);
ret.RelocateOffset(offset);
return ret;
}
float Position::GetAngle(const Position* obj) const
{
if (!obj)
return 0;
return GetAngle(obj->GetPositionX(), obj->GetPositionY());
}
// Return angle in range 0..2*pi
float Position::GetAngle(const float x, const float y) const
{
float dx = x - GetPositionX();
float dy = y - GetPositionY();
float ang = std::atan2(dy, dx);
ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang;
return ang;
}
void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const
{
float dx = GetPositionX() - x;
float dy = GetPositionY() - y;
if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f)
{
float angle = (float)rand_norm()*static_cast<float>(2*M_PI);
vcos = std::cos(angle);
vsin = std::sin(angle);
}
else
{
float dist = std::sqrt((dx*dx) + (dy*dy));
vcos = dx / dist;
vsin = dy / dist;
}
}
bool Position::HasInArc(float arc, const Position* obj, float border) const
{
// always have self in arc
if (obj == this)
return true;
// move arc to range 0.. 2*pi
arc = NormalizeOrientation(arc);
float angle = GetAngle(obj);
angle -= m_orientation;
// move angle to range -pi ... +pi
angle = NormalizeOrientation(angle);
if (angle > float(M_PI))
angle -= 2.0f * float(M_PI);
float lborder = -1 * (arc/border); // in range -pi..0
float rborder = (arc/border); // in range 0..pi
return ((angle >= lborder) && (angle <= rborder));
}
bool WorldObject::IsInBetween(const WorldObject* obj1, const WorldObject* obj2, float size) const
{
if (!obj1 || !obj2)
@@ -1833,11 +1692,6 @@ void WorldObject::UpdateAllowedPositionZ(float x, float y, float &z) const
}
}
bool Position::IsPositionValid() const
{
return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
}
float WorldObject::GetGridActivationRange() const
{
if (ToPlayer())
+1 -135
View File
@@ -20,6 +20,7 @@
#define _OBJECT_H
#include "Common.h"
#include "Position.h"
#include "UpdateMask.h"
#include "GridReference.h"
#include "ObjectDefines.h"
@@ -250,141 +251,6 @@ class Object
Object& operator=(Object const& right) = delete;
};
struct Position
{
Position(float x = 0, float y = 0, float z = 0, float o = 0)
: m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { }
Position(const Position &loc) { Relocate(loc); }
struct PositionXYZStreamer
{
explicit PositionXYZStreamer(Position& pos) : m_pos(&pos) { }
Position* m_pos;
};
struct PositionXYZOStreamer
{
explicit PositionXYZOStreamer(Position& pos) : m_pos(&pos) { }
Position* m_pos;
};
float m_positionX;
float m_positionY;
float m_positionZ;
// Better to limit access to m_orientation field, but this will be hard to achieve with many scripts using array initialization for this structure
//private:
float m_orientation;
//public:
bool operator==(Position const &a);
inline bool operator!=(Position const &a)
{
return !(operator==(a));
}
void Relocate(float x, float y)
{ m_positionX = x; m_positionY = y;}
void Relocate(float x, float y, float z)
{ m_positionX = x; m_positionY = y; m_positionZ = z; }
void Relocate(float x, float y, float z, float orientation)
{ m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation); }
void Relocate(Position const &pos)
{ m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation); }
void Relocate(Position const* pos)
{ m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation); }
void RelocateOffset(Position const &offset);
void SetOrientation(float orientation)
{ m_orientation = NormalizeOrientation(orientation); }
float GetPositionX() const { return m_positionX; }
float GetPositionY() const { return m_positionY; }
float GetPositionZ() const { return m_positionZ; }
float GetOrientation() const { return m_orientation; }
void GetPosition(float &x, float &y) const
{ x = m_positionX; y = m_positionY; }
void GetPosition(float &x, float &y, float &z) const
{ x = m_positionX; y = m_positionY; z = m_positionZ; }
void GetPosition(float &x, float &y, float &z, float &o) const
{ x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation; }
Position GetPosition() const
{
return *this;
}
Position::PositionXYZStreamer PositionXYZStream()
{
return PositionXYZStreamer(*this);
}
Position::PositionXYZOStreamer PositionXYZOStream()
{
return PositionXYZOStreamer(*this);
}
bool IsPositionValid() const;
float GetExactDist2dSq(float x, float y) const
{ float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy; }
float GetExactDist2d(const float x, const float y) const
{ return std::sqrt(GetExactDist2dSq(x, y)); }
float GetExactDist2dSq(Position const* pos) const
{ float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy; }
float GetExactDist2d(Position const* pos) const
{ return std::sqrt(GetExactDist2dSq(pos)); }
float GetExactDistSq(float x, float y, float z) const
{ float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz; }
float GetExactDist(float x, float y, float z) const
{ return std::sqrt(GetExactDistSq(x, y, z)); }
float GetExactDistSq(Position const* pos) const
{ float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz; }
float GetExactDist(Position const* pos) const
{ return std::sqrt(GetExactDistSq(pos)); }
void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const;
Position GetPositionWithOffset(Position const& offset) const;
float GetAngle(Position const* pos) const;
float GetAngle(float x, float y) const;
float GetRelativeAngle(Position const* pos) const
{ return GetAngle(pos) - m_orientation; }
float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; }
void GetSinCos(float x, float y, float &vsin, float &vcos) const;
bool IsInDist2d(float x, float y, float dist) const
{ return GetExactDist2dSq(x, y) < dist * dist; }
bool IsInDist2d(Position const* pos, float dist) const
{ return GetExactDist2dSq(pos) < dist * dist; }
bool IsInDist(float x, float y, float z, float dist) const
{ return GetExactDistSq(x, y, z) < dist * dist; }
bool IsInDist(Position const* pos, float dist) const
{ return GetExactDistSq(pos) < dist * dist; }
bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
bool HasInLine(WorldObject const* target, float width) const;
std::string ToString() const;
// modulos a radian orientation to the range of 0..2PI
static float NormalizeOrientation(float o)
{
// fmod only supports positive numbers. Thus we have
// to emulate negative numbers
if (o < 0)
{
float mod = o *-1;
mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI));
mod = -mod + 2.0f * static_cast<float>(M_PI);
return mod;
}
return std::fmod(o, 2.0f * static_cast<float>(M_PI));
}
};
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
struct MovementInfo
{
// common
+22 -36
View File
@@ -88,51 +88,41 @@ class ObjectGuid
public:
static ObjectGuid const Empty;
ObjectGuid() { _data._guid = UI64LIT(0); }
explicit ObjectGuid(uint64 guid) { _data._guid = guid; }
ObjectGuid(HighGuid hi, uint32 entry, uint32 counter) { _data._guid = counter ? uint64(counter) | (uint64(entry) << 32) | (uint64(hi) << ((hi == HIGHGUID_CORPSE || hi == HIGHGUID_AREATRIGGER) ? 48 : 52)) : 0; }
ObjectGuid(HighGuid hi, uint32 counter) { _data._guid = counter ? uint64(counter) | (uint64(hi) << ((hi == HIGHGUID_CORPSE || hi == HIGHGUID_AREATRIGGER) ? 48 : 52)) : 0; }
typedef uint32 LowType;
operator uint64() const { return _data._guid; }
ObjectGuid() : _guid(0) { }
explicit ObjectGuid(uint64 guid) : _guid(guid) { }
ObjectGuid(HighGuid hi, uint32 entry, LowType counter) : _guid(counter ? uint64(counter) | (uint64(entry) << 24) | (uint64(hi) << 48) : 0) { }
ObjectGuid(HighGuid hi, LowType counter) : _guid(counter ? uint64(counter) | (uint64(hi) << 48) : 0) { }
operator uint64() const { return _guid; }
PackedGuidReader ReadAsPacked() { return PackedGuidReader(*this); }
void Set(uint64 guid) { _data._guid = guid; }
void Clear() { _data._guid = 0; }
void Set(uint64 guid) { _guid = guid; }
void Clear() { _guid = 0; }
PackedGuid WriteAsPacked() const;
uint64 GetRawValue() const { return _data._guid; }
HighGuid GetHigh() const
uint64 GetRawValue() const { return _guid; }
HighGuid GetHigh() const { return HighGuid((_guid >> 48) & 0x0000FFFF); }
uint32 GetEntry() const { return HasEntry() ? uint32((_guid >> 24) & UI64LIT(0x0000000000FFFFFF)) : 0; }
LowType GetCounter() const
{
uint32 temp = ((uint64(_data._guid) >> 48) & 0x0000FFFF);
return HighGuid((temp == HIGHGUID_CORPSE || temp == HIGHGUID_AREATRIGGER) ? temp : ((temp >> 4) & 0x00000FFF));
}
uint32 GetEntry() const { return HasEntry() ? uint32((_data._guid >> 32) & UI64LIT(0x00000000000FFFFF)) : 0; }
uint32 GetCounter() const
{
return uint32(_data._guid & UI64LIT(0x00000000FFFFFFFF));
return HasEntry()
? LowType(_guid & UI64LIT(0x0000000000FFFFFF))
: LowType(_guid & UI64LIT(0x00000000FFFFFFFF));
}
static uint32 GetMaxCounter(HighGuid /*high*/)
static uint32 GetMaxCounter(HighGuid high)
{
return uint32(0xFFFFFFFF);
return HasEntry(high)
? uint32(0x00FFFFFF)
: uint32(0xFFFFFFFF);
}
uint32 GetMaxCounter() const { return GetMaxCounter(GetHigh()); }
uint8& operator[](uint32 index)
{
ASSERT(index < sizeof(uint64));
return _data._bytes[index];
}
uint8 const& operator[](uint32 index) const
{
ASSERT(index < sizeof(uint64));
return _data._bytes[index];
}
bool IsEmpty() const { return _data._guid == 0; }
bool IsEmpty() const { return _guid == 0; }
bool IsCreature() const { return GetHigh() == HIGHGUID_UNIT; }
bool IsPet() const { return GetHigh() == HIGHGUID_PET; }
bool IsVehicle() const { return GetHigh() == HIGHGUID_VEHICLE; }
@@ -218,11 +208,7 @@ class ObjectGuid
ObjectGuid(HighGuid, uint32, uint64 counter) = delete; // no implementation, used to catch wrong type assignment
ObjectGuid(HighGuid, uint64 counter) = delete; // no implementation, used to catch wrong type assignment
union
{
uint64 _guid;
uint8 _bytes[sizeof(uint64)];
} _data;
uint64 _guid;
};
// Some Shared defines
@@ -0,0 +1,184 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "Position.h"
#include "ByteBuffer.h"
#include "G3D/g3dmath.h"
#include "GridDefines.h"
bool Position::operator==(Position const &a)
{
return (G3D::fuzzyEq(a.m_positionX, m_positionX) &&
G3D::fuzzyEq(a.m_positionY, m_positionY) &&
G3D::fuzzyEq(a.m_positionZ, m_positionZ) &&
G3D::fuzzyEq(a.m_orientation, m_orientation));
}
void Position::RelocateOffset(const Position & offset)
{
m_positionX = GetPositionX() + (offset.GetPositionX() * std::cos(GetOrientation()) + offset.GetPositionY() * std::sin(GetOrientation() + float(M_PI)));
m_positionY = GetPositionY() + (offset.GetPositionY() * std::cos(GetOrientation()) + offset.GetPositionX() * std::sin(GetOrientation()));
m_positionZ = GetPositionZ() + offset.GetPositionZ();
SetOrientation(GetOrientation() + offset.GetOrientation());
}
bool Position::IsPositionValid() const
{
return Trinity::IsValidMapCoord(m_positionX, m_positionY, m_positionZ, m_orientation);
}
void Position::GetPositionOffsetTo(const Position & endPos, Position & retOffset) const
{
float dx = endPos.GetPositionX() - GetPositionX();
float dy = endPos.GetPositionY() - GetPositionY();
retOffset.m_positionX = dx * std::cos(GetOrientation()) + dy * std::sin(GetOrientation());
retOffset.m_positionY = dy * std::cos(GetOrientation()) - dx * std::sin(GetOrientation());
retOffset.m_positionZ = endPos.GetPositionZ() - GetPositionZ();
retOffset.SetOrientation(endPos.GetOrientation() - GetOrientation());
}
Position Position::GetPositionWithOffset(Position const& offset) const
{
Position ret(*this);
ret.RelocateOffset(offset);
return ret;
}
float Position::GetAngle(const Position* obj) const
{
if (!obj)
return 0;
return GetAngle(obj->GetPositionX(), obj->GetPositionY());
}
// Return angle in range 0..2*pi
float Position::GetAngle(float x, float y) const
{
float dx = x - GetPositionX();
float dy = y - GetPositionY();
float ang = std::atan2(dy, dx);
ang = (ang >= 0) ? ang : 2 * float(M_PI) + ang;
return ang;
}
void Position::GetSinCos(const float x, const float y, float &vsin, float &vcos) const
{
float dx = GetPositionX() - x;
float dy = GetPositionY() - y;
if (std::fabs(dx) < 0.001f && std::fabs(dy) < 0.001f)
{
float angle = (float)rand_norm()*static_cast<float>(2 * M_PI);
vcos = std::cos(angle);
vsin = std::sin(angle);
}
else
{
float dist = std::sqrt((dx*dx) + (dy*dy));
vcos = dx / dist;
vsin = dy / dist;
}
}
bool Position::HasInArc(float arc, const Position* obj, float border) const
{
// always have self in arc
if (obj == this)
return true;
// move arc to range 0.. 2*pi
arc = NormalizeOrientation(arc);
float angle = GetAngle(obj);
angle -= m_orientation;
// move angle to range -pi ... +pi
angle = NormalizeOrientation(angle);
if (angle > float(M_PI))
angle -= 2.0f * float(M_PI);
float lborder = -1 * (arc / border); // in range -pi..0
float rborder = (arc / border); // in range 0..pi
return ((angle >= lborder) && (angle <= rborder));
}
bool Position::HasInLine(Position const* pos, float width) const
{
if (!HasInArc(float(M_PI), pos))
return false;
float angle = GetRelativeAngle(pos);
return std::fabs(std::sin(angle)) * GetExactDist2d(pos->GetPositionX(), pos->GetPositionY()) < width;
}
std::string Position::ToString() const
{
std::stringstream sstr;
sstr << "X: " << m_positionX << " Y: " << m_positionY << " Z: " << m_positionZ << " O: " << m_orientation;
return sstr.str();
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer)
{
float x, y;
buf >> x >> y;
streamer.Pos->Relocate(x, y);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
buf << streamer.Pos->GetPositionZ();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer)
{
float x, y, z;
buf >> x >> y >> z;
streamer.Pos->Relocate(x, y, z);
return buf;
}
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
buf << streamer.Pos->GetPositionX();
buf << streamer.Pos->GetPositionY();
buf << streamer.Pos->GetPositionZ();
buf << streamer.Pos->GetOrientation();
return buf;
}
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer)
{
float x, y, z, o;
buf >> x >> y >> z >> o;
streamer.Pos->Relocate(x, y, z, o);
return buf;
}
+225
View File
@@ -0,0 +1,225 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef Trinity_game_Position_h__
#define Trinity_game_Position_h__
#include "Common.h"
class ByteBuffer;
struct Position
{
Position(float x = 0, float y = 0, float z = 0, float o = 0)
: m_positionX(x), m_positionY(y), m_positionZ(z), m_orientation(NormalizeOrientation(o)) { }
Position(Position const& loc) { Relocate(loc); }
struct PositionXYStreamer
{
explicit PositionXYStreamer(Position& pos) : Pos(&pos) { }
Position* Pos;
};
struct PositionXYZStreamer
{
explicit PositionXYZStreamer(Position& pos) : Pos(&pos) { }
Position* Pos;
};
struct PositionXYZOStreamer
{
explicit PositionXYZOStreamer(Position& pos) : Pos(&pos) { }
Position* Pos;
};
float m_positionX;
float m_positionY;
float m_positionZ;
// Better to limit access to _orientation field, to guarantee the value is normalized
private:
float m_orientation;
public:
bool operator==(Position const &a);
inline bool operator!=(Position const &a)
{
return !(operator==(a));
}
void Relocate(float x, float y)
{
m_positionX = x; m_positionY = y;
}
void Relocate(float x, float y, float z)
{
m_positionX = x; m_positionY = y; m_positionZ = z;
}
void Relocate(float x, float y, float z, float orientation)
{
m_positionX = x; m_positionY = y; m_positionZ = z; SetOrientation(orientation);
}
void Relocate(Position const &pos)
{
m_positionX = pos.m_positionX; m_positionY = pos.m_positionY; m_positionZ = pos.m_positionZ; SetOrientation(pos.m_orientation);
}
void Relocate(Position const* pos)
{
m_positionX = pos->m_positionX; m_positionY = pos->m_positionY; m_positionZ = pos->m_positionZ; SetOrientation(pos->m_orientation);
}
void RelocateOffset(Position const &offset);
void SetOrientation(float orientation)
{
m_orientation = NormalizeOrientation(orientation);
}
float GetPositionX() const { return m_positionX; }
float GetPositionY() const { return m_positionY; }
float GetPositionZ() const { return m_positionZ; }
float GetOrientation() const { return m_orientation; }
void GetPosition(float &x, float &y) const
{
x = m_positionX; y = m_positionY;
}
void GetPosition(float &x, float &y, float &z) const
{
x = m_positionX; y = m_positionY; z = m_positionZ;
}
void GetPosition(float &x, float &y, float &z, float &o) const
{
x = m_positionX; y = m_positionY; z = m_positionZ; o = m_orientation;
}
Position GetPosition() const { return *this; }
Position::PositionXYStreamer PositionXYStream() { return PositionXYStreamer(*this); }
Position::PositionXYZStreamer PositionXYZStream() { return PositionXYZStreamer(*this); }
Position::PositionXYZOStreamer PositionXYZOStream() { return PositionXYZOStreamer(*this); }
bool IsPositionValid() const;
float GetExactDist2dSq(float x, float y) const
{
float dx = m_positionX - x; float dy = m_positionY - y; return dx*dx + dy*dy;
}
float GetExactDist2d(const float x, const float y) const
{
return std::sqrt(GetExactDist2dSq(x, y));
}
float GetExactDist2dSq(Position const* pos) const
{
float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; return dx*dx + dy*dy;
}
float GetExactDist2d(Position const* pos) const
{
return std::sqrt(GetExactDist2dSq(pos));
}
float GetExactDistSq(float x, float y, float z) const
{
float dz = m_positionZ - z; return GetExactDist2dSq(x, y) + dz*dz;
}
float GetExactDist(float x, float y, float z) const
{
return std::sqrt(GetExactDistSq(x, y, z));
}
float GetExactDistSq(Position const* pos) const
{
float dx = m_positionX - pos->m_positionX; float dy = m_positionY - pos->m_positionY; float dz = m_positionZ - pos->m_positionZ; return dx*dx + dy*dy + dz*dz;
}
float GetExactDist(Position const* pos) const
{
return std::sqrt(GetExactDistSq(pos));
}
void GetPositionOffsetTo(Position const & endPos, Position & retOffset) const;
Position GetPositionWithOffset(Position const& offset) const;
float GetAngle(Position const* pos) const;
float GetAngle(float x, float y) const;
float GetRelativeAngle(Position const* pos) const
{
return GetAngle(pos) - m_orientation;
}
float GetRelativeAngle(float x, float y) const { return GetAngle(x, y) - m_orientation; }
void GetSinCos(float x, float y, float &vsin, float &vcos) const;
bool IsInDist2d(float x, float y, float dist) const
{
return GetExactDist2dSq(x, y) < dist * dist;
}
bool IsInDist2d(Position const* pos, float dist) const
{
return GetExactDist2dSq(pos) < dist * dist;
}
bool IsInDist(float x, float y, float z, float dist) const
{
return GetExactDistSq(x, y, z) < dist * dist;
}
bool IsInDist(Position const* pos, float dist) const
{
return GetExactDistSq(pos) < dist * dist;
}
bool HasInArc(float arcangle, Position const* pos, float border = 2.0f) const;
bool HasInLine(Position const* pos, float width) const;
std::string ToString() const;
// modulos a radian orientation to the range of 0..2PI
static float NormalizeOrientation(float o)
{
// fmod only supports positive numbers. Thus we have
// to emulate negative numbers
if (o < 0)
{
float mod = o *-1;
mod = std::fmod(mod, 2.0f * static_cast<float>(M_PI));
mod = -mod + 2.0f * static_cast<float>(M_PI);
return mod;
}
return std::fmod(o, 2.0f * static_cast<float>(M_PI));
}
};
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZStreamer const& streamer);
ByteBuffer& operator<<(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
ByteBuffer& operator>>(ByteBuffer& buf, Position::PositionXYZOStreamer const& streamer);
#endif // Trinity_game_Position_h__
+4 -103
View File
@@ -24,6 +24,7 @@
#include "SpellMgr.h"
#include "Pet.h"
#include "Formulas.h"
#include "SpellHistory.h"
#include "SpellAuras.h"
#include "SpellAuraEffects.h"
#include "Unit.h"
@@ -409,7 +410,7 @@ void Pet::SavePetToDB(PetSaveMode mode)
RemoveAllAuras();
_SaveSpells(trans);
_SaveSpellCooldowns(trans);
GetSpellHistory()->SaveToDB<Pet>(trans);
CharacterDatabase.CommitTransaction(trans);
// current/stable/not_in_slot
@@ -1069,77 +1070,11 @@ uint32 Pet::GetCurrentFoodBenefitLevel(uint32 itemlevel) const
void Pet::_LoadSpellCooldowns()
{
m_CreatureSpellCooldowns.clear();
m_CreatureCategoryCooldowns.clear();
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_PET_SPELL_COOLDOWN);
stmt->setUInt32(0, m_charmInfo->GetPetNumber());
PreparedQueryResult result = CharacterDatabase.Query(stmt);
PreparedQueryResult cooldownsResult = CharacterDatabase.Query(stmt);
if (result)
{
time_t curTime = time(NULL);
PacketCooldowns cooldowns;
WorldPacket data;
do
{
Field* fields = result->Fetch();
uint32 spell_id = fields[0].GetUInt32();
time_t db_time = time_t(fields[1].GetUInt32());
if (!sSpellMgr->GetSpellInfo(spell_id))
{
TC_LOG_ERROR("entities.pet", "Pet %u have unknown spell %u in `pet_spell_cooldown`, skipping.", m_charmInfo->GetPetNumber(), spell_id);
continue;
}
// skip outdated cooldown
if (db_time <= curTime)
continue;
cooldowns[spell_id] = uint32(db_time - curTime)*IN_MILLISECONDS;
_AddCreatureSpellCooldown(spell_id, db_time);
TC_LOG_DEBUG("entities.pet", "Pet (Number: %u) spell %u cooldown loaded (%u secs).", m_charmInfo->GetPetNumber(), spell_id, uint32(db_time-curTime));
}
while (result->NextRow());
if (!cooldowns.empty())
{
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns);
GetOwner()->GetSession()->SendPacket(&data);
}
}
}
void Pet::_SaveSpellCooldowns(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_PET_SPELL_COOLDOWNS);
stmt->setUInt32(0, m_charmInfo->GetPetNumber());
trans->Append(stmt);
time_t curTime = time(NULL);
// remove oudated and save active
for (CreatureSpellCooldowns::iterator itr = m_CreatureSpellCooldowns.begin(); itr != m_CreatureSpellCooldowns.end();)
{
if (itr->second <= curTime)
m_CreatureSpellCooldowns.erase(itr++);
else
{
stmt = CharacterDatabase.GetPreparedStatement(CHAR_INS_PET_SPELL_COOLDOWN);
stmt->setUInt32(0, m_charmInfo->GetPetNumber());
stmt->setUInt32(1, itr->first);
stmt->setUInt32(2, uint32(itr->second));
trans->Append(stmt);
++itr;
}
}
GetSpellHistory()->LoadFromDB<Pet>(cooldownsResult);
}
void Pet::_LoadSpells()
@@ -1989,40 +1924,6 @@ void Pet::SynchronizeLevelWithOwner()
}
}
void Pet::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
{
PacketCooldowns cooldowns;
WorldPacket data;
time_t curTime = time(NULL);
for (PetSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{
if (itr->second.state == PETSPELL_REMOVED)
continue;
uint32 unSpellId = itr->first;
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(unSpellId);
// Not send cooldown for this spells
if (spellInfo->IsCooldownStartedOnEvent())
continue;
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
continue;
if ((idSchoolMask & spellInfo->GetSchoolMask()) && GetCreatureSpellCooldownDelay(unSpellId) < unTimeMs)
{
cooldowns[unSpellId] = unTimeMs;
_AddCreatureSpellCooldown(unSpellId, curTime + unTimeMs/IN_MILLISECONDS);
}
}
if (!cooldowns.empty())
{
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns);
GetOwner()->GetSession()->SendPacket(&data);
}
}
Player* Pet::GetOwner() const
{
return Minion::GetOwner()->ToPlayer();
-2
View File
@@ -106,7 +106,6 @@ class Pet : public Guardian
bool IsPetAura(Aura const* aura);
void _LoadSpellCooldowns();
void _SaveSpellCooldowns(SQLTransaction& trans);
void _LoadAuras(uint32 timediff);
void _SaveAuras(SQLTransaction& trans);
void _LoadSpells();
@@ -119,7 +118,6 @@ class Pet : public Guardian
bool unlearnSpell(uint32 spell_id, bool learn_prev, bool clear_ab = true);
bool removeSpell(uint32 spell_id, bool learn_prev, bool clear_ab = true);
void CleanupActionBar();
virtual void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
PetSpellMap m_spells;
AutoSpellList m_autospells;
+37 -514
View File
@@ -69,6 +69,7 @@
#include "SpellAuraEffects.h"
#include "SpellAuras.h"
#include "SpellMgr.h"
#include "SpellHistory.h"
#include "Transport.h"
#include "UpdateData.h"
#include "UpdateFieldFlags.h"
@@ -3420,12 +3421,10 @@ void Player::InitStatsForLevel(bool reapplyMods)
void Player::SendInitialSpells()
{
time_t curTime = time(NULL);
time_t infTime = curTime + infinityCooldownDelayCheck;
uint16 spellCooldowns = GetSpellHistory()->GetCooldownsSizeForPacket();
uint16 spellCount = 0;
WorldPacket data(SMSG_INITIAL_SPELLS, (1+2+4*m_spells.size()+2+m_spellCooldowns.size()*(2+2+2+4+4)));
WorldPacket data(SMSG_INITIAL_SPELLS, (1 + 2 + 4 * m_spells.size() + 2 + spellCooldowns * (2 + 2 + 2 + 4 + 4)));
data << uint8(0);
size_t countPos = data.wpos();
@@ -3447,40 +3446,7 @@ void Player::SendInitialSpells()
data.put<uint16>(countPos, spellCount); // write real count value
uint16 spellCooldowns = m_spellCooldowns.size();
data << uint16(spellCooldowns);
for (SpellCooldowns::const_iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); ++itr)
{
SpellInfo const* sEntry = sSpellMgr->GetSpellInfo(itr->first);
if (!sEntry)
continue;
data << uint32(itr->first);
data << uint32(itr->second.itemid); // cast item id
data << uint16(sEntry->GetCategory()); // spell category
// send infinity cooldown in special format
if (itr->second.end >= infTime)
{
data << uint32(1); // cooldown
data << uint32(0x80000000); // category cooldown
continue;
}
time_t cooldown = itr->second.end > curTime ? (itr->second.end-curTime)*IN_MILLISECONDS : 0;
if (sEntry->GetCategory()) // may be wrong, but anyway better than nothing...
{
data << uint32(0); // cooldown
data << uint32(cooldown); // category cooldown
}
else
{
data << uint32(cooldown); // cooldown
data << uint32(0); // category cooldown
}
}
GetSpellHistory()->WritePacket<Player>(data);
GetSession()->SendPacket(&data);
@@ -4230,152 +4196,19 @@ void Player::RemoveSpell(uint32 spell_id, bool disabled, bool learn_low_rank)
}
}
void Player::RemoveSpellCooldown(uint32 spell_id, bool update /* = false */)
{
m_spellCooldowns.erase(spell_id);
if (update)
SendClearCooldown(spell_id, this);
}
// I am not sure which one is more efficient
void Player::RemoveCategoryCooldown(uint32 cat)
{
SpellCategoryStore::const_iterator i_scstore = sSpellsByCategoryStore.find(cat);
if (i_scstore != sSpellsByCategoryStore.end())
for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
RemoveSpellCooldown(*i_scset, true);
}
void Player::RemoveSpellCategoryCooldown(uint32 cat, bool update /* = false */)
{
SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(cat);
if (ct == sSpellsByCategoryStore.end())
return;
const SpellCategorySet& ct_set = ct->second;
for (SpellCooldowns::const_iterator i = m_spellCooldowns.begin(); i != m_spellCooldowns.end();)
{
if (ct_set.find(i->first) != ct_set.end())
RemoveSpellCooldown((i++)->first, update);
else
++i;
}
}
void Player::RemoveArenaSpellCooldowns(bool removeActivePetCooldowns)
{
// remove cooldowns on spells that have < 10 min CD
SpellCooldowns::iterator itr, next;
for (itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end(); itr = next)
GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
{
next = itr;
++next;
SpellInfo const* entry = sSpellMgr->GetSpellInfo(itr->first);
// check if spellentry is present and if the cooldown is less than 10 min
if (entry &&
entry->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS &&
entry->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS)
{
// remove & notify
RemoveSpellCooldown(itr->first, true);
}
}
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
return spellInfo->RecoveryTime < 10 * MINUTE * IN_MILLISECONDS && spellInfo->CategoryRecoveryTime < 10 * MINUTE * IN_MILLISECONDS;
}, true);
// pet cooldowns
if (removeActivePetCooldowns)
if (Pet* pet = GetPet())
{
// notify player
for (CreatureSpellCooldowns::const_iterator itr2 = pet->m_CreatureSpellCooldowns.begin(); itr2 != pet->m_CreatureSpellCooldowns.end(); ++itr2)
SendClearCooldown(itr2->first, pet);
// actually clear cooldowns
pet->m_CreatureSpellCooldowns.clear();
}
}
void Player::RemoveAllSpellCooldown()
{
if (!m_spellCooldowns.empty())
{
SendClearAllCooldowns(this);
m_spellCooldowns.clear();
}
}
void Player::_LoadSpellCooldowns(PreparedQueryResult result)
{
// some cooldowns can be already set at aura loading...
//QueryResult* result = CharacterDatabase.PQuery("SELECT spell, item, time FROM character_spell_cooldown WHERE guid = '%u'", GetGUIDLow());
if (result)
{
time_t curTime = time(NULL);
do
{
Field* fields = result->Fetch();
uint32 spell_id = fields[0].GetUInt32();
uint32 item_id = fields[1].GetUInt32();
time_t db_time = time_t(fields[2].GetUInt32());
if (!sSpellMgr->GetSpellInfo(spell_id))
{
TC_LOG_ERROR("entities.player.loading", "Player %u has unknown spell %u in `character_spell_cooldown`, skipping.", GetGUIDLow(), spell_id);
continue;
}
// skip outdated cooldown
if (db_time <= curTime)
continue;
AddSpellCooldown(spell_id, item_id, db_time);
TC_LOG_DEBUG("entities.player.loading", "Player (GUID: %u) spell %u, item %u cooldown loaded (%u secs).", GetGUIDLow(), spell_id, item_id, uint32(db_time-curTime));
}
while (result->NextRow());
}
}
void Player::_SaveSpellCooldowns(SQLTransaction& trans)
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_COOLDOWN);
stmt->setUInt32(0, GetGUIDLow());
trans->Append(stmt);
time_t curTime = time(NULL);
time_t infTime = curTime + infinityCooldownDelayCheck;
bool first_round = true;
std::ostringstream ss;
// remove outdated and save active
for (SpellCooldowns::iterator itr = m_spellCooldowns.begin(); itr != m_spellCooldowns.end();)
{
if (itr->second.end <= curTime)
m_spellCooldowns.erase(itr++);
else if (itr->second.end <= infTime) // not save locked cooldowns, it will be reset or set at reload
{
if (first_round)
{
ss << "INSERT INTO character_spell_cooldown (guid, spell, item, time) VALUES ";
first_round = false;
}
// next new/changed record prefix
else
ss << ',';
ss << '(' << GetGUIDLow() << ',' << itr->first << ',' << itr->second.itemid << ',' << uint64(itr->second.end) << ')';
++itr;
}
else
++itr;
}
// if something changed execute
if (!first_round)
trans->Append(ss.str().c_str());
pet->GetSpellHistory()->ResetAllCooldowns();
}
uint32 Player::GetNextResetTalentsCost() const
@@ -4919,7 +4752,7 @@ void Player::DeleteFromDB(ObjectGuid playerguid, uint32 accountId, bool updateRe
stmt->setUInt32(0, guid);
trans->Append(stmt);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_COOLDOWN);
stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CHAR_SPELL_COOLDOWNS);
stmt->setUInt32(0, guid);
trans->Append(stmt);
@@ -8631,7 +8464,7 @@ void Player::CastItemCombatSpell(Unit* target, WeaponAttackType attType, uint32
if (procVictim & PROC_FLAG_TAKEN_DAMAGE)
//if (damageInfo->procVictim & PROC_FLAG_TAKEN_ANY_DAMAGE)
{
for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i)
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
{
_Spell const& spellData = proto->Spells[i];
@@ -12252,10 +12085,9 @@ Item* Player::EquipItem(uint16 pos, Item* pItem, bool update)
{
m_weaponChangeTimer = spellProto->StartRecoveryTime;
GetGlobalCooldownMgr().AddGlobalCooldown(spellProto, m_weaponChangeTimer);
GetSpellHistory()->AddGlobalCooldown(spellProto, m_weaponChangeTimer);
WorldPacket data;
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_INCLUDE_GCD, cooldownSpell, 0);
GetSpellHistory()->BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_INCLUDE_GCD, cooldownSpell, 0);
GetSession()->SendPacket(&data);
}
}
@@ -17905,7 +17737,7 @@ bool Player::LoadFromDB(ObjectGuid guid, SQLQueryHolder *holder)
// has to be called after last Relocate() in Player::LoadFromDB
SetFallInformation(0, GetPositionZ());
_LoadSpellCooldowns(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELL_COOLDOWNS));
GetSpellHistory()->LoadFromDB<Player>(holder->GetPreparedResult(PLAYER_LOGIN_QUERY_LOAD_SPELL_COOLDOWNS));
// Spell code allow apply any auras to dead character in load time in aura/spell/item loading
// Do now before stats re-calculation cleanup for ghost state unexpected auras
@@ -19748,7 +19580,7 @@ void Player::SaveToDB(bool create /*=false*/)
_SaveMonthlyQuestStatus(trans);
_SaveTalents(trans);
_SaveSpells(trans);
_SaveSpellCooldowns(trans);
GetSpellHistory()->SaveToDB<Player>(trans);
_SaveActions(trans);
_SaveAuras(trans);
_SaveSkills(trans);
@@ -21070,41 +20902,8 @@ void Player::PetSpellInitialize()
data.put<uint8>(spellsCountPos, addlist);
uint8 cooldownsCount = pet->m_CreatureSpellCooldowns.size() + pet->m_CreatureCategoryCooldowns.size();
data << uint8(cooldownsCount);
time_t curTime = time(NULL);
for (CreatureSpellCooldowns::const_iterator itr = pet->m_CreatureSpellCooldowns.begin(); itr != pet->m_CreatureSpellCooldowns.end(); ++itr)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
if (!spellInfo)
{
data << uint32(0);
data << uint16(0);
data << uint32(0);
data << uint32(0);
continue;
}
time_t cooldown = (itr->second > curTime) ? (itr->second - curTime) * IN_MILLISECONDS : 0;
data << uint32(itr->first); // spell ID
CreatureSpellCooldowns::const_iterator categoryitr = pet->m_CreatureCategoryCooldowns.find(spellInfo->GetCategory());
if (categoryitr != pet->m_CreatureCategoryCooldowns.end())
{
time_t categoryCooldown = (categoryitr->second > curTime) ? (categoryitr->second - curTime) * IN_MILLISECONDS : 0;
data << uint16(spellInfo->GetCategory()); // spell category
data << uint32(cooldown); // spell cooldown
data << uint32(categoryCooldown); // category cooldown
}
else
{
data << uint16(0);
data << uint32(cooldown);
data << uint32(0);
}
}
//Cooldowns
pet->GetSpellHistory()->WritePacket<Pet>(data);
GetSession()->SendPacket(&data);
}
@@ -21143,7 +20942,7 @@ void Player::VehicleSpellInitialize()
if (!vehicle)
return;
uint8 cooldownCount = vehicle->m_CreatureSpellCooldowns.size();
uint8 cooldownCount = vehicle->GetSpellHistory()->GetCooldownsSizeForPacket();
WorldPacket data(SMSG_PET_SPELLS, 8 + 2 + 4 + 4 + 4 * 10 + 1 + 1 + cooldownCount * (4 + 2 + 4 + 4));
data << uint64(vehicle->GetGUID()); // Guid
@@ -21184,41 +20983,7 @@ void Player::VehicleSpellInitialize()
data << uint8(0); // Auras?
// Cooldowns
data << uint8(cooldownCount);
time_t now = sWorld->GetGameTime();
for (CreatureSpellCooldowns::const_iterator itr = vehicle->m_CreatureSpellCooldowns.begin(); itr != vehicle->m_CreatureSpellCooldowns.end(); ++itr)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
if (!spellInfo)
{
data << uint32(0);
data << uint16(0);
data << uint32(0);
data << uint32(0);
continue;
}
time_t cooldown = (itr->second > now) ? (itr->second - now) * IN_MILLISECONDS : 0;
data << uint32(itr->first); // spell ID
CreatureSpellCooldowns::const_iterator categoryitr = vehicle->m_CreatureCategoryCooldowns.find(spellInfo->GetCategory());
if (categoryitr != vehicle->m_CreatureCategoryCooldowns.end())
{
time_t categoryCooldown = (categoryitr->second > now) ? (categoryitr->second - now) * IN_MILLISECONDS : 0;
data << uint16(spellInfo->GetCategory()); // spell category
data << uint32(cooldown); // spell cooldown
data << uint32(categoryCooldown); // category cooldown
}
else
{
data << uint16(0);
data << uint32(cooldown);
data << uint32(0);
}
}
vehicle->GetSpellHistory()->WritePacket<Pet>(data);
GetSession()->SendPacket(&data);
}
@@ -21842,9 +21607,9 @@ void Player::ContinueTaxiFlight()
float distPrev = MAP_SIZE*MAP_SIZE;
float distNext =
(nodeList[0].x-GetPositionX())*(nodeList[0].x-GetPositionX())+
(nodeList[0].y-GetPositionY())*(nodeList[0].y-GetPositionY())+
(nodeList[0].z-GetPositionZ())*(nodeList[0].z-GetPositionZ());
(nodeList[0].LocX-GetPositionX())*(nodeList[0].LocX-GetPositionX())+
(nodeList[0].LocY-GetPositionY())*(nodeList[0].LocY-GetPositionY())+
(nodeList[0].LocZ-GetPositionZ())*(nodeList[0].LocZ-GetPositionZ());
for (uint32 i = 1; i < nodeList.size(); ++i)
{
@@ -21852,20 +21617,20 @@ void Player::ContinueTaxiFlight()
TaxiPathNodeEntry const& prevNode = nodeList[i-1];
// skip nodes at another map
if (node.mapid != GetMapId())
if (node.MapID != GetMapId())
continue;
distPrev = distNext;
distNext =
(node.x-GetPositionX())*(node.x-GetPositionX())+
(node.y-GetPositionY())*(node.y-GetPositionY())+
(node.z-GetPositionZ())*(node.z-GetPositionZ());
(node.LocX-GetPositionX())*(node.LocX-GetPositionX())+
(node.LocY-GetPositionY())*(node.LocY-GetPositionY())+
(node.LocZ-GetPositionZ())*(node.LocZ-GetPositionZ());
float distNodes =
(node.x-prevNode.x)*(node.x-prevNode.x)+
(node.y-prevNode.y)*(node.y-prevNode.y)+
(node.z-prevNode.z)*(node.z-prevNode.z);
(node.LocX-prevNode.LocX)*(node.LocX-prevNode.LocX)+
(node.LocY-prevNode.LocY)*(node.LocY-prevNode.LocY)+
(node.LocZ-prevNode.LocZ)*(node.LocZ-prevNode.LocZ);
if (distNext + distPrev < distNodes)
{
@@ -21877,39 +21642,6 @@ void Player::ContinueTaxiFlight()
GetSession()->SendDoFlight(mountDisplayId, path, startNode);
}
void Player::ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs)
{
PacketCooldowns cooldowns;
WorldPacket data;
time_t curTime = time(NULL);
for (PlayerSpellMap::const_iterator itr = m_spells.begin(); itr != m_spells.end(); ++itr)
{
if (itr->second->state == PLAYERSPELL_REMOVED)
continue;
uint32 unSpellId = itr->first;
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(unSpellId);
// Not send cooldown for this spells
if (spellInfo->IsCooldownStartedOnEvent())
continue;
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
continue;
if ((idSchoolMask & spellInfo->GetSchoolMask()) && GetSpellCooldownDelay(unSpellId) < unTimeMs)
{
cooldowns[unSpellId] = unTimeMs;
AddSpellCooldown(unSpellId, 0, curTime + unTimeMs/IN_MILLISECONDS);
}
}
if (!cooldowns.empty())
{
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, cooldowns);
GetSession()->SendPacket(&data);
}
}
void Player::InitDataForForm(bool reapplyMods)
{
ShapeshiftForm form = GetShapeshiftForm();
@@ -22545,94 +22277,6 @@ void Player::UpdatePvP(bool state, bool _override)
}
}
bool Player::HasSpellCooldown(uint32 spell_id) const
{
SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id);
return itr != m_spellCooldowns.end() && itr->second.end > time(NULL);
}
uint32 Player::GetSpellCooldownDelay(uint32 spell_id) const
{
SpellCooldowns::const_iterator itr = m_spellCooldowns.find(spell_id);
time_t t = time(NULL);
return uint32(itr != m_spellCooldowns.end() && itr->second.end > t ? itr->second.end - t : 0);
}
void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 itemId, Spell* spell, bool infinityCooldown)
{
// init cooldown values
uint32 cat = 0;
int32 rec = -1;
int32 catrec = -1;
// some special item spells without correct cooldown in SpellInfo
// cooldown information stored in item prototype
// This used in same way in WorldSession::HandleItemQuerySingleOpcode data sending to client.
if (itemId)
{
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
{
for (uint8 idx = 0; idx < MAX_ITEM_SPELLS; ++idx)
{
if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id)
{
cat = proto->Spells[idx].SpellCategory;
rec = proto->Spells[idx].SpellCooldown;
catrec = proto->Spells[idx].SpellCategoryCooldown;
break;
}
}
}
}
// if no cooldown found above then base at DBC data
if (rec < 0 && catrec < 0)
{
cat = spellInfo->GetCategory();
rec = spellInfo->RecoveryTime;
catrec = spellInfo->CategoryRecoveryTime;
}
time_t curTime = time(NULL);
time_t catrecTime;
time_t recTime;
bool needsCooldownPacket = false;
// overwrite time for selected category
if (infinityCooldown)
{
// use +MONTH as infinity mark for spell cooldown (will checked as MONTH/2 at save ans skipped)
// but not allow ignore until reset or re-login
catrecTime = catrec > 0 ? curTime+infinityCooldownDelay : 0;
recTime = rec > 0 ? curTime+infinityCooldownDelay : catrecTime;
}
else
{
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
// prevent 0 cooldowns set by another way
if (rec <= 0 && catrec <= 0 && (cat == 76 || (spellInfo->IsAutoRepeatRangedSpell() && spellInfo->Id != 75)))
rec = GetAttackTime(RANGED_ATTACK);
// Now we have cooldown data (if found any), time to apply mods
if (rec > 0)
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, rec, spell);
if (catrec > 0 && !spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, catrec, spell);
if (int32 cooldownMod = GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
{
// Apply SPELL_AURA_MOD_COOLDOWN only to own spells
if (HasSpell(spellInfo->Id))
{
needsCooldownPacket = true;
rec += cooldownMod * IN_MILLISECONDS; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
}
}
// Apply SPELL_AURA_MOD_SPELL_CATEGORY_COOLDOWN modifiers
// Note: This aura applies its modifiers to all cooldowns of spells with set category, not to category cooldown only
if (cat)
@@ -22656,121 +22300,9 @@ void Player::AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 ite
}
}
// replace negative cooldowns by 0
if (rec < 0)
rec = 0;
if (catrec < 0)
catrec = 0;
// no cooldown after applying spell mods
if (rec == 0 && catrec == 0)
return;
catrecTime = catrec ? curTime+catrec/IN_MILLISECONDS : 0;
recTime = rec ? curTime+rec/IN_MILLISECONDS : catrecTime;
}
// self spell cooldown
if (recTime > 0)
{
AddSpellCooldown(spellInfo->Id, itemId, recTime);
if (needsCooldownPacket)
{
WorldPacket data;
BuildCooldownPacket(data, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, rec);
SendDirectMessage(&data);
}
}
// category spells
if (cat && catrec > 0)
{
SpellCategoryStore::const_iterator i_scstore = sSpellsByCategoryStore.find(cat);
if (i_scstore != sSpellsByCategoryStore.end())
{
for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
{
if (*i_scset == spellInfo->Id) // skip main spell, already handled above
continue;
AddSpellCooldown(*i_scset, itemId, catrecTime);
}
}
}
}
void Player::AddSpellCooldown(uint32 spellid, uint32 itemid, time_t end_time)
{
SpellCooldown sc;
sc.end = end_time;
sc.itemid = itemid;
m_spellCooldowns[spellid] = sc;
}
void Player::ModifySpellCooldown(uint32 spellId, int32 cooldown)
{
SpellCooldowns::iterator itr = m_spellCooldowns.find(spellId);
if (itr == m_spellCooldowns.end())
return;
time_t now = time(NULL);
if (itr->second.end + (cooldown / IN_MILLISECONDS) > now)
itr->second.end += (cooldown / IN_MILLISECONDS);
else
m_spellCooldowns.erase(itr);
WorldPacket data(SMSG_MODIFY_COOLDOWN, 4 + 8 + 4);
data << uint32(spellId); // Spell ID
data << uint64(GetGUID()); // Player GUID
data << int32(cooldown); // Cooldown mod in milliseconds
GetSession()->SendPacket(&data);
TC_LOG_DEBUG("misc", "ModifySpellCooldown:: Player: %s (GUID: %u) Spell: %u cooldown: %u", GetName().c_str(), GetGUIDLow(), spellId, GetSpellCooldownDelay(spellId));
}
void Player::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, Spell* spell /*= NULL*/, bool setCooldown /*= true*/)
{
// start cooldowns at server side, if any
if (setCooldown)
AddSpellAndCategoryCooldowns(spellInfo, itemId, spell);
// Send activate cooldown timer (possible 0) at client side
WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
data << uint32(spellInfo->Id);
data << uint64(GetGUID());
SendDirectMessage(&data);
uint32 cat = spellInfo->GetCategory();
if (cat && spellInfo->CategoryRecoveryTime)
{
SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(cat);
if (ct != sSpellsByCategoryStore.end())
{
SpellCategorySet const& catSet = ct->second;
for (SpellCooldowns::const_iterator i = m_spellCooldowns.begin(); i != m_spellCooldowns.end(); ++i)
{
if (i->first == spellInfo->Id) // skip main spell, already handled above
continue;
SpellInfo const* spellInfo2 = sSpellMgr->GetSpellInfo(i->first);
if (!spellInfo2 || !spellInfo2->IsCooldownStartedOnEvent())
continue;
if (catSet.find(i->first) != catSet.end())
{
// Send activate cooldown timer (possible 0) at client side
WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
data << uint32(i->first);
data << uint64(GetGUID());
SendDirectMessage(&data);
}
}
}
}
}
void Player::UpdatePotionCooldown(Spell* spell)
{
// no potion used i combat or still in combat
@@ -22782,14 +22314,14 @@ void Player::UpdatePotionCooldown(Spell* spell)
{
// spell/item pair let set proper cooldown (except not existed charged spell cooldown spellmods for potions)
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(m_lastPotionId))
for (uint8 idx = 0; idx < MAX_ITEM_SPELLS; ++idx)
for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx)
if (proto->Spells[idx].SpellId && proto->Spells[idx].SpellTrigger == ITEM_SPELLTRIGGER_ON_USE)
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(proto->Spells[idx].SpellId))
SendCooldownEvent(spellInfo, m_lastPotionId);
GetSpellHistory()->SendCooldownEvent(spellInfo, m_lastPotionId);
}
// from spell cases (m_lastPotionId set in Spell::SendSpellCooldown)
else
SendCooldownEvent(spell->m_spellInfo, m_lastPotionId, spell);
GetSpellHistory()->SendCooldownEvent(spell->m_spellInfo, m_lastPotionId, spell);
m_lastPotionId = 0;
}
@@ -23703,14 +23235,13 @@ void Player::ApplyEquipCooldown(Item* pItem)
continue;
// Don't replace longer cooldowns by equip cooldown if we have any.
SpellCooldowns::iterator itr = m_spellCooldowns.find(spellData.SpellId);
if (itr != m_spellCooldowns.end() && itr->second.itemid == pItem->GetEntry() && itr->second.end > time(NULL) + 30)
if (GetSpellHistory()->GetRemainingCooldown(spellData.SpellId) > 30 * IN_MILLISECONDS)
continue;
AddSpellCooldown(spellData.SpellId, pItem->GetEntry(), time(NULL) + 30);
GetSpellHistory()->AddCooldown(spellData.SpellId, pItem->GetEntry(), std::chrono::seconds(30));
WorldPacket data(SMSG_ITEM_COOLDOWN, 12);
data << pItem->GetGUID();
WorldPacket data(SMSG_ITEM_COOLDOWN, 8 + 4);
data << uint64(pItem->GetGUID());
data << uint32(spellData.SpellId);
GetSession()->SendPacket(&data);
}
@@ -24582,7 +24113,7 @@ uint32 Player::GetResurrectionSpellId()
}
// Reincarnation (passive spell) // prio: 1 // Glyph of Renewed Life
if (prio < 1 && HasSpell(20608) && !HasSpellCooldown(21169) && (HasAura(58059) || HasItemCount(17030)))
if (prio < 1 && HasSpell(20608) && !GetSpellHistory()->HasCooldown(21169) && (HasAura(58059) || HasItemCount(17030)))
spell_id = 21169;
return spell_id;
@@ -26708,14 +26239,6 @@ void Player::RemoveAtLoginFlag(AtLoginFlags flags, bool persist /*= false*/)
}
}
void Player::SendClearCooldown(uint32 spell_id, Unit* target)
{
WorldPacket data(SMSG_CLEAR_COOLDOWN, 4+8);
data << uint32(spell_id);
data << uint64(target->GetGUID());
SendDirectMessage(&data);
}
void Player::SendClearAllCooldowns(Unit* target)
{
uint32 spellCount = m_spellCooldowns.size();
+3 -37
View File
@@ -276,13 +276,6 @@ struct CUFProfile
// More fields can be added to BoolOptions without changing DB schema (up to 32, currently 27)
};
struct SpellCooldown
{
time_t end;
uint16 itemid;
};
typedef std::map<uint32, SpellCooldown> SpellCooldowns;
typedef std::unordered_map<uint32 /*instanceId*/, time_t/*releaseTime*/> InstanceTimeMap;
enum TrainerSpellState
@@ -489,9 +482,9 @@ struct Runes
struct EnchantDuration
{
EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { };
EnchantDuration() : item(NULL), slot(MAX_ENCHANTMENT_SLOT), leftduration(0) { }
EnchantDuration(Item* _item, EnchantmentSlot _slot, uint32 _leftduration) : item(_item), slot(_slot),
leftduration(_leftduration){ ASSERT(item); };
leftduration(_leftduration){ ASSERT(item); }
Item* item;
EnchantmentSlot slot;
@@ -1858,8 +1851,6 @@ class Player : public Unit, public GridObject<Player>
PlayerSpellMap const& GetSpellMap() const { return m_spells; }
PlayerSpellMap & GetSpellMap() { return m_spells; }
SpellCooldowns const& GetSpellCooldownMap() const { return m_spellCooldowns; }
void AddSpellMod(SpellModifier* mod, bool apply);
bool IsAffectedBySpellmod(SpellInfo const* spellInfo, SpellModifier* mod, Spell* spell = NULL);
template <class T> T ApplySpellMod(uint32 spellId, SpellModOp op, T &basevalue, Spell* spell = NULL);
@@ -1869,27 +1860,8 @@ class Player : public Unit, public GridObject<Player>
void DropModCharge(SpellModifier* mod, Spell* spell);
void SetSpellModTakingSpell(Spell* spell, bool apply);
static uint32 const infinityCooldownDelay = MONTH; // used for set "infinity cooldowns" for spells and check
static uint32 const infinityCooldownDelayCheck = MONTH/2;
bool HasSpellCooldown(uint32 spell_id) const;
uint32 GetSpellCooldownDelay(uint32 spell_id) const;
void AddSpellAndCategoryCooldowns(SpellInfo const* spellInfo, uint32 itemId, Spell* spell = NULL, bool infinityCooldown = false);
void AddSpellCooldown(uint32 spell_id, uint32 itemid, time_t end_time);
void ModifySpellCooldown(uint32 spellId, int32 cooldown);
void SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId = 0, Spell* spell = NULL, bool setCooldown = true);
void ProhibitSpellSchool(SpellSchoolMask idSchoolMask, uint32 unTimeMs) override;
void RemoveSpellCooldown(uint32 spell_id, bool update = false);
void RemoveSpellCategoryCooldown(uint32 cat, bool update = false);
void SendClearCooldown(uint32 spell_id, Unit* target);
void SendClearAllCooldowns(Unit* target);
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
void RemoveCategoryCooldown(uint32 cat);
void RemoveArenaSpellCooldowns(bool removeActivePetCooldowns = false);
void RemoveAllSpellCooldown();
void _LoadSpellCooldowns(PreparedQueryResult result);
void _SaveSpellCooldowns(SQLTransaction& trans);
uint32 GetLastPotionId() { return m_lastPotionId; }
void SetLastPotionId(uint32 item_id) { m_lastPotionId = item_id; }
void UpdatePotionCooldown(Spell* spell = NULL);
@@ -2083,7 +2055,7 @@ class Player : public Unit, public GridObject<Player>
bool UpdatePosition(const Position &pos, bool teleport = false) { return UpdatePosition(pos.GetPositionX(), pos.GetPositionY(), pos.GetPositionZ(), pos.GetOrientation(), teleport); }
void UpdateUnderwaterState(Map* m, float x, float y, float z) override;
void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); };// overwrite Object::SendMessageToSet
void SendMessageToSet(WorldPacket* data, bool self) override {SendMessageToSetInRange(data, GetVisibilityRange(), self); }// overwrite Object::SendMessageToSet
void SendMessageToSetInRange(WorldPacket* data, float fist, bool self) override;// overwrite Object::SendMessageToSetInRange
void SendMessageToSetInRange(WorldPacket* data, float dist, bool self, bool own_team_only);
void SendMessageToSet(WorldPacket* data, Player const* skipped_rcvr) override;
@@ -2178,8 +2150,6 @@ class Player : public Unit, public GridObject<Player>
//End of PvP System
inline SpellCooldowns GetSpellCooldowns() const { return m_spellCooldowns; }
void SetDrunkValue(uint8 newDrunkValue, uint32 itemId = 0);
uint8 GetDrunkValue() const { return GetByteValue(PLAYER_BYTES_3, 1); }
static DrunkenState GetDrunkenstateByValue(uint8 value);
@@ -2754,8 +2724,6 @@ class Player : public Unit, public GridObject<Player>
PlayerSpellMap m_spells;
uint32 m_lastPotionId; // last used health/mana potion in combat, that block next potion use
GlobalCooldownMgr m_GlobalCooldownMgr;
PlayerTalentInfo* _talentMgr;
ActionButtonList m_actionButtons;
@@ -2914,8 +2882,6 @@ class Player : public Unit, public GridObject<Player>
AchievementMgr<Player>* m_achievementMgr;
ReputationMgr* m_reputationMgr;
SpellCooldowns m_spellCooldowns;
uint32 m_ChampioningFaction;
std::queue<uint32> m_timeSyncQueue;
+2 -1
View File
@@ -20,6 +20,7 @@
#include "Group.h"
#include "Opcodes.h"
#include "Player.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "SpellInfo.h"
#include "WorldPacket.h"
@@ -122,7 +123,7 @@ void Totem::UnSummon(uint32 msTime)
owner->SendAutoRepeatCancel(this);
if (SpellInfo const* spell = sSpellMgr->GetSpellInfo(GetUInt32Value(UNIT_CREATED_BY_SPELL)))
owner->SendCooldownEvent(spell, 0, NULL, false);
GetSpellHistory()->SendCooldownEvent(spell, 0, nullptr, false);
if (Group* group = owner->GetGroup())
{
@@ -32,7 +32,7 @@
Transport::Transport() : GameObject(),
_transportInfo(NULL), _isMoving(true), _pendingStop(false),
_triggeredArrivalEvent(false), _triggeredDepartureEvent(false),
_passengerTeleportItr(_passengers.begin()), _delayedAddModel(false)
_passengerTeleportItr(_passengers.begin()), _delayedAddModel(false), _delayedTeleport(false)
{
m_updateFlag = UPDATEFLAG_TRANSPORT | UPDATEFLAG_LOWGUID | UPDATEFLAG_STATIONARY_POSITION | UPDATEFLAG_ROTATION;
}
@@ -173,13 +173,13 @@ void Transport::Update(uint32 diff)
MoveToNextWaypoint();
sScriptMgr->OnRelocate(this, _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z);
sScriptMgr->OnRelocate(this, _currentFrame->Node->NodeIndex, _currentFrame->Node->MapID, _currentFrame->Node->LocX, _currentFrame->Node->LocY, _currentFrame->Node->LocZ);
TC_LOG_DEBUG("entities.transport", "Transport %u (%s) moved to node %u %u %f %f %f", GetEntry(), GetName().c_str(), _currentFrame->Node->index, _currentFrame->Node->mapid, _currentFrame->Node->x, _currentFrame->Node->y, _currentFrame->Node->z);
TC_LOG_DEBUG("entities.transport", "Transport %u (%s) moved to node %u %u %f %f %f", GetEntry(), GetName().c_str(), _currentFrame->Node->NodeIndex, _currentFrame->Node->MapID, _currentFrame->Node->LocX, _currentFrame->Node->LocY, _currentFrame->Node->LocZ);
// Departure event
if (_currentFrame->IsTeleportFrame())
if (TeleportTransport(_nextFrame->Node->mapid, _nextFrame->Node->x, _nextFrame->Node->y, _nextFrame->Node->z, _nextFrame->InitialOrientation))
if (TeleportTransport(_nextFrame->Node->MapID, _nextFrame->Node->LocX, _nextFrame->Node->LocY, _nextFrame->Node->LocZ, _nextFrame->InitialOrientation))
return; // Update more in new map thread
}
@@ -226,6 +226,14 @@ void Transport::Update(uint32 diff)
sScriptMgr->OnTransportUpdate(this, diff);
}
void Transport::DelayedUpdate(uint32 /*diff*/)
{
if (GetKeyFrames().size() <= 1)
return;
DelayedTeleportTransport();
}
void Transport::AddPassenger(WorldObject* passenger)
{
if (!IsInWorld())
@@ -600,36 +608,8 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
if (oldMap->GetId() != newMapid)
{
Map* newMap = sMapMgr->CreateBaseMap(newMapid);
_delayedTeleport = true;
UnloadStaticPassengers();
GetMap()->RemoveFromMap<Transport>(this, false);
SetMap(newMap);
for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
{
WorldObject* obj = (*_passengerTeleportItr++);
float destX, destY, destZ, destO;
obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
switch (obj->GetTypeId())
{
case TYPEID_PLAYER:
if (!obj->ToPlayer()->TeleportTo(newMapid, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
RemovePassenger(obj);
break;
case TYPEID_DYNAMICOBJECT:
obj->AddObjectToRemoveList();
break;
default:
RemovePassenger(obj);
break;
}
}
Relocate(x, y, z, o);
GetMap()->AddToMap<Transport>(this);
return true;
}
else
@@ -652,6 +632,48 @@ bool Transport::TeleportTransport(uint32 newMapid, float x, float y, float z, fl
}
}
void Transport::DelayedTeleportTransport()
{
if (!_delayedTeleport)
return;
_delayedTeleport = false;
Map* newMap = sMapMgr->CreateBaseMap(_nextFrame->Node->MapID);
GetMap()->RemoveFromMap<Transport>(this, false);
SetMap(newMap);
float x = _nextFrame->Node->LocX,
y = _nextFrame->Node->LocY,
z = _nextFrame->Node->LocZ,
o =_nextFrame->InitialOrientation;
for (_passengerTeleportItr = _passengers.begin(); _passengerTeleportItr != _passengers.end();)
{
WorldObject* obj = (*_passengerTeleportItr++);
float destX, destY, destZ, destO;
obj->m_movementInfo.transport.pos.GetPosition(destX, destY, destZ, destO);
TransportBase::CalculatePassengerPosition(destX, destY, destZ, &destO, x, y, z, o);
switch (obj->GetTypeId())
{
case TYPEID_PLAYER:
if (!obj->ToPlayer()->TeleportTo(_nextFrame->Node->MapID, destX, destY, destZ, destO, TELE_TO_NOT_LEAVE_TRANSPORT))
RemovePassenger(obj);
break;
case TYPEID_DYNAMICOBJECT:
obj->AddObjectToRemoveList();
break;
default:
RemovePassenger(obj);
break;
}
}
Relocate(x, y, z, o);
GetMap()->AddToMap<Transport>(this);
}
void Transport::UpdatePassengerPositions(PassengerSet& passengers)
{
for (PassengerSet::iterator itr = passengers.begin(); itr != passengers.end(); ++itr)
@@ -706,9 +728,9 @@ void Transport::UpdatePassengerPositions(PassengerSet& passengers)
void Transport::DoEventIfAny(KeyFrame const& node, bool departure)
{
if (uint32 eventid = departure ? node.Node->departureEventID : node.Node->arrivalEventID)
if (uint32 eventid = departure ? node.Node->DepartureEventID : node.Node->ArrivalEventID)
{
TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of %s path", departure ? "departure" : "arrival", eventid, node.Node->index, GetName().c_str());
TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of %s path", departure ? "departure" : "arrival", eventid, node.Node->NodeIndex, GetName().c_str());
GetMap()->ScriptsStart(sEventScripts, eventid, this, this);
EventInform(eventid);
}
@@ -39,6 +39,7 @@ class Transport : public GameObject, public TransportBase
void CleanupsBeforeDelete(bool finalCleanup = true) override;
void Update(uint32 diff) override;
void DelayedUpdate(uint32 diff);
void BuildUpdate(UpdateDataMapType& data_map) override;
@@ -103,6 +104,7 @@ class Transport : public GameObject, public TransportBase
void MoveToNextWaypoint();
float CalculateSegmentPos(float perc);
bool TeleportTransport(uint32 newMapid, float x, float y, float z, float o);
void DelayedTeleportTransport();
void UpdatePassengerPositions(PassengerSet& passengers);
void DoEventIfAny(KeyFrame const& node, bool departure);
@@ -127,6 +129,7 @@ class Transport : public GameObject, public TransportBase
PassengerSet _staticPassengers;
bool _delayedAddModel;
bool _delayedTeleport;
};
#endif
+68 -94
View File
@@ -50,6 +50,7 @@
#include "SpellAuras.h"
#include "Spell.h"
#include "SpellInfo.h"
#include "SpellHistory.h"
#include "SpellMgr.h"
#include "TemporarySummon.h"
#include "Totem.h"
@@ -163,7 +164,7 @@ Unit::Unit(bool isWorldObject) :
i_AI(NULL), i_disabledAI(NULL), m_AutoRepeatFirstCast(false), m_procDeep(0),
m_removedAurasCount(0), i_motionMaster(new MotionMaster(this)), m_regenTimer(0), m_ThreatManager(this),
m_vehicle(NULL), m_vehicleKit(NULL), m_unitTypeMask(UNIT_MASK_NONE),
m_HostileRefManager(this), _lastDamagedTime(0)
m_HostileRefManager(this), _lastDamagedTime(0), m_spellHistory(new SpellHistory(this))
{
m_objectType |= TYPEMASK_UNIT;
m_objectTypeId = TYPEID_UNIT;
@@ -259,24 +260,6 @@ Unit::Unit(bool isWorldObject) :
_meleeAnimKitId = 0;
}
////////////////////////////////////////////////////////////
// Methods of class GlobalCooldownMgr
bool GlobalCooldownMgr::HasGlobalCooldown(SpellInfo const* spellInfo) const
{
GlobalCooldownList::const_iterator itr = m_GlobalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != m_GlobalCooldowns.end() && itr->second.duration && getMSTimeDiff(itr->second.cast_time, getMSTime()) < itr->second.duration;
}
void GlobalCooldownMgr::AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory] = GlobalCooldown(gcd, getMSTime());
}
void GlobalCooldownMgr::CancelGlobalCooldown(SpellInfo const* spellInfo)
{
m_GlobalCooldowns[spellInfo->StartRecoveryCategory].duration = 0;
}
////////////////////////////////////////////////////////////
// Methods of class Unit
Unit::~Unit()
@@ -294,6 +277,7 @@ Unit::~Unit()
delete i_motionMaster;
delete m_charmInfo;
delete movespline;
delete m_spellHistory;
ASSERT(!m_duringRemoveFromWorld);
ASSERT(!m_attacking);
@@ -2702,6 +2686,8 @@ void Unit::_UpdateSpells(uint32 time)
++itr;
}
}
m_spellHistory->Update();
}
void Unit::_UpdateAutoRepeatSpell()
@@ -4641,13 +4627,13 @@ void Unit::AddGameObject(GameObject* gameObj)
m_gameObj.push_back(gameObj);
gameObj->SetOwnerGUID(GetGUID());
if (GetTypeId() == TYPEID_PLAYER && gameObj->GetSpellId())
if (gameObj->GetSpellId())
{
SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(gameObj->GetSpellId());
// Need disable spell use for owner
if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
ToPlayer()->AddSpellAndCategoryCooldowns(createBySpell, 0, NULL, true);
GetSpellHistory()->StartCooldown(createBySpell, 0, nullptr, true);
}
}
@@ -4672,14 +4658,11 @@ void Unit::RemoveGameObject(GameObject* gameObj, bool del)
{
RemoveAurasDueToSpell(spellid);
if (GetTypeId() == TYPEID_PLAYER)
{
SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(spellid);
// Need activate spell use for owner
if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
ToPlayer()->SendCooldownEvent(createBySpell);
}
SpellInfo const* createBySpell = sSpellMgr->GetSpellInfo(spellid);
// Need activate spell use for owner
if (createBySpell && createBySpell->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existing cases)
GetSpellHistory()->SendCooldownEvent(createBySpell);
}
m_gameObj.remove(gameObj);
@@ -5387,8 +5370,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr)
{
if (!ToPlayer()->HasSpellCooldown(*itr))
ToPlayer()->AddSpellCooldown(*itr, 0, time(NULL) + cooldown);
if (!GetSpellHistory()->HasCooldown(*itr))
GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown));
}
break;
}
@@ -5433,8 +5416,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastSpell(target, RandomSpells[rand_spell], true, castItem, triggeredByAura, originalCaster);
for (std::vector<uint32>::iterator itr = RandomSpells.begin(); itr != RandomSpells.end(); ++itr)
{
if (!ToPlayer()->HasSpellCooldown(*itr))
ToPlayer()->AddSpellCooldown(*itr, 0, time(NULL) + cooldown);
if (!GetSpellHistory()->HasCooldown(*itr))
GetSpellHistory()->AddCooldown(*itr, 0, std::chrono::seconds(cooldown));
}
break;
}
@@ -5683,9 +5666,13 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
basepoints0 = int32(CountPctFromMaxHealth(triggerAmount));
target = this;
triggered_spell_id = 34299;
// Regenerate 4% mana
int32 mana = CalculatePct(GetCreateMana(), triggerAmount);
CastCustomSpell(this, 68285, &mana, NULL, NULL, true, castItem, triggeredByAura);
if (triggeredByAura->GetCasterGUID() != GetGUID())
break;
int32 basepoints1 = CalculatePct(GetMaxPower(Powers(POWER_MANA)), triggerAmount * 2);
// Improved Leader of the Pack
// Check cooldown of heal spell cooldown
if (!GetSpellHistory()->HasCooldown(34299))
CastCustomSpell(this, 68285, &basepoints1, 0, 0, true, 0, triggeredByAura);
break;
}
// Healing Touch (Dreamwalker Raiment set)
@@ -6022,7 +6009,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
return false;
// custom cooldown processing case
if (cooldown && player->HasSpellCooldown(dummySpell->Id))
if (cooldown && GetSpellHistory()->HasCooldown(dummySpell->Id))
return false;
if (triggeredByAura->GetBase() && castItem->GetGUID() != triggeredByAura->GetBase()->GetCastItemGUID())
@@ -6069,7 +6056,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
// apply cooldown before cast to prevent processing itself
if (cooldown)
player->AddSpellCooldown(dummySpell->Id, 0, time(NULL) + cooldown);
player->GetSpellHistory()->AddCooldown(dummySpell->Id, 0, std::chrono::seconds(cooldown));
// Attack Twice
for (uint32 i = 0; i < 2; ++i)
@@ -6252,8 +6239,8 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
uint32 spell = 26364;
// custom cooldown processing case
if (GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(spell))
ToPlayer()->RemoveSpellCooldown(spell);
if (GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(spell))
GetSpellHistory()->ResetCooldown(spell);
CastSpell(target, spell, true, castItem, triggeredByAura);
return true;
@@ -6400,7 +6387,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
if (cooldown_spell_id == 0)
cooldown_spell_id = triggered_spell_id;
if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(cooldown_spell_id))
if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(cooldown_spell_id))
return false;
if (basepoints0)
@@ -6409,7 +6396,7 @@ bool Unit::HandleDummyAuraProc(Unit* victim, uint32 damage, AuraEffect* triggere
CastSpell(target, triggered_spell_id, true, castItem, triggeredByAura, originalCaster);
if (cooldown && GetTypeId() == TYPEID_PLAYER)
ToPlayer()->AddSpellCooldown(cooldown_spell_id, 0, time(NULL) + cooldown);
GetSpellHistory()->AddCooldown(cooldown_spell_id, 0, std::chrono::seconds(cooldown));
return true;
}
@@ -6596,9 +6583,9 @@ bool Unit::HandleAuraProc(Unit* victim, uint32 /*damage*/, Aura* triggeredByAura
*handled = true;
if (cooldown && GetTypeId() == TYPEID_PLAYER)
{
if (ToPlayer()->HasSpellCooldown(100000))
if (GetSpellHistory()->HasCooldown(100000))
return false;
ToPlayer()->AddSpellCooldown(100000, 0, time(NULL) + cooldown);
GetSpellHistory()->AddCooldown(100000, 0, std::chrono::seconds(cooldown));
}
return true;
}
@@ -7073,6 +7060,9 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
break;
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
return spellInfo && spellInfo->GetCategory() == 1209;
}, true);
// Maelstrom Weapon
case 53817:
{
@@ -7125,7 +7115,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
}
}
if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(trigger_spell_id))
if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(trigger_spell_id))
return false;
// extra attack should hit same target
@@ -7142,7 +7132,7 @@ bool Unit::HandleProcTriggerSpell(Unit* victim, uint32 damage, AuraEffect* trigg
CastSpell(target, trigger_spell_id, true, castItem, triggeredByAura);
if (cooldown && GetTypeId() == TYPEID_PLAYER)
ToPlayer()->AddSpellCooldown(trigger_spell_id, 0, time(NULL) + cooldown);
GetSpellHistory()->AddCooldown(trigger_spell_id, 0, std::chrono::seconds(cooldown));
return true;
}
@@ -7197,13 +7187,13 @@ bool Unit::HandleOverrideClassScriptAuraProc(Unit* victim, uint32 /*damage*/, Au
return false;
}
if (cooldown && GetTypeId() == TYPEID_PLAYER && ToPlayer()->HasSpellCooldown(triggered_spell_id))
if (cooldown && GetTypeId() == TYPEID_PLAYER && GetSpellHistory()->HasCooldown(triggered_spell_id))
return false;
CastSpell(victim, triggered_spell_id, true, castItem, triggeredByAura);
if (cooldown && GetTypeId() == TYPEID_PLAYER)
ToPlayer()->AddSpellCooldown(triggered_spell_id, 0, time(NULL) + cooldown);
GetSpellHistory()->AddCooldown(triggered_spell_id, 0, std::chrono::seconds(cooldown));
return true;
}
@@ -7934,14 +7924,11 @@ void Unit::SetMinion(Minion *minion, bool apply)
if (minion->IsPetGhoul())
minion->setPowerType(POWER_ENERGY);
if (GetTypeId() == TYPEID_PLAYER)
{
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
// Send infinity cooldown - client does that automatically but after relog cooldown needs to be set again
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
ToPlayer()->AddSpellAndCategoryCooldowns(spellInfo, 0, NULL, true);
}
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
GetSpellHistory()->StartCooldown(spellInfo, 0, nullptr, true);
}
else
{
@@ -7975,13 +7962,10 @@ void Unit::SetMinion(Minion *minion, bool apply)
}
}
if (GetTypeId() == TYPEID_PLAYER)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
// Remove infinity cooldown
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
ToPlayer()->SendCooldownEvent(spellInfo);
}
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(minion->GetUInt32Value(UNIT_CREATED_BY_SPELL));
// Remove infinity cooldown
if (spellInfo && (spellInfo->IsCooldownStartedOnEvent()))
GetSpellHistory()->SendCooldownEvent(spellInfo);
//if (minion->HasUnitTypeMask(UNIT_MASK_GUARDIAN))
{
@@ -8542,11 +8526,15 @@ uint32 Unit::SpellDamageBonusDone(Unit* victim, SpellInfo const* spellProto, uin
DoneTotal += int32(DoneAdvertisedBenefit * coeff * factorMod);
}
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
float tmpDamage = (int32(pdamage) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellDamagePctDone(victim, spellProto, damagetype));
// apply spellmod to Done damage (flat and pct)
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, tmpDamage);
float tmpDamage = float(int32(pdamage) + DoneTotal);
// SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicDamageAurasTick.
if (damagetype != DOT)
{
tmpDamage *= SpellDamagePctDone(victim, spellProto, damagetype);
// apply spellmod to Done damage (flat and pct)
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, tmpDamage);
}
return uint32(std::max(tmpDamage, 0.0f));
}
@@ -9251,11 +9239,15 @@ uint32 Unit::SpellHealingBonusDone(Unit* victim, SpellInfo const* spellProto, ui
DoneTotal = 0;
}
// Done Percentage for DOT is already calculated, no need to do it again. The percentage mod is applied in Aura::HandleAuraSpecificMods.
float heal = float(int32(healamount) + DoneTotal) * (damagetype == DOT ? 1.0f : SpellHealingPctDone(victim, spellProto));
// apply spellmod to Done amount
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, damagetype == DOT ? SPELLMOD_DOT : SPELLMOD_DAMAGE, heal);
float heal = float(int32(healamount) + DoneTotal);
// SPELLMOD_DOT will be applied in AuraEffect::HandlePeriodicHealAurasTick.
if (damagetype != DOT)
{
heal *= SpellHealingPctDone(victim, spellProto);
// apply spellmod to Done amount
if (Player* modOwner = GetSpellModOwner())
modOwner->ApplySpellMod(spellProto->Id, SPELLMOD_DAMAGE, heal);
}
return uint32(std::max(heal, 0.0f));
}
@@ -14854,6 +14846,9 @@ void Unit::KnockbackFrom(float x, float y, float speedXY, float speedZ)
float vcos, vsin;
GetSinCos(x, y, vsin, vcos);
SendMoveKnockBack(player, speedXY, -speedZ, vcos, vsin);
if (player->HasAuraType(SPELL_AURA_MOD_INCREASE_MOUNTED_FLIGHT_SPEED) || player->HasAuraType(SPELL_AURA_FLY))
player->SetCanFly(true, true);
}
}
@@ -16320,7 +16315,7 @@ bool Unit::SetSwim(bool enable)
return true;
}
bool Unit::SetCanFly(bool enable)
bool Unit::SetCanFly(bool enable, bool /*packetOnly = false */)
{
if (enable == HasUnitMovementFlag(MOVEMENTFLAG_CAN_FLY))
return false;
@@ -16642,27 +16637,6 @@ void Unit::BuildValuesUpdate(uint8 updateType, ByteBuffer* data, Player* target)
data->append(fieldBuffer);
}
void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown)
{
data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + 4 + 4);
data << uint64(GetGUID());
data << uint8(flags);
data << uint32(spellId);
data << uint32(cooldown);
}
void Unit::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns)
{
data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + (4 + 4) * cooldowns.size());
data << uint64(GetGUID());
data << uint8(flags);
for (std::unordered_map<uint32, uint32>::const_iterator itr = cooldowns.begin(); itr != cooldowns.end(); ++itr)
{
data << uint32(itr->first);
data << uint32(itr->second);
}
}
int32 Unit::GetHighestExclusiveSameEffectSpellGroupValue(AuraEffect const* aurEff, AuraType auraType, bool checkMiscValue /*= false*/, int32 miscValue /*= 0*/) const
{
int32 val = 0;
+7 -57
View File
@@ -274,13 +274,6 @@ enum UnitRename
#define MAX_AGGRO_RESET_TIME 10 // in seconds
#define MAX_AGGRO_RADIUS 45.0f // yards
enum Swing
{
NOSWING = 0,
SINGLEHANDEDSWING = 1,
TWOHANDEDSWING = 2
};
enum VictimState
{
VICTIMSTATE_INTACT = 0, // set when attacker misses
@@ -340,6 +333,7 @@ class AuraEffect;
class Creature;
class Spell;
class SpellInfo;
class SpellHistory;
class DynamicObject;
class GameObject;
class Item;
@@ -361,7 +355,7 @@ namespace Movement
}
typedef std::list<Unit*> UnitList;
typedef std::list< std::pair<Aura*, uint8> > DispelChargesList;
typedef std::list<std::pair<Aura*, uint8>> DispelChargesList;
struct SpellImmune
{
@@ -386,13 +380,6 @@ enum WeaponDamageRange
MAXDAMAGE
};
enum DamageTypeToSchool
{
RESISTANCE,
DAMAGE_DEALT,
DAMAGE_TAKEN
};
enum AuraRemoveMode
{
AURA_REMOVE_NONE = 0,
@@ -1047,30 +1034,6 @@ enum CurrentSpellTypes
#define CURRENT_FIRST_NON_MELEE_SPELL 1
#define CURRENT_MAX_SPELL 4
struct GlobalCooldown
{
explicit GlobalCooldown(uint32 _dur = 0, uint32 _time = 0) : duration(_dur), cast_time(_time) { }
uint32 duration;
uint32 cast_time;
};
typedef std::unordered_map<uint32 /*category*/, GlobalCooldown> GlobalCooldownList;
class GlobalCooldownMgr // Shared by Player and CharmInfo
{
public:
GlobalCooldownMgr() { }
public:
bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
void AddGlobalCooldown(SpellInfo const* spellInfo, uint32 gcd);
void CancelGlobalCooldown(SpellInfo const* spellInfo);
private:
GlobalCooldownList m_GlobalCooldowns;
};
enum ActiveStates
{
ACT_PASSIVE = 0x01, // 0x01 - passive
@@ -1188,8 +1151,6 @@ struct CharmInfo
CharmSpellInfo* GetCharmSpell(uint8 index) { return &(_charmspells[index]); }
GlobalCooldownMgr& GetGlobalCooldownMgr() { return m_GlobalCooldownMgr; }
void SetIsCommandAttack(bool val);
bool IsCommandAttack();
void SetIsCommandFollow(bool val);
@@ -1222,8 +1183,6 @@ struct CharmInfo
float _stayX;
float _stayY;
float _stayZ;
GlobalCooldownMgr m_GlobalCooldownMgr;
};
// for clearing special attacks
@@ -1254,16 +1213,6 @@ enum PlayerTotemType
SUMMON_TYPE_TOTEM_AIR = 83
};
/// Spell cooldown flags sent in SMSG_SPELL_COOLDOWN
enum SpellCooldownFlags
{
SPELL_COOLDOWN_FLAG_NONE = 0x0,
SPELL_COOLDOWN_FLAG_INCLUDE_GCD = 0x1, ///< Starts GCD in addition to normal cooldown specified in the packet
SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS = 0x2 ///< Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUDE_GCD set
};
typedef std::unordered_map<uint32, uint32> PacketCooldowns;
// delay time next attack to prevent client attack animation problems
#define ATTACK_DISPLAY_DELAY 200
#define MAX_PLAYER_STEALTH_DETECT_RANGE 30.0f // max distance for detection targets by player
@@ -1600,8 +1549,6 @@ class Unit : public WorldObject
Aura* AddAura(SpellInfo const* spellInfo, uint8 effMask, Unit* target);
void SetAuraStack(uint32 spellId, Unit* target, uint32 stack);
void SendPlaySpellVisualKit(uint32 id, uint32 unkParam);
void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown);
void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns);
void DeMorph();
@@ -1862,7 +1809,6 @@ class Unit : public WorldObject
void SetChannelObjectGuid(ObjectGuid guid) { SetGuidValue(UNIT_FIELD_CHANNEL_OBJECT, guid); }
void SetCurrentCastSpell(Spell* pSpell);
virtual void ProhibitSpellSchool(SpellSchoolMask /*idSchoolMask*/, uint32 /*unTimeMs*/) { }
void InterruptSpell(CurrentSpellTypes spellType, bool withDelayed = true, bool withInstant = true);
void FinishSpell(CurrentSpellTypes spellType, bool ok = true);
@@ -1880,6 +1826,9 @@ class Unit : public WorldObject
Spell* FindCurrentSpellBySpellId(uint32 spell_id) const;
int32 GetCurrentSpellCastTime(uint32 spell_id) const;
SpellHistory* GetSpellHistory() { return m_spellHistory; }
SpellHistory const* GetSpellHistory() const { return m_spellHistory; }
ObjectGuid m_SummonSlot[MAX_SUMMON_SLOT];
ObjectGuid m_ObjectSlot[MAX_GAMEOBJECT_SLOT];
@@ -1950,7 +1899,7 @@ class Unit : public WorldObject
void TauntApply(Unit* victim);
void TauntFadeOut(Unit* taunter);
ThreatManager& getThreatManager() { return m_ThreatManager; }
void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); };
void addHatedBy(HostileReference* pHostileReference) { m_HostileRefManager.insertFirst(pHostileReference); }
void removeHatedBy(HostileReference* /*pHostileReference*/) { /* nothing to do yet */ }
HostileRefManager& getHostileRefManager() { return m_HostileRefManager; }
@@ -2312,6 +2261,7 @@ class Unit : public WorldObject
time_t _lastDamagedTime; // Part of Evade mechanics
SpellHistory* m_spellHistory;
uint16 _aiAnimKitId;
uint16 _movementAnimKitId;
uint16 _meleeAnimKitId;
+1 -1
View File
@@ -97,7 +97,7 @@ class GameEventMgr
{
private:
GameEventMgr();
~GameEventMgr() { };
~GameEventMgr() { }
public:
static GameEventMgr* instance()
+64 -4
View File
@@ -1079,6 +1079,66 @@ void ObjectMgr::LoadCreatureAddons()
TC_LOG_INFO("server.loading", ">> Loaded %u creature addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void ObjectMgr::LoadGameObjectAddons()
{
uint32 oldMSTime = getMSTime();
// 0 1 2
QueryResult result = WorldDatabase.Query("SELECT guid, invisibilityType, invisibilityValue FROM gameobject_addon");
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 gameobject addon definitions. DB table `gameobject_addon` is empty.");
return;
}
uint32 count = 0;
do
{
Field* fields = result->Fetch();
ObjectGuid::LowType guid = fields[0].GetUInt32();
const GameObjectData* goData = GetGOData(guid);
if (!goData)
{
TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) does not exist but has a record in `gameobject_addon`", guid);
continue;
}
GameObjectAddon& gameObjectAddon = _gameObjectAddonStore[guid];
gameObjectAddon.invisibilityType = InvisibilityType(fields[1].GetUInt8());
gameObjectAddon.InvisibilityValue = fields[2].GetUInt32();
if (gameObjectAddon.invisibilityType >= TOTAL_INVISIBILITY_TYPES)
{
TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has invalid InvisibilityType in `gameobject_addon`", guid);
gameObjectAddon.invisibilityType = INVISIBILITY_GENERAL;
gameObjectAddon.InvisibilityValue = 0;
}
if (gameObjectAddon.invisibilityType && !gameObjectAddon.InvisibilityValue)
{
TC_LOG_ERROR("sql.sql", "GameObject (GUID: %u) has InvisibilityType set but has no InvisibilityValue in `gameobject_addon`, set to 1", guid);
gameObjectAddon.InvisibilityValue = 1;
}
++count;
}
while (result->NextRow());
TC_LOG_INFO("server.loading", ">> Loaded %u gameobject addons in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
GameObjectAddon const* ObjectMgr::GetGameObjectAddon(ObjectGuid::LowType lowguid)
{
GameObjectAddonContainer::const_iterator itr = _gameObjectAddonStore.find(lowguid);
if (itr != _gameObjectAddonStore.end())
return &(itr->second);
return NULL;
}
CreatureAddon const* ObjectMgr::GetCreatureAddon(uint32 lowguid)
{
CreatureAddonContainer::const_iterator itr = _creatureAddonStore.find(lowguid);
@@ -5011,11 +5071,11 @@ void ObjectMgr::LoadEventScripts()
{
TaxiPathNodeEntry const& node = sTaxiPathNodesByPath[path_idx][node_idx];
if (node.arrivalEventID)
evt_scripts.insert(node.arrivalEventID);
if (node.ArrivalEventID)
evt_scripts.insert(node.ArrivalEventID);
if (node.departureEventID)
evt_scripts.insert(node.departureEventID);
if (node.DepartureEventID)
evt_scripts.insert(node.DepartureEventID);
}
}
+3 -10
View File
@@ -48,12 +48,7 @@ struct AccessRequirement;
struct PlayerInfo;
struct PlayerLevelInfo;
// 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__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct PageText
{
@@ -81,12 +76,7 @@ private:
uint8 _summonGroup; ///< Summon's group id
};
// GCC have alternative #pragma pack() syntax and old gcc version not support pack(pop), also any gcc version not support it at some platform
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
// DB scripting commands
enum ScriptCommands
@@ -743,6 +733,7 @@ class ObjectMgr
static void ChooseCreatureFlags(CreatureTemplate const* cinfo, uint32& npcflag, uint32& unit_flags, uint32& dynamicflags, CreatureData const* data = NULL);
EquipmentInfo const* GetEquipmentInfo(uint32 entry, int8& id);
CreatureAddon const* GetCreatureAddon(uint32 lowguid);
GameObjectAddon const* GetGameObjectAddon(ObjectGuid::LowType lowguid);
CreatureAddon const* GetCreatureTemplateAddon(uint32 entry);
ItemTemplate const* GetItemTemplate(uint32 entry);
ItemTemplateContainer const* GetItemTemplateStore() const { return &_itemTemplateStore; }
@@ -972,6 +963,7 @@ class ObjectMgr
void LoadLinkedRespawn();
bool SetCreatureLinkedRespawn(uint32 guid, uint32 linkedGuid);
void LoadCreatureAddons();
void LoadGameObjectAddons();
void LoadCreatureModelInfo();
void LoadEquipmentTemplates();
void LoadGameObjectLocales();
@@ -1451,6 +1443,7 @@ class ObjectMgr
CreatureModelContainer _creatureModelStore;
CreatureAddonContainer _creatureAddonStore;
CreatureAddonContainer _creatureTemplateAddonStore;
GameObjectAddonContainer _gameObjectAddonStore;
EquipmentInfoContainer _equipmentInfoStore;
LinkedRespawnContainer _linkedRespawnStore;
CreatureLocaleContainer _creatureLocaleStore;
+3
View File
@@ -1905,6 +1905,9 @@ GroupJoinBattlegroundResult Group::CanJoinBattlegroundQueue(Battleground const*
// check if someone in party is using dungeon system
if (member->isUsingLfg())
return ERR_LFG_CANT_USE_BATTLEGROUND;
// check Freeze debuff
if (member->HasAura(9454))
return ERR_BATTLEGROUND_JOIN_FAILED;
}
// only check for MinPlayerCount since MinPlayerCount == MaxPlayerCount for arenas...
+1 -1
View File
@@ -222,7 +222,7 @@ class Group
ObjectGuid GetMasterLooterGuid() const;
ItemQualities GetLootThreshold() const;
uint32 GetDbStoreId() const { return m_dbStoreId; };
uint32 GetDbStoreId() const { return m_dbStoreId; }
// member manipulation methods
bool IsMember(ObjectGuid guid) const;
@@ -194,6 +194,10 @@ void WorldSession::HandleBattlemasterJoinOpcode(WorldPacket& recvData)
return;
}
// check Freeze debuff
if (_player->HasAura(9454))
return;
BattlegroundQueue& bgQueue = sBattlegroundMgr->GetBattlegroundQueue(bgQueueTypeId);
GroupQueueInfo* ginfo = bgQueue.AddGroup(_player, NULL, bgTypeId, bracketEntry, 0, false, isPremade, 0, 0);
@@ -519,6 +523,10 @@ void WorldSession::HandleBattleFieldPortOpcode(WorldPacket &recvData)
WorldPacket data;
if (action)
{
// check Freeze debuff
if (_player->HasAura(9454))
return;
if (!_player->IsInvitedForBattlegroundQueueType(bgQueueTypeId))
return; // cheating?
+5 -15
View File
@@ -30,6 +30,7 @@
#include "Pet.h"
#include "World.h"
#include "Group.h"
#include "SpellHistory.h"
#include "SpellInfo.h"
#include "Player.h"
@@ -361,8 +362,6 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
if (result == SPELL_CAST_OK)
{
pet->ToCreature()->AddCreatureSpellCooldown(spellid);
unit_target = spell->m_targets.GetUnitTarget();
//10% chance to play special pet attack talk, else growl
@@ -396,8 +395,8 @@ void WorldSession::HandlePetActionHelper(Unit* pet, ObjectGuid guid1, uint32 spe
else
spell->SendPetCastResult(result);
if (!pet->ToCreature()->HasSpellCooldown(spellid))
GetPlayer()->SendClearCooldown(spellid, pet);
if (!pet->GetSpellHistory()->HasCooldown(spellid))
pet->GetSpellHistory()->ResetCooldown(spellid, true);
spell->finish(false);
delete spell;
@@ -803,7 +802,6 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
if (Creature* creature = caster->ToCreature())
{
creature->AddCreatureSpellCooldown(spellId);
if (Pet* pet = creature->ToPet())
{
// 10% chance to play special pet attack talk, else growl
@@ -821,16 +819,8 @@ void WorldSession::HandlePetCastSpellOpcode(WorldPacket& recvPacket)
{
spell->SendPetCastResult(result);
if (caster->GetTypeId() == TYPEID_PLAYER)
{
if (!caster->ToPlayer()->HasSpellCooldown(spellId))
GetPlayer()->SendClearCooldown(spellId, caster);
}
else
{
if (!caster->ToCreature()->HasSpellCooldown(spellId))
GetPlayer()->SendClearCooldown(spellId, caster);
}
if (!caster->GetSpellHistory()->HasCooldown(spellId))
caster->GetSpellHistory()->ResetCooldown(spellId, true);
spell->finish(false);
delete spell;
@@ -536,8 +536,6 @@ void WorldSession::HandlePetCancelAuraOpcode(WorldPacket& recvPacket)
}
pet->RemoveOwnedAura(spellId, ObjectGuid::Empty, 0, AURA_REMOVE_BY_CANCEL);
pet->AddCreatureSpellCooldown(spellId);
}
void WorldSession::HandleCancelGrowthAuraOpcode(WorldPacket& /*recvPacket*/) { }
+1 -1
View File
@@ -234,7 +234,7 @@ void WorldSession::HandleMoveSplineDoneOpcode(WorldPacket& recvData)
TaxiPathNodeEntry const& node = flight->GetPath()[flight->GetCurrentNode()];
flight->SkipCurrentNode();
GetPlayer()->TeleportTo(curDestNode->map_id, node.x, node.y, node.z, GetPlayer()->GetOrientation());
GetPlayer()->TeleportTo(curDestNode->map_id, node.LocX, node.LocY, node.LocZ, GetPlayer()->GetOrientation());
}
return;
}
+20 -1
View File
@@ -426,7 +426,26 @@ void InstanceScript::DoUseDoorOrButton(ObjectGuid guid, uint32 withRestoreTime /
TC_LOG_ERROR("scripts", "InstanceScript: DoUseDoorOrButton can't use gameobject entry %u, because type is %u.", go->GetEntry(), go->GetGoType());
}
else
TC_LOG_DEBUG("scripts", "InstanceScript: HandleGameObject failed");
TC_LOG_DEBUG("scripts", "InstanceScript: DoUseDoorOrButton failed");
}
void InstanceScript::DoCloseDoorOrButton(ObjectGuid guid)
{
if (!guid)
return;
if (GameObject* go = instance->GetGameObject(guid))
{
if (go->GetGoType() == GAMEOBJECT_TYPE_DOOR || go->GetGoType() == GAMEOBJECT_TYPE_BUTTON)
{
if (go->getLootState() == GO_ACTIVATED)
go->ResetDoorOrButton();
}
else
TC_LOG_ERROR("scripts", "InstanceScript: DoCloseDoorOrButton can't use gameobject entry %u, because type is %u.", go->GetEntry(), go->GetGoType());
}
else
TC_LOG_DEBUG("scripts", "InstanceScript: DoCloseDoorOrButton failed");
}
void InstanceScript::DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn /*= MINUTE*/)
@@ -194,6 +194,7 @@ class InstanceScript : public ZoneScript
// Change active state of doors or buttons
void DoUseDoorOrButton(ObjectGuid guid, uint32 withRestoreTime = 0, bool useAlternativeState = false);
void DoCloseDoorOrButton(ObjectGuid guid);
// Respawns a GO having negative spawntimesecs in gameobject-table
void DoRespawnGameObject(ObjectGuid guid, uint32 timeToDespawn = MINUTE);
+11
View File
@@ -2586,6 +2586,17 @@ inline void Map::setNGrid(NGridType *grid, uint32 x, uint32 y)
void Map::DelayedUpdate(const uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
{
Transport* transport = *_transportsUpdateIter;
++_transportsUpdateIter;
if (!transport->IsInWorld())
continue;
transport->DelayedUpdate(t_diff);
}
RemoveAllObjectsInRemoveList();
// Don't unload grids if it's battleground, since we may have manually added GOs, creatures, those doesn't load from DB at grid re-load !
-9
View File
@@ -210,12 +210,7 @@ public:
ZLiquidStatus getLiquidStatus(float x, float y, float z, uint8 ReqLiquidType, LiquidData* data = 0);
};
// 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__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct InstanceTemplate
{
@@ -241,11 +236,7 @@ struct ZoneDynamicInfo
uint32 LightFadeInTime;
};
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
#define MAX_HEIGHT 100000.0f // can be use for find ground height at surface
#define INVALID_HEIGHT -100000.0f // for check, must be equal to VMAP_INVALID_HEIGHT, real value for unknown height is VMAP_INVALID_HEIGHT_VALUE
+12 -12
View File
@@ -112,7 +112,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
Movement::PointsArray splinePath, allPoints;
bool mapChange = false;
for (size_t i = 0; i < path.size(); ++i)
allPoints.push_back(G3D::Vector3(path[i].x, path[i].y, path[i].z));
allPoints.push_back(G3D::Vector3(path[i].LocX, path[i].LocY, path[i].LocZ));
// Add extra points to allow derivative calculations for all path nodes
allPoints.insert(allPoints.begin(), allPoints.front().lerp(allPoints[1], -0.2f));
@@ -129,7 +129,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
if (!mapChange)
{
TaxiPathNodeEntry const& node_i = path[i];
if (i != path.size() - 1 && (node_i.actionFlag & 1 || node_i.mapid != path[i + 1].mapid))
if (i != path.size() - 1 && (node_i.Flags & 1 || node_i.MapID != path[i + 1].MapID))
{
keyFrames.back().Teleport = true;
mapChange = true;
@@ -142,8 +142,8 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
k.InitialOrientation = Position::NormalizeOrientation(std::atan2(h.y, h.x) + float(M_PI));
keyFrames.push_back(k);
splinePath.push_back(G3D::Vector3(node_i.x, node_i.y, node_i.z));
transport->mapsUsed.insert(k.Node->mapid);
splinePath.push_back(G3D::Vector3(node_i.LocX, node_i.LocY, node_i.LocZ));
transport->mapsUsed.insert(k.Node->MapID);
}
}
else
@@ -153,12 +153,12 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
if (splinePath.size() >= 2)
{
// Remove special catmull-rom spline points
if (!keyFrames.front().IsStopFrame() && !keyFrames.front().Node->arrivalEventID && !keyFrames.front().Node->departureEventID)
if (!keyFrames.front().IsStopFrame() && !keyFrames.front().Node->ArrivalEventID && !keyFrames.front().Node->DepartureEventID)
{
splinePath.erase(splinePath.begin());
keyFrames.erase(keyFrames.begin());
}
if (!keyFrames.back().IsStopFrame() && !keyFrames.back().Node->arrivalEventID && !keyFrames.back().Node->departureEventID)
if (!keyFrames.back().IsStopFrame() && !keyFrames.back().Node->ArrivalEventID && !keyFrames.back().Node->DepartureEventID)
{
splinePath.pop_back();
keyFrames.pop_back();
@@ -311,7 +311,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
float curPathTime = 0.0f;
if (keyFrames[0].IsStopFrame())
{
curPathTime = float(keyFrames[0].Node->delay);
curPathTime = float(keyFrames[0].Node->Delay);
keyFrames[0].DepartureTime = uint32(curPathTime * IN_MILLISECONDS);
}
@@ -322,7 +322,7 @@ void TransportMgr::GeneratePath(GameObjectTemplate const* goInfo, TransportTempl
{
keyFrames[i].ArriveTime = uint32(curPathTime * IN_MILLISECONDS);
keyFrames[i - 1].NextArriveTime = keyFrames[i].ArriveTime;
curPathTime += float(keyFrames[i].Node->delay);
curPathTime += float(keyFrames[i].Node->Delay);
keyFrames[i].DepartureTime = uint32(curPathTime * IN_MILLISECONDS);
}
else
@@ -374,10 +374,10 @@ Transport* TransportMgr::CreateTransport(uint32 entry, uint32 guid /*= 0*/, Map*
// ...at first waypoint
TaxiPathNodeEntry const* startNode = tInfo->keyFrames.begin()->Node;
uint32 mapId = startNode->mapid;
float x = startNode->x;
float y = startNode->y;
float z = startNode->z;
uint32 mapId = startNode->MapID;
float x = startNode->LocX;
float y = startNode->LocY;
float z = startNode->LocZ;
float o = tInfo->keyFrames.begin()->InitialOrientation;
// initialize the gameobject base
+1 -1
View File
@@ -61,7 +61,7 @@ struct KeyFrame
uint32 NextArriveTime;
bool IsTeleportFrame() const { return Teleport; }
bool IsStopFrame() const { return Node->actionFlag == 2; }
bool IsStopFrame() const { return Node->Flags == 2; }
};
struct TransportTemplate
+2 -2
View File
@@ -29,8 +29,8 @@ class ZoneScript
ZoneScript() { }
virtual ~ZoneScript() { }
virtual uint32 GetCreatureEntry(uint32 /*guidlow*/, CreatureData const* data) { return data->id; }
virtual uint32 GetGameObjectEntry(uint32 /*guidlow*/, uint32 entry) { return entry; }
virtual uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) { return data->id; }
virtual uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) { return entry; }
virtual void OnCreatureCreate(Creature* ) { }
virtual void OnCreatureRemove(Creature* ) { }
@@ -4143,4 +4143,12 @@ enum DiminishingLevels
DIMINISHING_LEVEL_TAUNT_IMMUNE = 4
};
/// Spell cooldown flags sent in SMSG_SPELL_COOLDOWN
enum SpellCooldownFlags
{
SPELL_COOLDOWN_FLAG_NONE = 0x0,
SPELL_COOLDOWN_FLAG_INCLUDE_GCD = 0x1, ///< Starts GCD in addition to normal cooldown specified in the packet
SPELL_COOLDOWN_FLAG_INCLUDE_EVENT_COOLDOWNS = 0x2 ///< Starts GCD for spells that should start their cooldown on events, requires SPELL_COOLDOWN_FLAG_INCLUDE_GCD set
};
#endif
+1 -1
View File
@@ -182,7 +182,7 @@ class MotionMaster //: private std::stack<MovementGenerator *>
void MoveKnockbackFrom(float srcX, float srcY, float speedXY, float speedZ);
void MoveJumpTo(float angle, float speedXY, float speedZ);
void MoveJump(Position const& pos, float speedXY, float speedZ, uint32 id = EVENT_JUMP)
{ MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); };
{ MoveJump(pos.m_positionX, pos.m_positionY, pos.m_positionZ, speedXY, speedZ, id); }
void MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id = EVENT_JUMP);
void MoveCirclePath(float x, float y, float z, float radius, bool clockwise, uint8 stepCount);
void MoveFall(uint32 id = 0);
@@ -248,10 +248,10 @@ uint32 FlightPathMovementGenerator::GetPathAtMapEnd() const
if (i_currentNode >= i_path->size())
return i_path->size();
uint32 curMapId = (*i_path)[i_currentNode].mapid;
uint32 curMapId = (*i_path)[i_currentNode].MapID;
for (uint32 i = i_currentNode; i < i_path->size(); ++i)
{
if ((*i_path)[i].mapid != curMapId)
if ((*i_path)[i].MapID != curMapId)
return i;
}
@@ -296,7 +296,7 @@ void FlightPathMovementGenerator::DoReset(Player* player)
uint32 end = GetPathAtMapEnd();
for (uint32 i = GetCurrentNode(); i != end; ++i)
{
G3D::Vector3 vertice((*i_path)[i].x, (*i_path)[i].y, (*i_path)[i].z);
G3D::Vector3 vertice((*i_path)[i].LocX, (*i_path)[i].LocY, (*i_path)[i].LocZ);
init.Path().push_back(vertice);
}
init.SetFirstPointId(GetCurrentNode());
@@ -335,10 +335,10 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
if (i_path->empty())
return;
uint32 map0 = (*i_path)[0].mapid;
uint32 map0 = (*i_path)[0].MapID;
for (size_t i = 1; i < i_path->size(); ++i)
{
if ((*i_path)[i].mapid != map0)
if ((*i_path)[i].MapID != map0)
{
i_currentNode = i;
return;
@@ -348,9 +348,9 @@ void FlightPathMovementGenerator::SetCurrentNodeAfterTeleport()
void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry const& node, bool departure)
{
if (uint32 eventid = departure ? node.departureEventID : node.arrivalEventID)
if (uint32 eventid = departure ? node.DepartureEventID : node.ArrivalEventID)
{
TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.index, node.path, player->GetName().c_str());
TC_LOG_DEBUG("maps.script", "Taxi %s event %u of node %u of path %u for player %s", departure ? "departure" : "arrival", eventid, node.NodeIndex, node.PathID, player->GetName().c_str());
player->GetMap()->ScriptsStart(sEventScripts, eventid, player, player);
}
}
@@ -358,7 +358,7 @@ void FlightPathMovementGenerator::DoEventIfAny(Player* player, TaxiPathNodeEntry
bool FlightPathMovementGenerator::GetResetPos(Player*, float& x, float& y, float& z)
{
const TaxiPathNodeEntry& node = (*i_path)[i_currentNode];
x = node.x; y = node.y; z = node.z;
x = node.LocX; y = node.LocY; z = node.LocZ;
return true;
}
@@ -367,10 +367,10 @@ void FlightPathMovementGenerator::InitEndGridInfo()
/*! Storage to preload flightmaster grid at end of flight. For multi-stop flights, this will
be reinitialized for each flightmaster at the end of each spline (or stop) in the flight. */
uint32 nodeCount = (*i_path).size(); //! Number of nodes in path.
_endMapId = (*i_path)[nodeCount - 1].mapid; //! MapId of last node
_endMapId = (*i_path)[nodeCount - 1].MapID; //! MapId of last node
_preloadTargetNode = nodeCount - 3;
_endGridX = (*i_path)[nodeCount - 1].x;
_endGridY = (*i_path)[nodeCount - 1].y;
_endGridX = (*i_path)[nodeCount - 1].LocX;
_endGridY = (*i_path)[nodeCount - 1].LocY;
}
void FlightPathMovementGenerator::PreloadEndGrid()
@@ -24,11 +24,7 @@
namespace Movement
{
#if defined( __GNUC__ )
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
class MoveSplineFlag
{
@@ -144,11 +140,7 @@ namespace Movement
bool unknown8 : 1;
bool unknown9 : 1;
};
#if defined( __GNUC__ )
#pragma pack()
#else
#pragma pack(pop)
#endif
}
#endif // TRINITYSERVER_MOVESPLINEFLAG_H
@@ -634,6 +634,7 @@ void AddSC_instance_magtheridons_lair();
void AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
void AddSC_boss_warbringer_omrogg();
void AddSC_boss_warchief_kargath_bladefist();
void AddSC_shattered_halls();
void AddSC_instance_shattered_halls();
void AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
void AddSC_boss_omor_the_unscarred();
@@ -1188,6 +1189,7 @@ void AddOutlandScripts()
AddSC_boss_grand_warlock_nethekurse(); //HC Shattered Halls
AddSC_boss_warbringer_omrogg();
AddSC_boss_warchief_kargath_bladefist();
AddSC_shattered_halls();
AddSC_instance_shattered_halls();
AddSC_boss_watchkeeper_gargolmar(); //HC Ramparts
AddSC_boss_omor_the_unscarred();
@@ -1408,11 +1408,7 @@ class WorldSession;
typedef void(WorldSession::*pOpcodeHandler)(WorldPacket& recvPacket);
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct OpcodeHandler
{
@@ -1460,11 +1456,7 @@ class OpcodeTable
extern OpcodeTable opcodeTable;
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
void InitOpcodes();
+1
View File
@@ -1343,6 +1343,7 @@ uint32 WorldSession::DosProtection::GetMaxPacketCounterAllowed(uint16 opcode) co
case MSG_RANDOM_ROLL: // not profiled
case CMSG_TIME_SYNC_RESP: // not profiled
case CMSG_TRAINER_BUY_SPELL: // not profiled
case CMSG_FORCE_RUN_SPEED_CHANGE_ACK: // not profiled
{
// "0" is a magic number meaning there's no limit for the opcode.
// All the opcodes above must cause little CPU usage and no sync/async database queries at all
@@ -27,6 +27,7 @@
#include "ObjectAccessor.h"
#include "Util.h"
#include "Spell.h"
#include "SpellHistory.h"
#include "SpellAuraEffects.h"
#include "Battleground.h"
#include "OutdoorPvPMgr.h"
@@ -1197,15 +1198,13 @@ void AuraEffect::HandleShapeshiftBoosts(Unit* target, bool apply) const
// Remove cooldown of spells triggered on stance change - they may share cooldown with stance spell
if (spellId)
{
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveSpellCooldown(spellId);
target->GetSpellHistory()->ResetCooldown(spellId);
target->CastSpell(target, spellId, true, NULL, this);
}
if (spellId2)
{
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveSpellCooldown(spellId2);
target->GetSpellHistory()->ResetCooldown(spellId2);
target->CastSpell(target, spellId2, true, NULL, this);
}
@@ -3919,10 +3918,11 @@ void AuraEffect::HandleAuraModIncreaseHealth(AuraApplication const* aurApp, uint
}
else
{
if (int32(target->GetHealth()) > GetAmount())
target->ModifyHealth(-GetAmount());
else
target->SetHealth(1);
if (target->GetHealth() > 0)
{
int32 value = std::min<int32>(target->GetHealth() - 1, GetAmount());
target->ModifyHealth(-value);
}
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
}
}
@@ -3934,19 +3934,15 @@ void AuraEffect::HandleAuraModIncreaseMaxHealth(AuraApplication const* aurApp, u
Unit* target = aurApp->GetTarget();
uint32 oldhealth = target->GetHealth();
double healthPercentage = (double)oldhealth / (double)target->GetMaxHealth();
float percent = target->GetHealthPct();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_VALUE, float(GetAmount()), apply);
// refresh percentage
if (oldhealth > 0)
if (target->GetHealth() > 0)
{
uint32 newhealth = uint32(ceil((double)target->GetMaxHealth() * healthPercentage));
if (newhealth == 0)
newhealth = 1;
target->SetHealth(newhealth);
uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
target->SetHealth(newHealth);
}
}
@@ -4010,8 +4006,12 @@ void AuraEffect::HandleAuraModIncreaseHealthPercent(AuraApplication const* aurAp
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = target->GetHealthPct();
target->HandleStatModifier(UNIT_MOD_HEALTH, TOTAL_PCT, float(GetAmount()), apply);
if (target->IsAlive())
target->SetHealth(target->CountPctFromMaxHealth(int32(percent)));
if (target->GetHealth() > 0)
{
uint32 newHealth = std::max<uint32>(target->CountPctFromMaxHealth(int32(percent)), 1);
target->SetHealth(newHealth);
}
}
void AuraEffect::HandleAuraIncreaseBaseHealthPercent(AuraApplication const* aurApp, uint8 mode, bool apply) const
@@ -5846,6 +5846,9 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
else
damage = std::max(int32(damage * GetDonePct()), 0);
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
damage = target->SpellDamageBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
// Calculate armor mitigation
@@ -6131,6 +6134,9 @@ void AuraEffect::HandlePeriodicHealAurasTick(Unit* target, Unit* caster) const
else
damage = std::max(int32(damage * GetDonePct()), 0);
if (Player* modOwner = caster->GetSpellModOwner())
modOwner->ApplySpellMod(GetSpellInfo()->Id, SPELLMOD_DOT, damage);
damage = target->SpellHealingBonusTaken(caster, GetSpellInfo(), damage, DOT, GetBase()->GetStackAmount());
}
+9 -11
View File
@@ -25,6 +25,7 @@
#include "Player.h"
#include "Unit.h"
#include "Spell.h"
#include "SpellHistory.h"
#include "SpellAuraEffects.h"
#include "DynamicObject.h"
#include "ObjectAccessor.h"
@@ -427,7 +428,7 @@ void Aura::_ApplyForTarget(Unit* target, Unit* caster, AuraApplication * auraApp
if (m_spellInfo->IsCooldownStartedOnEvent())
{
Item* castItem = m_castItemGuid ? caster->ToPlayer()->GetItemByGuid(m_castItemGuid) : NULL;
caster->ToPlayer()->AddSpellAndCategoryCooldowns(m_spellInfo, castItem ? castItem->GetEntry() : 0, NULL, true);
caster->GetSpellHistory()->StartCooldown(m_spellInfo, castItem ? castItem->GetEntry() : 0, nullptr, true);
}
}
}
@@ -455,12 +456,9 @@ void Aura::_UnapplyForTarget(Unit* target, Unit* caster, AuraApplication * auraA
m_removedApplications.push_back(auraApp);
// reset cooldown state for spells
if (caster && caster->GetTypeId() == TYPEID_PLAYER)
{
if (GetSpellInfo()->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
caster->ToPlayer()->SendCooldownEvent(GetSpellInfo());
}
if (caster && GetSpellInfo()->IsCooldownStartedOnEvent())
// note: item based cooldowns and cooldown spell mods with charges ignored (unknown existed cases)
caster->GetSpellHistory()->SendCooldownEvent(GetSpellInfo());
}
// removes aura from all targets
@@ -1244,7 +1242,7 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
break;
case 60970: // Heroic Fury (remove Intercept cooldown)
if (target->GetTypeId() == TYPEID_PLAYER)
target->ToPlayer()->RemoveSpellCooldown(20252, true);
target->GetSpellHistory()->ResetCooldown(20252, true);
break;
}
break;
@@ -1404,15 +1402,15 @@ void Aura::HandleAuraSpecificMods(AuraApplication const* aurApp, Unit* caster, b
// check cooldown
if (caster->GetTypeId() == TYPEID_PLAYER)
{
if (caster->ToPlayer()->HasSpellCooldown(aura->GetId()))
if (caster->GetSpellHistory()->HasCooldown(aura->GetId()))
{
// This additional check is needed to add a minimal delay before cooldown in in effect
// to allow all bubbles broken by a single damage source proc mana return
if (caster->ToPlayer()->GetSpellCooldownDelay(aura->GetId()) <= 11)
if (caster->GetSpellHistory()->GetRemainingCooldown(aura->GetId()) <= 11)
break;
}
else // and add if needed
caster->ToPlayer()->AddSpellCooldown(aura->GetId(), 0, uint32(time(NULL) + 12));
caster->GetSpellHistory()->AddCooldown(aura->GetId(), 0, std::chrono::seconds(12));
}
// effect on caster
+34 -55
View File
@@ -51,6 +51,7 @@
#include "SpellScript.h"
#include "InstanceScript.h"
#include "SpellInfo.h"
#include "SpellHistory.h"
#include "DB2Stores.h"
#include "Battlefield.h"
#include "BattlefieldMgr.h"
@@ -3235,7 +3236,7 @@ void Spell::cast(bool skipCheck)
//Clear spell cooldowns after every spell is cast if .cheat cooldown is enabled.
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
m_caster->GetSpellHistory()->ResetCooldown(m_spellInfo->Id, true);
}
SetExecutedCurrently(false);
@@ -3442,30 +3443,7 @@ void Spell::_handle_finish_phase()
void Spell::SendSpellCooldown()
{
Player* _player = m_caster->ToPlayer();
if (!_player)
{
// Handle pet cooldowns here if needed instead of in PetAI to avoid hidden cooldown restarts
Creature* _creature = m_caster->ToCreature();
if (_creature && (_creature->IsPet() || _creature->IsGuardian()))
_creature->AddCreatureSpellCooldown(m_spellInfo->Id);
return;
}
// mana/health/etc potions, disabled by client (until combat out as declarate)
if (m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent()))
{
// need in some way provided data for Spell::finish SendCooldownEvent
_player->SetLastPotionId(m_CastItem->GetEntry());
return;
}
// have infinity cooldown but set at aura apply // do not set cooldown for triggered spells (needed by reincarnation)
if (m_spellInfo->IsCooldownStartedOnEvent() || m_spellInfo->IsPassive() || (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD))
return;
_player->AddSpellAndCategoryCooldowns(m_spellInfo, m_CastItem ? m_CastItem->GetEntry() : 0, this);
m_caster->GetSpellHistory()->HandleCooldowns(m_spellInfo, m_CastItem, this);
}
void Spell::update(uint32 difftime)
@@ -4702,23 +4680,26 @@ SpellCastResult Spell::CheckCast(bool strict)
return SPELL_FAILED_CASTER_DEAD;
// check cooldowns to prevent cheating
if (m_caster->GetTypeId() == TYPEID_PLAYER && !m_spellInfo->HasAttribute(SPELL_ATTR0_PASSIVE))
if (!m_spellInfo->IsPassive())
{
//can cast triggered (by aura only?) spells while have this flag
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURASTATE) && m_caster->ToPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY))
return SPELL_FAILED_SPELL_IN_PROGRESS;
if (m_caster->GetTypeId() == TYPEID_PLAYER)
{
//can cast triggered (by aura only?) spells while have this flag
if (!(_triggeredCastFlags & TRIGGERED_IGNORE_CASTER_AURASTATE) && m_caster->ToPlayer()->HasFlag(PLAYER_FLAGS, PLAYER_ALLOW_ONLY_ABILITY))
return SPELL_FAILED_SPELL_IN_PROGRESS;
if (m_caster->ToPlayer()->HasSpellCooldown(m_spellInfo->Id))
// check if we are using a potion in combat for the 2nd+ time. Cooldown is added only after caster gets out of combat
if (m_caster->ToPlayer()->GetLastPotionId() && m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent()))
return SPELL_FAILED_NOT_READY;
}
if (!m_caster->GetSpellHistory()->IsReady(m_spellInfo))
{
if (m_triggeredByAuraSpell)
return SPELL_FAILED_DONT_REPORT;
else
return SPELL_FAILED_NOT_READY;
}
// check if we are using a potion in combat for the 2nd+ time. Cooldown is added only after caster gets out of combat
if (m_caster->ToPlayer()->GetLastPotionId() && m_CastItem && (m_CastItem->IsPotion() || m_spellInfo->IsCooldownStartedOnEvent()))
return SPELL_FAILED_NOT_READY;
}
if (m_spellInfo->HasAttribute(SPELL_ATTR7_IS_CHEAT_SPELL) && !m_caster->HasFlag(UNIT_FIELD_FLAGS_2, UNIT_FLAG2_ALLOW_CHEAT_SPELLS))
@@ -5570,13 +5551,13 @@ SpellCastResult Spell::CheckPetCast(Unit* target)
}
// cooldown
if (Creature const* creatureCaster = m_caster->ToCreature())
if (creatureCaster->HasSpellCooldown(m_spellInfo->Id))
if (Creature* creatureCaster = m_caster->ToCreature())
if (!creatureCaster->GetSpellHistory()->IsReady(m_spellInfo))
return SPELL_FAILED_NOT_READY;
// Check if spell is affected by GCD
if (m_spellInfo->StartRecoveryCategory > 0)
if (m_caster->GetCharmInfo() && m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo))
if (m_caster->GetCharmInfo() && m_caster->GetSpellHistory()->HasGlobalCooldown(m_spellInfo))
return SPELL_FAILED_NOT_READY;
return CheckCast(true);
@@ -5899,7 +5880,7 @@ SpellCastResult Spell::CheckItems()
if (!proto)
return SPELL_FAILED_ITEM_NOT_READY;
for (uint8 i = 0; i < MAX_ITEM_SPELLS; ++i)
for (uint8 i = 0; i < MAX_ITEM_PROTO_SPELLS; ++i)
if (proto->Spells[i].SpellCharges)
if (m_CastItem->GetSpellCharges(i) == 0)
return SPELL_FAILED_NO_CHARGES_REMAIN;
@@ -7283,13 +7264,11 @@ enum GCDLimits
bool Spell::HasGlobalCooldown() const
{
// Only player or controlled units have global cooldown
if (m_caster->GetCharmInfo())
return m_caster->GetCharmInfo()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
return m_caster->ToPlayer()->GetGlobalCooldownMgr().HasGlobalCooldown(m_spellInfo);
else
// Only players or controlled units have global cooldown
if (m_caster->GetTypeId() != TYPEID_PLAYER && !m_caster->GetCharmInfo())
return false;
return m_caster->GetSpellHistory()->HasGlobalCooldown(m_spellInfo);
}
void Spell::TriggerGlobalCooldown()
@@ -7298,6 +7277,10 @@ void Spell::TriggerGlobalCooldown()
if (!gcd)
return;
// Only players or controlled units have global cooldown
if (m_caster->GetTypeId() != TYPEID_PLAYER && !m_caster->GetCharmInfo())
return;
if (m_caster->GetTypeId() == TYPEID_PLAYER)
if (m_caster->ToPlayer()->GetCommandStatus(CHEAT_COOLDOWN))
return;
@@ -7319,11 +7302,7 @@ void Spell::TriggerGlobalCooldown()
gcd = MAX_GCD;
}
// Only players or controlled units have global cooldown
if (m_caster->GetCharmInfo())
m_caster->GetCharmInfo()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->GetGlobalCooldownMgr().AddGlobalCooldown(m_spellInfo, gcd);
m_caster->GetSpellHistory()->AddGlobalCooldown(m_spellInfo, gcd);
}
void Spell::CancelGlobalCooldown()
@@ -7336,10 +7315,10 @@ void Spell::CancelGlobalCooldown()
return;
// Only players or controlled units have global cooldown
if (m_caster->GetCharmInfo())
m_caster->GetCharmInfo()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
else if (m_caster->GetTypeId() == TYPEID_PLAYER)
m_caster->ToPlayer()->GetGlobalCooldownMgr().CancelGlobalCooldown(m_spellInfo);
if (m_caster->GetTypeId() != TYPEID_PLAYER && !m_caster->GetCharmInfo())
return;
m_caster->GetSpellHistory()->CancelGlobalCooldown(m_spellInfo);
}
namespace Trinity
@@ -7458,7 +7437,7 @@ bool WorldObjectSpellConeTargetCheck::operator()(WorldObject* target)
}
else if (_spellInfo->HasAttribute(SPELL_ATTR0_CU_CONE_LINE))
{
if (!_caster->HasInLine(target, _caster->GetObjectSize()))
if (!_caster->HasInLine(target, _caster->GetObjectSize() + target->GetObjectSize()))
return false;
}
else
@@ -7475,7 +7454,7 @@ WorldObjectSpellTrajTargetCheck::WorldObjectSpellTrajTargetCheck(float range, Po
bool WorldObjectSpellTrajTargetCheck::operator()(WorldObject* target)
{
// return all targets on missile trajectory (0 - size of a missile)
if (!_caster->HasInLine(target, 0))
if (!_caster->HasInLine(target, target->GetObjectSize()))
return false;
return WorldObjectSpellAreaTargetCheck::operator ()(target);
}
+1
View File
@@ -478,6 +478,7 @@ class Spell
void ReSetTimer() { m_timer = m_casttime > 0 ? m_casttime : 0; }
bool IsNextMeleeSwingSpell() const;
bool IsTriggered() const { return (_triggeredCastFlags & TRIGGERED_FULL_MASK) != 0; }
bool IsIgnoringCooldowns() const { return (_triggeredCastFlags & TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD) != 0; }
bool IsChannelActive() const { return m_caster->GetUInt32Value(UNIT_CHANNEL_SPELL) != 0; }
bool IsAutoActionResetSpell() const;
+7 -6
View File
@@ -48,6 +48,7 @@
#include "GridNotifiers.h"
#include "Formulas.h"
#include "ScriptMgr.h"
#include "SpellHistory.h"
#include "GameObjectAI.h"
#include "AccountMgr.h"
#include "InstanceScript.h"
@@ -632,8 +633,8 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
return;
// Reset cooldown on stealth if needed
if (unitTarget->ToPlayer()->HasSpellCooldown(1784))
unitTarget->ToPlayer()->RemoveSpellCooldown(1784);
if (unitTarget->GetSpellHistory()->HasCooldown(1784))
unitTarget->GetSpellHistory()->ResetCooldown(1784);
unitTarget->CastSpell(unitTarget, 1784, true);
return;
@@ -738,7 +739,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
// Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
&& m_spellInfo->GetCategory() == spellInfo->GetCategory())
m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
m_caster->GetSpellHistory()->ResetCooldown(spellInfo->Id);
// original caster guid only for GO cast
m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
@@ -791,7 +792,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex)
// Remove spell cooldown (not category) if spell triggering spell with cooldown and same category
if (m_caster->GetTypeId() == TYPEID_PLAYER && m_spellInfo->CategoryRecoveryTime && spellInfo->CategoryRecoveryTime
&& m_spellInfo->GetCategory() == spellInfo->GetCategory())
m_caster->ToPlayer()->RemoveSpellCooldown(spellInfo->Id);
m_caster->GetSpellHistory()->ResetCooldown(spellInfo->Id);
// original caster guid only for GO cast
m_caster->CastSpell(targets, spellInfo, &values, TRIGGERED_FULL_MASK, NULL, NULL, m_originalCasterGUID);
@@ -3166,7 +3167,7 @@ void Spell::EffectInterruptCast(SpellEffIndex effIndex)
if (m_originalCaster)
{
int32 duration = m_spellInfo->GetDuration();
unitTarget->ProhibitSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex));
unitTarget->GetSpellHistory()->LockSpellSchool(curSpellInfo->GetSchoolMask(), unitTarget->ModSpellDuration(m_spellInfo, unitTarget, duration, false, 1 << effIndex));
}
ExecuteLogEffectInterruptCast(effIndex, unitTarget, curSpellInfo->Id);
unitTarget->InterruptSpell(CurrentSpellTypes(i), false);
@@ -5600,7 +5601,7 @@ void Spell::EffectCastButtons(SpellEffIndex effIndex)
if (!spellInfo)
continue;
if (!p_caster->HasSpell(spell_id) || p_caster->HasSpellCooldown(spell_id))
if (!p_caster->HasSpell(spell_id) || p_caster->GetSpellHistory()->HasCooldown(spell_id))
continue;
if (!(spellInfo->AttributesEx9 & SPELL_ATTR9_SUMMON_PLAYER_TOTEM))
+643
View File
@@ -0,0 +1,643 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "WorldPacket.h"
#include "SpellHistory.h"
#include "Pet.h"
#include "Player.h"
#include "SpellInfo.h"
#include "Spell.h"
#include "World.h"
#include "Opcodes.h"
SpellHistory::Clock::duration const SpellHistory::InfinityCooldownDelay = std::chrono::duration_cast<SpellHistory::Clock::duration>(std::chrono::seconds(MONTH));
SpellHistory::Clock::duration const SpellHistory::InfinityCooldownDelayCheck = std::chrono::duration_cast<SpellHistory::Clock::duration>(std::chrono::seconds(MONTH / 2));
template<>
struct SpellHistory::PersistenceHelper<Player>
{
static CharacterDatabaseStatements const CooldownsDeleteStatement = CHAR_DEL_CHAR_SPELL_COOLDOWNS;
static CharacterDatabaseStatements const CooldownsInsertStatement = CHAR_INS_CHAR_SPELL_COOLDOWN;
static void SetIdentifier(PreparedStatement* stmt, uint8 index, Unit* owner) { stmt->setUInt32(index, owner->GetGUID().GetCounter()); }
static bool ReadCooldown(Field* fields, uint32* spellId, CooldownEntry* cooldownEntry)
{
*spellId = fields[0].GetUInt32();
if (!sSpellMgr->GetSpellInfo(*spellId))
return false;
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[2].GetUInt32()));
cooldownEntry->ItemId = fields[1].GetUInt32();
return true;
}
static void WriteCooldown(PreparedStatement* stmt, uint8& index, CooldownStorageType::value_type const& cooldown)
{
stmt->setUInt32(index++, cooldown.first);
stmt->setUInt32(index++, cooldown.second.ItemId);
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
}
};
template<>
struct SpellHistory::PersistenceHelper<Pet>
{
static CharacterDatabaseStatements const CooldownsDeleteStatement = CHAR_DEL_PET_SPELL_COOLDOWNS;
static CharacterDatabaseStatements const CooldownsInsertStatement = CHAR_INS_PET_SPELL_COOLDOWN;
static void SetIdentifier(PreparedStatement* stmt, uint8 index, Unit* owner) { stmt->setUInt32(index, owner->GetCharmInfo()->GetPetNumber()); }
static bool ReadCooldown(Field* fields, uint32* spellId, CooldownEntry* cooldownEntry)
{
*spellId = fields[0].GetUInt32();
if (!sSpellMgr->GetSpellInfo(*spellId))
return false;
cooldownEntry->CooldownEnd = Clock::from_time_t(time_t(fields[1].GetUInt32()));
cooldownEntry->ItemId = 0;
return true;
}
static void WriteCooldown(PreparedStatement* stmt, uint8& index, CooldownStorageType::value_type const& cooldown)
{
stmt->setUInt32(index++, cooldown.first);
stmt->setUInt32(index++, uint32(Clock::to_time_t(cooldown.second.CooldownEnd)));
}
};
template<class OwnerType>
void SpellHistory::LoadFromDB(PreparedQueryResult cooldownsResult)
{
typedef PersistenceHelper<OwnerType> StatementInfo;
if (cooldownsResult)
{
do
{
uint32 spellId;
CooldownEntry cooldown;
if (StatementInfo::ReadCooldown(cooldownsResult->Fetch(), &spellId, &cooldown))
_spellCooldowns[spellId] = cooldown;
} while (cooldownsResult->NextRow());
}
}
template<class OwnerType>
void SpellHistory::SaveToDB(SQLTransaction& trans)
{
typedef PersistenceHelper<OwnerType> StatementInfo;
uint8 index = 0;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::CooldownsDeleteStatement);
StatementInfo::SetIdentifier(stmt, index++, _owner);
trans->Append(stmt);
for (auto const& p : _spellCooldowns)
{
if (!p.second.OnHold)
{
index = 0;
stmt = CharacterDatabase.GetPreparedStatement(StatementInfo::CooldownsInsertStatement);
StatementInfo::SetIdentifier(stmt, index++, _owner);
StatementInfo::WriteCooldown(stmt, index, p);
trans->Append(stmt);
}
}
}
void SpellHistory::Update()
{
SQLTransaction t;
Clock::time_point now = Clock::now();
for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
{
if (itr->second.CooldownEnd < now)
itr = _spellCooldowns.erase(itr);
else
++itr;
}
}
void SpellHistory::HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell /*= nullptr*/)
{
if (Player* player = _owner->ToPlayer())
{
// potions start cooldown until exiting combat
if (item && (item->IsPotion() || spellInfo->IsCooldownStartedOnEvent()))
{
player->SetLastPotionId(item->GetEntry());
return;
}
}
if (spellInfo->IsCooldownStartedOnEvent() || spellInfo->IsPassive() || (spell && spell->IsIgnoringCooldowns()))
return;
StartCooldown(spellInfo, item ? item->GetEntry() : 0, spell);
}
bool SpellHistory::IsReady(SpellInfo const* spellInfo) const
{
if (spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
if (IsSchoolLocked(spellInfo->GetSchoolMask()))
return false;
if (HasCooldown(spellInfo->Id))
return false;
return true;
}
template<>
void SpellHistory::WritePacket<Pet>(WorldPacket& packet) const
{
Clock::time_point now = Clock::now();
uint8 cooldownsCount = _spellCooldowns.size();
packet << uint8(cooldownsCount);
for (auto const& spellCooldown : _spellCooldowns)
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellCooldown.first);
if (!spellInfo)
{
packet << uint32(0);
packet << uint16(0);
packet << uint32(0);
packet << uint32(0);
continue;
}
packet << uint32(spellCooldown.first); // spell ID
packet << uint16(spellInfo->GetCategory()); // spell category
if (!spellCooldown.second.OnHold)
{
uint32 cooldownDuration = spellCooldown.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now).count() : 0;
if (cooldownDuration <= 0)
{
packet << uint32(0);
packet << uint32(0);
continue;
}
if (spellInfo->GetCategory())
{
packet << uint32(0);
packet << uint32(cooldownDuration);
}
else
{
packet << uint32(cooldownDuration);
packet << uint32(0);
}
}
}
}
template<>
void SpellHistory::WritePacket<Player>(WorldPacket& packet) const
{
Clock::time_point now = Clock::now();
Clock::time_point infTime = now + InfinityCooldownDelayCheck;
uint16 cooldownsCount = _spellCooldowns.size();
size_t dataPos = packet.wpos();
packet << uint16(cooldownsCount);
for (auto const& spellCooldown : _spellCooldowns)
{
SpellInfo const* sEntry = sSpellMgr->GetSpellInfo(spellCooldown.first);
if (!sEntry)
{
--cooldownsCount;
continue;
}
packet << uint32(spellCooldown.first);
packet << uint16(spellCooldown.second.ItemId); // cast item id
packet << uint16(sEntry->GetCategory()); // spell category
// send infinity cooldown in special format
if (spellCooldown.second.CooldownEnd >= infTime)
{
packet << uint32(1); // cooldown
packet << uint32(0x80000000); // category cooldown
continue;
}
uint32 cooldownDuration = spellCooldown.second.CooldownEnd > now ? std::chrono::duration_cast<std::chrono::milliseconds>(spellCooldown.second.CooldownEnd - now).count() : 0;
if (sEntry->GetCategory()) // may be wrong, but anyway better than nothing...
{
packet << uint32(0); // cooldown
packet << uint32(cooldownDuration); // category cooldown
}
else
{
packet << uint32(cooldownDuration); // cooldown
packet << uint32(0); // category cooldown
}
}
packet.put<uint16>(dataPos, cooldownsCount);
}
void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell /*= nullptr*/, bool onHold /*= false*/)
{
// init cooldown values
uint32 categoryId = 0;
int32 cooldown = -1;
int32 categoryCooldown = -1;
// some special item spells without correct cooldown in SpellInfo
// cooldown information stored in item prototype
if (itemId)
{
if (ItemTemplate const* proto = sObjectMgr->GetItemTemplate(itemId))
{
for (uint8 idx = 0; idx < MAX_ITEM_PROTO_SPELLS; ++idx)
{
if (uint32(proto->Spells[idx].SpellId) == spellInfo->Id)
{
categoryId = proto->Spells[idx].SpellCategory;
cooldown = proto->Spells[idx].SpellCooldown;
categoryCooldown = proto->Spells[idx].SpellCategoryCooldown;
break;
}
}
}
}
// if no cooldown found above then base at DBC data
if (cooldown < 0 && categoryCooldown < 0)
{
categoryId = spellInfo->GetCategory();
cooldown = spellInfo->RecoveryTime;
categoryCooldown = spellInfo->CategoryRecoveryTime;
}
Clock::time_point curTime = Clock::now();
Clock::time_point catrecTime;
Clock::time_point recTime;
bool needsCooldownPacket = false;
// overwrite time for selected category
if (onHold)
{
// use +MONTH as infinite cooldown marker
catrecTime = categoryCooldown > 0 ? (curTime + InfinityCooldownDelay) : curTime;
recTime = cooldown > 0 ? (curTime + InfinityCooldownDelay) : catrecTime;
}
else
{
// shoot spells used equipped item cooldown values already assigned in GetAttackTime(RANGED_ATTACK)
// prevent 0 cooldowns set by another way
if (cooldown <= 0 && categoryCooldown <= 0 && (categoryId == 76 || (spellInfo->IsAutoRepeatRangedSpell() && spellInfo->Id != 75)))
cooldown = _owner->GetAttackTime(RANGED_ATTACK);
// Now we have cooldown data (if found any), time to apply mods
if (Player* modOwner = _owner->GetSpellModOwner())
{
if (cooldown > 0)
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, cooldown, spell);
if (categoryCooldown > 0 && !spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_CATEGORY_COOLDOWN_MODS))
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_COOLDOWN, categoryCooldown, spell);
}
if (int32 cooldownMod = _owner->GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
{
// Apply SPELL_AURA_MOD_COOLDOWN only to own spells
Player* playerOwner = GetPlayerOwner();
if (!playerOwner || playerOwner->HasSpell(spellInfo->Id))
{
needsCooldownPacket = true;
cooldown += cooldownMod * IN_MILLISECONDS; // SPELL_AURA_MOD_COOLDOWN does not affect category cooldows, verified with shaman shocks
}
}
// replace negative cooldowns by 0
if (cooldown < 0)
cooldown = 0;
if (categoryCooldown < 0)
categoryCooldown = 0;
// no cooldown after applying spell mods
if (cooldown == 0 && categoryCooldown == 0)
return;
catrecTime = categoryCooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(categoryCooldown)) : curTime;
recTime = cooldown ? curTime + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldown)) : catrecTime;
}
// self spell cooldown
if (recTime != curTime)
{
AddCooldown(spellInfo->Id, itemId, recTime, onHold);
if (needsCooldownPacket)
{
if (Player* playerOwner = GetPlayerOwner())
{
WorldPacket spellCooldown;
BuildCooldownPacket(spellCooldown, SPELL_COOLDOWN_FLAG_NONE, spellInfo->Id, cooldown);
playerOwner->SendDirectMessage(&spellCooldown);
}
}
}
// category spells
if (categoryId && catrecTime != curTime)
{
SpellCategoryStore::const_iterator i_scstore = sSpellsByCategoryStore.find(categoryId);
if (i_scstore != sSpellsByCategoryStore.end())
{
for (SpellCategorySet::const_iterator i_scset = i_scstore->second.begin(); i_scset != i_scstore->second.end(); ++i_scset)
{
if (*i_scset == spellInfo->Id) // skip main spell, already handled above
continue;
AddCooldown(*i_scset, itemId, catrecTime, onHold);
}
}
}
}
void SpellHistory::SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId /*= 0*/, Spell* spell /*= nullptr*/, bool startCooldown /*= true*/)
{
// start cooldowns at server side, if any
if (startCooldown)
StartCooldown(spellInfo, itemId, spell);
if (Player* player = GetPlayerOwner())
{
// Send activate cooldown timer (possible 0) at client side
WorldPacket data(SMSG_COOLDOWN_EVENT, 4 + 8);
data << uint32(spellInfo->Id);
data << uint64(_owner->GetGUID());
player->SendDirectMessage(&data);
uint32 category = spellInfo->GetCategory();
if (category && spellInfo->CategoryRecoveryTime)
{
SpellCategoryStore::const_iterator ct = sSpellsByCategoryStore.find(category);
if (ct != sSpellsByCategoryStore.end())
{
for (auto const& cooldownPair : _spellCooldowns)
{
uint32 categorySpell = cooldownPair.first;
if (!ct->second.count(categorySpell))
continue;
if (categorySpell == spellInfo->Id) // skip main spell, already handled above
continue;
SpellInfo const* spellInfo2 = sSpellMgr->EnsureSpellInfo(categorySpell);
if (!spellInfo2->IsCooldownStartedOnEvent())
continue;
data.Initialize(SMSG_COOLDOWN_EVENT, 4 + 8);
data << uint32(categorySpell);
data << uint64(_owner->GetGUID());
player->SendDirectMessage(&data);
}
}
}
}
}
void SpellHistory::AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold /*= false*/)
{
CooldownEntry& cooldownEntry = _spellCooldowns[spellId];
cooldownEntry.CooldownEnd = cooldownEnd;
cooldownEntry.ItemId = itemId;
cooldownEntry.OnHold = onHold;
}
void SpellHistory::ModifyCooldown(uint32 spellId, int32 cooldownModMs)
{
auto itr = _spellCooldowns.find(spellId);
if (!cooldownModMs || itr == _spellCooldowns.end())
return;
Clock::time_point now = Clock::now();
Clock::duration offset = std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(cooldownModMs));
if (itr->second.CooldownEnd + offset > now)
itr->second.CooldownEnd += offset;
else
_spellCooldowns.erase(itr);
if (Player* playerOwner = GetPlayerOwner())
{
WorldPacket modifyCooldown(SMSG_MODIFY_COOLDOWN, 4 + 8 + 4);
modifyCooldown << uint32(spellId);
modifyCooldown << uint64(_owner->GetGUID());
modifyCooldown << int32(cooldownModMs);
playerOwner->SendDirectMessage(&modifyCooldown);
}
}
void SpellHistory::ResetCooldown(uint32 spellId, bool update /*= false*/)
{
auto itr = _spellCooldowns.find(spellId);
if (itr == _spellCooldowns.end())
return;
ResetCooldown(itr, update);
}
void SpellHistory::ResetCooldown(CooldownStorageType::iterator& itr, bool update /*= false*/)
{
if (update)
{
if (Player* playerOwner = GetPlayerOwner())
{
WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8);
data << uint32(itr->first);
data << uint64(_owner->GetGUID());
playerOwner->SendDirectMessage(&data);
}
}
itr = _spellCooldowns.erase(itr);
}
void SpellHistory::ResetAllCooldowns()
{
if (GetPlayerOwner())
{
std::vector<int32> cooldowns;
cooldowns.reserve(_spellCooldowns.size());
for (auto const& p : _spellCooldowns)
cooldowns.push_back(p.first);
SendClearCooldowns(cooldowns);
}
_spellCooldowns.clear();
}
bool SpellHistory::HasCooldown(uint32 spellId) const
{
return _spellCooldowns.count(spellId) != 0;
}
uint32 SpellHistory::GetRemainingCooldown(uint32 spellId) const
{
auto itr = _spellCooldowns.find(spellId);
if (itr == _spellCooldowns.end())
return 0;
Clock::time_point now = Clock::now();
if (itr->second.CooldownEnd < now)
return 0;
Clock::duration remaining = itr->second.CooldownEnd - now;
return uint32(std::chrono::duration_cast<std::chrono::milliseconds>(remaining).count());
}
void SpellHistory::LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime)
{
Clock::time_point lockoutEnd = Clock::now() + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(lockoutTime));
for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (SpellSchoolMask(1 << i) & schoolMask)
_schoolLockouts[i] = lockoutEnd;
std::set<uint32> knownSpells;
if (Player* plrOwner = _owner->ToPlayer())
{
for (auto const& p : plrOwner->GetSpellMap())
if (p.second->state != PLAYERSPELL_REMOVED)
knownSpells.insert(p.first);
}
else if (Pet* petOwner = _owner->ToPet())
{
for (auto const& p : petOwner->m_spells)
if (p.second.state != PETSPELL_REMOVED)
knownSpells.insert(p.first);
}
else
{
Creature* creatureOwner = _owner->ToCreature();
for (uint8 i = 0; i < CREATURE_MAX_SPELLS; ++i)
if (creatureOwner->m_spells[i])
knownSpells.insert(creatureOwner->m_spells[i]);
}
PacketCooldowns cooldowns;
WorldPacket spellCooldowns;
for (uint32 spellId : knownSpells)
{
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(spellId);
if (spellInfo->IsCooldownStartedOnEvent())
continue;
if (spellInfo->PreventionType != SPELL_PREVENTION_TYPE_SILENCE)
continue;
if ((schoolMask & spellInfo->GetSchoolMask()) && GetRemainingCooldown(spellId) < lockoutTime)
{
cooldowns[spellId] = lockoutTime;
AddCooldown(spellId, 0, lockoutEnd);
}
}
if (Player* player = GetPlayerOwner())
{
if (!cooldowns.empty())
{
BuildCooldownPacket(spellCooldowns, SPELL_COOLDOWN_FLAG_NONE, cooldowns);
player->SendDirectMessage(&spellCooldowns);
}
}
}
bool SpellHistory::IsSchoolLocked(SpellSchoolMask schoolMask) const
{
Clock::time_point now = Clock::now();
for (uint32 i = 0; i < MAX_SPELL_SCHOOL; ++i)
if (SpellSchoolMask(1 << i) & schoolMask)
if (_schoolLockouts[i] > now)
return true;
return false;
}
bool SpellHistory::HasGlobalCooldown(SpellInfo const* spellInfo) const
{
auto itr = _globalCooldowns.find(spellInfo->StartRecoveryCategory);
return itr != _globalCooldowns.end() && itr->second > Clock::now();
}
void SpellHistory::AddGlobalCooldown(SpellInfo const* spellInfo, uint32 duration)
{
_globalCooldowns[spellInfo->StartRecoveryCategory] = Clock::now() + std::chrono::duration_cast<Clock::duration>(std::chrono::milliseconds(duration));
}
void SpellHistory::CancelGlobalCooldown(SpellInfo const* spellInfo)
{
_globalCooldowns[spellInfo->StartRecoveryCategory] = Clock::time_point(Clock::duration(0));
}
Player* SpellHistory::GetPlayerOwner() const
{
return _owner->GetCharmerOrOwnerPlayerOrPlayerItself();
}
void SpellHistory::SendClearCooldowns(std::vector<int32> const& cooldowns) const
{
if (Player* playerOwner = GetPlayerOwner())
{
for (int32 spell : cooldowns)
{
WorldPacket data(SMSG_CLEAR_COOLDOWN, 4 + 8);
data << uint32(spell);
data << uint64(_owner->GetGUID());
playerOwner->SendDirectMessage(&data);
}
}
}
void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown) const
{
data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + 4 + 4);
data << uint64(_owner->GetGUID());
data << uint8(flags);
data << uint32(spellId);
data << uint32(cooldown);
}
void SpellHistory::BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const
{
data.Initialize(SMSG_SPELL_COOLDOWN, 8 + 1 + (4 + 4) * cooldowns.size());
data << uint64(_owner->GetGUID());
data << uint8(flags);
for (auto const& cooldown : cooldowns)
{
data << cooldown.first;
data << cooldown.second;
}
}
template void SpellHistory::LoadFromDB<Player>(PreparedQueryResult cooldownsResult);
template void SpellHistory::LoadFromDB<Pet>(PreparedQueryResult cooldownsResult);
template void SpellHistory::SaveToDB<Player>(SQLTransaction& trans);
template void SpellHistory::SaveToDB<Pet>(SQLTransaction& trans);
+137
View File
@@ -0,0 +1,137 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#ifndef SpellHistory_h__
#define SpellHistory_h__
#include "SharedDefines.h"
#include "QueryResult.h"
#include "Transaction.h"
#include <chrono>
#include <deque>
class Item;
class Player;
class Spell;
class SpellInfo;
class Unit;
struct SpellCategoryEntry;
class SpellHistory
{
public:
typedef std::chrono::system_clock Clock;
struct CooldownEntry
{
CooldownEntry() : ItemId(0), OnHold(false) { }
CooldownEntry(Clock::time_point endTime, uint32 itemId) : CooldownEnd(endTime), ItemId(itemId), OnHold(false) { }
Clock::time_point CooldownEnd;
uint32 ItemId;
bool OnHold;
};
typedef std::unordered_map<uint32 /*spellId*/, CooldownEntry> CooldownStorageType;
typedef std::unordered_map<uint32 /*categoryId*/, Clock::time_point> GlobalCooldownStorageType;
explicit SpellHistory(Unit* owner) : _owner(owner), _schoolLockouts() { }
template<class OwnerType>
void LoadFromDB(PreparedQueryResult cooldownsResult);
template<class OwnerType>
void SaveToDB(SQLTransaction& trans);
void Update();
void HandleCooldowns(SpellInfo const* spellInfo, Item const* item, Spell* spell = nullptr);
bool IsReady(SpellInfo const* spellInfo) const;
template<class OwnerType>
void WritePacket(WorldPacket& packet) const;
// Cooldowns
static Clock::duration const InfinityCooldownDelay; // used for set "infinity cooldowns" for spells and check
static Clock::duration const InfinityCooldownDelayCheck;
void StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spell* spell = nullptr, bool onHold = false);
void SendCooldownEvent(SpellInfo const* spellInfo, uint32 itemId = 0, Spell* spell = nullptr, bool startCooldown = true);
template<class Type, class Period>
void AddCooldown(uint32 spellId, uint32 itemId, std::chrono::duration<Type, Period> cooldownDuration)
{
AddCooldown(spellId, itemId, Clock::now() + std::chrono::duration_cast<Clock::duration>(cooldownDuration));
}
void AddCooldown(uint32 spellId, uint32 itemId, Clock::time_point cooldownEnd, bool onHold = false);
void ModifyCooldown(uint32 spellId, int32 cooldownModMs);
void ResetCooldown(uint32 spellId, bool update = false);
void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
template<typename Predicate>
void ResetCooldowns(Predicate predicate, bool update = false)
{
std::vector<int32> resetCooldowns;
resetCooldowns.reserve(_spellCooldowns.size());
for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end();)
{
if (predicate(itr))
{
resetCooldowns.push_back(itr->first);
ResetCooldown(itr, false);
}
else
++itr;
}
if (update && !resetCooldowns.empty())
SendClearCooldowns(resetCooldowns);
}
void ResetAllCooldowns();
bool HasCooldown(uint32 spellId) const;
uint32 GetRemainingCooldown(uint32 spellId) const;
// School lockouts
void LockSpellSchool(SpellSchoolMask schoolMask, uint32 lockoutTime);
bool IsSchoolLocked(SpellSchoolMask schoolMask) const;
// Global cooldown
bool HasGlobalCooldown(SpellInfo const* spellInfo) const;
void AddGlobalCooldown(SpellInfo const* spellInfo, uint32 duration);
void CancelGlobalCooldown(SpellInfo const* spellInfo);
void BuildCooldownPacket(WorldPacket& data, uint8 flags, uint32 spellId, uint32 cooldown) const;
CooldownStorageType::size_type GetCooldownsSizeForPacket() const { return _spellCooldowns.size(); }
private:
Player* GetPlayerOwner() const;
void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
typedef std::unordered_map<uint32, uint32> PacketCooldowns;
void BuildCooldownPacket(WorldPacket& data, uint8 flags, PacketCooldowns const& cooldowns) const;
Unit* _owner;
CooldownStorageType _spellCooldowns;
Clock::time_point _schoolLockouts[MAX_SPELL_SCHOOL];
GlobalCooldownStorageType _globalCooldowns;
template<class T>
struct PersistenceHelper { };
};
#endif // SpellHistory_h__
+1 -1
View File
@@ -1790,7 +1790,7 @@ SpellCastResult SpellInfo::CheckTarget(Unit const* caster, WorldObject const* ta
}
// not allow casting on flying player
if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT))
if (unitTarget->HasUnitState(UNIT_STATE_IN_FLIGHT) && !(AttributesCu & SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET))
return SPELL_FAILED_BAD_TARGETS;
/* TARGET_UNIT_MASTER gets blocked here for passengers, because the whole idea of this check is to
+1
View File
@@ -189,6 +189,7 @@ enum SpellCustomAttributes
SPELL_ATTR0_CU_IGNORE_ARMOR = 0x00008000,
SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER = 0x00010000,
SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET = 0x00020000,
SPELL_ATTR0_CU_ALLOW_INFLIGHT_TARGET = 0x00040000,
SPELL_ATTR0_CU_NEGATIVE = SPELL_ATTR0_CU_NEGATIVE_EFF0 | SPELL_ATTR0_CU_NEGATIVE_EFF1 | SPELL_ATTR0_CU_NEGATIVE_EFF2
};
+5
View File
@@ -3033,6 +3033,10 @@ void SpellMgr::LoadSpellInfoCorrections()
switch (spellInfo->Id)
{
case 63026: // Force Cast (HACK: Target shouldn't be changed)
case 63137: // Force Cast (HACK: Target shouldn't be changed; summon position should be untied from spell destination)
spellInfo->Effects[0].TargetA = SpellImplicitTargetInfo(TARGET_DEST_DB);
break;
case 70743: // AoD Special
case 70614: // AoD Special - Vegard
case 42436: // Drink! (Brewfest)
@@ -3187,6 +3191,7 @@ void SpellMgr::LoadSpellInfoCorrections()
case 57761: // Fireball!
case 64823: // Item - Druid T8 Balance 4P Bonus
case 88819: // Daybreak
case 18820: // Insight
spellInfo->ProcCharges = 1;
break;
case 44544: // Fingers of Frost
-8
View File
@@ -57,11 +57,7 @@ enum WardenCheckType
MODULE_CHECK = 0xD9 // 217: uint Seed + byte[20] SHA1 (check to ensure module isn't injected)
};
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct WardenModuleUse
{
@@ -84,11 +80,7 @@ struct WardenHashRequest
uint8 Seed[16];
};
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
struct ClientWardenModule
{
-8
View File
@@ -25,11 +25,7 @@
#include "ByteBuffer.h"
#include "Warden.h"
#if defined(__GNUC__)
#pragma pack(1)
#else
#pragma pack(push, 1)
#endif
struct WardenInitModuleRequest
{
@@ -61,11 +57,7 @@ struct WardenInitModuleRequest
uint8 Function3_set;
};
#if defined(__GNUC__)
#pragma pack()
#else
#pragma pack(pop)
#endif
class WorldSession;
class Warden;
+3
View File
@@ -1571,6 +1571,9 @@ void World::SetInitialWorldSettings()
TC_LOG_INFO("server.loading", "Loading Gameobject Data...");
sObjectMgr->LoadGameobjects();
TC_LOG_INFO("server.loading", "Loading GameObject Addon Data...");
sObjectMgr->LoadGameObjectAddons(); // must be after LoadGameObjectTemplate() and LoadGameobjects()
TC_LOG_INFO("server.loading", "Loading Creature Linked Respawn...");
sObjectMgr->LoadLinkedRespawn(); // must be after LoadCreatures(), LoadGameObjects()
+7 -5
View File
@@ -35,6 +35,7 @@
#include "GroupMgr.h"
#include "MMapFactory.h"
#include "DisableMgr.h"
#include "SpellHistory.h"
class misc_commandscript : public CommandScript
{
@@ -723,7 +724,7 @@ public:
if (!*args)
{
target->RemoveAllSpellCooldown();
target->GetSpellHistory()->ResetAllCooldowns();
handler->PSendSysMessage(LANG_REMOVEALL_COOLDOWN, nameLink.c_str());
}
else
@@ -733,14 +734,15 @@ public:
if (!spellIid)
return false;
if (!sSpellMgr->GetSpellInfo(spellIid))
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellIid);
if (!spellInfo)
{
handler->PSendSysMessage(LANG_UNKNOWN_SPELL, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str());
handler->SetSentErrorMessage(true);
return false;
}
target->RemoveSpellCooldown(spellIid, true);
target->GetSpellHistory()->ResetCooldown(spellIid, true);
handler->PSendSysMessage(LANG_REMOVE_COOLDOWN, spellIid, target == handler->GetSession()->GetPlayer() ? handler->GetTrinityString(LANG_YOU) : nameLink.c_str());
}
return true;
@@ -1453,7 +1455,7 @@ public:
* Player %s %s (guid: %u) - I. LANG_PINFO_PLAYER
* ** GM Mode active, Phase: -1 - II. LANG_PINFO_GM_ACTIVE (if GM)
* ** Banned: (Type, Reason, Time, By) - III. LANG_PINFO_BANNED (if banned)
* ** Muted: (Time, Reason, By) - IV. LANG_PINFO_MUTED (if muted)
* ** Muted: (Reason, Time, By) - IV. LANG_PINFO_MUTED (if muted)
* * Account: %s (id: %u), GM Level: %u - V. LANG_PINFO_ACC_ACCOUNT
* * Last Login: %u (Failed Logins: %u) - VI. LANG_PINFO_ACC_LASTLOGIN
* * Uses OS: %s - Latency: %u ms - VII. LANG_PINFO_ACC_OS
@@ -1706,7 +1708,7 @@ public:
// Output IV. LANG_PINFO_MUTED if mute is applied
if (muteTime > 0)
handler->PSendSysMessage(LANG_PINFO_MUTED, secsToTimeString(muteTime - time(NULL), true).c_str(), muteReason.c_str(), muteBy.c_str());
handler->PSendSysMessage(LANG_PINFO_MUTED, muteReason.c_str(), secsToTimeString(muteTime - time(nullptr), true).c_str(), muteBy.c_str());
// Output V. LANG_PINFO_ACC_ACCOUNT
handler->PSendSysMessage(LANG_PINFO_ACC_ACCOUNT, userName.c_str(), accId, security);
+11 -33
View File
@@ -137,7 +137,7 @@ public:
return false;
}
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -165,17 +165,6 @@ public:
if (!*args)
return false;
// char* pmana = strtok((char*)args, " ");
// if (!pmana)
// return false;
// char* pmanaMax = strtok(NULL, " ");
// if (!pmanaMax)
// return false;
// int32 manam = atoi(pmanaMax);
// int32 mana = atoi(pmana);
int32 energy = atoi((char*)args)*10;
int32 energym = atoi((char*)args)*10;
@@ -186,7 +175,7 @@ public:
return false;
}
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -216,17 +205,6 @@ public:
if (!*args)
return false;
// char* pmana = strtok((char*)args, " ");
// if (!pmana)
// return false;
// char* pmanaMax = strtok(NULL, " ");
// if (!pmanaMax)
// return false;
// int32 manam = atoi(pmanaMax);
// int32 mana = atoi(pmana);
int32 rage = atoi((char*)args)*10;
int32 ragem = atoi((char*)args)*10;
@@ -237,7 +215,7 @@ public:
return false;
}
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -275,7 +253,7 @@ public:
return false;
}
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -391,7 +369,7 @@ public:
else
mark = atoi(pmark);
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (target == NULL)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -946,7 +924,7 @@ public:
return false;
}
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -987,7 +965,7 @@ public:
if (!*args)
return false;
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_NO_CHAR_SELECTED);
@@ -1112,7 +1090,7 @@ public:
if (!*args)
return false;
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
@@ -1142,7 +1120,7 @@ public:
if (drunklevel > 100)
drunklevel = 100;
if (Player* target = handler->getSelectedPlayer())
if (Player* target = handler->getSelectedPlayerOrSelf())
target->SetDrunkValue(drunklevel);
return true;
@@ -1153,7 +1131,7 @@ public:
if (!*args)
return false;
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
handler->SendSysMessage(LANG_PLAYER_NOT_FOUND);
@@ -1306,7 +1284,7 @@ public:
if (!*args)
return false;
Player* target = handler->getSelectedPlayer();
Player* target = handler->getSelectedPlayerOrSelf();
if (!target)
{
+17 -56
View File
@@ -378,28 +378,13 @@ public:
uint32 lowGuid = atoi((char*)guidStr);
Creature* creature = NULL;
/* FIXME: impossible without entry
if (lowguid)
creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
*/
// attempt check creature existence by DB data
if (!creature)
CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
if (!data)
{
CreatureData const* data = sObjectMgr->GetCreatureData(lowGuid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
{
// obtain real GUID for DB operations
lowGuid = creature->GetDBTableGUIDLow();
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowGuid);
handler->SetSentErrorMessage(true);
return false;
}
int wait = waitStr ? atoi(waitStr) : 0;
@@ -415,18 +400,6 @@ public:
WorldDatabase.Execute(stmt);
if (creature && creature->GetWaypointPath())
{
creature->SetDefaultMovementType(WAYPOINT_MOTION_TYPE);
creature->GetMotionMaster()->Initialize();
if (creature->IsAlive()) // dead creature will reset movement generator at respawn
{
creature->setDeathState(JUST_DIED);
creature->Respawn(true);
}
creature->SaveToDB();
}
handler->SendSysMessage(LANG_WAYPOINT_ADDED);
return true;
@@ -840,34 +813,22 @@ public:
lowguid = atoi(cId);
/* FIXME: impossible without entry
if (lowguid)
creature = ObjectAccessor::GetCreature(*handler->GetSession()->GetPlayer(), MAKE_GUID(lowguid, HIGHGUID_UNIT));
*/
// Attempting creature load from DB data
if (!creature)
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
CreatureData const* data = sObjectMgr->GetCreatureData(lowguid);
if (!data)
{
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
uint32 map_id = data->mapid;
if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
{
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
handler->PSendSysMessage(LANG_COMMAND_CREATGUIDNOTFOUND, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
else
uint32 map_id = data->mapid;
if (handler->GetSession()->GetPlayer()->GetMapId() != map_id)
{
lowguid = creature->GetDBTableGUIDLow();
handler->PSendSysMessage(LANG_COMMAND_CREATUREATSAMEMAP, lowguid);
handler->SetSentErrorMessage(true);
return false;
}
}
else
@@ -102,7 +102,7 @@ public:
}
}
virtual void Update(uint32 /*diff*/) // correct order goes form 1-6
virtual void Update(uint32 /*diff*/) override // correct order goes form 1-6
{
switch (State)
{
@@ -202,7 +202,7 @@ class boss_archaedas : public CreatureScript
DoMeleeAttackIfReady();
}
void JustDied (Unit* /*killer*/)
void JustDied (Unit* /*killer*/) override
{
instance->SetData(DATA_ANCIENT_DOOR, DONE); // open the vault door
instance->SetData(DATA_MINIONS, SPECIAL); // deactivate his minions
@@ -26,6 +26,8 @@
#include "Cell.h"
#include "CellImpl.h"
me->SetDisplayId(me->GetCreatureTemplate()->Modelid1);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NOT_SELECTABLE);
/*####
# npc_omen
####*/
@@ -377,12 +377,12 @@ public:
void DoSummonPriestess()
{
// Summon 2 Elune priestess and make each of them move to a different spot
if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[0].m_positionX, wingThicketLocations[0].m_positionY, wingThicketLocations[0].m_positionZ, wingThicketLocations[0].m_orientation, TEMPSUMMON_CORPSE_DESPAWN, 0))
if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[0].m_positionX, wingThicketLocations[0].m_positionY, wingThicketLocations[0].m_positionZ, wingThicketLocations[0].GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0))
{
priestess->GetMotionMaster()->MovePoint(0, wingThicketLocations[3].m_positionX, wingThicketLocations[3].m_positionY, wingThicketLocations[3].m_positionZ);
_firstPriestessGUID = priestess->GetGUID();
}
if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[1].m_positionX, wingThicketLocations[1].m_positionY, wingThicketLocations[1].m_positionZ, wingThicketLocations[1].m_orientation, TEMPSUMMON_CORPSE_DESPAWN, 0))
if (Creature* priestess = me->SummonCreature(NPC_PRIESTESS_ELUNE, wingThicketLocations[1].m_positionX, wingThicketLocations[1].m_positionY, wingThicketLocations[1].m_positionZ, wingThicketLocations[1].GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0))
{
// Left priestess should have a distinct move point because she is the one who starts the dialogue at point reach
priestess->GetMotionMaster()->MovePoint(1, wingThicketLocations[4].m_positionX, wingThicketLocations[4].m_positionY, wingThicketLocations[4].m_positionZ);
@@ -480,7 +480,7 @@ public:
break;
case SAY_PRIESTESS_ALTAR_13:
// summon the Guardian of Elune
if (Creature* guard = me->SummonCreature(NPC_GUARDIAN_ELUNE, wingThicketLocations[2].m_positionX, wingThicketLocations[2].m_positionY, wingThicketLocations[2].m_positionZ, wingThicketLocations[2].m_orientation, TEMPSUMMON_CORPSE_DESPAWN, 0))
if (Creature* guard = me->SummonCreature(NPC_GUARDIAN_ELUNE, wingThicketLocations[2].m_positionX, wingThicketLocations[2].m_positionY, wingThicketLocations[2].m_positionZ, wingThicketLocations[2].GetOrientation(), TEMPSUMMON_CORPSE_DESPAWN, 0))
{
guard->GetMotionMaster()->MovePoint(0, wingThicketLocations[5].m_positionX, wingThicketLocations[5].m_positionY, wingThicketLocations[5].m_positionZ);
_guardEluneGUID = guard->GetGUID();
@@ -741,7 +741,7 @@ class boss_dreadscale : public CreatureScript
switch (pointId)
{
case 0:
instance->DoUseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
instance->DoCloseDoorOrButton(instance->GetGuidData(GO_MAIN_GATE_DOOR));
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_NON_ATTACKABLE | UNIT_FLAG_NOT_SELECTABLE);
me->SetReactState(REACT_AGGRESSIVE);
me->SetInCombatWithZone();
@@ -196,7 +196,7 @@ class instance_halls_of_reflection : public InstanceMapScript
}
}
uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
if (!_teamInInstance)
{
@@ -24,6 +24,7 @@
#include "PassiveAI.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellHistory.h"
#include "SpellAuraEffects.h"
#include "SpellScript.h"
#include "Transport.h"
@@ -644,10 +645,10 @@ protected:
{
if (Instance->GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) == IN_PROGRESS &&
!me->HasUnitState(UNIT_STATE_CASTING) && !me->HasReactState(REACT_PASSIVE) &&
!me->HasSpellCooldown(BurningPitchId))
!me->GetSpellHistory()->HasCooldown(BurningPitchId))
{
DoCastAOE(BurningPitchId, true);
me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + urand(3000, 4000) / IN_MILLISECONDS);
me->GetSpellHistory()->AddCooldown(BurningPitchId, 0, std::chrono::milliseconds(urand(3000, 4000)));
}
}
@@ -1469,7 +1470,7 @@ struct npc_gunship_boarding_addAI : public gunship_npc_AI
DoCast(me, SPELL_BATTLE_EXPERIENCE, true);
DoCast(me, SPELL_TELEPORT_TO_ENEMY_SHIP, true);
DoCast(me, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_MELEE_TARGETING_ON_ORGRIMS_HAMMER : SPELL_MELEE_TARGETING_ON_SKYBREAKER, true);
me->_AddCreatureSpellCooldown(BurningPitchId, time(NULL) + 3);
me->GetSpellHistory()->AddCooldown(BurningPitchId, 0, std::chrono::seconds(3));
std::list<Player*> players;
Trinity::UnitAuraCheck check(true, Instance->GetData(DATA_TEAM_IN_INSTANCE) == HORDE ? SPELL_ON_ORGRIMS_HAMMER_DECK : SPELL_ON_SKYBREAKER_DECK);
@@ -1698,11 +1699,11 @@ class npc_gunship_rocketeer : public CreatureScript
return;
uint32 spellId = me->GetEntry() == NPC_SKYBREAKER_MORTAR_SOLDIER ? SPELL_ROCKET_ARTILLERY_A : SPELL_ROCKET_ARTILLERY_H;
if (me->HasSpellCooldown(spellId))
if (me->GetSpellHistory()->HasCooldown(spellId))
return;
DoCastAOE(spellId, true);
me->_AddCreatureSpellCooldown(spellId, time(NULL) + 9);
me->GetSpellHistory()->AddCooldown(spellId, 0, std::chrono::seconds(9));
}
};
@@ -1060,8 +1060,8 @@ class spell_putricide_ooze_eruption_searcher : public SpellScriptLoader
uint32 adhesiveId = sSpellMgr->GetSpellIdForDifficulty(SPELL_VOLATILE_OOZE_ADHESIVE, GetCaster());
if (GetHitUnit()->HasAura(adhesiveId))
{
GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
GetHitUnit()->RemoveAurasDueToSpell(adhesiveId, GetCaster()->GetGUID(), 0, AURA_REMOVE_BY_ENEMY_SPELL);
GetCaster()->CastSpell(GetHitUnit(), SPELL_OOZE_ERUPTION, true);
}
}
@@ -348,7 +348,7 @@ class boss_sindragosa : public CreatureScript
events.ScheduleEvent(EVENT_AIR_MOVEMENT, 1);
break;
case POINT_AIR_PHASE:
me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL);
me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, RAID_MODE<int32>(2, 5, 2, 6), NULL, TRIGGERED_FULL_MASK);
me->SetFacingTo(float(M_PI));
events.ScheduleEvent(EVENT_AIR_MOVEMENT_FAR, 1);
events.ScheduleEvent(EVENT_FROST_BOMB, 9000);
@@ -491,7 +491,7 @@ class boss_sindragosa : public CreatureScript
if (Unit* target = SelectTarget(SELECT_TARGET_RANDOM, 1, FrostBeaconSelector(me)))
{
Talk(EMOTE_WARN_FROZEN_ORB, target);
DoCast(target, SPELL_ICE_TOMB_DUMMY, true);
me->CastCustomSpell(SPELL_ICE_TOMB_TARGET, SPELLVALUE_MAX_TARGETS, 1, nullptr, TRIGGERED_FULL_MASK);
}
events.ScheduleEvent(EVENT_ICE_TOMB, urand(16000, 23000));
break;
@@ -1631,7 +1631,7 @@ void AddSC_boss_sindragosa()
new spell_rimefang_icy_blast();
new spell_frostwarden_handler_order_whelp();
new spell_frostwarden_handler_focus_fire();
new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY);
new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb", SPELL_ICE_TOMB_DUMMY, TRIGGERED_IGNORE_SET_FACING);
new spell_trigger_spell_from_caster("spell_sindragosa_ice_tomb_dummy", SPELL_FROST_BEACON);
new at_sindragosa_lair();
new achievement_all_you_can_eat();
@@ -524,14 +524,16 @@ enum AreaIds
class spell_trigger_spell_from_caster : public SpellScriptLoader
{
public:
spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId) : SpellScriptLoader(scriptName), _triggerId(triggerId) { }
spell_trigger_spell_from_caster(char const* scriptName, uint32 triggerId, TriggerCastFlags triggerFlags = TRIGGERED_FULL_MASK)
: SpellScriptLoader(scriptName), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
class spell_trigger_spell_from_caster_SpellScript : public SpellScript
{
PrepareSpellScript(spell_trigger_spell_from_caster_SpellScript);
public:
spell_trigger_spell_from_caster_SpellScript(uint32 triggerId) : SpellScript(), _triggerId(triggerId) { }
spell_trigger_spell_from_caster_SpellScript(uint32 triggerId, TriggerCastFlags triggerFlags)
: SpellScript(), _triggerId(triggerId), _triggerFlags(triggerFlags) { }
bool Validate(SpellInfo const* /*spell*/) override
{
@@ -542,7 +544,7 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
void HandleTrigger()
{
GetCaster()->CastSpell(GetHitUnit(), _triggerId, true);
GetCaster()->CastSpell(GetHitUnit(), _triggerId, _triggerFlags);
}
void Register() override
@@ -551,15 +553,17 @@ class spell_trigger_spell_from_caster : public SpellScriptLoader
}
uint32 _triggerId;
TriggerCastFlags _triggerFlags;
};
SpellScript* GetSpellScript() const override
{
return new spell_trigger_spell_from_caster_SpellScript(_triggerId);
return new spell_trigger_spell_from_caster_SpellScript(_triggerId, _triggerFlags);
}
private:
uint32 _triggerId;
TriggerCastFlags _triggerFlags;
};
template<class AI>
@@ -317,7 +317,7 @@ class instance_icecrown_citadel : public InstanceMapScript
}
// Weekly quest spawn prevention
uint32 GetCreatureEntry(uint32 /*guidLow*/, CreatureData const* data) override
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{
uint32 entry = data->id;
switch (entry)
@@ -372,7 +372,7 @@ class instance_icecrown_citadel : public InstanceMapScript
return entry;
}
uint32 GetGameObjectEntry(uint32 /*guidLow*/, uint32 entry) override
uint32 GetGameObjectEntry(ObjectGuid::LowType /*guidLow*/, uint32 entry) override
{
switch (entry)
{
@@ -482,40 +482,47 @@ class boss_flame_leviathan : public CreatureScript
if (action && action <= 4) // Tower destruction, debuff leviathan loot and reduce active tower count
{
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3 | LOOT_MODE_HARD_MODE_4) && ActiveTowersCount == 4)
{
me->RemoveLootMode(LOOT_MODE_HARD_MODE_4);
--ActiveTowersCount;
}
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2 | LOOT_MODE_HARD_MODE_3) && ActiveTowersCount == 3)
{
me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
--ActiveTowersCount;
}
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1 | LOOT_MODE_HARD_MODE_2) && ActiveTowersCount == 2)
{
me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
--ActiveTowersCount;
}
if (me->HasLootMode(LOOT_MODE_DEFAULT | LOOT_MODE_HARD_MODE_1) && ActiveTowersCount == 1)
{
me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
--ActiveTowersCount;
}
}
switch (action)
{
case ACTION_TOWER_OF_STORM_DESTROYED:
towerOfStorms = false;
if (towerOfStorms)
{
towerOfStorms = false;
--ActiveTowersCount;
}
break;
case ACTION_TOWER_OF_FROST_DESTROYED:
towerOfFrost = false;
if (towerOfFrost)
{
towerOfFrost = false;
--ActiveTowersCount;
}
break;
case ACTION_TOWER_OF_FLAMES_DESTROYED:
towerOfFlames = false;
if (towerOfFlames)
{
towerOfFlames = false;
--ActiveTowersCount;
}
break;
case ACTION_TOWER_OF_LIFE_DESTROYED:
towerOfLife = false;
if (towerOfLife)
{
towerOfLife = false;
--ActiveTowersCount;
}
break;
case ACTION_START_HARD_MODE: // Activate hard-mode enable all towers, apply buffs on leviathan
ActiveTowers = true;
@@ -903,17 +903,15 @@ class boss_yogg_saron : public CreatureScript
DoCast(me, SPELL_KNOCK_AWAY);
me->ResetLootMode();
switch (_instance->GetData(DATA_KEEPERS_COUNT))
{
case 0:
me->AddLootMode(LOOT_MODE_HARD_MODE_4);
case 1:
me->AddLootMode(LOOT_MODE_HARD_MODE_3);
case 2:
me->AddLootMode(LOOT_MODE_HARD_MODE_2);
case 3:
me->AddLootMode(LOOT_MODE_HARD_MODE_1);
}
uint32 keepersCount = _instance->GetData(DATA_KEEPERS_COUNT);
if (keepersCount == 0)
me->AddLootMode(LOOT_MODE_HARD_MODE_4);
if (keepersCount <= 1)
me->AddLootMode(LOOT_MODE_HARD_MODE_3);
if (keepersCount <= 2)
me->AddLootMode(LOOT_MODE_HARD_MODE_2);
if (keepersCount <= 3)
me->AddLootMode(LOOT_MODE_HARD_MODE_1);
}
void SpellHit(Unit* /*caster*/, SpellInfo const* spell) override
@@ -174,7 +174,7 @@ class npc_commander_eligor_dawnbringer : public CreatureScript
{
if (id == 1)
{
me->SetFacingTo(PosTalkLocations[talkWing].m_orientation);
me->SetFacingTo(PosTalkLocations[talkWing].GetOrientation());
TurnAudience();
switch (talkWing)
@@ -24,53 +24,6 @@
#include "TemporarySummon.h"
#include "CombatAI.h"
/*######
## npc_squire_david
######*/
enum SquireDavid
{
QUEST_THE_ASPIRANT_S_CHALLENGE_H = 13680,
QUEST_THE_ASPIRANT_S_CHALLENGE_A = 13679,
NPC_ARGENT_VALIANT = 33448,
GOSSIP_TEXTID_SQUIRE = 14407
};
#define GOSSIP_SQUIRE_ITEM_1 "I am ready to fight!"
#define GOSSIP_SQUIRE_ITEM_2 "How do the Argent Crusader raiders fight?"
class npc_squire_david : public CreatureScript
{
public:
npc_squire_david() : CreatureScript("npc_squire_david") { }
bool OnGossipHello(Player* player, Creature* creature) override
{
if (player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_H) == QUEST_STATUS_INCOMPLETE ||
player->GetQuestStatus(QUEST_THE_ASPIRANT_S_CHALLENGE_A) == QUEST_STATUS_INCOMPLETE)//We need more info about it.
{
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_1, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+1);
player->ADD_GOSSIP_ITEM(GOSSIP_ICON_CHAT, GOSSIP_SQUIRE_ITEM_2, GOSSIP_SENDER_MAIN, GOSSIP_ACTION_INFO_DEF+2);
}
player->SEND_GOSSIP_MENU(GOSSIP_TEXTID_SQUIRE, creature->GetGUID());
return true;
}
bool OnGossipSelect(Player* player, Creature* creature, uint32 /*sender*/, uint32 action) override
{
player->PlayerTalkClass->ClearMenus();
if (action == GOSSIP_ACTION_INFO_DEF+1)
{
player->CLOSE_GOSSIP_MENU();
creature->SummonCreature(NPC_ARGENT_VALIANT, 8575.451f, 952.472f, 547.554f, 0.38f);
}
return true;
}
};
/*######
## npc_argent_valiant
######*/
@@ -837,7 +790,6 @@ class npc_frostbrood_skytalon : public CreatureScript
void AddSC_icecrown()
{
new npc_squire_david;
new npc_argent_valiant;
new npc_guardian_pavilion;
new npc_tournament_training_dummy;
@@ -19,6 +19,7 @@
#include "ScriptedCreature.h"
#include "ScriptedGossip.h"
#include "ScriptedEscortAI.h"
#include "SpellHistory.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "Vehicle.h"
+4 -4
View File
@@ -261,13 +261,13 @@ class OPvPCapturePointNA : public OPvPCapturePoint
public:
OPvPCapturePointNA(OutdoorPvP* pvp);
bool Update(uint32 diff);
bool Update(uint32 diff) override;
void ChangeState();
void ChangeState() override;
void FillInitialWorldStates(WorldPacket & data);
void FillInitialWorldStates(WorldPacket & data) override;
bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go);
bool HandleCustomSpell(Player* player, uint32 spellId, GameObject* go) override;
int32 HandleOpenGo(Player* player, ObjectGuid guid) override;
@@ -113,7 +113,7 @@ public:
Map::PlayerList const &PlayerList = map->GetPlayers();
for (Map::PlayerList::const_iterator i = PlayerList.begin(); i != PlayerList.end(); ++i)
if (Player* i_pl = i->GetSource())
if (i_pl->IsAlive() && (dist = i_pl->IsWithinDist(me, 45)))
if (i_pl->IsAlive() && (dist = i_pl->GetDistance(me)) < 45)
{
i_pl->RemoveAurasDueToSpell(SPELL_INHIBITMAGIC);
me->AddAura(SPELL_INHIBITMAGIC, i_pl);
@@ -27,6 +27,7 @@ set(scripts_STAT_SRCS
Outland/HellfireCitadel/ShatteredHalls/shattered_halls.h
Outland/HellfireCitadel/ShatteredHalls/boss_warchief_kargath_bladefist.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_nethekurse.cpp
Outland/HellfireCitadel/ShatteredHalls/shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/instance_shattered_halls.cpp
Outland/HellfireCitadel/ShatteredHalls/boss_warbringer_omrogg.cpp
Outland/CoilfangReservoir/SteamVault/boss_mekgineer_steamrigger.cpp
@@ -87,11 +87,11 @@ class boss_warchief_kargath_bladefist : public CreatureScript
resetcheck_timer = 5000;
}
void SetData(uint32 type, uint32 data) override
void DoAction(int32 action) override
{
if (type == 1)
if (action == ACTION_EXECUTIONER_TAUNT)
{
switch (data)
switch (instance->GetData(DATA_TEAM_IN_INSTANCE))
{
case ALLIANCE:
Talk(SAY_CALL_EXECUTIONER_A);
@@ -32,20 +32,11 @@ EndScriptData */
#include "SpellAuras.h"
#include "shattered_halls.h"
enum Spells
{
SPELL_CLEAVE = 15284,
SPELL_EXECUTE_1 = 39288,
SPELL_EXECUTE_2,
SPELL_EXECUTE_3
};
DoorData const doorData[] =
{
{GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_S },
{GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_N },
{0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE}
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_1, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ GO_GRAND_WARLOCK_CHAMBER_DOOR_2, DATA_NETHEKURSE, DOOR_TYPE_PASSAGE, BOUNDARY_NONE },
{ 0, 0, DOOR_TYPE_ROOM, BOUNDARY_NONE }
};
class instance_shattered_halls : public InstanceMapScript
@@ -77,9 +68,7 @@ class instance_shattered_halls : public InstanceMapScript
if (!_team)
_team = player->GetTeam();
player->RemoveAurasDueToSpell(SPELL_EXECUTE_1);
player->RemoveAurasDueToSpell(SPELL_EXECUTE_2);
player->RemoveAurasDueToSpell(SPELL_EXECUTE_3);
player->CastSpell(player, SPELL_REMOVE_KARGATH_EXECUTIONER, true);
if (!executionTimer || executionerGUID.IsEmpty())
return;
@@ -87,13 +76,13 @@ class instance_shattered_halls : public InstanceMapScript
switch (executed)
{
case 0:
ex = player->AddAura(SPELL_EXECUTE_1, player);
ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_1, player);
break;
case 1:
ex = player->AddAura(SPELL_EXECUTE_2, player);
ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_2, player);
break;
case 2:
ex = player->AddAura(SPELL_EXECUTE_3, player);
ex = player->AddAura(SPELL_KARGATH_EXECUTIONER_3, player);
break;
default:
break;
@@ -151,10 +140,22 @@ class instance_shattered_halls : public InstanceMapScript
break;
case NPC_SHATTERED_EXECUTIONER:
executionTimer = 55 * MINUTE * IN_MILLISECONDS;
DoCastSpellOnPlayers(SPELL_EXECUTE_1);
DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_1);
executionerGUID = creature->GetGUID();
SaveToDB();
break;
case NPC_CAPTAIN_ALINA:
case NPC_CAPTAIN_BONESHATTER:
victimsGUID[0] = creature->GetGUID();
break;
case NPC_ALLIANCE_VICTIM_1:
case NPC_HORDE_VICTIM_1:
victimsGUID[1] = creature->GetGUID();
break;
case NPC_ALLIANCE_VICTIM_2:
case NPC_HORDE_VICTIM_2:
victimsGUID[2] = creature->GetGUID();
break;
}
}
@@ -168,16 +169,14 @@ class instance_shattered_halls : public InstanceMapScript
case DATA_SHATTERED_EXECUTIONER:
if (state == DONE)
{
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1);
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2);
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3);
DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
executionTimer = 0;
SaveToDB();
}
break;
case DATA_KARGATH:
if (Creature* executioner = instance->GetCreature(executionerGUID))
executioner->AI()->Reset();
executioner->AI()->Reset(); // trigger removal of IMMUNE_TO_PC flag
break;
case DATA_OMROGG:
break;
@@ -191,16 +190,16 @@ class instance_shattered_halls : public InstanceMapScript
{
case NPC_GRAND_WARLOCK_NETHEKURSE:
return nethekurseGUID;
break;
case NPC_KARGATH_BLADEFIST:
return kargathGUID;
break;
case NPC_SHATTERED_EXECUTIONER:
return executionerGUID;
break;
case DATA_FIRST_PRISONER:
case DATA_SECOND_PRISONER:
case DATA_THIRD_PRISONER:
return victimsGUID[data - DATA_FIRST_PRISONER];
default:
return ObjectGuid::Empty;
break;
}
}
@@ -253,13 +252,10 @@ class instance_shattered_halls : public InstanceMapScript
{
case DATA_PRISONERS_EXECUTED:
return executed;
break;
case DATA_TEAM_IN_INSTANCE:
return _team;
break;
default:
return 0;
break;
}
}
@@ -269,27 +265,25 @@ class instance_shattered_halls : public InstanceMapScript
return;
if (executionTimer <= diff)
{
{
DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
switch (++executed)
{
case 1:
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_1);
DoCastSpellOnPlayers(SPELL_EXECUTE_2);
DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_2);
executionTimer = 10 * MINUTE * IN_MILLISECONDS;
break;
case 2:
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_2);
DoCastSpellOnPlayers(SPELL_EXECUTE_3);
DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_3);
executionTimer = 15 * MINUTE * IN_MILLISECONDS;
break;
default:
DoRemoveAurasDueToSpellOnPlayers(SPELL_EXECUTE_3);
executionTimer = 0;
break;
}
if (Creature* executioner = instance->GetCreature(executionerGUID))
executioner->AI()->SetData(1, executed);
executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed);
SaveToDB();
}
@@ -297,10 +291,11 @@ class instance_shattered_halls : public InstanceMapScript
executionTimer -= diff;
}
protected:
private:
ObjectGuid nethekurseGUID;
ObjectGuid kargathGUID;
ObjectGuid executionerGUID;
ObjectGuid victimsGUID[3];
uint8 executed;
uint32 executionTimer;
@@ -308,189 +303,7 @@ class instance_shattered_halls : public InstanceMapScript
};
};
class at_nethekurse_exit : public AreaTriggerScript
{
public:
at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { };
bool OnTrigger(Player* player, AreaTriggerEntry const*) override
{
if (InstanceScript* is = player->GetInstanceScript())
{
if (is->instance->IsHeroic())
{
Creature* executioner = nullptr;
is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST)))
{
if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty())
{
executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
kargath->AI()->SetData(1, is->GetData(DATA_TEAM_IN_INSTANCE));
}
}
if (executioner)
for (uint8 i = 0; i < VictimCount; ++i)
executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
}
}
return false;
}
};
class boss_shattered_executioner : public CreatureScript
{
public:
boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { }
struct boss_shattered_executionerAI : public BossAI
{
boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER)
{
Initialize();
};
void Initialize()
{
cleaveTimer = 500;
me->ResetLootMode();
switch (instance->GetData(DATA_PRISONERS_EXECUTED))
{
case 0:
me->AddLootMode(LOOT_MODE_HARD_MODE_3);
case 1:
me->AddLootMode(LOOT_MODE_HARD_MODE_2);
case 2:
me->AddLootMode(LOOT_MODE_HARD_MODE_1);
}
}
void Reset() override
{
_Reset();
if (instance->GetBossState(DATA_KARGATH) == DONE)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
else
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
Initialize();
}
void JustSummoned(Creature*) override { }
void JustDied(Unit*) override
{
_JustDied();
Map::PlayerList const &players = instance->instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
Player* pl = itr->GetSource();
uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
if (pl->GetQuestStatus(qId) != QUEST_STATUS_NONE && pl->GetQuestStatus(qId) != QUEST_STATUS_FAILED)
pl->CompleteQuest(qId);
}
}
void SetData(uint32 type, uint32 data) override
{
if (type == 1)
{
uint32 entry = executionerVictims[data - 1](instance->GetData(DATA_TEAM_IN_INSTANCE));
if (Creature* victim = me->FindNearestCreature(entry, 30.0f, true))
me->Kill(victim);
if (data == 1)
{
Map::PlayerList const &players = instance->instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
Player* pl = itr->GetSource();
uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
pl->FailQuest(qId);
}
}
switch (data)
{
case 3:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
case 2:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
case 1:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
default:
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (cleaveTimer <= diff)
{
DoCast(SPELL_CLEAVE);
cleaveTimer = urand(5000, 7000);
}
else
cleaveTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 cleaveTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_shattered_executionerAI>(creature);
}
};
class spell_kargath_executioner : public SpellScriptLoader
{
public:
spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { }
class spell_kargath_executioner_AuraScript : public AuraScript
{
PrepareAuraScript(spell_kargath_executioner_AuraScript);
bool AreaCheck(Unit* target)
{
if (target->GetMap()->GetId() != 540)
return false;
return true;
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void Register() override
{
DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_kargath_executioner_AuraScript();
}
};
void AddSC_instance_shattered_halls()
{
new instance_shattered_halls();
new at_nethekurse_exit();
new boss_shattered_executioner();
new spell_kargath_executioner();
}
@@ -0,0 +1,255 @@
/*
* Copyright (C) 2008-2015 TrinityCore <http://www.trinitycore.org/>
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "InstanceScript.h"
#include "Player.h"
#include "SpellAuras.h"
#include "shattered_halls.h"
class at_nethekurse_exit : public AreaTriggerScript
{
public:
at_nethekurse_exit() : AreaTriggerScript("at_nethekurse_exit") { };
bool OnTrigger(Player* player, AreaTriggerEntry const*) override
{
if (InstanceScript* is = player->GetInstanceScript())
{
if (is->instance->IsHeroic())
{
Creature* executioner = nullptr;
is->instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
if (Creature* kargath = ObjectAccessor::GetCreature(*player, is->GetGuidData(NPC_KARGATH_BLADEFIST)))
{
if (is->GetGuidData(NPC_SHATTERED_EXECUTIONER).IsEmpty())
{
executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
kargath->AI()->DoAction(ACTION_EXECUTIONER_TAUNT);
}
}
if (executioner)
for (uint8 i = 0; i < VictimCount; ++i)
executioner->SummonCreature(executionerVictims[i](is->GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
}
}
return false;
}
};
enum Spells
{
SPELL_CLEAVE = 15284
};
class boss_shattered_executioner : public CreatureScript
{
public:
boss_shattered_executioner() : CreatureScript("boss_shattered_executioner") { }
struct boss_shattered_executionerAI : public BossAI
{
boss_shattered_executionerAI(Creature* creature) : BossAI(creature, DATA_SHATTERED_EXECUTIONER)
{
Initialize();
};
void Initialize()
{
cleaveTimer = 500;
}
void Reset() override
{
_Reset();
// _Reset() resets the loot mode, so we add them again, if any
uint32 prisonersExecuted = instance->GetData(DATA_PRISONERS_EXECUTED);
if (prisonersExecuted == 0)
me->AddLootMode(LOOT_MODE_HARD_MODE_3);
if (prisonersExecuted <= 1)
me->AddLootMode(LOOT_MODE_HARD_MODE_2);
if (prisonersExecuted <= 2)
me->AddLootMode(LOOT_MODE_HARD_MODE_1);
if (instance->GetBossState(DATA_KARGATH) == DONE)
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
else
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_IMMUNE_TO_PC);
Initialize();
}
void JustSummoned(Creature*) override { } // avoid despawn of prisoners on death/reset
void JustDied(Unit*) override
{
_JustDied();
if (instance->GetData(DATA_PRISONERS_EXECUTED) > 0)
return;
Map::PlayerList const &players = instance->instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
Player* pl = itr->GetSource();
uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
pl->CompleteQuest(qId);
}
}
void SetData(uint32 type, uint32 data) override
{
if (type == DATA_PRISONERS_EXECUTED && data <= 3)
{
if (Creature* victim = ObjectAccessor::GetCreature(*me, instance->GetGuidData(DATA_FIRST_PRISONER + data - 1)))
me->Kill(victim);
if (data == 1)
{
Map::PlayerList const &players = instance->instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
{
Player* pl = itr->GetSource();
uint32 qId = pl->GetTeam() == ALLIANCE ? QUEST_IMPRISONED_A : QUEST_IMPRISONED_H;
if (pl->GetQuestStatus(qId) == QUEST_STATUS_INCOMPLETE)
pl->FailQuest(qId);
}
}
switch (data)
{
case 3:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_1);
case 2:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_2);
case 1:
me->RemoveLootMode(LOOT_MODE_HARD_MODE_3);
default:
break;
}
}
}
void UpdateAI(uint32 diff) override
{
if (!UpdateVictim())
return;
if (cleaveTimer <= diff)
{
DoCast(SPELL_CLEAVE);
cleaveTimer = urand(5000, 7000);
}
else
cleaveTimer -= diff;
DoMeleeAttackIfReady();
}
private:
uint32 cleaveTimer;
};
CreatureAI* GetAI(Creature* creature) const override
{
return GetInstanceAI<boss_shattered_executionerAI>(creature);
}
};
class spell_kargath_executioner : public SpellScriptLoader
{
public:
spell_kargath_executioner() : SpellScriptLoader("spell_kargath_executioner") { }
class spell_kargath_executioner_AuraScript : public AuraScript
{
PrepareAuraScript(spell_kargath_executioner_AuraScript);
bool AreaCheck(Unit* target)
{
if (target->GetMap()->GetId() != 540)
return false;
return true;
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void Register() override
{
DoCheckAreaTarget += AuraCheckAreaTargetFn(spell_kargath_executioner_AuraScript::AreaCheck);
}
};
AuraScript* GetAuraScript() const override
{
return new spell_kargath_executioner_AuraScript();
}
};
class spell_remove_kargath_executioner : public SpellScriptLoader
{
public:
spell_remove_kargath_executioner() : SpellScriptLoader("spell_remove_kargath_executioner") { }
class spell_remove_kargath_executioner_SpellScript : public SpellScript
{
PrepareSpellScript(spell_remove_kargath_executioner_SpellScript);
void HandleScript(SpellEffIndex /*effIndex*/)
{
Unit* target = GetCaster();
target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_1);
target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_2);
target->RemoveAurasDueToSpell(SPELL_KARGATH_EXECUTIONER_3);
}
bool Load() override
{
return GetCaster()->GetTypeId() == TYPEID_PLAYER;
}
void Register() override
{
OnEffectHitTarget += SpellEffectFn(spell_remove_kargath_executioner_SpellScript::HandleScript, EFFECT_0, SPELL_EFFECT_SCRIPT_EFFECT);
}
};
SpellScript* GetSpellScript() const override
{
return new spell_remove_kargath_executioner_SpellScript();
}
};
void AddSC_shattered_halls()
{
new at_nethekurse_exit();
new boss_shattered_executioner();
new spell_kargath_executioner();
new spell_remove_kargath_executioner();
}
@@ -33,7 +33,11 @@ enum DataTypes
DATA_SHATTERED_EXECUTIONER = 3,
DATA_PRISONERS_EXECUTED = 4,
DATA_TEAM_IN_INSTANCE = 5
DATA_TEAM_IN_INSTANCE = 5,
DATA_FIRST_PRISONER,
DATA_SECOND_PRISONER,
DATA_THIRD_PRISONER
};
enum CreatureIds
@@ -70,6 +74,20 @@ enum QuestIds
QUEST_IMPRISONED_H = 9525
};
enum InstanceSpells
{
SPELL_KARGATH_EXECUTIONER_1 = 39288,
SPELL_KARGATH_EXECUTIONER_2 = 39289,
SPELL_KARGATH_EXECUTIONER_3 = 39290,
SPELL_REMOVE_KARGATH_EXECUTIONER = 39291
};
enum Actions
{
ACTION_EXECUTIONER_TAUNT = 1
};
const Position Executioner = { 152.8524f, -83.63912f, 2.021005f, 0.06981317f };
struct FactionSpawnerHelper
@@ -77,7 +95,7 @@ struct FactionSpawnerHelper
FactionSpawnerHelper(uint32 allianceEntry, uint32 hordeEntry, const Position& pos) : _allianceNPC(allianceEntry), _hordeNPC(hordeEntry), _spawnPos(pos) { }
inline uint32 operator()(uint32 teamID) const { return teamID == ALLIANCE ? _allianceNPC : _hordeNPC; }
inline const Position GetPos() const { return _spawnPos; }
inline Position const& GetPos() const { return _spawnPos; }
private:
const uint32 _allianceNPC;
@@ -420,10 +420,482 @@ public:
}
};
enum ExorcismSpells
{
SPELL_JULES_GOES_PRONE = 39283,
SPELL_JULES_THREATENS_AURA = 39284,
SPELL_JULES_GOES_UPRIGHT = 39294,
SPELL_JULES_VOMITS_AURA = 39295,
SPELL_BARADAS_COMMAND = 39277,
SPELL_BARADA_FALTERS = 39278,
};
enum ExorcismTexts
{
SAY_BARADA_1 = 0,
SAY_BARADA_2 = 1,
SAY_BARADA_3 = 2,
SAY_BARADA_4 = 3,
SAY_BARADA_5 = 4,
SAY_BARADA_6 = 5,
SAY_BARADA_7 = 6,
SAY_BARADA_8 = 7,
SAY_JULES_1 = 0,
SAY_JULES_2 = 1,
SAY_JULES_3 = 2,
SAY_JULES_4 = 3,
SAY_JULES_5 = 4,
};
Position const exorcismPos[11] =
{
{ -707.123f, 2751.686f, 101.592f, 4.577416f }, //Barada Waypoint-1 0
{ -710.731f, 2749.075f, 101.592f, 1.513286f }, //Barada Cast position 1
{ -710.332f, 2754.394f, 102.948f, 3.207566f }, //Jules 2
{ -714.261f, 2747.754f, 103.391f, 0.0f }, //Jules Waypoint-1 3
{ -713.113f, 2750.194f, 103.391f, 0.0f }, //Jules Waypoint-2 4
{ -710.385f, 2750.896f, 103.391f, 0.0f }, //Jules Waypoint-3 5
{ -708.309f, 2750.062f, 103.391f, 0.0f }, //Jules Waypoint-4 6
{ -707.401f, 2747.696f, 103.391f, 0.0f }, //Jules Waypoint-5 7
{ -708.591f, 2745.266f, 103.391f, 0.0f }, //Jules Waypoint-6 8
{ -710.597f, 2744.035f, 103.391f, 0.0f }, //Jules Waypoint-7 9
{ -713.089f, 2745.302f, 103.391f, 0.0f }, //Jules Waypoint-8 10
};
enum ExorcismMisc
{
NPC_DARKNESS_RELEASED = 22507,
NPC_FOUL_PURGE = 22506,
NPC_COLONEL_JULES = 22432,
BARADAS_GOSSIP_MESSAGE = 10683,
QUEST_THE_EXORCISM_OF_COLONEL_JULES = 10935,
ACTION_START_EVENT = 1,
ACTION_JULES_HOVER = 2,
ACTION_JULES_FLIGHT = 3,
ACTION_JULES_MOVE_HOME = 4,
};
enum ExorcismEvents
{
EVENT_BARADAS_TALK = 1,
//Colonel Jules
EVENT_SUMMON_SKULL = 1,
};
/*######
## npc_barada
######*/
class npc_barada : public CreatureScript
{
public:
npc_barada() : CreatureScript("npc_barada") { }
struct npc_baradaAI : public ScriptedAI
{
npc_baradaAI(Creature* creature) : ScriptedAI(creature)
{
Initialize();
}
void Initialize()
{
step = 0;
}
void Reset() override
{
events.Reset();
Initialize();
playerGUID.Clear();
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
}
void sGossipSelect(Player* player, uint32 /*menuId*/, uint32 gossipListId) override
{
player->PlayerTalkClass->ClearMenus();
switch (gossipListId)
{
case 1:
player->PlayerTalkClass->SendCloseGossip();
me->AI()->Talk(SAY_BARADA_1);
me->AI()->DoAction(ACTION_START_EVENT);
break;
default:
break;
}
}
void DoAction(int32 action) override
{
if (action == ACTION_START_EVENT)
{
if (Creature* jules = me->FindNearestCreature(NPC_COLONEL_JULES, 20.0f, true))
{
julesGUID = jules->GetGUID();
jules->AI()->Talk(SAY_JULES_1);
}
me->GetMotionMaster()->MovePoint(0, exorcismPos[1]);
Talk(SAY_BARADA_2);
me->SetFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
}
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
if (id == 0)
me->GetMotionMaster()->MovePoint(1, exorcismPos[1]);
if (id == 1)
events.ScheduleEvent(EVENT_BARADAS_TALK, 2000);
}
void JustDied(Unit* /*killer*/) override
{
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
{
jules->AI()->DoAction(ACTION_JULES_MOVE_HOME);
jules->RemoveAllAuras();
}
}
void UpdateAI(uint32 diff) override
{
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_BARADAS_TALK:
switch (step)
{
case 0:
me->SetFacingTo(1.513286f);
me->HandleEmoteCommand(EMOTE_ONESHOT_KNEEL);
events.ScheduleEvent(EVENT_BARADAS_TALK, 3000);
step++;
break;
case 1:
DoCast(SPELL_BARADAS_COMMAND);
events.ScheduleEvent(EVENT_BARADAS_TALK, 5000);
step++;
break;
case 2:
Talk(SAY_BARADA_3);
events.ScheduleEvent(EVENT_BARADAS_TALK, 7000);
step++;
break;
case 3:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_2);
events.ScheduleEvent(EVENT_BARADAS_TALK, 18000);
step++;
break;
case 4:
DoCast(SPELL_BARADA_FALTERS);
me->HandleEmoteCommand(EMOTE_STAND_STATE_NONE);
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->DoAction(ACTION_JULES_HOVER);
events.ScheduleEvent(EVENT_BARADAS_TALK, 11000);
step++;
break;
case 5:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_3);
events.ScheduleEvent(EVENT_BARADAS_TALK, 13000);
step++;
break;
case 6:
Talk(SAY_BARADA_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 5000);
step++;
break;
case 7:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_3);
events.ScheduleEvent(EVENT_BARADAS_TALK, 13000);
step++;
break;
case 8:
Talk(SAY_BARADA_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 12000);
step++;
break;
case 9:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 12000);
step++;
break;
case 10:
Talk(SAY_BARADA_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 5000);
step++;
break;
case 11:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->DoAction(ACTION_JULES_FLIGHT);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 12:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 8000);
step++;
break;
case 13:
Talk(SAY_BARADA_5);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 14:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_4);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 15:
Talk(SAY_BARADA_6);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 16:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_5);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 17:
Talk(SAY_BARADA_7);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 18:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->AI()->Talk(SAY_JULES_3);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 19:
Talk(SAY_BARADA_7);
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 20:
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
{
jules->AI()->DoAction(ACTION_JULES_MOVE_HOME);
jules->RemoveAura(SPELL_JULES_VOMITS_AURA);
}
events.ScheduleEvent(EVENT_BARADAS_TALK, 10000);
step++;
break;
case 21:
//End
if (Player* player = ObjectAccessor::FindPlayer(playerGUID))
player->KilledMonsterCredit(NPC_COLONEL_JULES, ObjectGuid::Empty);
if (Creature* jules = ObjectAccessor::GetCreature(*me, julesGUID))
jules->RemoveAllAuras();
me->RemoveAura(SPELL_BARADAS_COMMAND);
me->RemoveFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PACIFIED);
Talk(SAY_BARADA_8);
me->GetMotionMaster()->MoveTargetedHome();
EnterEvadeMode();
break;
}
break;
}
}
}
private:
EventMap events;
uint8 step;
ObjectGuid julesGUID;
ObjectGuid playerGUID;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_baradaAI(creature);
}
};
/*######
## npc_colonel_jules
######*/
class npc_colonel_jules : public CreatureScript
{
public:
npc_colonel_jules() : CreatureScript("npc_colonel_jules") { }
struct npc_colonel_julesAI : public ScriptedAI
{
npc_colonel_julesAI(Creature* creature) : ScriptedAI(creature), summons(me)
{
Initialize();
}
void Initialize()
{
circleRounds = 0;
point = 3;
wpreached = false;
}
void Reset() override
{
events.Reset();
summons.DespawnAll();
Initialize();
}
void DoAction(int32 action) override
{
switch (action)
{
case ACTION_JULES_HOVER:
me->AddAura(SPELL_JULES_GOES_PRONE, me);
me->AddAura(SPELL_JULES_THREATENS_AURA, me);
me->SetCanFly(true);
me->SetSpeed(MOVE_RUN, 0.2f);
me->SetFacingTo(3.207566f);
me->GetMotionMaster()->MoveJump(exorcismPos[2], 2.0f, 2.0f);
events.ScheduleEvent(EVENT_SUMMON_SKULL, 10000);
break;
case ACTION_JULES_FLIGHT:
circleRounds++;
me->RemoveAura(SPELL_JULES_GOES_PRONE);
me->AddAura(SPELL_JULES_GOES_UPRIGHT, me);
me->AddAura(SPELL_JULES_VOMITS_AURA, me);
wpreached = true;
me->GetMotionMaster()->MovePoint(point, exorcismPos[point]);
break;
case ACTION_JULES_MOVE_HOME:
wpreached = false;
me->SetSpeed(MOVE_RUN, 1.0f);
me->GetMotionMaster()->MovePoint(11, exorcismPos[2]);
events.CancelEvent(EVENT_SUMMON_SKULL);
break;
}
}
void JustSummoned(Creature* summon) override
{
summons.Summon(summon);
summon->GetMotionMaster()->MoveRandom(10.0f);
}
void MovementInform(uint32 type, uint32 id) override
{
if (type != POINT_MOTION_TYPE)
return;
if (id < 10)
wpreached = true;
if (id == 8)
{
for (uint8 i = 0; i < circleRounds; i++)
DoSummon(NPC_FOUL_PURGE, exorcismPos[8]);
}
if (id == 10)
{
wpreached = true;
point = 3;
circleRounds++;
}
}
void UpdateAI(uint32 diff) override
{
if (wpreached)
{
me->GetMotionMaster()->MovePoint(point, exorcismPos[point]);
point++;
wpreached = false;
}
events.Update(diff);
while (uint32 eventId = events.ExecuteEvent())
{
switch (eventId)
{
case EVENT_SUMMON_SKULL:
uint8 summonCount = urand(1,3);
for (uint8 i = 0; i < summonCount; i++)
me->SummonCreature(NPC_DARKNESS_RELEASED, me->GetPositionX(), me->GetPositionY(), me->GetPositionZ() + 1.5f, 0, TEMPSUMMON_MANUAL_DESPAWN);
events.ScheduleEvent(EVENT_SUMMON_SKULL, urand(10000, 15000));
break;
}
}
}
private:
EventMap events;
SummonList summons;
uint8 circleRounds;
uint8 point;
bool wpreached;
};
CreatureAI* GetAI(Creature* creature) const override
{
return new npc_colonel_julesAI(creature);
}
};
void AddSC_hellfire_peninsula()
{
new npc_aeranas();
new npc_ancestral_wolf();
new npc_wounded_blood_elf();
new npc_fel_guard_hound();
new npc_barada();
new npc_colonel_jules();
}
+4 -3
View File
@@ -34,6 +34,7 @@
#include "Pet.h"
#include "ReputationMgr.h"
#include "SkillDiscovery.h"
#include "SpellHistory.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "Vehicle.h"
@@ -1310,8 +1311,8 @@ class spell_gen_divine_storm_cd_reset : public SpellScriptLoader
void HandleScript(SpellEffIndex /*effIndex*/)
{
Player* caster = GetCaster()->ToPlayer();
if (caster->HasSpellCooldown(SPELL_DIVINE_STORM))
caster->RemoveSpellCooldown(SPELL_DIVINE_STORM, true);
if (caster->GetSpellHistory()->HasCooldown(SPELL_DIVINE_STORM))
caster->GetSpellHistory()->ResetCooldown(SPELL_DIVINE_STORM, true);
}
void Register() override
@@ -3318,7 +3319,7 @@ class spell_pvp_trinket_wotf_shared_cd : public SpellScriptLoader
{
// This is only needed because spells cast from spell_linked_spell are triggered by default
// Spell::SendSpellCooldown() skips all spells with TRIGGERED_IGNORE_SPELL_AND_CATEGORY_CD
GetCaster()->ToPlayer()->AddSpellAndCategoryCooldowns(GetSpellInfo(), GetCastItem() ? GetCastItem()->GetEntry() : 0, GetSpell());
GetCaster()->GetSpellHistory()->StartCooldown(GetSpellInfo(), 0, GetSpell());
}
void Register() override
+7 -10
View File
@@ -27,6 +27,7 @@
#include "CellImpl.h"
#include "GridNotifiers.h"
#include "GridNotifiersImpl.h"
#include "SpellHistory.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
@@ -713,24 +714,20 @@ class spell_hun_readiness : public SpellScriptLoader
void HandleDummy(SpellEffIndex /*effIndex*/)
{
Player* caster = GetCaster()->ToPlayer();
// immediately finishes the cooldown on your other Hunter abilities except Bestial Wrath
const SpellCooldowns& cm = caster->ToPlayer()->GetSpellCooldownMap();
for (SpellCooldowns::const_iterator itr = cm.begin(); itr != cm.end();)
GetCaster()->GetSpellHistory()->ResetCooldowns([](SpellHistory::CooldownStorageType::iterator itr) -> bool
{
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(itr->first);
SpellInfo const* spellInfo = sSpellMgr->EnsureSpellInfo(itr->first);
///! If spellId in cooldown map isn't valid, the above will return a null pointer.
if (spellInfo &&
spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
if (spellInfo->SpellFamilyName == SPELLFAMILY_HUNTER &&
spellInfo->Id != SPELL_HUNTER_READINESS &&
spellInfo->Id != SPELL_HUNTER_BESTIAL_WRATH &&
spellInfo->Id != SPELL_DRAENEI_GIFT_OF_THE_NAARU &&
spellInfo->GetRecoveryTime() > 0)
caster->RemoveSpellCooldown((itr++)->first, true);
else
++itr;
}
return true;
return false;
}, true);
}
void Register() override
+3 -2
View File
@@ -24,6 +24,7 @@
#include "Player.h"
#include "ScriptMgr.h"
#include "ScriptedCreature.h"
#include "SpellHistory.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
#include "SkillDiscovery.h"
@@ -1349,7 +1350,7 @@ class spell_item_red_rider_air_rifle : public SpellScriptLoader
caster->CastSpell(caster, SPELL_AIR_RIFLE_HOLD_VISUAL, true);
// needed because this spell shares GCD with its triggered spells (which must not be cast with triggered flag)
if (Player* player = caster->ToPlayer())
player->GetGlobalCooldownMgr().CancelGlobalCooldown(GetSpellInfo());
player->GetSpellHistory()->CancelGlobalCooldown(GetSpellInfo());
if (urand(0, 4))
caster->CastSpell(target, SPELL_AIR_RIFLE_SHOOT, false);
else
@@ -2368,7 +2369,7 @@ class spell_item_rocket_boots : public SpellScriptLoader
if (Battleground* bg = caster->GetBattleground())
bg->EventPlayerDroppedFlag(caster);
caster->RemoveSpellCooldown(SPELL_ROCKET_BOOTS_PROC);
caster->GetSpellHistory()->ResetCooldown(SPELL_ROCKET_BOOTS_PROC);
caster->CastSpell(caster, SPELL_ROCKET_BOOTS_PROC, true, NULL);
}
Loaded 100 of 119 files, more files were not shown because too many files have changed in this diff. Show more