Core/DB/Achievements:

- fixed arena season title achievements and rewards
- added mailtemplate support for `achievement_reward` table
- fixed typo in GetBattleMasterBG which causes achievement reward mail expire in 1 day

Ref #8777
This commit is contained in:
joschiwald
2014-02-10 00:14:29 +01:00
parent a5a6799b4e
commit b72273014f
15 changed files with 162 additions and 42 deletions

View File

@@ -0,0 +1,68 @@
ALTER TABLE `achievement_reward`
ADD COLUMN `mailTemplate` MEDIUMINT(8) UNSIGNED DEFAULT 0 NULL AFTER `text`;
DELETE FROM `disables` WHERE `sourceType`=4 AND `entry`=11238;
INSERT INTO `disables` (`sourceType`, `entry`, `comment`) VALUES
(4,11238, 'Achievement: Jade Tiger');
DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (5597,5599,5600,6789,7408,7412,7415,7416,7418,7419,9058,9718,9719,9720,9721,10718,10878,10879,10881,10898,11238,11402,12562,12912,12999,13000,13001,13002,13003,13004,13005,13006,13007);
INSERT INTO `achievement_criteria_data` (`criteria_id`, `type`, `value1`, `value2`, `ScriptName`) VALUES
(5597, 23, 62, 0, ''), -- Merciless Gladiator Season 2
(5599, 23, 71, 0, ''), -- Vengeful Gladiator Season 3
(5600, 23, 80, 0, ''), -- Brutal Gladiator Season 4
(6789, 23, 53, 0, ''), -- Champion of the Naaru
(7408, 23, 45, 0, ''), -- Challenger
(7412, 23, 42, 0, ''), -- Gladiator
(7415, 23, 43, 0, ''), -- Duelist - Duelist
(7416, 23, 42, 0, ''), -- Duelist - Gladiator
(7418, 23, 44, 0, ''), -- Rival - Rival
(7419, 23, 43, 0, ''), -- Rival - Duelist
(9058, 22, 4, 0, ''), -- 4th Anniversary
(9718, 23, 42, 0, ''), -- Rival - Gladiator
(9719, 23, 44, 0, ''), -- Challenger - Rival
(9720, 23, 43, 0, ''), -- Challenger - Duelist
(9721, 23, 42, 0, ''), -- Challenger - Gladiator
(10718, 23, 157, 0, ''), -- Deadly Gladiator Season 5
(10878, 23, 157, 0, ''), -- Challenger - Deadly Gladiator
(10879, 23, 157, 0, ''), -- Rival - Deadly Gladiator
(10881, 23, 157, 0, ''), -- Gladiator - Deadly Gladiator
(10898, 23, 167, 0, ''), -- Furious Gladiator Season 6
-- (11238, 0, 0, 0, ''), -- Jade Tiger
(11402, 23, 169, 0, ''), -- Relentless Gladiator Season 7
(12562, 22, 5, 0, ''), -- 5th Anniversary
(12912, 23, 177, 0, ''), -- Wrathful Gladiator Season 8
(12999, 23, 167, 0, ''), -- Gladiator - Furious Gladiator
(13000, 23, 169, 0, ''), -- Gladiator - Relentless Gladiator
(13001, 23, 157, 0, ''), -- Duelist - Deadly Gladiator
(13002, 23, 167, 0, ''), -- Duelist - Furious Gladiator
(13003, 23, 169, 0, ''), -- Duelist - Relentless Gladiator
(13004, 23, 167, 0, ''), -- Rival - Furious Gladiator
(13005, 23, 169, 0, ''), -- Rival - Relentless Gladiator
(13006, 23, 167, 0, ''), -- Challenger - Furious Gladiator
(13007, 23, 169, 0, ''); -- Challenger - Relentless Gladiator
DELETE FROM `achievement_reward` WHERE `entry` IN (432,2090,2091,2092,2093);
INSERT INTO `achievement_reward` (`entry`, `title_A`, `title_H`) VALUES
( 432,53,53), -- Champion of the Naaru
(2090,45,45), -- Challenger
(2091,42,42), -- Gladiator
(2092,43,43), -- Duelist
(2093,44,44); -- Rival
DELETE FROM `achievement_reward` WHERE `entry` IN (419,420,3336,3436,3758,4599);
INSERT INTO `achievement_reward` (`entry`, `sender`, `mailTemplate`) VALUES
( 419,18897,211), -- Vengeful Gladiator
( 420,18897,262), -- Brutal Gladiator
(3336,18897,266), -- Deadly Gladiator
(3436,18897,267), -- Furious Gladiator
(3758,18897,286), -- Relentless Gladiator
(4599,18897,287); -- Wrathful Gladiator
DELETE FROM `mail_loot_template` WHERE `entry` IN (211,262,266,267,286,287);
INSERT INTO `mail_loot_template` (`entry`,`item`,`ChanceOrQuestChance`,`lootmode`,`groupid`,`mincountOrRef`,`maxcount`) VALUES
(211,37676,100,1,0,1,1), -- Vengeful Gladiator
(262,43516,100,1,0,1,1), -- Brutal Gladiator
(266,46708,100,1,0,1,1), -- Deadly Gladiator
(267,46171,100,1,0,1,1), -- Furious Gladiator
(286,47840,100,1,0,1,1), -- Relentless Gladiator
(287,50435,100,1,0,1,1); -- Wrathful Gladiator

View File

@@ -297,7 +297,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria)
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE:
if (!sCharTitlesStore.LookupEntry(known_title.title_id))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
TC_LOG_ERROR("sql.sql", "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE (%u) have unknown title_id in value1 (%u), ignore.",
criteria->ID, criteria->requiredType, dataType, known_title.title_id);
return false;
}
@@ -400,7 +400,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un
{
TC_LOG_ERROR("achievement", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u",
dataType, criteria_id, map->GetId());
return false;
return false;
}
InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript();
if (!instance)
@@ -2082,25 +2082,30 @@ void AchievementMgr::CompletedAchievement(AchievementEntry const* achievement)
// mail
if (reward->sender)
{
Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
MailDraft draft(reward->mailTemplate);
int loc_idx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
// subject and text
std::string subject = reward->subject;
std::string text = reward->text;
if (loc_idx >= 0)
if (!reward->mailTemplate)
{
if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
// subject and text
std::string subject = reward->subject;
std::string text = reward->text;
int locIdx = GetPlayer()->GetSession()->GetSessionDbLocaleIndex();
if (locIdx >= 0)
{
ObjectMgr::GetLocaleString(loc->subject, loc_idx, subject);
ObjectMgr::GetLocaleString(loc->text, loc_idx, text);
if (AchievementRewardLocale const* loc = sAchievementMgr->GetAchievementRewardLocale(achievement))
{
ObjectMgr::GetLocaleString(loc->subject, locIdx, subject);
ObjectMgr::GetLocaleString(loc->text, locIdx, text);
}
}
draft = MailDraft(subject, text);
}
MailDraft draft(subject, text);
SQLTransaction trans = CharacterDatabase.BeginTransaction();
Item* item = reward->itemId ? Item::CreateItem(reward->itemId, 1, GetPlayer()) : NULL;
if (item)
{
// save new item before send
@@ -2441,8 +2446,8 @@ void AchievementGlobalMgr::LoadRewards()
m_achievementRewards.clear(); // need for reload case
// 0 1 2 3 4 5 6
QueryResult result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward");
// 0 1 2 3 4 5 6 7
QueryResult result = WorldDatabase.Query("SELECT entry, title_A, title_H, item, sender, subject, text, mailTemplate FROM achievement_reward");
if (!result)
{
@@ -2456,20 +2461,21 @@ void AchievementGlobalMgr::LoadRewards()
{
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
const AchievementEntry* pAchievement = GetAchievement(entry);
if (!pAchievement)
AchievementEntry const* achievement = GetAchievement(entry);
if (!achievement)
{
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` has wrong achievement (Entry: %u), ignored.", entry);
continue;
}
AchievementReward reward;
reward.titleId[0] = fields[1].GetUInt32();
reward.titleId[1] = fields[2].GetUInt32();
reward.itemId = fields[3].GetUInt32();
reward.sender = fields[4].GetUInt32();
reward.subject = fields[5].GetString();
reward.text = fields[6].GetString();
reward.titleId[0] = fields[1].GetUInt32();
reward.titleId[1] = fields[2].GetUInt32();
reward.itemId = fields[3].GetUInt32();
reward.sender = fields[4].GetUInt32();
reward.subject = fields[5].GetString();
reward.text = fields[6].GetString();
reward.mailTemplate = fields[7].GetUInt32();
// must be title or mail at least
if (!reward.titleId[0] && !reward.titleId[1] && !reward.sender)
@@ -2478,7 +2484,7 @@ void AchievementGlobalMgr::LoadRewards()
continue;
}
if (pAchievement->requiredFaction == ACHIEVEMENT_FACTION_ANY && ((reward.titleId[0] == 0) != (reward.titleId[1] == 0)))
if (achievement->requiredFaction == ACHIEVEMENT_FACTION_ANY && (!reward.titleId[0] ^ !reward.titleId[1]))
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) for only one team.", entry, reward.titleId[0], reward.titleId[1]);
if (reward.titleId[0])
@@ -2520,6 +2526,20 @@ void AchievementGlobalMgr::LoadRewards()
if (!reward.text.empty())
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data but has mail text.", entry);
if (reward.mailTemplate)
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) does not have sender data but has mailTemplate.", entry);
}
if (reward.mailTemplate)
{
if (!sMailTemplateStore.LookupEntry(reward.mailTemplate))
{
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has invalid mailTemplate (%u).", entry, reward.mailTemplate);
reward.mailTemplate = 0;
}
else if (!reward.subject.empty() || !reward.text.empty())
TC_LOG_ERROR("sql.sql", "Table `achievement_reward` (Entry: %u) has mailTemplate (%u) and mail subject/text.", entry, reward.mailTemplate);
}
if (reward.itemId)

View File

@@ -233,6 +233,7 @@ struct AchievementReward
uint32 sender;
std::string subject;
std::string text;
uint32 mailTemplate;
};
typedef UNORDERED_MAP<uint32, AchievementReward> AchievementRewards;

View File

@@ -1082,6 +1082,17 @@ void BattlegroundMgr::LoadBattleMastersEntry()
Field* fields = result->Fetch();
uint32 entry = fields[0].GetUInt32();
if (CreatureTemplate const* cInfo = sObjectMgr->GetCreatureTemplate(entry))
{
if ((cInfo->npcflag & UNIT_NPC_FLAG_BATTLEMASTER) == 0)
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) listed in `battlemaster_entry` is not a battlemaster.", entry);
}
else
{
TC_LOG_ERROR("sql.sql", "Creature (Entry: %u) listed in `battlemaster_entry` does not exist.", entry);
continue;
}
uint32 bgTypeId = fields[1].GetUInt32();
if (!sBattlemasterListStore.LookupEntry(bgTypeId))
{
@@ -1093,9 +1104,24 @@ void BattlegroundMgr::LoadBattleMastersEntry()
}
while (result->NextRow());
CheckBattleMasters();
TC_LOG_INFO("server.loading", ">> Loaded %u battlemaster entries in %u ms", count, GetMSTimeDiffToNow(oldMSTime));
}
void BattlegroundMgr::CheckBattleMasters()
{
CreatureTemplateContainer const* ctc = sObjectMgr->GetCreatureTemplates();
for (CreatureTemplateContainer::const_iterator itr = ctc->begin(); itr != ctc->end(); ++itr)
{
if ((itr->second.npcflag & UNIT_NPC_FLAG_BATTLEMASTER) && mBattleMastersMap.find(itr->second.Entry) == mBattleMastersMap.end())
{
TC_LOG_ERROR("sql.sql", "CreatureTemplate (Entry: %u) has UNIT_NPC_FLAG_BATTLEMASTER but no data in `battlemaster_entry` table. Removing flag!", itr->second.Entry);
const_cast<CreatureTemplate*>(&itr->second)->npcflag &= ~UNIT_NPC_FLAG_BATTLEMASTER;
}
}
}
HolidayIds BattlegroundMgr::BGTypeToWeekendHolidayId(BattlegroundTypeId bgTypeId)
{
switch (bgTypeId)

View File

@@ -126,12 +126,13 @@ class BattlegroundMgr
uint32 GetRatingDiscardTimer() const;
void InitAutomaticArenaPointDistribution();
void LoadBattleMastersEntry();
void CheckBattleMasters();
BattlegroundTypeId GetBattleMasterBG(uint32 entry) const
{
BattleMastersMap::const_iterator itr = mBattleMastersMap.find(entry);
if (itr != mBattleMastersMap.end())
return itr->second;
return BATTLEGROUND_WS;
return BATTLEGROUND_TYPE_NONE;
}
private:

View File

@@ -651,9 +651,9 @@ struct CharTitlesEntry
{
uint32 ID; // 0, title ids, for example in Quest::GetCharTitleId()
//uint32 unk1; // 1 flags?
char* name[16]; // 2-17
char* nameMale[16]; // 2-17
// 18 string flag, unused
//char* name2[16]; // 19-34, unused
char* nameFemale[16]; // 19-34
// 35 string flag, unused
uint32 bit_index; // 36 used in PLAYER_CHOSEN_TITLE and 1<<index in PLAYER__FIELD_KNOWN_TITLES
};
@@ -1270,7 +1270,7 @@ struct MailTemplateEntry
uint32 ID; // 0
//char* subject[16]; // 1-16
// 17 name flags, unused
char* content[16]; // 18-33
char* content[16]; // 18-33
};
struct MapEntry

View File

@@ -33,7 +33,7 @@ char const BannedAddOnsfmt[] = "nxxxxxxxxxx";
char const BarberShopStyleEntryfmt[] = "nixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxiii";
char const BattlemasterListEntryfmt[] = "niiiiiiiiixssssssssssssssssxiixx";
char const CharStartOutfitEntryfmt[] = "dbbbXiiiiiiiiiiiiiiiiiiiiiiiixxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char const CharTitlesEntryfmt[] = "nxssssssssssssssssxxxxxxxxxxxxxxxxxxi";
char const CharTitlesEntryfmt[] = "nxssssssssssssssssxssssssssssssssssxi";
char const ChatChannelsEntryfmt[] = "nixssssssssssssssssxxxxxxxxxxxxxxxxxx";
char const ChrClassesEntryfmt[] = "nxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixii";
char const ChrRacesEntryfmt[] = "nxixiixixxxxixssssssssssssssssxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxi";

View File

@@ -20,6 +20,7 @@
#include "AchievementMgr.h"
#include "ArenaTeam.h"
#include "ArenaTeamMgr.h"
#include "BattlegroundMgr.h"
#include "Chat.h"
#include "Common.h"
#include "DatabaseEnv.h"

View File

@@ -193,10 +193,12 @@ void MailDraft::SendMailTo(SQLTransaction& trans, MailReceiver const& receiver,
expire_delay = DAY;
// default case: expire time if COD 3 days, if no COD 30 days (or 90 days if sender is a game master)
else
{
if (m_COD)
expire_delay = 3 * DAY;
else
expire_delay = pSender && pSender->IsGameMaster() ? 90 * DAY : 30 * DAY;
}
time_t expire_time = deliver_time + expire_delay;

View File

@@ -122,7 +122,7 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
{
MapEntry const* entry = sMapStore.LookupEntry(mapid);
if (!entry)
return false;
return false;
if (!entry->IsDungeon())
return true;
@@ -220,12 +220,12 @@ bool MapManager::CanPlayerEnter(uint32 mapid, Player* player, bool loginCheck)
// players are only allowed to enter 5 instances per hour
if (entry->IsDungeon() && (!player->GetGroup() || (player->GetGroup() && !player->GetGroup()->isLFGGroup())))
{
uint32 instaceIdToCheck = 0;
uint32 instanceIdToCheck = 0;
if (InstanceSave* save = player->GetInstanceSave(mapid, entry->IsRaid()))
instaceIdToCheck = save->GetInstanceId();
instanceIdToCheck = save->GetInstanceId();
// instanceId can never be 0 - will not be found
if (!player->CheckInstanceCount(instaceIdToCheck) && !player->isDead())
if (!player->CheckInstanceCount(instanceIdToCheck) && !player->isDead())
{
player->SendTransferAborted(mapid, TRANSFER_ABORT_TOO_MANY_INSTANCES);
return false;

View File

@@ -3324,7 +3324,7 @@ enum BattlegroundTypeId
BATTLEGROUND_DS = 10, // Dalaran Sewers
BATTLEGROUND_RV = 11, // Ring of Valor
BATTLEGROUND_IC = 30, // Isle of Conquest
BATTLEGROUND_RB = 32 // Random Battleground
BATTLEGROUND_RB = 32 // Random Battleground
};
#define MAX_BATTLEGROUND_TYPE_ID 33

View File

@@ -1633,7 +1633,7 @@ void World::SetInitialWorldSettings()
sObjectMgr->LoadGameObjectForQuests();
TC_LOG_INFO("server.loading", "Loading BattleMasters...");
sBattlegroundMgr->LoadBattleMastersEntry();
sBattlegroundMgr->LoadBattleMastersEntry(); // must be after load CreatureTemplate
TC_LOG_INFO("server.loading", "Loading GameTeleports...");
sObjectMgr->LoadGameTele();

View File

@@ -277,7 +277,7 @@ public:
if (titleInfo && target->HasTitle(titleInfo))
{
std::string name = titleInfo->name[loc];
std::string name = target->getGender() == GENDER_MALE ? titleInfo->nameMale[loc] : titleInfo->nameFemale[loc];
if (name.empty())
continue;

View File

@@ -1183,8 +1183,9 @@ public:
CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(id);
if (titleInfo)
{
/// @todo: implement female support
int locale = handler->GetSessionDbcLocale();
std::string name = titleInfo->name[locale];
std::string name = titleInfo->nameMale[locale];
if (name.empty())
continue;
@@ -1196,7 +1197,7 @@ public:
if (locale == handler->GetSessionDbcLocale())
continue;
name = titleInfo->name[locale];
name = titleInfo->nameMale[locale];
if (name.empty())
continue;

View File

@@ -96,7 +96,7 @@ public:
target->SetTitle(titleInfo); // to be sure that title now known
target->SetUInt32Value(PLAYER_CHOSEN_TITLE, titleInfo->bit_index);
handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, titleInfo->name[handler->GetSessionDbcLocale()], tNameLink.c_str());
handler->PSendSysMessage(LANG_TITLE_CURRENT_RES, id, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], tNameLink.c_str());
return true;
}
@@ -139,7 +139,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
snprintf(titleNameStr, 80, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], target->GetName().c_str());
target->SetTitle(titleInfo);
handler->PSendSysMessage(LANG_TITLE_ADD_RES, id, titleNameStr, tNameLink.c_str());
@@ -187,7 +187,7 @@ public:
std::string tNameLink = handler->GetNameLink(target);
char titleNameStr[80];
snprintf(titleNameStr, 80, titleInfo->name[handler->GetSessionDbcLocale()], target->GetName().c_str());
snprintf(titleNameStr, 80, target->getGender() == GENDER_MALE ? titleInfo->nameMale[handler->GetSessionDbcLocale()] : titleInfo->nameFemale[handler->GetSessionDbcLocale()], target->GetName().c_str());
handler->PSendSysMessage(LANG_TITLE_REMOVE_RES, id, titleNameStr, tNameLink.c_str());