aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/game/AchievementMgr.cpp127
-rw-r--r--src/game/AchievementMgr.h66
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;