diff --git a/data/sql/updates/pending_db_world/rev_1630947176293030300.sql b/data/sql/updates/pending_db_world/rev_1630947176293030300.sql new file mode 100644 index 000000000..f97277b14 --- /dev/null +++ b/data/sql/updates/pending_db_world/rev_1630947176293030300.sql @@ -0,0 +1,4 @@ +INSERT INTO `version_db_world` (`sql_rev`) VALUES ('1630947176293030300'); + +UPDATE `achievement_criteria_data` SET `type`=24, `value1`=1600 WHERE `criteria_id` IN (611,1235,1238); +UPDATE `achievement_criteria_data` SET `type`=24, `value1`=3 WHERE `criteria_id`=1236; diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index 64577264b..5bdc18a4a 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -248,6 +248,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) } return true; case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_TEAMS_SCORES: return true; // not check correctness node indexes case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM: if (equipped_item.item_quality >= MAX_ITEM_QUALITY) @@ -341,11 +342,11 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: return source->HasAuraEffect(aura.spell_id, aura.effect_idx); case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA: - { - uint32 zone_id, area_id; - source->GetZoneAndAreaId(zone_id, area_id); - return area.id == zone_id || area.id == area_id; - } + { + uint32 zone_id, area_id; + source->GetZoneAndAreaId(zone_id, area_id); + return area.id == zone_id || area.id == area_id; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: return target && target->HasAuraEffect(aura.spell_id, aura.effect_idx); case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE: @@ -361,89 +362,107 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT: return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast(source), const_cast(target), criteria_id); case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_DIFFICULTY: - { - if (source->GetMap()->IsRaid()) - if (source->GetMap()->Is25ManRaid() != ((difficulty.difficulty & RAID_DIFFICULTY_MASK_25MAN) != 0)) - return false; + { + if (source->GetMap()->IsRaid()) + if (source->GetMap()->Is25ManRaid() != ((difficulty.difficulty & RAID_DIFFICULTY_MASK_25MAN) != 0)) + return false; - AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id); - uint8 spawnMode = source->GetMap()->GetSpawnMode(); - // Dungeons completed on heroic mode count towards both in general achievement, but not in statistics. - return sAchievementMgr->IsStatisticCriteria(criteria) ? spawnMode == difficulty.difficulty : spawnMode >= difficulty.difficulty; - } + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id); + uint8 spawnMode = source->GetMap()->GetSpawnMode(); + // Dungeons completed on heroic mode count towards both in general achievement, but not in statistics. + return sAchievementMgr->IsStatisticCriteria(criteria) ? spawnMode == difficulty.difficulty : spawnMode >= difficulty.difficulty; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT: return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM: - { - if (!target || target->GetTypeId() != TYPEID_PLAYER) - return false; + { + if (!target || target->GetTypeId() != TYPEID_PLAYER) + return false; - // DB data compatibility... - uint32 teamOld = target->ToPlayer()->GetTeamId() == TEAM_ALLIANCE ? ALLIANCE : HORDE; - return teamOld == team.team; - } + // DB data compatibility... + uint32 teamOld = target->ToPlayer()->GetTeamId() == TEAM_ALLIANCE ? ALLIANCE : HORDE; + return teamOld == team.team; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK: return Player::GetDrunkenstateByValue(source->GetDrunkValue()) >= DrunkenState(drunk.state); case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY: return IsHolidayActive(HolidayIds(holiday.id)); case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE: - { - Battleground* bg = source->GetBattleground(); - if (!bg) - return false; + { + Battleground* bg = source->GetBattleground(); + if (!bg) + return false; - uint32 score = bg->GetTeamScore(source->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); - return score >= bg_loss_team_score.min_score && score <= bg_loss_team_score.max_score; - } + uint32 score = bg->GetTeamScore(source->GetTeamId() == TEAM_ALLIANCE ? TEAM_HORDE : TEAM_ALLIANCE); + return score >= bg_loss_team_score.min_score && score <= bg_loss_team_score.max_score; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT: + { + if (!source->IsInWorld()) + return false; + Map* map = source->GetMap(); + if (!map->IsDungeon()) { - if (!source->IsInWorld()) - return false; - Map* map = source->GetMap(); - if (!map->IsDungeon()) - { - LOG_ERROR("sql.sql", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u", - ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT, criteria_id, map->GetId()); - return false; - } - InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript(); - if (!instance) - { - LOG_ERROR("sql.sql", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for map %u but map does not have a instance script", - ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT, criteria_id, map->GetId()); - return false; - } - return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1); + LOG_ERROR("sql.sql", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u", + ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT, criteria_id, map->GetId()); + return false; } + InstanceScript* instance = map->ToInstanceMap()->GetInstanceScript(); + if (!instance) + { + LOG_ERROR("sql.sql", "Achievement system call ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT (%u) for achievement criteria %u for map %u but map does not have a instance script", + ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT, criteria_id, map->GetId()); + return false; + } + return instance->CheckAchievementCriteriaMeet(criteria_id, source, target, miscvalue1); + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM: - { - ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1); - if (!pProto) - return false; - return pProto->ItemLevel >= equipped_item.item_level && pProto->Quality >= equipped_item.item_quality; - } + { + ItemTemplate const* pProto = sObjectMgr->GetItemTemplate(miscvalue1); + if (!pProto) + return false; + return pProto->ItemLevel >= equipped_item.item_level && pProto->Quality >= equipped_item.item_quality; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_ID: return source->GetMapId() == map_id.mapId; case ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY: - { - time_t birthday_start = time_t(sWorld->getIntConfig(CONFIG_BIRTHDAY_TIME)); - tm birthday_tm; - localtime_r(&birthday_start, &birthday_tm); + { + time_t birthday_start = time_t(sWorld->getIntConfig(CONFIG_BIRTHDAY_TIME)); + tm birthday_tm; + localtime_r(&birthday_start, &birthday_tm); - // exactly N birthday - birthday_tm.tm_year += birthday_login.nth_birthday; + // 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; - } + time_t birthday = mktime(&birthday_tm); + time_t now = sWorld->GetGameTime(); + return now <= birthday + DAY && now >= birthday; + } case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE: - { - if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id)) - return source && source->HasTitle(titleInfo->bit_index); + { + if (CharTitlesEntry const* titleInfo = sCharTitlesStore.LookupEntry(known_title.title_id)) + return source && source->HasTitle(titleInfo->bit_index); + return false; + } + case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_TEAMS_SCORES: + { + Battleground* bg = source->GetBattleground(); + if (!bg) + { return false; } + + TeamId winnerTeam = bg->GetWinner(); + if (winnerTeam == TEAM_NEUTRAL) + { + return false; + } + + uint32 winnnerScore = bg->GetTeamScore(winnerTeam); + uint32 loserScore = bg->GetTeamScore(TeamId(!uint32(winnerTeam))); + return source->GetTeamId() == winnerTeam && winnnerScore == teams_scores.winner_score && loserScore == teams_scores.loser_score; + } default: break; } diff --git a/src/server/game/Achievements/AchievementMgr.h b/src/server/game/Achievements/AchievementMgr.h index ef7ea3821..850eb2c65 100644 --- a/src/server/game/Achievements/AchievementMgr.h +++ b/src/server/game/Achievements/AchievementMgr.h @@ -55,9 +55,10 @@ enum AchievementCriteriaDataType 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_NTH_BIRTHDAY = 22, // N login on day of N-th Birthday - ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23 // title_id known (pvp) title, values from dbc + ACHIEVEMENT_CRITERIA_DATA_TYPE_S_KNOWN_TITLE = 23, // title_id known (pvp) title, values from dbc + ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_TEAMS_SCORES = 24, // winner_score loser score player's team win bg and their teams have exact scores }; -#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 24 // maximum value in AchievementCriteriaDataType enum +#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 25 // maximum value in AchievementCriteriaDataType enum enum AchievementCommonCategories { @@ -156,7 +157,7 @@ struct AchievementCriteriaData uint32 min_score; uint32 max_score; } bg_loss_team_score; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data) + // ACHIEVEMENT_CRITERIA_DATA_TYPE_INSTANCE_SCRIPT = 18 (no data) // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM = 19 struct { @@ -168,16 +169,22 @@ struct AchievementCriteriaData { uint32 mapId; } map_id; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 21 + // ACHIEVEMENT_CRITERIA_DATA_TYPE_NTH_BIRTHDAY = 22 struct { uint32 nth_birthday; } birthday_login; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 22 + // ACHIEVEMENT_CRITERIA_DATA_TYPE_KNOWN_TITLE = 23 struct { uint32 title_id; } known_title; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_TEAMS_SCORES = 24 + struct + { + uint32 winner_score; + uint32 loser_score; + } teams_scores; // ... struct {