aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/authserver/Server/AuthSocket.cpp12
-rw-r--r--src/server/game/Achievements/AchievementMgr.cpp49
-rw-r--r--src/server/game/Achievements/AchievementMgr.h16
-rw-r--r--src/server/game/DataStores/DBCEnums.h8
-rw-r--r--src/server/game/DungeonFinding/LFGMgr.cpp5
-rw-r--r--src/server/game/Entities/Player/Player.cpp12
-rw-r--r--src/server/game/Entities/Player/Player.h7
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp21
-rw-r--r--src/server/game/Globals/ObjectMgr.cpp24
-rw-r--r--src/server/game/Groups/Group.cpp5
-rw-r--r--src/server/game/Handlers/CharacterHandler.cpp3
-rw-r--r--src/server/game/Handlers/ChatHandler.cpp8
-rw-r--r--src/server/game/Handlers/MiscHandler.cpp1
-rw-r--r--src/server/game/Handlers/NPCHandler.cpp2
-rw-r--r--src/server/game/Movement/MotionMaster.cpp5
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp7
-rw-r--r--src/server/game/Spells/Spell.cpp78
-rw-r--r--src/server/game/Spells/Spell.h2
-rw-r--r--src/server/game/Spells/SpellEffects.cpp61
-rw-r--r--src/server/game/Spells/SpellMgr.cpp198
-rw-r--r--src/server/game/Spells/SpellScript.cpp16
-rw-r--r--src/server/game/Spells/SpellScript.h3
-rw-r--r--src/server/game/World/World.cpp2
-rw-r--r--src/server/game/World/World.h1
-rw-r--r--src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp1
-rw-r--r--src/server/scripts/Outland/zone_nagrand.cpp65
-rw-r--r--src/server/scripts/Spells/spell_dk.cpp273
-rw-r--r--src/server/shared/CompilerDefs.h2
-rw-r--r--src/server/shared/Utilities/ByteConverter.h4
-rw-r--r--src/server/shared/Utilities/Util.cpp3
-rw-r--r--src/server/worldserver/worldserver.conf.dist9
31 files changed, 519 insertions, 384 deletions
diff --git a/src/server/authserver/Server/AuthSocket.cpp b/src/server/authserver/Server/AuthSocket.cpp
index 8a2a6c67496..c7bb600024a 100644
--- a/src/server/authserver/Server/AuthSocket.cpp
+++ b/src/server/authserver/Server/AuthSocket.cpp
@@ -321,7 +321,7 @@ bool AuthSocket::_HandleLogonChallenge()
socket().recv((char *)&buf[0], 4);
- EndianConvert(*((uint16*)(buf[0])));
+ EndianConvertPtr<uint16>(&buf[0]);
uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
TC_LOG_DEBUG("server.authserver", "[AuthChallenge] got header, body is %#04x bytes", remaining);
@@ -341,11 +341,11 @@ bool AuthSocket::_HandleLogonChallenge()
// BigEndian code, nop in little endian case
// size already converted
- EndianConvert(*((uint32*)(&ch->gamename[0])));
+ EndianConvertPtr<uint32>(&ch->gamename[0]);
EndianConvert(ch->build);
- EndianConvert(*((uint32*)(&ch->platform[0])));
- EndianConvert(*((uint32*)(&ch->os[0])));
- EndianConvert(*((uint32*)(&ch->country[0])));
+ EndianConvertPtr<uint32>(&ch->platform[0]);
+ EndianConvertPtr<uint32>(&ch->os[0]);
+ EndianConvertPtr<uint32>(&ch->country[0]);
EndianConvert(ch->timezone_bias);
EndianConvert(ch->ip);
@@ -779,7 +779,7 @@ bool AuthSocket::_HandleReconnectChallenge()
socket().recv((char *)&buf[0], 4);
- EndianConvert(*((uint16*)(buf[0])));
+ EndianConvertPtr<uint16>(&buf[0]);
uint16 remaining = ((sAuthLogonChallenge_C *)&buf[0])->size;
TC_LOG_DEBUG("server.authserver", "[ReconnectChallenge] got header, body is %#04x bytes", remaining);
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp
index 7d53f481fe8..8d0f6938532 100644
--- a/src/server/game/Achievements/AchievementMgr.cpp
+++ b/src/server/game/Achievements/AchievementMgr.cpp
@@ -97,6 +97,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM: // only Children's Week achievements
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL:
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
break;
default:
if (dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT)
@@ -111,6 +112,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE:
case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT:
+ case ACHIEVEMENT_CRITERIA_REQUIRE_NTH_BIRTHDAY:
return true;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE:
if (!creature.id || !sObjectMgr->GetCreatureTemplate(creature.id))
@@ -292,6 +294,16 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
return false;
}
return true;
+ case ACHIEVEMENT_CRITERIA_REQUIRE_KNOWN_TITLE:
+ {
+ if (!sCharTitlesStore.LookupEntry(known_title.title_id))
+ {
+ TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
+ criteria->ID, criteria->requiredType, dataType, known_title.title_id);
+ return false;
+ }
+ return true;
+ }
default:
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored.", criteria->ID, criteria->requiredType, dataType);
return false;
@@ -410,6 +422,26 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID:
return source->GetMapId() == map_id.mapId;
+ case ACHIEVEMENT_CRITERIA_REQUIRE_NTH_BIRTHDAY:
+ {
+ time_t birthday_start = time_t(sWorld->getIntConfig(CONFIG_BIRTHDAY_TIME));
+ tm birthday_tm;
+ ACE_OS::localtime_r(&birthday_start, &birthday_tm);
+
+ // exactly N birthday
+ birthday_tm.tm_year += birthday_login.nth_birthday;
+
+ time_t birthday = mktime(&birthday_tm);
+ time_t now = sWorld->GetGameTime();
+ return now <= birthday + DAY && now >= birthday;
+ }
+ case ACHIEVEMENT_CRITERIA_REQUIRE_KNOWN_TITLE:
+ {
+ if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id))
+ return source && source->HasTitle(titleInfo->bit_index);
+
+ return false;
+ }
default:
break;
}
@@ -1562,6 +1594,20 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ {
+ // This criteria is only called directly after login - with expected miscvalue1 == 1
+ if (!miscValue1)
+ continue;
+
+ // They have no proper requirements in dbc
+ AchievementCriteriaDataSet const* data = sAchievementMgr->GetCriteriaDataSet(achievementCriteria);
+ if (!data || !data->Meets(GetPlayer(), unit))
+ continue;
+
+ SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
+ break;
+ }
// std case: not exist in DBC, not triggered in code as result
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALTH:
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_SPELLPOWER:
@@ -1574,7 +1620,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA:
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK:
- case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE:
break; // Not implemented yet :(
}
@@ -1717,6 +1762,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
return progress->counter >= achievementCriteria->get_killing_blow.killCount;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
return achievementCriteria->win_arena.count && progress->counter >= achievementCriteria->win_arena.count;
+ case ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN:
+ return true;
// handle all statistic-only criteria here
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h
index 1a6777d1055..26270cdec80 100644
--- a/src/server/game/Achievements/AchievementMgr.h
+++ b/src/server/game/Achievements/AchievementMgr.h
@@ -68,10 +68,12 @@ enum AchievementCriteriaDataType
ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT = 18, // 0 0 maker instance script call for check current criteria requirements fit
ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19, // item_level item_quality for equipped item in slot to check item level and quality
ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID = 20, // map_id 0 player must be on map with id in map_id
- ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21 // class_id race_id
+ ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE = 21, // class_id race_id
+ ACHIEVEMENT_CRITERIA_REQUIRE_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday
+ ACHIEVEMENT_CRITERIA_REQUIRE_KNOWN_TITLE = 23, // title_id known (pvp) title, values from dbc
};
-#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 22 // maximum value in AchievementCriteriaDataType enum
+#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum
struct AchievementCriteriaData
{
@@ -173,6 +175,16 @@ struct AchievementCriteriaData
{
uint32 mapId;
} map_id;
+ // ACHIEVEMENT_CRITERIA_REQUIRE_NTH_BIRTHDAY = 21
+ struct
+ {
+ uint32 nth_birthday;
+ } birthday_login;
+ // ACHIEVEMENT_CRITERIA_REQUIRE_KNOWN_TITLE = 22
+ struct
+ {
+ uint32 title_id;
+ } known_title;
// ...
struct
{
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 87397c6685b..8d8b7c89a5c 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -91,9 +91,9 @@ enum AchievementCriteriaFlags
{
ACHIEVEMENT_CRITERIA_FLAG_SHOW_PROGRESS_BAR = 0x00000001, // Show progress as bar
ACHIEVEMENT_CRITERIA_FLAG_HIDDEN = 0x00000002, // Not show criteria in client
- ACHIEVEMENT_CRITERIA_FLAG_UNK3 = 0x00000004, // BG related??
- ACHIEVEMENT_CRITERIA_FLAG_UNK4 = 0x00000008, //
- ACHIEVEMENT_CRITERIA_FLAG_UNK5 = 0x00000010, // not used
+ ACHIEVEMENT_CRITERIA_FLAG_FAIL_ACHIEVEMENT = 0x00000004, // BG related??
+ ACHIEVEMENT_CRITERIA_FLAG_RESET_ON_START = 0x00000008, //
+ ACHIEVEMENT_CRITERIA_FLAG_IS_DATE = 0x00000010, // not used
ACHIEVEMENT_CRITERIA_FLAG_MONEY_COUNTER = 0x00000020 // Displays counter as money
};
@@ -174,7 +174,7 @@ enum AchievementCriteriaTypes
ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL = 70,
ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT = 72,
/// @todo 73: Achievements 1515, 1241, 1103 (Name: Mal'Ganis)
- ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE = 74, /// @todo title id is not mentioned in dbc
+ ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN = 74,
ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS = 75,
ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL = 76,
ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL = 77,
diff --git a/src/server/game/DungeonFinding/LFGMgr.cpp b/src/server/game/DungeonFinding/LFGMgr.cpp
index 2dcba7b6a76..1665eae0fcc 100644
--- a/src/server/game/DungeonFinding/LFGMgr.cpp
+++ b/src/server/game/DungeonFinding/LFGMgr.cpp
@@ -405,7 +405,9 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */)
lockData = LFG_LOCKSTATUS_NOT_IN_SEASON;
else if (AccessRequirement const* ar = sObjectMgr->GetAccessRequirement(dungeon->map, Difficulty(dungeon->difficulty)))
{
- if (ar->achievement && !player->HasAchieved(ar->achievement))
+ if (player->GetAverageItemLevel() < ar->item_level)
+ lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
+ else if (ar->achievement && !player->HasAchieved(ar->achievement))
lockData = LFG_LOCKSTATUS_MISSING_ACHIEVEMENT;
else if (player->GetTeam() == ALLIANCE && ar->quest_A && !player->GetQuestRewardStatus(ar->quest_A))
lockData = LFG_LOCKSTATUS_QUEST_NOT_COMPLETED;
@@ -422,7 +424,6 @@ void LFGMgr::InitializeLockedDungeons(Player* player, uint8 level /* = 0 */)
}
/* @todo VoA closed if WG is not under team control (LFG_LOCKSTATUS_RAID_LOCKED)
- lockData = LFG_LOCKSTATUS_TOO_LOW_GEAR_SCORE;
lockData = LFG_LOCKSTATUS_TOO_HIGH_GEAR_SCORE;
lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_LOW_LEVEL;
lockData = LFG_LOCKSTATUS_ATTUNEMENT_TOO_HIGH_LEVEL;
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 6b7fbebcfb5..9ea9c153f36 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -687,7 +687,7 @@ Player::Player(WorldSession* session): Unit(true)
m_regenTimerCount = 0;
m_weaponChangeTimer = 0;
- m_zoneUpdateId = 0;
+ m_zoneUpdateId = uint32(-1);
m_zoneUpdateTimer = 0;
m_areaUpdateId = 0;
@@ -18494,6 +18494,9 @@ void Player::_LoadGroup(PreparedQueryResult result)
{
if (Group* group = sGroupMgr->GetGroupByDbStoreId((*result)[0].GetUInt32()))
{
+ if (group->IsLeader(GetGUID()))
+ SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
+
uint8 subgroup = group->GetMemberGroup(GetGUID());
SetGroup(group, subgroup);
if (getLevel() >= LEVELREQUIREMENT_HEROIC)
@@ -18504,6 +18507,9 @@ void Player::_LoadGroup(PreparedQueryResult result)
}
}
}
+
+ if (!GetGroup() || !GetGroup()->IsLeader(GetGUID()))
+ RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
}
void Player::_LoadBoundInstances(PreparedQueryResult result)
@@ -23609,7 +23615,7 @@ uint32 Player::GetResurrectionSpellId()
}
// Used in triggers for check "Only to targets that grant experience or honor" req
-bool Player::isHonorOrXPTarget(Unit* victim)
+bool Player::isHonorOrXPTarget(Unit* victim) const
{
uint8 v_level = victim->getLevel();
uint8 k_grey = Trinity::XP::GetGrayLevel(getLevel());
@@ -24314,7 +24320,7 @@ bool Player::isTotalImmune()
return false;
}
-bool Player::HasTitle(uint32 bitIndex)
+bool Player::HasTitle(uint32 bitIndex) const
{
if (bitIndex > MAX_TITLE_INDEX)
return false;
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 1f5f9fee7d4..5026489daff 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -840,6 +840,7 @@ struct AccessRequirement
{
uint8 levelMin;
uint8 levelMax;
+ uint16 item_level;
uint32 item;
uint32 item2;
uint32 quest_A;
@@ -1894,7 +1895,7 @@ class Player : public Unit, public GridObject<Player>
bool IsAtRecruitAFriendDistance(WorldObject const* pOther) const;
void RewardPlayerAndGroupAtKill(Unit* victim, bool isBattleGround);
void RewardPlayerAndGroupAtEvent(uint32 creature_id, WorldObject* pRewardSource);
- bool isHonorOrXPTarget(Unit* victim);
+ bool isHonorOrXPTarget(Unit* victim) const;
bool GetsRecruitAFriendBonus(bool forXP);
uint8 GetGrantableLevels() { return m_grantableLevels; }
@@ -2263,8 +2264,8 @@ class Player : public Unit, public GridObject<Player>
void RemoveTimedAchievement(AchievementCriteriaTimedTypes type, uint32 entry);
void CompletedAchievement(AchievementEntry const* entry);
- bool HasTitle(uint32 bitIndex);
- bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
+ bool HasTitle(uint32 bitIndex) const;
+ bool HasTitle(CharTitlesEntry const* title) const { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title, bool lost = false);
//bool isActiveObject() const { return true; }
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index e0bf7019acb..ff402488c2c 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -8716,13 +8716,28 @@ ReputationRank Unit::GetReactionTo(Unit const* target) const
if (GetCharmerOrOwnerOrSelf() == target->GetCharmerOrOwnerOrSelf())
return REP_FRIENDLY;
+ Player const* selfPlayerOwner = GetAffectingPlayer();
+ Player const* targetPlayerOwner = target->GetAffectingPlayer();
+
+ // check forced reputation to support SPELL_AURA_FORCE_REACTION
+ if (selfPlayerOwner)
+ {
+ if (FactionTemplateEntry const* targetFactionTemplateEntry = target->GetFactionTemplateEntry())
+ if (ReputationRank const* repRank = selfPlayerOwner->GetReputationMgr().GetForcedRankIfAny(targetFactionTemplateEntry))
+ return *repRank;
+ }
+ else if (targetPlayerOwner)
+ {
+ if (FactionTemplateEntry const* selfFactionTemplateEntry = GetFactionTemplateEntry())
+ if (ReputationRank const* repRank = targetPlayerOwner->GetReputationMgr().GetForcedRankIfAny(selfFactionTemplateEntry))
+ return *repRank;
+ }
+
+
if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
{
if (target->HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_PVP_ATTACKABLE))
{
- Player const* selfPlayerOwner = GetAffectingPlayer();
- Player const* targetPlayerOwner = target->GetAffectingPlayer();
-
if (selfPlayerOwner && targetPlayerOwner)
{
// always friendly to other unit controlled by player, or to the player himself
diff --git a/src/server/game/Globals/ObjectMgr.cpp b/src/server/game/Globals/ObjectMgr.cpp
index 04f3395653d..ff87f41ae78 100644
--- a/src/server/game/Globals/ObjectMgr.cpp
+++ b/src/server/game/Globals/ObjectMgr.cpp
@@ -705,12 +705,6 @@ void ObjectMgr::CheckCreatureTemplate(CreatureTemplate const* cInfo)
cInfo->Entry, cInfo->type, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type);
}
- if (cInfo->type_flags != difficultyInfo->type_flags)
- {
- TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, type_flags %u) has different `type_flags` in difficulty %u mode (Entry: %u, type_flags %u).",
- cInfo->Entry, cInfo->type_flags, diff + 1, cInfo->DifficultyEntry[diff], difficultyInfo->type_flags);
- }
-
if (!cInfo->VehicleId && difficultyInfo->VehicleId)
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u, VehicleId %u) has different `VehicleId` in difficulty %u mode (Entry: %u, VehicleId %u).",
@@ -6012,8 +6006,9 @@ void ObjectMgr::LoadAccessRequirements()
_accessRequirementStore.clear(); // need for reload case
}
- // 0 1 2 3 4 5 6 7 8 9
- QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement");
+ // 0 1 2 3 4 5 6 7 8 9 10
+ QueryResult result = WorldDatabase.Query("SELECT mapid, difficulty, level_min, level_max, item_level, item, item2, quest_done_A, quest_done_H, completed_achievement, quest_failed_text FROM access_requirement");
+
if (!result)
{
TC_LOG_INFO("server.loading", ">> Loaded 0 access requirement definitions. DB table `access_requirement` is empty.");
@@ -6036,12 +6031,13 @@ void ObjectMgr::LoadAccessRequirements()
ar->levelMin = fields[2].GetUInt8();
ar->levelMax = fields[3].GetUInt8();
- ar->item = fields[4].GetUInt32();
- ar->item2 = fields[5].GetUInt32();
- ar->quest_A = fields[6].GetUInt32();
- ar->quest_H = fields[7].GetUInt32();
- ar->achievement = fields[8].GetUInt32();
- ar->questFailedText = fields[9].GetString();
+ ar->item_level = fields[4].GetUInt16();
+ ar->item = fields[5].GetUInt32();
+ ar->item2 = fields[6].GetUInt32();
+ ar->quest_A = fields[7].GetUInt32();
+ ar->quest_H = fields[8].GetUInt32();
+ ar->achievement = fields[9].GetUInt32();
+ ar->questFailedText = fields[10].GetString();
if (ar->item)
{
diff --git a/src/server/game/Groups/Group.cpp b/src/server/game/Groups/Group.cpp
index 354f00a9e91..a3fee2d52aa 100644
--- a/src/server/game/Groups/Group.cpp
+++ b/src/server/game/Groups/Group.cpp
@@ -99,6 +99,7 @@ bool Group::Create(Player* leader)
m_guid = MAKE_NEW_GUID(lowguid, 0, HIGHGUID_GROUP);
m_leaderGuid = leaderGuid;
m_leaderName = leader->GetName();
+ leader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
if (isBGGroup() || isBFGroup())
m_groupType = GROUPTYPE_BGRAID;
@@ -666,6 +667,10 @@ void Group::ChangeLeader(uint64 newLeaderGuid)
CharacterDatabase.CommitTransaction(trans);
}
+ if (Player* oldLeader = ObjectAccessor::FindPlayer(m_leaderGuid))
+ oldLeader->RemoveFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
+
+ newLeader->SetFlag(PLAYER_FLAGS, PLAYER_FLAGS_GROUP_LEADER);
m_leaderGuid = newLeader->GetGUID();
m_leaderName = newLeader->GetName();
ToggleGroupMemberFlag(slot, MEMBER_FLAG_ASSISTANT, false);
diff --git a/src/server/game/Handlers/CharacterHandler.cpp b/src/server/game/Handlers/CharacterHandler.cpp
index 4c7d1669233..333d4d893cd 100644
--- a/src/server/game/Handlers/CharacterHandler.cpp
+++ b/src/server/game/Handlers/CharacterHandler.cpp
@@ -1027,6 +1027,9 @@ void WorldSession::HandlePlayerLogin(LoginQueryHolder* holder)
m_playerLoading = false;
+ // Handle Login-Achievements (should be handled after loading)
+ _player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_ON_LOGIN, 1);
+
sScriptMgr->OnPlayerLogin(pCurrChar);
delete holder;
}
diff --git a/src/server/game/Handlers/ChatHandler.cpp b/src/server/game/Handlers/ChatHandler.cpp
index 17b5974d1ca..fbc78564ea5 100644
--- a/src/server/game/Handlers/ChatHandler.cpp
+++ b/src/server/game/Handlers/ChatHandler.cpp
@@ -55,6 +55,14 @@ void WorldSession::HandleMessagechatOpcode(WorldPacket& recvData)
return;
}
+ if (lang == LANG_UNIVERSAL && type != CHAT_MSG_AFK && type != CHAT_MSG_DND)
+ {
+ TC_LOG_ERROR("network", "CMSG_MESSAGECHAT: Possible hacking-attempt: %s tried to send a message in universal language", GetPlayerInfo().c_str());
+ SendNotification(LANG_UNKNOWN_LANGUAGE);
+ recvData.rfinish();
+ return;
+ }
+
Player* sender = GetPlayer();
//TC_LOG_DEBUG("CHAT: packet received. type %u, lang %u", type, lang);
diff --git a/src/server/game/Handlers/MiscHandler.cpp b/src/server/game/Handlers/MiscHandler.cpp
index fcec4f38852..60f4fb09c28 100644
--- a/src/server/game/Handlers/MiscHandler.cpp
+++ b/src/server/game/Handlers/MiscHandler.cpp
@@ -1135,7 +1135,6 @@ void WorldSession::HandleMoveRootAck(WorldPacket& recvData)
void WorldSession::HandleSetActionBarToggles(WorldPacket& recvData)
{
uint8 actionBar;
-
recvData >> actionBar;
if (!GetPlayer()) // ignore until not logged (check needed because STATUS_AUTHED)
diff --git a/src/server/game/Handlers/NPCHandler.cpp b/src/server/game/Handlers/NPCHandler.cpp
index 4d78064423c..fc14797ea94 100644
--- a/src/server/game/Handlers/NPCHandler.cpp
+++ b/src/server/game/Handlers/NPCHandler.cpp
@@ -390,7 +390,6 @@ void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket& recvData)
TC_LOG_DEBUG("network", "WORLD: CMSG_SPIRIT_HEALER_ACTIVATE");
uint64 guid;
-
recvData >> guid;
Creature* unit = GetPlayer()->GetNPCIfCanInteractWith(guid, UNIT_NPC_FLAG_SPIRITHEALER);
@@ -410,7 +409,6 @@ void WorldSession::HandleSpiritHealerActivateOpcode(WorldPacket& recvData)
void WorldSession::SendSpiritResurrect()
{
_player->ResurrectPlayer(0.5f, true);
-
_player->DurabilityLossAll(0.25f, true);
// get corpse nearest graveyard
diff --git a/src/server/game/Movement/MotionMaster.cpp b/src/server/game/Movement/MotionMaster.cpp
index d224c21efe8..55f745d993b 100644
--- a/src/server/game/Movement/MotionMaster.cpp
+++ b/src/server/game/Movement/MotionMaster.cpp
@@ -337,6 +337,9 @@ void MotionMaster::MoveKnockbackFrom(float srcX, float srcY, float speedXY, floa
if (_owner->GetTypeId() == TYPEID_PLAYER)
return;
+ if (speedXY <= 0.1f)
+ return;
+
float x, y, z;
float moveTimeHalf = speedZ / Movement::gravity;
float dist = 2 * moveTimeHalf * speedXY;
@@ -370,6 +373,8 @@ void MotionMaster::MoveJumpTo(float angle, float speedXY, float speedZ)
void MotionMaster::MoveJump(float x, float y, float z, float speedXY, float speedZ, uint32 id)
{
TC_LOG_DEBUG("misc", "Unit (GUID: %u) jump to point (X: %f Y: %f Z: %f)", _owner->GetGUIDLow(), x, y, z);
+ if (speedXY <= 0.1f)
+ return;
float moveTimeHalf = speedZ / Movement::gravity;
float max_height = -Movement::computeFallElevation(moveTimeHalf, false, -speedZ);
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index c769a0b6aea..b7aabcc7589 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -5843,6 +5843,13 @@ void AuraEffect::HandlePeriodicDamageAurasTick(Unit* target, Unit* caster) const
else
damage = uint32(target->CountPctFromMaxHealth(damage));
+ if (m_spellInfo->Effects[m_effIndex].IsTargetingArea() || m_spellInfo->Effects[m_effIndex].IsAreaAuraEffect() || m_spellInfo->Effects[m_effIndex].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
+ {
+ damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
+ if (caster->GetTypeId() != TYPEID_PLAYER)
+ damage = int32(float(damage) * target->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
+ }
+
bool crit = IsPeriodicTickCrit(target, caster);
if (crit)
damage = caster->SpellCriticalDamageBonus(m_spellInfo, damage, target);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index e72a1da563e..9098ac96376 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -1171,77 +1171,6 @@ void Spell::SelectImplicitAreaTargets(SpellEffIndex effIndex, SpellImplicitTarge
float radius = m_spellInfo->Effects[effIndex].CalcRadius(m_caster) * m_spellValue->RadiusMod;
SearchAreaTargets(targets, radius, center, referer, targetType.GetObjectType(), targetType.GetCheckType(), m_spellInfo->Effects[effIndex].ImplicitTargetConditions);
- // Custom entries
- /// @todo remove those
- switch (m_spellInfo->Id)
- {
- case 46584: // Raise Dead
- {
- if (Player* playerCaster = m_caster->ToPlayer())
- {
- for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
- {
- switch ((*itr)->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- {
- Unit* unitTarget = (*itr)->ToUnit();
- if (unitTarget->IsAlive() || !playerCaster->isHonorOrXPTarget(unitTarget)
- || ((unitTarget->GetCreatureTypeMask() & (1 << (CREATURE_TYPE_HUMANOID-1))) == 0)
- || (unitTarget->GetDisplayId() != unitTarget->GetNativeDisplayId()))
- break;
- AddUnitTarget(unitTarget, effMask, false);
- // no break;
- }
- case TYPEID_CORPSE: // wont work until corpses are allowed in target lists, but at least will send dest in packet
- m_targets.SetDst(*(*itr));
- return; // nothing more to do here
- default:
- break;
- }
- }
- }
- return; // don't add targets to target map
- }
- // Corpse Explosion
- case 49158:
- case 51325:
- case 51326:
- case 51327:
- case 51328:
- // check if our target is not valid (spell can target ghoul or dead unit)
- if (!(m_targets.GetUnitTarget() && m_targets.GetUnitTarget()->GetDisplayId() == m_targets.GetUnitTarget()->GetNativeDisplayId() &&
- ((m_targets.GetUnitTarget()->GetEntry() == 26125 && m_targets.GetUnitTarget()->GetOwnerGUID() == m_caster->GetGUID())
- || m_targets.GetUnitTarget()->isDead())))
- {
- // remove existing targets
- CleanupTargetList();
-
- for (std::list<WorldObject*>::iterator itr = targets.begin(); itr != targets.end(); ++itr)
- {
- switch ((*itr)->GetTypeId())
- {
- case TYPEID_UNIT:
- case TYPEID_PLAYER:
- if (!(*itr)->ToUnit()->isDead())
- break;
- AddUnitTarget((*itr)->ToUnit(), 1 << effIndex, false);
- return;
- default:
- break;
- }
- }
- if (m_caster->GetTypeId() == TYPEID_PLAYER)
- m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
- SendCastResult(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
- finish(false);
- }
- return;
- default:
- break;
- }
-
CallScriptObjectAreaTargetSelectHandlers(targets, effIndex);
if (!targets.empty())
@@ -4866,8 +4795,7 @@ SpellCastResult Spell::CheckCast(bool strict)
uint32 zone, area;
m_caster->GetZoneAndAreaId(zone, area);
- SpellCastResult locRes= m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area,
- m_caster->GetTypeId() == TYPEID_PLAYER ? m_caster->ToPlayer() : NULL);
+ SpellCastResult locRes = m_spellInfo->CheckLocation(m_caster->GetMapId(), zone, area, m_caster->ToPlayer());
if (locRes != SPELL_CAST_OK)
return locRes;
}
@@ -6722,10 +6650,10 @@ void Spell::DoAllEffectOnLaunchTarget(TargetInfo& targetInfo, float* multiplier)
if (m_damage > 0)
{
- if (m_spellInfo->Effects[i].IsTargetingArea())
+ if (m_spellInfo->Effects[i].IsTargetingArea() || m_spellInfo->Effects[i].IsAreaAuraEffect() || m_spellInfo->Effects[i].IsEffect(SPELL_EFFECT_PERSISTENT_AREA_AURA))
{
m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
- if (m_caster->GetTypeId() == TYPEID_UNIT)
+ if (m_caster->GetTypeId() != TYPEID_PLAYER)
m_damage = int32(float(m_damage) * unit->GetTotalAuraMultiplierByMiscMask(SPELL_AURA_MOD_CREATURE_AOE_DAMAGE_AVOIDANCE, m_spellInfo->SchoolMask));
if (m_caster->GetTypeId() == TYPEID_PLAYER)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 76be075e94d..031311f2749 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -557,7 +557,7 @@ class Spell
GameObject* focusObject;
// Damage and healing in effects need just calculate
- int32 m_damage; // Damge in effects count here
+ int32 m_damage; // Damage in effects count here
int32 m_healing; // Healing in effects count here
// ******************************************
diff --git a/src/server/game/Spells/SpellEffects.cpp b/src/server/game/Spells/SpellEffects.cpp
index b2b4690f893..19cc2fe95c5 100644
--- a/src/server/game/Spells/SpellEffects.cpp
+++ b/src/server/game/Spells/SpellEffects.cpp
@@ -682,11 +682,6 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
if (!unitTarget && !gameObjTarget && !itemTarget)
return;
- uint32 spell_id = 0;
- int32 bp = 0;
- bool triggered = true;
- SpellCastTargets targets;
-
// selection by spell family
switch (m_spellInfo->SpellFamilyName)
{
@@ -723,60 +718,10 @@ void Spell::EffectDummy(SpellEffIndex effIndex)
}
}
break;
- case SPELLFAMILY_DEATHKNIGHT:
- switch (m_spellInfo->Id)
- {
- case 46584: // Raise Dead
- if (m_caster->GetTypeId() != TYPEID_PLAYER)
- return;
-
- // Do we have talent Master of Ghouls?
- if (m_caster->HasAura(52143))
- // summon as pet
- bp = 52150;
- else
- // or guardian
- bp = 46585;
-
- if (m_targets.HasDst())
- targets.SetDst(*m_targets.GetDstPos());
- else
- {
- targets.SetDst(*m_caster);
- // Corpse not found - take reagents (only not triggered cast can take them)
- triggered = false;
- }
- // Remove cooldown - summon spellls have category
- m_caster->ToPlayer()->RemoveSpellCooldown(m_spellInfo->Id, true);
- spell_id = 48289;
- break;
- // Raise dead - take reagents and trigger summon spells
- case 48289:
- if (m_targets.HasDst())
- targets.SetDst(*m_targets.GetDstPos());
- spell_id = CalculateDamage(0, NULL);
- break;
- }
+ default:
break;
}
- //spells triggered by dummy effect should not miss
- if (spell_id)
- {
- SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spell_id);
-
- if (!spellInfo)
- {
- TC_LOG_ERROR("spells", "EffectDummy of spell %u: triggering unknown spell id %i\n", m_spellInfo->Id, spell_id);
- return;
- }
-
- targets.SetUnitTarget(unitTarget);
- Spell* spell = new Spell(m_caster, spellInfo, triggered ? TRIGGERED_FULL_MASK : TRIGGERED_NONE, m_originalCasterGUID, true);
- if (bp) spell->SetSpellValue(SPELLVALUE_BASE_POINT0, bp);
- spell->prepare(&targets);
- }
-
// pet auras
if (PetAura const* petSpell = sSpellMgr->GetPetAura(m_spellInfo->Id, effIndex))
{
@@ -910,7 +855,7 @@ void Spell::EffectTriggerSpell(SpellEffIndex effIndex)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
if (!spellInfo)
{
- TC_LOG_DEBUG("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
+ TC_LOG_ERROR("spells", "Spell::EffectTriggerSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
return;
}
@@ -962,7 +907,7 @@ void Spell::EffectTriggerMissileSpell(SpellEffIndex effIndex)
SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(triggered_spell_id);
if (!spellInfo)
{
- TC_LOG_DEBUG("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
+ TC_LOG_ERROR("spells", "Spell::EffectTriggerMissileSpell spell %u tried to trigger unknown spell %u", m_spellInfo->Id, triggered_spell_id);
return;
}
diff --git a/src/server/game/Spells/SpellMgr.cpp b/src/server/game/Spells/SpellMgr.cpp
index 8b31e749c62..93f264d2d61 100644
--- a/src/server/game/Spells/SpellMgr.cpp
+++ b/src/server/game/Spells/SpellMgr.cpp
@@ -2714,8 +2714,39 @@ void SpellMgr::UnloadSpellInfoImplicitTargetConditionLists()
void SpellMgr::LoadSpellInfoCustomAttributes()
{
uint32 oldMSTime = getMSTime();
-
+ uint32 oldMSTime2 = oldMSTime;
SpellInfo* spellInfo = NULL;
+
+ QueryResult result = WorldDatabase.Query("SELECT entry, attributes FROM spell_custom_attr");
+
+ if (!result)
+ TC_LOG_INFO("server.loading", ">> Loaded 0 spell custom attributes from DB. DB table `spell_custom_attr` is empty.");
+ else
+ {
+ uint32 count = 0;
+ do
+ {
+ Field* fields = result->Fetch();
+
+ uint32 spellId = fields[0].GetUInt32();
+ uint32 attributes = fields[1].GetUInt32();
+
+ spellInfo = _GetSpellInfo(spellId);
+ if (!spellInfo)
+ {
+ TC_LOG_ERROR("sql.sql", "Table `spell_custom_attr` has wrong spell (entry: %u), ignored.", spellId);
+ continue;
+ }
+
+ // TODO: validate attributes
+
+ spellInfo->AttributesCu |= attributes;
+ ++count;
+ } while (result->NextRow());
+
+ TC_LOG_INFO("server.loading", ">> Loaded %u spell custom attributes from DB in %u ms", count, GetMSTimeDiffToNow(oldMSTime2));
+ }
+
for (uint32 i = 0; i < GetSpellInfoStoreSize(); ++i)
{
spellInfo = mSpellInfoMap[i];
@@ -2826,171 +2857,6 @@ void SpellMgr::LoadSpellInfoCustomAttributes()
if (spellInfo->SpellVisual[0] == 3879)
spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_BACK;
- switch (spellInfo->Id)
- {
- case 1776: // Gouge
- case 1777:
- case 8629:
- case 11285:
- case 11286:
- case 12540:
- case 13579:
- case 24698:
- case 28456:
- case 29425:
- case 34940:
- case 36862:
- case 38764:
- case 38863:
- case 52743: // Head Smack
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_REQ_TARGET_FACING_CASTER;
- break;
- case 53: // Backstab
- case 2589:
- case 2590:
- case 2591:
- case 7159:
- case 8627:
- case 8721:
- case 11279:
- case 11280:
- case 11281:
- case 15582:
- case 15657:
- case 22416:
- case 25300:
- case 26863:
- case 37685:
- case 48656:
- case 48657:
- case 703: // Garrote
- case 8631:
- case 8632:
- case 8633:
- case 11289:
- case 11290:
- case 26839:
- case 26884:
- case 48675:
- case 48676:
- case 5221: // Shred
- case 6800:
- case 8992:
- case 9829:
- case 9830:
- case 27001:
- case 27002:
- case 48571:
- case 48572:
- case 8676: // Ambush
- case 8724:
- case 8725:
- case 11267:
- case 11268:
- case 11269:
- case 27441:
- case 48689:
- case 48690:
- case 48691:
- case 6785: // Ravage
- case 6787:
- case 9866:
- case 9867:
- case 27005:
- case 48578:
- case 48579:
- case 21987: // Lash of Pain
- case 23959: // Test Stab R50
- case 24825: // Test Backstab
- case 58563: // Assassinate Restless Lookout
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_REQ_CASTER_BEHIND_TARGET;
- break;
- case 26029: // Dark Glare
- case 37433: // Spout
- case 43140: // Flame Breath
- case 43215: // Flame Breath
- case 70461: // Coldflame Trap
- case 72133: // Pain and Suffering
- case 73788: // Pain and Suffering
- case 73789: // Pain and Suffering
- case 73790: // Pain and Suffering
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_CONE_LINE;
- break;
- case 24340: // Meteor
- case 26558: // Meteor
- case 28884: // Meteor
- case 36837: // Meteor
- case 38903: // Meteor
- case 41276: // Meteor
- case 57467: // Meteor
- case 26789: // Shard of the Fallen Star
- case 31436: // Malevolent Cleave
- case 35181: // Dive Bomb
- case 40810: // Saber Lash
- case 43267: // Saber Lash
- case 43268: // Saber Lash
- case 42384: // Brutal Swipe
- case 45150: // Meteor Slash
- case 64688: // Sonic Screech
- case 72373: // Shared Suffering
- case 71904: // Chaos Bane
- case 70492: // Ooze Eruption
- case 72505: // Ooze Eruption
- case 72624: // Ooze Eruption
- case 72625: // Ooze Eruption
- // ONLY SPELLS WITH SPELLFAMILY_GENERIC and EFFECT_SCHOOL_DAMAGE
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE;
- break;
- case 18500: // Wing Buffet
- case 33086: // Wild Bite
- case 49749: // Piercing Blow
- case 52890: // Penetrating Strike
- case 53454: // Impale
- case 59446: // Impale
- case 62383: // Shatter
- case 64777: // Machine Gun
- case 65239: // Machine Gun
- case 65919: // Impale
- case 67858: // Impale
- case 67859: // Impale
- case 67860: // Impale
- case 69293: // Wing Buffet
- case 74439: // Machine Gun
- case 63278: // Mark of the Faceless (General Vezax)
- case 62544: // Thrust (Argent Tournament)
- case 64588: // Thrust (Argent Tournament)
- case 66479: // Thrust (Argent Tournament)
- case 68505: // Thrust (Argent Tournament)
- case 62709: // Counterattack! (Argent Tournament)
- case 62626: // Break-Shield (Argent Tournament, Player)
- case 64590: // Break-Shield (Argent Tournament, Player)
- case 64342: // Break-Shield (Argent Tournament, NPC)
- case 64686: // Break-Shield (Argent Tournament, NPC)
- case 65147: // Break-Shield (Argent Tournament, NPC)
- case 68504: // Break-Shield (Argent Tournament, NPC)
- case 62874: // Charge (Argent Tournament, Player)
- case 68498: // Charge (Argent Tournament, Player)
- case 64591: // Charge (Argent Tournament, Player)
- case 63003: // Charge (Argent Tournament, NPC)
- case 63010: // Charge (Argent Tournament, NPC)
- case 68321: // Charge (Argent Tournament, NPC)
- case 72255: // Mark of the Fallen Champion (Deathbringer Saurfang)
- case 72444: // Mark of the Fallen Champion (Deathbringer Saurfang)
- case 72445: // Mark of the Fallen Champion (Deathbringer Saurfang)
- case 72446: // Mark of the Fallen Champion (Deathbringer Saurfang)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR;
- break;
- case 64422: // Sonic Screech (Auriaya)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_SHARE_DAMAGE;
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_IGNORE_ARMOR;
- break;
- case 72293: // Mark of the Fallen Champion (Deathbringer Saurfang)
- spellInfo->AttributesCu |= SPELL_ATTR0_CU_NEGATIVE_EFF0;
- break;
- default:
- break;
- }
-
switch (spellInfo->SpellFamilyName)
{
case SPELLFAMILY_WARRIOR:
diff --git a/src/server/game/Spells/SpellScript.cpp b/src/server/game/Spells/SpellScript.cpp
index c7eebb495c0..c0bcd477e5b 100644
--- a/src/server/game/Spells/SpellScript.cpp
+++ b/src/server/game/Spells/SpellScript.cpp
@@ -576,16 +576,28 @@ void SpellScript::PreventHitDefaultEffect(SpellEffIndex effIndex)
m_hitPreventDefaultEffectMask |= 1 << effIndex;
}
-int32 SpellScript::GetEffectValue()
+int32 SpellScript::GetEffectValue() const
{
if (!IsInEffectHook())
{
- TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::PreventHitDefaultEffect was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
+ TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::GetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
return 0;
}
+
return m_spell->damage;
}
+void SpellScript::SetEffectValue(int32 value)
+{
+ if (!IsInEffectHook())
+ {
+ TC_LOG_ERROR("scripts", "Script: `%s` Spell: `%u`: function SpellScript::SetEffectValue was called, but function has no effect in current hook!", m_scriptName->c_str(), m_scriptSpellId);
+ return;
+ }
+
+ m_spell->damage = value;
+}
+
Item* SpellScript::GetCastItem()
{
return m_spell->m_CastItem;
diff --git a/src/server/game/Spells/SpellScript.h b/src/server/game/Spells/SpellScript.h
index dfa494e38e6..6378a8bed9b 100644
--- a/src/server/game/Spells/SpellScript.h
+++ b/src/server/game/Spells/SpellScript.h
@@ -411,7 +411,8 @@ class SpellScript : public _SpellScript
void PreventHitDefaultEffect(SpellEffIndex effIndex);
// method avalible only in EffectHandler method
- int32 GetEffectValue();
+ int32 GetEffectValue() const;
+ void SetEffectValue(int32 value);
// returns: cast item if present.
Item* GetCastItem();
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index 3fde3ad4a11..af2fb90ea1b 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -1262,6 +1262,8 @@ void World::LoadConfigSettings(bool reload)
m_int_configs[CONFIG_PACKET_SPOOF_BANDURATION] = sConfigMgr->GetIntDefault("PacketSpoof.BanDuration", 86400);
+ m_int_configs[CONFIG_BIRTHDAY_TIME] = sConfigMgr->GetIntDefault("BirthdayTime", 1222964635);
+
// call ScriptMgr if we're reloading the configuration
if (reload)
sScriptMgr->OnConfigLoad(reload);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index a320933e181..4c43507d038 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -339,6 +339,7 @@ enum WorldIntConfigs
CONFIG_BG_REWARD_WINNER_ARENA_LAST,
CONFIG_BG_REWARD_LOSER_HONOR_FIRST,
CONFIG_BG_REWARD_LOSER_HONOR_LAST,
+ CONFIG_BIRTHDAY_TIME,
INT_CONFIG_VALUE_COUNT
};
diff --git a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
index 027a6843c87..1f4713415ac 100644
--- a/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
+++ b/src/server/scripts/Northrend/FrozenHalls/HallsOfReflection/halls_of_reflection.cpp
@@ -1837,7 +1837,6 @@ public:
void IsSummonedBy(Unit*) OVERRIDE
{
DoCast(me, SPELL_EMERGE_VISUAL);
- DoZoneInCombat(me, 100.00f);
}
void JustDied(Unit* /*killer*/) OVERRIDE
diff --git a/src/server/scripts/Outland/zone_nagrand.cpp b/src/server/scripts/Outland/zone_nagrand.cpp
index 8d5c81d1c01..9b7a3f8aa2a 100644
--- a/src/server/scripts/Outland/zone_nagrand.cpp
+++ b/src/server/scripts/Outland/zone_nagrand.cpp
@@ -182,13 +182,11 @@ public:
{
if (quest->GetQuestId() == QUEST_TOTEM_KARDASH_H)
{
- if (npc_maghar_captiveAI* pEscortAI = dynamic_cast<npc_maghar_captiveAI*>(creature->AI()))
+ if (npc_maghar_captiveAI* EscortAI = dynamic_cast<npc_maghar_captiveAI*>(creature->AI()))
{
creature->SetStandState(UNIT_STAND_STATE_STAND);
creature->setFaction(232);
-
- pEscortAI->Start(true, false, player->GetGUID(), quest);
-
+ EscortAI->Start(true, false, player->GetGUID(), quest);
creature->AI()->Talk(SAY_MAG_START);
creature->SummonCreature(NPC_MURK_RAIDER, m_afAmbushA[0]+2.5f, m_afAmbushA[1]-2.5f, m_afAmbushA[2], 0.0f, TEMPSUMMON_TIMED_DESPAWN_OUT_OF_COMBAT, 25000);
@@ -208,15 +206,15 @@ public:
{
npc_maghar_captiveAI(Creature* creature) : npc_escortAI(creature) { Reset(); }
- uint32 m_uiChainLightningTimer;
- uint32 m_uiHealTimer;
- uint32 m_uiFrostShockTimer;
+ uint32 ChainLightningTimer;
+ uint32 HealTimer;
+ uint32 FrostShockTimer;
void Reset() OVERRIDE
{
- m_uiChainLightningTimer = 1000;
- m_uiHealTimer = 0;
- m_uiFrostShockTimer = 6000;
+ ChainLightningTimer = 1000;
+ HealTimer = 0;
+ FrostShockTimer = 6000;
}
void EnterCombat(Unit* /*who*/) OVERRIDE
@@ -224,6 +222,18 @@ public:
DoCast(me, SPELL_EARTHBIND_TOTEM, false);
}
+ void JustDied(Unit* /*killer*/) OVERRIDE
+ {
+ if (!HasEscortState(STATE_ESCORT_ESCORTING))
+ return;
+
+ if (Player* player = GetPlayerForEscort())
+ {
+ if (player->GetQuestStatus(QUEST_TOTEM_KARDASH_H) != QUEST_STATUS_COMPLETE)
+ player->FailQuest(QUEST_TOTEM_KARDASH_H);
+ }
+ }
+
void WaypointReached(uint32 waypointId) OVERRIDE
{
switch (waypointId)
@@ -263,9 +273,9 @@ public:
}
- void SpellHitTarget(Unit* /*target*/, const SpellInfo* pSpell) OVERRIDE
+ void SpellHitTarget(Unit* /*target*/, const SpellInfo* spell) OVERRIDE
{
- if (pSpell->Id == SPELL_CHAIN_LIGHTNING)
+ if (spell->Id == SPELL_CHAIN_LIGHTNING)
{
if (rand()%10)
return;
@@ -274,38 +284,42 @@ public:
}
}
- void UpdateAI(uint32 uiDiff) OVERRIDE
+ void UpdateAI(uint32 diff) OVERRIDE
{
- npc_escortAI::UpdateAI(uiDiff);
- if (!me->GetVictim())
+ npc_escortAI::UpdateAI(diff);
+
+ if (!UpdateVictim())
+ return;
+
+ if (me->HasUnitState(UNIT_STATE_CASTING))
return;
- if (m_uiChainLightningTimer <= uiDiff)
+ if (ChainLightningTimer <= diff)
{
DoCastVictim(SPELL_CHAIN_LIGHTNING);
- m_uiChainLightningTimer = urand(7000, 14000);
+ ChainLightningTimer = urand(7000, 14000);
}
else
- m_uiChainLightningTimer -= uiDiff;
+ ChainLightningTimer -= diff;
if (HealthBelowPct(30))
{
- if (m_uiHealTimer <= uiDiff)
+ if (HealTimer <= diff)
{
DoCast(me, SPELL_HEALING_WAVE);
- m_uiHealTimer = 5000;
+ HealTimer = 5000;
}
else
- m_uiHealTimer -= uiDiff;
+ HealTimer -= diff;
}
- if (m_uiFrostShockTimer <= uiDiff)
+ if (FrostShockTimer <= diff)
{
DoCastVictim(SPELL_FROST_SHOCK);
- m_uiFrostShockTimer = urand(7500, 15000);
+ FrostShockTimer = urand(7500, 15000);
}
else
- m_uiFrostShockTimer -= uiDiff;
+ FrostShockTimer -= diff;
DoMeleeAttackIfReady();
}
@@ -517,6 +531,7 @@ public:
if (npc_kurenai_captiveAI* EscortAI = dynamic_cast<npc_kurenai_captiveAI*>(creature->AI()))
{
creature->SetStandState(UNIT_STAND_STATE_STAND);
+ creature->setFaction(231);
EscortAI->Start(true, false, player->GetGUID(), quest);
creature->AI()->Talk(SAY_KUR_START);
@@ -629,6 +644,8 @@ public:
void UpdateAI(uint32 diff) OVERRIDE
{
+ npc_escortAI::UpdateAI(diff);
+
if (!UpdateVictim())
return;
diff --git a/src/server/scripts/Spells/spell_dk.cpp b/src/server/scripts/Spells/spell_dk.cpp
index e2e4d30541c..e8108f03e7d 100644
--- a/src/server/scripts/Spells/spell_dk.cpp
+++ b/src/server/scripts/Spells/spell_dk.cpp
@@ -25,6 +25,7 @@
#include "ScriptMgr.h"
#include "SpellScript.h"
#include "SpellAuraEffects.h"
+#include "Containers.h"
enum DeathKnightSpells
{
@@ -49,6 +50,8 @@ enum DeathKnightSpells
SPELL_DK_IMPROVED_UNHOLY_PRESENCE_TRIGGERED = 63622,
SPELL_DK_ITEM_SIGIL_VENGEFUL_HEART = 64962,
SPELL_DK_ITEM_T8_MELEE_4P_BONUS = 64736,
+ SPELL_DK_MASTER_OF_GHOULS = 52143,
+ SPELL_DK_RAISE_DEAD_USE_REAGENT = 48289,
SPELL_DK_RUNIC_POWER_ENERGIZE = 49088,
SPELL_DK_SCENT_OF_BLOOD = 50422,
SPELL_DK_SCOURGE_STRIKE_TRIGGERED = 70890,
@@ -63,6 +66,11 @@ enum DeathKnightSpellIcons
DK_ICON_ID_IMPROVED_DEATH_STRIKE = 2751
};
+enum Misc
+{
+ NPC_DK_GHOUL = 26125
+};
+
// 50462 - Anti-Magic Shell (on raid member)
class spell_dk_anti_magic_shell_raid : public SpellScriptLoader
{
@@ -311,6 +319,28 @@ class spell_dk_blood_gorged : public SpellScriptLoader
}
};
+class CorpseExplosionCheck
+{
+public:
+ explicit CorpseExplosionCheck(uint64 casterGUID) : _casterGUID(casterGUID) { }
+
+ bool operator()(WorldObject* obj) const
+ {
+ if (Unit* target = obj->ToUnit())
+ {
+ if ((target->isDead() || (target->GetEntry() == NPC_DK_GHOUL && target->GetOwnerGUID() == _casterGUID))
+ && !(target->GetCreatureTypeMask() & CREATURE_TYPEMASK_MECHANICAL_OR_ELEMENTAL)
+ && target->GetDisplayId() == target->GetNativeDisplayId())
+ return false;
+ }
+
+ return true;
+ }
+
+private:
+ uint64 _casterGUID;
+};
+
// 49158 - Corpse Explosion (51325, 51326, 51327, 51328)
class spell_dk_corpse_explosion : public SpellScriptLoader
{
@@ -321,41 +351,87 @@ class spell_dk_corpse_explosion : public SpellScriptLoader
{
PrepareSpellScript(spell_dk_corpse_explosion_SpellScript);
- bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ bool Validate(SpellInfo const* spellInfo) OVERRIDE
{
- if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED) || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE))
- return false;
- if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL))
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)
+ || !sSpellMgr->GetSpellInfo(SPELL_DK_GHOUL_EXPLODE)
+ || !sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_VISUAL)
+ || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue()))
return false;
return true;
}
- void HandleDummy(SpellEffIndex /*effIndex*/)
+ bool Load() OVERRIDE
+ {
+ _target = NULL;
+ return true;
+ }
+
+ void CheckTarget(WorldObject*& target)
+ {
+ if (CorpseExplosionCheck(GetCaster()->GetGUID())(target))
+ target = NULL;
+
+ _target = target;
+ }
+
+ void CheckTargets(std::list<WorldObject*>& targets)
+ {
+ WorldObject* target = _target;
+ if (!target)
+ {
+ targets.remove_if(CorpseExplosionCheck(GetCaster()->GetGUID()));
+ if (targets.empty())
+ {
+ FinishCast(SPELL_FAILED_CANT_DO_THAT_RIGHT_NOW);
+ return;
+ }
+ target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ }
+ else
+ targets.clear();
+ }
+
+ void HandleDamage(SpellEffIndex effIndex, Unit* target)
+ {
+ if (effIndex == EFFECT_0)
+ GetCaster()->CastCustomSpell(GetSpellInfo()->Effects[EFFECT_1].CalcValue(), SPELLVALUE_BASE_POINT0, GetEffectValue(), target, true);
+ else if (effIndex == EFFECT_1)
+ GetCaster()->CastCustomSpell(GetEffectValue(), SPELLVALUE_BASE_POINT0, GetSpell()->CalculateDamage(EFFECT_0, NULL), target, true);
+ }
+
+ void HandleCorpseExplosion(SpellEffIndex effIndex)
{
if (Unit* unitTarget = GetHitUnit())
{
- int32 bp = 0;
if (unitTarget->IsAlive()) // Living ghoul as a target
{
- bp = int32(unitTarget->CountPctFromMaxHealth(25));
- unitTarget->CastCustomSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, &bp, NULL, NULL, false);
+ unitTarget->CastSpell(unitTarget, SPELL_DK_GHOUL_EXPLODE, false);
+ // Corpse Explosion (Suicide) and Set corpse look handled in SpellScript of SPELL_DK_GHOUL_EXPLODE
}
else // Some corpse
{
- bp = GetEffectValue();
- GetCaster()->CastCustomSpell(unitTarget, GetSpellInfo()->Effects[EFFECT_1].CalcValue(), &bp, NULL, NULL, true);
+ HandleDamage(effIndex, unitTarget);
// Corpse Explosion (Suicide)
unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true);
+ // Set corpse look
+ GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
- // Set corpse look
- GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
}
void Register() OVERRIDE
{
- OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleDummy, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTarget, EFFECT_0, TARGET_UNIT_TARGET_ANY);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_corpse_explosion_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY);
+ OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_0, SPELL_EFFECT_DUMMY);
+ OnEffectHitTarget += SpellEffectFn(spell_dk_corpse_explosion_SpellScript::HandleCorpseExplosion, EFFECT_1, SPELL_EFFECT_DUMMY);
}
+
+ private:
+ WorldObject* _target;
};
SpellScript* GetSpellScript() const OVERRIDE
@@ -616,24 +692,34 @@ class spell_dk_ghoul_explode : public SpellScriptLoader
{
PrepareSpellScript(spell_dk_ghoul_explode_SpellScript);
- bool Validate(SpellInfo const* /*spellInfo*/) OVERRIDE
+ bool Validate(SpellInfo const* spellInfo) OVERRIDE
{
- if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED))
+ if (!sSpellMgr->GetSpellInfo(SPELL_DK_CORPSE_EXPLOSION_TRIGGERED)
+ || spellInfo->Effects[EFFECT_2].CalcValue() <= 0)
return false;
return true;
}
+ void HandleDamage(SpellEffIndex /*effIndex*/)
+ {
+ int32 value = int32(GetCaster()->CountPctFromMaxHealth(GetSpellInfo()->Effects[EFFECT_2].CalcValue(GetCaster())));
+ SetEffectValue(value);
+ }
+
void Suicide(SpellEffIndex /*effIndex*/)
{
if (Unit* unitTarget = GetHitUnit())
{
// Corpse Explosion (Suicide)
unitTarget->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_TRIGGERED, true);
+ // Set corpse look
+ GetCaster()->CastSpell(unitTarget, SPELL_DK_CORPSE_EXPLOSION_VISUAL, true);
}
}
void Register() OVERRIDE
{
+ OnEffectLaunchTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::HandleDamage, EFFECT_0, SPELL_EFFECT_SCHOOL_DAMAGE);
OnEffectHitTarget += SpellEffectFn(spell_dk_ghoul_explode_SpellScript::Suicide, EFFECT_1, SPELL_EFFECT_SCHOOL_DAMAGE);
}
};
@@ -940,6 +1026,162 @@ class spell_dk_presence : public SpellScriptLoader
}
};
+class RaiseDeadCheck
+{
+ public:
+ explicit RaiseDeadCheck(Player const* caster) : _caster(caster) { }
+
+ bool operator()(WorldObject* obj) const
+ {
+ if (Unit* target = obj->ToUnit())
+ {
+ if (!target->IsAlive()
+ && _caster->isHonorOrXPTarget(target)
+ && target->GetCreatureType() == CREATURE_TYPE_HUMANOID
+ && target->GetDisplayId() == target->GetNativeDisplayId())
+ return false;
+ }
+
+ return true;
+ }
+
+ private:
+ Player const* _caster;
+};
+
+// 46584 - Raise Dead
+class spell_dk_raise_dead : public SpellScriptLoader
+{
+ public:
+ spell_dk_raise_dead() : SpellScriptLoader("spell_dk_raise_dead") { }
+
+ class spell_dk_raise_dead_SpellScript : public SpellScript
+ {
+ PrepareSpellScript(spell_dk_raise_dead_SpellScript);
+
+ bool Validate(SpellInfo const* spellInfo) OVERRIDE
+ {
+ if (!sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_1].CalcValue())
+ || !sSpellMgr->GetSpellInfo(spellInfo->Effects[EFFECT_2].CalcValue())
+ || !sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT)
+ || !sSpellMgr->GetSpellInfo(SPELL_DK_MASTER_OF_GHOULS))
+ return false;
+ return true;
+ }
+
+ bool Load() OVERRIDE
+ {
+ _result = SPELL_CAST_OK;
+ _corpse = false;
+ return GetCaster()->GetTypeId() == TYPEID_PLAYER;
+ }
+
+ SpellCastResult CheckCast()
+ {
+ /// process spell target selection before cast starts
+ /// targets of effect_1 are used to check cast
+ GetSpell()->SelectSpellTargets();
+ /// cleanup spell target map, and fill it again on normal way
+ GetSpell()->CleanupTargetList();
+ /// _result is set in spell target selection
+ return _result;
+ }
+
+ SpellCastResult CheckReagents()
+ {
+ /// @workaround: there is no access to castresult of other spells, check it manually
+ SpellInfo const* reagentSpell = sSpellMgr->GetSpellInfo(SPELL_DK_RAISE_DEAD_USE_REAGENT);
+ Player* player = GetCaster()->ToPlayer();
+ if (!player->CanNoReagentCast(reagentSpell))
+ {
+ for (uint32 i = 0; i < MAX_SPELL_REAGENTS; i++)
+ {
+ if (reagentSpell->Reagent[i] <= 0)
+ continue;
+
+ if (!player->HasItemCount(reagentSpell->Reagent[i], reagentSpell->ReagentCount[i]))
+ {
+ Spell::SendCastResult(player, reagentSpell, 0, SPELL_FAILED_REAGENTS);
+ return SPELL_FAILED_DONT_REPORT;
+ }
+ }
+ }
+ return SPELL_CAST_OK;
+ }
+
+ void CheckTargets(std::list<WorldObject*>& targets)
+ {
+ targets.remove_if(RaiseDeadCheck(GetCaster()->ToPlayer()));
+
+ if (targets.empty())
+ {
+ if (GetSpell()->getState() == SPELL_STATE_PREPARING)
+ _result = CheckReagents();
+
+ return;
+ }
+
+ WorldObject* target = Trinity::Containers::SelectRandomContainerElement(targets);
+ targets.clear();
+ targets.push_back(target);
+ _corpse = true;
+ }
+
+ void CheckTarget(WorldObject*& target)
+ {
+ // Don't add caster to target map, if we found a corpse to raise dead
+ if (_corpse)
+ target = NULL;
+ }
+
+ void ConsumeReagents()
+ {
+ // No corpse found, take reagents
+ if (!_corpse)
+ GetCaster()->CastSpell(GetCaster(), SPELL_DK_RAISE_DEAD_USE_REAGENT, TriggerCastFlags(TRIGGERED_FULL_MASK & ~TRIGGERED_IGNORE_POWER_AND_REAGENT_COST));
+ }
+
+ uint32 GetGhoulSpellId()
+ {
+ // Do we have talent Master of Ghouls?
+ if (GetCaster()->HasAura(SPELL_DK_MASTER_OF_GHOULS))
+ // summon as pet
+ return GetSpellInfo()->Effects[EFFECT_2].CalcValue();
+
+ // or guardian
+ return GetSpellInfo()->Effects[EFFECT_1].CalcValue();
+ }
+
+ void HandleRaiseDead(SpellEffIndex /*effIndex*/)
+ {
+ SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(GetGhoulSpellId());
+ SpellCastTargets targets;
+ targets.SetDst(*GetHitUnit());
+
+ GetCaster()->CastSpell(targets, spellInfo, NULL, TRIGGERED_FULL_MASK);
+ }
+
+ void Register() OVERRIDE
+ {
+ OnCheckCast += SpellCheckCastFn(spell_dk_raise_dead_SpellScript::CheckCast);
+ OnObjectAreaTargetSelect += SpellObjectAreaTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTargets, EFFECT_1, TARGET_UNIT_DEST_AREA_ENTRY);
+ OnObjectTargetSelect += SpellObjectTargetSelectFn(spell_dk_raise_dead_SpellScript::CheckTarget, EFFECT_2, TARGET_UNIT_CASTER);
+ OnCast += SpellCastFn(spell_dk_raise_dead_SpellScript::ConsumeReagents);
+ OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_1, SPELL_EFFECT_SCRIPT_EFFECT);
+ OnEffectHitTarget += SpellEffectFn(spell_dk_raise_dead_SpellScript::HandleRaiseDead, EFFECT_2, SPELL_EFFECT_DUMMY);
+ }
+
+ private:
+ SpellCastResult _result;
+ bool _corpse;
+ };
+
+ SpellScript* GetSpellScript() const OVERRIDE
+ {
+ return new spell_dk_raise_dead_SpellScript();
+ }
+};
+
// 59754 Rune Tap - Party
class spell_dk_rune_tap_party : public SpellScriptLoader
{
@@ -1224,6 +1466,7 @@ void AddSC_deathknight_spell_scripts()
new spell_dk_improved_frost_presence();
new spell_dk_improved_unholy_presence();
new spell_dk_presence();
+ new spell_dk_raise_dead();
new spell_dk_rune_tap_party();
new spell_dk_scent_of_blood();
new spell_dk_scourge_strike();
diff --git a/src/server/shared/CompilerDefs.h b/src/server/shared/CompilerDefs.h
index 71b20a4d175..8a557328af4 100644
--- a/src/server/shared/CompilerDefs.h
+++ b/src/server/shared/CompilerDefs.h
@@ -57,6 +57,8 @@
#if defined(__cplusplus) && __cplusplus == 201103L
# define COMPILER_HAS_CPP11_SUPPORT 1
+#elif _MSC_VER >= 1700
+# define COMPILER_HAS_CPP11_SUPPORT 1
#else
# define COMPILER_HAS_CPP11_SUPPORT 0
#endif
diff --git a/src/server/shared/Utilities/ByteConverter.h b/src/server/shared/Utilities/ByteConverter.h
index bf1342a10e4..8eebb05bb13 100644
--- a/src/server/shared/Utilities/ByteConverter.h
+++ b/src/server/shared/Utilities/ByteConverter.h
@@ -47,9 +47,13 @@ namespace ByteConverter
#if TRINITY_ENDIAN == TRINITY_BIGENDIAN
template<typename T> inline void EndianConvert(T& val) { ByteConverter::apply<T>(&val); }
template<typename T> inline void EndianConvertReverse(T&) { }
+template<typename T> inline void EndianConvertPtr(void* val) { ByteConverter::apply<T>(val); }
+template<typename T> inline void EndianConvertPtrReverse(void*) { }
#else
template<typename T> inline void EndianConvert(T&) { }
template<typename T> inline void EndianConvertReverse(T& val) { ByteConverter::apply<T>(&val); }
+template<typename T> inline void EndianConvertPtr(void*) { }
+template<typename T> inline void EndianConvertPtrReverse(void* val) { ByteConverter::apply<T>(val); }
#endif
template<typename T> void EndianConvert(T*); // will generate link error
diff --git a/src/server/shared/Utilities/Util.cpp b/src/server/shared/Utilities/Util.cpp
index 499ad0502b7..ffef61557fc 100644
--- a/src/server/shared/Utilities/Util.cpp
+++ b/src/server/shared/Utilities/Util.cpp
@@ -510,6 +510,9 @@ void vutf8printf(FILE* out, const char *str, va_list* ap)
wchar_t wtemp_buf[32*1024];
size_t temp_len = vsnprintf(temp_buf, 32*1024, str, *ap);
+ //vsnprintf returns -1 if the buffer is too small
+ if (temp_len == size_t(-1))
+ temp_len = 32*1024-1;
size_t wtemp_len = 32*1024-1;
Utf8toWStr(temp_buf, temp_len, wtemp_buf, wtemp_len);
diff --git a/src/server/worldserver/worldserver.conf.dist b/src/server/worldserver/worldserver.conf.dist
index 2a47c8f989e..1762859afae 100644
--- a/src/server/worldserver/worldserver.conf.dist
+++ b/src/server/worldserver/worldserver.conf.dist
@@ -1140,6 +1140,15 @@ AccountInstancesPerHour = 5
Account.PasswordChangeSecurity = 0
#
+# BirthdayTime
+# Description: Set to date of project's birth in UNIX time. By default the date when TrinityCore was started (Thu Oct 2, 2008)
+# Default: 1222964635
+#
+#
+
+BirthdayTime = 1222964635
+
+#
###################################################################################################
###################################################################################################