diff options
author | megamage <none@none> | 2009-04-08 16:24:34 -0500 |
---|---|---|
committer | megamage <none@none> | 2009-04-08 16:24:34 -0500 |
commit | 7b2ae4d96460db4b2642b83cfe8abd92692f75e8 (patch) | |
tree | ec5a202ed15ee7a36beec8fe08a4e6a96692a66c | |
parent | bf7499d1ce3677128b55c994740665b7bd6cf3f0 (diff) |
[7627] Replace built-in in code table by new DB table `achievement_criteria_data` for store additional data for achievement criteria. Author: VladimirMangos
--HG--
branch : trunk
-rw-r--r-- | sql/mangos.sql | 26 | ||||
-rw-r--r-- | sql/updates/7627_01_mangos_achievement_criteria_data.sql | 10 | ||||
-rw-r--r-- | src/game/AchievementMgr.cpp | 243 | ||||
-rw-r--r-- | src/game/AchievementMgr.h | 77 | ||||
-rw-r--r-- | src/game/World.cpp | 1 |
5 files changed, 277 insertions, 80 deletions
diff --git a/sql/mangos.sql b/sql/mangos.sql index 83ac68521e4..4ae50613a6d 100644 --- a/sql/mangos.sql +++ b/sql/mangos.sql @@ -22,7 +22,7 @@ DROP TABLE IF EXISTS `db_version`; CREATE TABLE `db_version` ( `version` varchar(120) default NULL, - `required_7622_03_mangos_creature_ai_texts` bit(1) default NULL + `required_7627_01_mangos_achievement_criteria_data` bit(1) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Used DB version notes'; -- @@ -37,6 +37,28 @@ INSERT INTO `db_version` VALUES UNLOCK TABLES; -- +-- Table structure for table `achievement_criteria_data` +-- + +DROP TABLE IF EXISTS `achievement_criteria_data`; +CREATE TABLE `achievement_criteria_data` ( + `criteria_id` mediumint(8) NOT NULL, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0', + `value1` mediumint(8) unsigned NOT NULL DEFAULT '0', + `value2` mediumint(8) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`criteria_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Achievment system'; + +-- +-- Dumping data for table `achievement_criteria_data` +-- + +LOCK TABLES `achievement_criteria_data` WRITE; +/*!40000 ALTER TABLE `achievement_criteria_data` DISABLE KEYS */; +/*!40000 ALTER TABLE `achievement_criteria_data` ENABLE KEYS */; +UNLOCK TABLES; + +-- -- Table structure for table `achievement_reward` -- @@ -50,7 +72,7 @@ CREATE TABLE `achievement_reward` ( `subject` varchar(255) default NULL, `text` text, PRIMARY KEY (`entry`) -) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Loot System'; +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Achievment system'; -- -- Dumping data for table `achievement_reward` diff --git a/sql/updates/7627_01_mangos_achievement_criteria_data.sql b/sql/updates/7627_01_mangos_achievement_criteria_data.sql new file mode 100644 index 00000000000..29a095c5dd5 --- /dev/null +++ b/sql/updates/7627_01_mangos_achievement_criteria_data.sql @@ -0,0 +1,10 @@ +ALTER TABLE db_version CHANGE COLUMN required_7622_03_mangos_creature_ai_texts required_7627_01_mangos_achievement_criteria_data bit; + +DROP TABLE IF EXISTS `achievement_criteria_data`; +CREATE TABLE `achievement_criteria_data` ( + `criteria_id` mediumint(8) NOT NULL, + `type` tinyint(3) unsigned NOT NULL DEFAULT '0', + `value1` mediumint(8) unsigned NOT NULL DEFAULT '0', + `value2` mediumint(8) unsigned NOT NULL DEFAULT '0', + PRIMARY KEY (`criteria_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8 ROW_FORMAT=FIXED COMMENT='Achievment system'; diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index da192844a70..c76a6b223c6 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -37,56 +37,6 @@ INSTANTIATE_SINGLETON_1(AchievementGlobalMgr); -const CriteriaCastSpellRequirement AchievementGlobalMgr::m_criteriaCastSpellRequirements[CRITERIA_CAST_SPELL_REQ_COUNT] = - { - {5272, 3057, 0, 0}, - {5273, 2784, 0, 0}, - {5752, 9099, 0, 0}, - {5753, 8403, 0, 0}, - {5772, 0, 0, RACE_GNOME}, - {5774, 0, 0, RACE_BLOODELF}, - {5775, 0, 0, RACE_DRAENEI}, - {5776, 0, 0, RACE_DWARF}, - {5777, 0, 0, RACE_HUMAN}, - {5778, 0, 0, RACE_NIGHTELF}, - {5779, 0, 0, RACE_ORC}, - {5780, 0, 0, RACE_TAUREN}, - {5781, 0, 0, RACE_TROLL}, - {5782, 0, 0, RACE_UNDEAD_PLAYER}, - {6225, 5661, 0, 0}, - {6226, 26044, 0, 0}, - {6228, 739, 0, 0}, - {6229, 927, 0, 0}, - {6230, 1444, 0, 0}, - {6231, 8140, 0, 0}, - {6232, 5489, 0, 0}, - {6233,12336, 0, 0}, - {6234, 1351, 0, 0}, - {6235, 5484, 0, 0}, - {6236, 1182, 0, 0}, - {6237, 0, CLASS_DEATH_KNIGHT, RACE_ORC}, - {6238, 0, CLASS_WARRIOR, RACE_HUMAN}, - {6239, 0, CLASS_SHAMAN, RACE_TAUREN}, - {6240, 0, CLASS_DRUID, RACE_NIGHTELF}, - {6241, 0, CLASS_ROGUE, RACE_UNDEAD_PLAYER}, - {6242, 0, CLASS_HUNTER, RACE_TROLL}, - {6243, 0, CLASS_MAGE, RACE_GNOME}, - {6244, 0, CLASS_PALADIN, RACE_DWARF}, - {6245, 0, CLASS_WARLOCK, RACE_BLOODELF}, - {6246, 0, CLASS_PRIEST, RACE_DRAENEI}, - {6312, 0, CLASS_WARLOCK, RACE_GNOME}, - {6313, 0, CLASS_DEATH_KNIGHT, RACE_HUMAN}, - {6314, 0, CLASS_PRIEST, RACE_NIGHTELF}, - {6315, 0, CLASS_SHAMAN, RACE_ORC}, - {6316, 0, CLASS_DRUID, RACE_TAUREN}, - {6317, 0, CLASS_ROGUE, RACE_TROLL}, - {6318, 0, CLASS_WARRIOR, RACE_UNDEAD_PLAYER}, - {6319, 0, CLASS_MAGE, RACE_BLOODELF}, - {6320, 0, CLASS_PALADIN, RACE_DRAENEI}, - {6321, 0, CLASS_HUNTER, RACE_DWARF}, - {6662, 31261, 0, 0} - }; - namespace MaNGOS { class AchievementChatBuilder @@ -117,6 +67,114 @@ namespace MaNGOS }; } // namespace MaNGOS + +bool AchievementCriteriaData::IsValid(AchievementCriteriaEntry const* criteria) +{ + if(dataType >= MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE) + { + sLog.outErrorDb( "Table `achievement_criteria_data` for criteria (Entry: %u) have wrong data type (%u), ignore.", criteria->ID,dataType); + return false; + } + + 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; + } + break; + default: + sLog.outErrorDb( "Table `achievement_criteria_data` have data for not supported criteria type (Entry: %u Type: %u), ignore.", criteria->ID, criteria->requiredType); + return false; + } + + switch(dataType) + { + case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE: + return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_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.", + criteria->ID, criteria->requiredType,dataType,creature.id); + return false; + } + return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_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.", + criteria->ID, criteria->requiredType,dataType); + return false; + } + if(classRace.class_id && ((1 << (classRace.class_id-1)) & CLASSMASK_ALL_PLAYABLE)==0) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed class in value1 (%u), ignore.", + criteria->ID, criteria->requiredType,dataType,classRace.class_id); + return false; + } + if(classRace.race_id && ((1 << (classRace.race_id-1)) & RACEMASK_ALL_PLAYABLE)==0) + { + sLog.outErrorDb( "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) have not existed race in value2 (%u), ignore.", + criteria->ID, criteria->requiredType,dataType,classRace.race_id); + return false; + } + return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_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.", + criteria->ID, criteria->requiredType,dataType,health.percent); + 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; + } + return false; +} + +bool AchievementCriteriaData::Meets( 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) + return false; + if (target->GetEntry() != creature.id) + return false; + return true; + case ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE: + if (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) + return false; + return target->GetHealth()*100 <= health.percent*target->GetMaxHealth(); + } + + return false; +} + AchievementMgr::AchievementMgr(Player *player) { m_player = player; @@ -884,24 +942,19 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui break; case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: { + if (!miscvalue1) + continue; + if (!miscvalue1 || miscvalue1 != achievementCriteria->cast_spell.spellID) continue; // those requirements couldn't be found in the dbc - if (CriteriaCastSpellRequirement const* requirement = AchievementGlobalMgr::GetCriteriaCastSpellRequirement(achievementCriteria)) - { - if (!unit) - continue; - - if (requirement->creatureEntry && unit->GetEntry() != requirement->creatureEntry) - continue; - - if (requirement->playerRace && (unit->GetTypeId() != TYPEID_PLAYER || unit->getRace()!=requirement->playerRace)) - continue; + AchievementCriteriaData const* data = achievementmgr.GetCriteriaData(achievementCriteria); + if(!data) + continue; - if (requirement->playerClass && (unit->GetTypeId() != TYPEID_PLAYER || unit->getClass()!=requirement->playerClass)) - continue; - } + if(!data->Meets(unit)) + continue; SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; @@ -1388,6 +1441,70 @@ void AchievementGlobalMgr::LoadAchievementReferenceList() sLog.outString(">> Loaded %u achievement references.",count); } +void AchievementGlobalMgr::LoadAchievementCriteriaData() +{ + QueryResult *result = WorldDatabase.Query("SELECT criteria_id, type, value1, value2 FROM achievement_criteria_data"); + + if(!result) + { + barGoLink bar(1); + bar.step(); + + sLog.outString(); + sLog.outString(">> Loaded 0 additional achievement criteria data. DB table `achievement_criteria_data` is empty."); + return; + } + + uint32 count = 0; + barGoLink bar(result->GetRowCount()); + do + { + bar.step(); + Field *fields = result->Fetch(); + uint32 criteria_id = fields[0].GetUInt32(); + + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(criteria_id); + + if (!criteria) + { + sLog.outErrorDb( "Table `achievement_criteria_data` have data for not existed criteria (Entry: %u), ignore.", criteria_id); + continue; + } + + AchievementCriteriaData data(fields[1].GetUInt32(),fields[2].GetUInt32(),fields[3].GetUInt32()); + + if(!data.IsValid(criteria)) + continue; + + m_criteriaDataMap[criteria_id] = data; + ++count; + } while(result->NextRow()); + + delete result; + + // post loading checks + for (uint32 entryId = 0; entryId < sAchievementCriteriaStore.GetNumRows(); ++entryId) + { + AchievementCriteriaEntry const* criteria = sAchievementCriteriaStore.LookupEntry(entryId); + if(!criteria) + continue; + + switch(criteria->requiredType) + { + case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2: + if(!GetCriteriaData(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 + break; + } + + } + + sLog.outString(); + sLog.outString(">> Loaded %u additional achievement criteria data.",count); +} + void AchievementGlobalMgr::LoadCompletedAchievements() { QueryResult *result = CharacterDatabase.Query("SELECT achievement FROM character_achievement GROUP BY achievement"); diff --git a/src/game/AchievementMgr.h b/src/game/AchievementMgr.h index b45c63f7301..faabaf011ef 100644 --- a/src/game/AchievementMgr.h +++ b/src/game/AchievementMgr.h @@ -27,9 +27,6 @@ #include <map> #include <string> -#define CRITERIA_CAST_SPELL_REQ_COUNT 46 -#define ACHIEVEMENT_REWARD_COUNT 57 - typedef std::list<AchievementCriteriaEntry const*> AchievementCriteriaEntryList; typedef std::list<AchievementEntry const*> AchievementEntryList; @@ -43,14 +40,66 @@ struct CriteriaProgress bool changed; }; -struct CriteriaCastSpellRequirement +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 +}; + +#define MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE 4 // maximum value in AchievementCriteriaDataType enum + +class Unit; + +struct AchievementCriteriaData { - uint32 achievementCriteriaId; - uint32 creatureEntry; - uint8 playerClass; - uint8 playerRace; + AchievementCriteriaDataType dataType; + union + { + // ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE + struct + { + uint32 id; + } creature; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_CLASS_RACE + struct + { + uint32 class_id; + uint32 race_id; + } classRace; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH + struct + { + uint32 percent; + } health; + // ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE + struct + { + uint32 value1; + uint32 value2; + } raw; + }; + + AchievementCriteriaData() : dataType(ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE) + { + raw.value1 = 0; + raw.value2 = 0; + } + + AchievementCriteriaData(uint32 _dataType, uint32 _value1, uint32 _value2) : dataType(AchievementCriteriaDataType(_dataType)) + { + raw.value1 = _value1; + raw.value2 = _value2; + } + + bool IsValid(AchievementCriteriaEntry const* criteria); + // Checks correctness of values + bool Meets(Unit const* target) const;// Checks if the target meets the requirement }; +typedef std::map<uint32,AchievementCriteriaData> AchievementCriteriaDataMap; + struct AchievementReward { uint32 titleId[2]; @@ -145,13 +194,10 @@ class AchievementGlobalMgr return iter!=m_achievementRewardLocales.end() ? &iter->second : NULL; } - static CriteriaCastSpellRequirement const * GetCriteriaCastSpellRequirement(AchievementCriteriaEntry const *achievementCriteria) + AchievementCriteriaData const* GetCriteriaData(AchievementCriteriaEntry const *achievementCriteria) { - for (uint32 i=0; i < CRITERIA_CAST_SPELL_REQ_COUNT; ++i) - if (m_criteriaCastSpellRequirements[i].achievementCriteriaId == achievementCriteria->ID) - return &m_criteriaCastSpellRequirements[i]; - - return NULL; + AchievementCriteriaDataMap::const_iterator iter = m_criteriaDataMap.find(achievementCriteria->ID); + return iter!=m_criteriaDataMap.end() ? &iter->second : NULL; } bool IsRealmCompleted(AchievementEntry const* achievement) const @@ -165,12 +211,13 @@ class AchievementGlobalMgr } void LoadAchievementCriteriaList(); + void LoadAchievementCriteriaData(); void LoadAchievementReferenceList(); void LoadCompletedAchievements(); void LoadRewards(); void LoadRewardLocales(); private: - static const CriteriaCastSpellRequirement m_criteriaCastSpellRequirements[]; + AchievementCriteriaDataMap m_criteriaDataMap; // store achievement criterias by type to speed up lookup AchievementCriteriaEntryList m_AchievementCriteriasByType[ACHIEVEMENT_CRITERIA_TYPE_TOTAL]; diff --git a/src/game/World.cpp b/src/game/World.cpp index 4bf272a21c8..a8dbff76114 100644 --- a/src/game/World.cpp +++ b/src/game/World.cpp @@ -1372,6 +1372,7 @@ void World::SetInitialWorldSettings() sLog.outString(); achievementmgr.LoadAchievementReferenceList(); achievementmgr.LoadAchievementCriteriaList(); + achievementmgr.LoadAchievementCriteriaData(); achievementmgr.LoadRewards(); achievementmgr.LoadRewardLocales(); achievementmgr.LoadCompletedAchievements(); |