diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/game/AchievementMgr.cpp | 127 | ||||
-rw-r--r-- | src/game/AchievementMgr.h | 66 |
2 files changed, 134 insertions, 59 deletions
diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index fc6be4603af..34ae3d1ae94 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -79,17 +79,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) switch(criteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: - switch(dataType) - { - case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: - case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE: - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH: - break; - default: - sLog.outErrorDb( "Table `achievement_criteria_data` for criteria (Entry: %u Type: %u) have wrong data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType); - return false; - } + case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: break; default: sLog.outErrorDb( "Table `achievement_criteria_data` have data for not supported criteria type (Entry: %u Type: %u), ignore.", criteria->ID, criteria->requiredType); @@ -100,7 +90,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) { case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE: if(!creature.id || !objmgr.GetCreatureTemplate(creature.id)) { sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed creature id in value1 (%u), ignore.", @@ -108,7 +98,7 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE: if(!classRace.class_id && !classRace.race_id) { sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE (%u) must have not 0 in one from value fields, ignore.", @@ -128,14 +118,48 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH: if(health.percent < 1 || health.percent > 100) { - sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) have prong percent value in value1 (%u), ignore.", + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) have wrong percent value in value1 (%u), ignore.", criteria->ID, criteria->requiredType,dataType,health.percent); return false; } return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD: + return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: + { + SpellEntry const* spellEntry = sSpellStore.LookupEntry(aura.spell_id); + if(!spellEntry) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell id in value1 (%u), ignore.", + criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id); + return false; + } + if(aura.effect_idx >= 3) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have wrong spell effect index in value2 (%u), ignore.", + criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.effect_idx); + return false; + } + if(!spellEntry->EffectApplyAuraName[aura.effect_idx]) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) have non-aura spell effect (ID: %u Effect: %u), ignore.", + criteria->ID, criteria->requiredType,(dataType==ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA?"ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA":"ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA"),dataType,aura.spell_id,aura.effect_idx); + return false; + } + return true; + } + case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA: + if(!GetAreaEntryByAreaID(area.id)) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA (%u) have wrong area id in value1 (%u), ignore.", + criteria->ID, criteria->requiredType,dataType,area.id); + return false; + } + return true; default: sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) have data for not supported data type (%u), ignore.", criteria->ID, criteria->requiredType,dataType); return false; @@ -143,38 +167,56 @@ bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) return false; } -bool AchievementCriteriaData::Meets( Unit const* target ) const +bool AchievementCriteriaData::Meets(Player const* source, Unit const* target) const { - if (!target) - return false; - switch(dataType) { case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE: - if (target->GetTypeId()!=TYPEID_UNIT) + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE: + if (!target || target->GetTypeId()!=TYPEID_UNIT) return false; if (target->GetEntry() != creature.id) return false; return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: - if (target->GetTypeId()!=TYPEID_PLAYER) + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE: + if (!target || target->GetTypeId()!=TYPEID_PLAYER) return false; if(classRace.class_id && classRace.class_id != ((Player*)target)->getClass()) return false; if(classRace.race_id && classRace.race_id != ((Player*)target)->getRace()) return false; return true; - case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH: - if (target->GetTypeId()!=TYPEID_PLAYER) + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH: + if (!target || target->GetTypeId()!=TYPEID_PLAYER) return false; return target->GetHealth()*100 <= health.percent*target->GetMaxHealth(); + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD: + return target && target->GetTypeId() == TYPEID_PLAYER && !target->isAlive() && ((Player*)target)->GetDeathTimer() != 0; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA: + return source->HasAura(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; + } + case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA: + return target && target->HasAura(aura.spell_id,aura.effect_idx); } return false; } +bool AchievementCriteriaDataSet::Meets(Player const* source, Unit const* target) const +{ + for(Storage::const_iterator itr = storage.begin(); itr != storage.end(); ++itr) + if(!itr->Meets(source,target)) + return false; + + return true; +} + AchievementMgr::AchievementMgr(Player *player) { m_player = player; @@ -863,22 +905,18 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: { // miscvalue1 = emote - // miscvalue2 = achievement->ID for special requirement if(!miscvalue1) continue; if(miscvalue1 != achievementCriteria->do_emote.emoteID) continue; if(achievementCriteria->do_emote.count) { - // harcoded case - if(achievement->ID==247) - { - if (!unit || unit->GetTypeId() != TYPEID_PLAYER || - unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0) - continue; - } - // expected as scripted case - else if(!miscvalue2 || !achievement->ID != miscvalue2) + // those requirements couldn't be found in the dbc + AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria); + if(!data) + continue; + + if(!data->Meets(GetPlayer(),unit)) continue; } @@ -949,11 +987,11 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui continue; // those requirements couldn't be found in the dbc - AchievementCriteriaData const* data = achievementmgr.GetCriteriaData(achievementCriteria); + AchievementCriteriaDataSet const* data = achievementmgr.GetCriteriaDataSet(achievementCriteria); if(!data) continue; - if(!data->Meets(unit)) + if(!data->Meets(GetPlayer(),unit)) continue; SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); @@ -1478,7 +1516,14 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() if(!data.IsValid(criteria)) continue; - m_criteriaDataMap[criteria_id] = data; + // this will allocate empty data set storage + AchievementCriteriaDataSet& dataSet = m_criteriaDataMap[criteria_id]; + + // add real data only for not NONE data types + if(data.dataType!=ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE) + dataSet.Add(data); + + // counting data by and data types ++count; } while(result->NextRow()); @@ -1494,7 +1539,11 @@ void AchievementGlobalMgr::LoadAchievementCriteriaData() switch(criteria->requiredType) { case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: - if(!GetCriteriaData(criteria)) + if(!GetCriteriaDataSet(criteria)) + sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType); + break; + case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: // need skip generic cases + if(criteria->do_emote.count && !GetCriteriaDataSet(criteria)) sLog.outErrorDb( "Table `achievement_criteria_data` not have expected data for for criteria (Entry: %u Type: %u).", criteria->ID, criteria->requiredType); break; default: // unexpected case processed in IsValid check diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index faabaf011ef..391afedbb46 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -41,15 +41,20 @@ struct CriteriaProgress }; enum AchievementCriteriaDataType -{ // value1 value2 for the Condition enumed - ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0 - ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE = 1, // creature_id - ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE = 2, // class_id race_id - ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH = 3, // health_percent +{ // value1 value2 comment + ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE = 0, // 0 0 + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE = 1, // creature_id 0 + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE = 2, // class_id race_id + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH= 3, // health_percent 0 + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_DEAD = 4, // 0 0 not corpse (not released body) + ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA = 5, // spell_id effect_idx + ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA = 6, // area id 0 + ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA = 7, // spell_id effect_idx }; -#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 4 // maximum value in AchievementCriteriaDataType enum +#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 8 // maximum value in AchievementCriteriaDataType enum +class Player; class Unit; struct AchievementCriteriaData @@ -57,27 +62,39 @@ struct AchievementCriteriaData AchievementCriteriaDataType dataType; union { - // ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE + // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE struct { - uint32 id; + uint32 id; } creature; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE + // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE struct { - uint32 class_id; - uint32 race_id; + uint32 class_id; + uint32 race_id; } classRace; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH + // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH struct { - uint32 percent; + uint32 percent; } health; - // ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE + // ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA + // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA + struct + { + uint32 spell_id; + uint32 effect_idx; + } aura; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AREA + struct + { + uint32 id; + } area; + // ... struct { - uint32 value1; - uint32 value2; + uint32 value1; + uint32 value2; } raw; }; @@ -94,11 +111,20 @@ struct AchievementCriteriaData } bool IsValid(AchievementCriteriaEntry const* criteria); - // Checks correctness of values - bool Meets(Unit const* target) const;// Checks if the target meets the requirement + bool Meets(Player const* source, Unit const* target) const; }; -typedef std::map<uint32,AchievementCriteriaData> AchievementCriteriaDataMap; +struct AchievementCriteriaDataSet +{ + typedef std::vector<AchievementCriteriaData> Storage; + void Add(AchievementCriteriaData const& data) { storage.push_back(data); } + bool Meets(Player const* source, Unit const* target) const; + private: + Storage storage; +}; + + +typedef std::map<uint32,AchievementCriteriaDataSet> AchievementCriteriaDataMap; struct AchievementReward { @@ -194,7 +220,7 @@ class AchievementGlobalMgr return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL; } - AchievementCriteriaData const* GetCriteriaData(AchievementCriteriaEntry const *achievementCriteria) + AchievementCriteriaDataSet const* GetCriteriaDataSet(AchievementCriteriaEntry const *achievementCriteria) { AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID); return iter!=m_criteriaDataMap.end() ? &iter->second : NULL; |