diff options
Diffstat (limited to 'src/server/game/Achievements/AchievementMgr.cpp')
-rw-r--r-- | src/server/game/Achievements/AchievementMgr.cpp | 128 |
1 files changed, 76 insertions, 52 deletions
diff --git a/src/server/game/Achievements/AchievementMgr.cpp b/src/server/game/Achievements/AchievementMgr.cpp index d6b6c928ebb..e5ab02c897e 100644 --- a/src/server/game/Achievements/AchievementMgr.cpp +++ b/src/server/game/Achievements/AchievementMgr.cpp @@ -316,7 +316,7 @@ bool AchievementCriteriaData::Meets(uint32 criteria_id, Player const* source, Un return false; return target->getGender() == gender.gender; case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT: - return sScriptMgr->OnCriteriaCheck(ScriptId, source, target); + return sScriptMgr->OnCriteriaCheck(ScriptId, const_cast<Player*>(source), const_cast<Unit*>(target)); case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT: return source->GetMap()->GetPlayersCountExceptGMs() <= map_players.maxcount; case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM: @@ -452,9 +452,9 @@ void AchievementMgr<Guild>::RemoveCriteriaProgress(const AchievementCriteriaEntr } template<class T> -void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1, uint32 miscValue2, bool evenIfCriteriaComplete) +void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1, uint64 miscValue2, bool evenIfCriteriaComplete) { - sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "ResetAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2); + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "ResetAchievementCriteria(%u, " UI64FMTD ", " UI64FMTD ")", type, miscValue1, miscValue2); // disable for gamemasters with GM-mode enabled if (GetOwner()->isGameMaster()) @@ -485,7 +485,7 @@ void AchievementMgr<T>::ResetAchievementCriteria(AchievementCriteriaTypes type, } template<> -void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint32 /*miscValue1*/, uint32 /*miscValue2*/, bool /*evenIfCriteriaComplete*/) +void AchievementMgr<Guild>::ResetAchievementCriteria(AchievementCriteriaTypes /*type*/, uint64 /*miscValue1*/, uint64 /*miscValue2*/, bool /*evenIfCriteriaComplete*/) { // Not needed } @@ -728,7 +728,7 @@ void AchievementMgr<Player>::LoadFromDB(PreparedQueryResult achievementResult, P { Field* fields = criteriaResult->Fetch(); uint32 id = fields[0].GetUInt16(); - uint32 counter = fields[1].GetUInt32(); + uint64 counter = fields[1].GetUInt64(); time_t date = time_t(fields[2].GetUInt32()); AchievementCriteriaEntry const* criteria = sAchievementMgr->GetAchievementCriteria(id); @@ -916,12 +916,13 @@ void AchievementMgr<T>::SendAchievementEarned(AchievementEntry const* achievemen // if player is in world he can tell his friends about new achievement else if (GetOwner()->IsInWorld()) { + Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); + CellCoord p = Trinity::ComputeCellCoord(GetOwner()->GetPositionX(), GetOwner()->GetPositionY()); Cell cell(p); cell.SetNoCreate(); - Trinity::AchievementChatBuilder say_builder(*GetOwner(), CHAT_MSG_ACHIEVEMENT, LANG_ACHIEVEMENT_EARNED, achievement->ID); Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> say_do(say_builder); Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> > say_worker(GetOwner(), sWorld->getFloatConfig(CONFIG_LISTEN_RANGE_SAY), say_do); TypeContainerVisitor<Trinity::PlayerDistWorker<Trinity::LocalizedPacketDo<Trinity::AchievementChatBuilder> >, WorldTypeMapContainer > message(say_worker); @@ -1052,7 +1053,7 @@ void AchievementMgr<T>::CheckAllAchievementCriteria(Player* referencePlayer) { // suppress sending packets for (uint32 i=0; i<ACHIEVEMENT_CRITERIA_TYPE_TOTAL; ++i) - UpdateAchievementCriteria(AchievementCriteriaTypes(i), 0, 0, NULL, referencePlayer); + UpdateAchievementCriteria(AchievementCriteriaTypes(i), 0, 0, 0, NULL, referencePlayer); } static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = {1057, 1107, 1108}; @@ -1075,13 +1076,30 @@ template<> bool IsGuild<Guild>() { return true; } * this function will be called whenever the user might have done a criteria relevant action */ template<class T> -void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscValue1 /*= 0*/, uint32 miscValue2 /*= 0*/, Unit const* unit /*= NULL*/, Player* referencePlayer /*= NULL*/) +void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, uint64 miscValue1 /*= 0*/, uint64 miscValue2 /*= 0*/, uint64 miscValue3 /*= 0*/, Unit const* unit /*= NULL*/, Player* referencePlayer /*= NULL*/) { - sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria(%u, %u, %u)", type, miscValue1, miscValue2); + if (type >= ACHIEVEMENT_CRITERIA_TYPE_TOTAL) + { + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: Wrong criteria type %u", type); + return; + } + + if (!referencePlayer) + { + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: Player is NULL! Cant update criteria"); + return; + } // disable for gamemasters with GM-mode enabled if (referencePlayer->isGameMaster()) + { + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: [Player %s GM mode on] %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD + , referencePlayer->GetName().c_str(), GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3); return; + } + + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "UpdateAchievementCriteria: %s, %s (%u), " UI64FMTD ", " UI64FMTD ", " UI64FMTD + , GetLogNameForGuid(GetOwner()->GetGUID()), AchievementGlobalMgr::GetCriteriaTypeString(type), type, miscValue1, miscValue2, miscValue3); // Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab if (IsGuild<T>() && !sWorld->getBoolConfig(CONFIG_GUILD_LEVELING_ENABLED)) @@ -1098,7 +1116,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, continue; } - if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, unit, referencePlayer)) + if (!CanUpdateCriteria(achievementCriteria, achievement, miscValue1, miscValue2, miscValue3, unit, referencePlayer)) continue; // requirements not found in the dbc @@ -1118,7 +1136,6 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED: case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN: case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS: - case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_DEATH: @@ -1161,6 +1178,7 @@ void AchievementMgr<T>::UpdateAchievementCriteria(AchievementCriteriaTypes type, case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS:/* FIXME: for online player only currently */ case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED: case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED: + case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS: case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG: case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND: case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE: @@ -1616,7 +1634,7 @@ bool AchievementMgr<T>::IsCompletedAchievement(AchievementEntry const* entry) AchievementCriteriaEntryList const* cList = sAchievementMgr->GetAchievementCriteriaByAchievement(achievementForTestId); if (!cList) return false; - uint32 count = 0; + uint64 count = 0; // For SUMM achievements, we have to count the progress of each criteria of the achievement. // Oddly, the target count is NOT contained in the achievement, but in each individual criteria @@ -1677,14 +1695,14 @@ CriteriaProgress* AchievementMgr<T>::GetCriteriaProgress(AchievementCriteriaEntr } template<class T> -void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint32 changeValue, Player* referencePlayer, ProgressType ptype) +void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entry, uint64 changeValue, Player* referencePlayer, ProgressType ptype) { // Don't allow to cheat - doing timed achievements without timer active TimedAchievementMap::iterator timedIter = m_timedAchievements.find(entry->ID); if (entry->timeLimit && timedIter == m_timedAchievements.end()) return; - sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "SetCriteriaProgress(%u, %u) for (%s GUID: %u)", + sLog->outDebug(LOG_FILTER_ACHIEVEMENTSYS, "SetCriteriaProgress(%u, " UI64FMTD ") for (%s GUID: %u)", entry->ID, changeValue, GetLogNameForGuid(GetOwner()->GetGUID()), GUID_LOPART(GetOwner()->GetGUID())); CriteriaProgress* progress = GetCriteriaProgress(entry); @@ -1700,7 +1718,7 @@ void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entr } else { - uint32 newValue = 0; + uint64 newValue = 0; switch (ptype) { case PROGRESS_SET: @@ -1709,7 +1727,7 @@ void AchievementMgr<T>::SetCriteriaProgress(AchievementCriteriaEntry const* entr case PROGRESS_ACCUMULATE: { // avoid overflow - uint32 max_value = std::numeric_limits<uint32>::max(); + uint64 max_value = std::numeric_limits<uint64>::max(); newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value; break; } @@ -1852,8 +1870,8 @@ void AchievementMgr<Player>::CompletedAchievement(AchievementEntry const* achiev _achievementPoints += achievement->points; - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, NULL, referencePlayer); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer); // reward items and titles if any AchievementReward const* reward = sAchievementMgr->GetAchievementReward(achievement); @@ -1940,8 +1958,8 @@ void AchievementMgr<Guild>::CompletedAchievement(AchievementEntry const* achieve _achievementPoints += achievement->points; - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, NULL, referencePlayer); - UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT, 0, 0, 0, NULL, referencePlayer); + UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS, achievement->points, 0, 0, NULL, referencePlayer); } struct VisibleAchievementPred @@ -2225,7 +2243,7 @@ bool AchievementMgr<T>::HasAchieved(uint32 achievementId) const } template<class T> -bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, Unit const* unit, Player* referencePlayer) +bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criteria, AchievementEntry const* achievement, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const* unit, Player* referencePlayer) { if (DisableMgr::IsDisabledFor(DISABLE_TYPE_ACHIEVEMENT_CRITERIA, criteria->ID, NULL)) { @@ -2256,7 +2274,7 @@ bool AchievementMgr<T>::CanUpdateCriteria(AchievementCriteriaEntry const* criter return false; } - if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, unit, referencePlayer)) + if (!RequirementsSatisfied(criteria, miscValue1, miscValue2, miscValue3, unit, referencePlayer)) { sLog->outTrace(LOG_FILTER_ACHIEVEMENTSYS, "CanUpdateCriteria: %s (Id: %u Type %s) Requirements not satisfied", criteria->name, criteria->ID, AchievementGlobalMgr::GetCriteriaTypeString(criteria->type)); @@ -2307,7 +2325,7 @@ bool AchievementMgr<T>::ConditionsSatisfied(AchievementCriteriaEntry const *crit } template<class T> -bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const *achievementCriteria, uint64 miscValue1, uint64 miscValue2, Unit const *unit, Player* referencePlayer) const +bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const *achievementCriteria, uint64 miscValue1, uint64 miscValue2, uint64 miscValue3, Unit const *unit, Player* referencePlayer) const { switch (AchievementCriteriaTypes(achievementCriteria->type)) { @@ -2468,11 +2486,7 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const *ac return false; break; case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER: - if (!miscValue1) - return false; - - // if team check required: must kill by opposition faction - if (achievementCriteria->achievement == 318 && miscValue2 == referencePlayer->GetTeam()) + if (!miscValue1 || !unit || unit->GetTypeId() != TYPEID_PLAYER) return false; break; case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM: @@ -2517,9 +2531,9 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const *ac return false; break; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE: - // miscValue1 = loot_type (note: 0 = LOOT_CORPSE and then it ignored) - // miscValue2 = count of item loot - if (!miscValue1 || !miscValue2 || miscValue1 != achievementCriteria->loot_type.lootType) + // miscValue1 = itemId - miscValue2 = count of item loot + // miscValue3 = loot_type (note: 0 = LOOT_CORPSE and then it ignored) + if (!miscValue1 || !miscValue2 || !miscValue3 || miscValue3 != achievementCriteria->loot_type.lootType) return false; break; case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM: @@ -2627,7 +2641,7 @@ bool AchievementMgr<T>::RequirementsSatisfied(AchievementCriteriaEntry const *ac { if (!miscValue1) return false; - ItemTemplate const* proto = sObjectMgr->GetItemTemplate(miscValue1); + ItemTemplate const* proto = sObjectMgr->GetItemTemplate(uint32(miscValue1)); if (!proto || proto->Quality < ITEM_QUALITY_EPIC) return false; break; @@ -2690,11 +2704,8 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry return false; break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY: // 7 - if (!unit) + if (!unit || !referencePlayer->IsHostileTo(unit)) return false; - if (const Player* player = unit->ToPlayer()) - if (player->GetTeam() == referencePlayer->GetTeam()) - return false; break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA: // 8 if (!referencePlayer->HasAura(reqValue)) @@ -2703,8 +2714,8 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA: // 10 if (!unit || !unit->HasAura(reqValue)) return false; - case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_MOUNTED: // 11 - if (!unit || !unit->IsMounted()) + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA_TYPE: // 11 + if (!unit || !unit->HasAuraType(AuraType(reqValue))) return false; break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN: // 14 @@ -2723,20 +2734,26 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry return false; break; } - case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20 - if (uint32(referencePlayer->GetMap()->GetDifficulty()) != reqValue) + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA_OR_ZONE: // 17 + { + uint32 zoneId, areaId; + referencePlayer->GetZoneAndAreaId(zoneId, areaId); + if (zoneId != reqValue && areaId != reqValue) return false; break; - case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32 - if (referencePlayer->GetMapId() != reqValue) + } + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_AREA_OR_ZONE: // 18 + { + if (!unit) return false; - break; - case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE: // 18 - if (referencePlayer->GetZoneId() != reqValue) + uint32 zoneId, areaId; + unit->GetZoneAndAreaId(zoneId, areaId); + if (zoneId != reqValue && areaId != reqValue) return false; break; - case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA: // 17 - if (referencePlayer->GetAreaId() != reqValue) + } + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY: // 20 + if (uint32(referencePlayer->GetMap()->GetDifficulty()) != reqValue) return false; break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE: // 25 @@ -2768,6 +2785,10 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry return false; break; } + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP: // 32 + if (referencePlayer->GetMapId() != reqValue) + return false; + break; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX: // 38 // miscValue1 is title's bit index if (miscValue1 != reqValue) @@ -2781,6 +2802,9 @@ bool AchievementMgr<T>::AdditionalRequirementsSatisfied(AchievementCriteriaEntry if (!unit || unit->getLevel() != reqValue) return false; break; + case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_ZONE: // 41 + if (!unit || unit->GetZoneId() != reqValue) + return false; case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW: // 46 if (!unit || unit->GetHealthPct() >= reqValue) return false; @@ -3019,10 +3043,12 @@ char const* AchievementGlobalMgr::GetCriteriaTypeString(AchievementCriteriaTypes return "HONORABLE_KILLS_GUILD"; case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD: return "KILL_CREATURE_TYPE_GUILD"; - default: - return "MISSING_TYPE"; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE_TYPE: + return "GUILD_CHALLENGE_TYPE"; + case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_GUILD_CHALLENGE: + return "GUILD_CHALLENGE"; } - return ""; + return "MISSING_TYPE"; } template class AchievementMgr<Guild>; @@ -3177,9 +3203,7 @@ void AchievementGlobalMgr::LoadCompletedAchievements() sLog->outError(LOG_FILTER_ACHIEVEMENTSYS, "Non-existing achievement %u data removed from table `character_achievement`.", achievementId); PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_INVALID_ACHIEVMENT); - stmt->setUInt16(0, uint16(achievementId)); - CharacterDatabase.Execute(stmt); continue; |