2010-10-07 15:35:36 +02:00
/*
2012-01-01 00:32:13 +01:00
* Copyright (C) 2008-2012 TrinityCore <http://www.trinitycore.org/>
2010-10-07 15:35:36 +02:00
* Copyright (C) 2005-2009 MaNGOS <http://getmangos.com/>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program. If not, see <http://www.gnu.org/licenses/>.
2008-12-24 09:58:26 -06:00
*/
2009-10-17 15:51:44 -07:00
2012-09-18 11:33:09 +02:00
#include "AchievementMgr.h"
2008-12-24 09:58:26 -06:00
#include "Common.h"
2009-03-27 09:58:20 -06:00
#include "DBCEnums.h"
2008-12-24 09:58:26 -06:00
#include "ObjectMgr.h"
2011-05-03 15:01:10 +02:00
#include "ArenaTeamMgr.h"
2011-05-04 10:08:09 +02:00
#include "GuildMgr.h"
2008-12-24 09:58:26 -06:00
#include "World.h"
2010-06-08 13:05:47 -06:00
#include "WorldPacket.h"
#include "DatabaseEnv.h"
2009-03-06 15:21:44 -06:00
#include "ArenaTeam.h"
2010-06-08 13:05:47 -06:00
#include "CellImpl.h"
#include "GameEventMgr.h"
#include "GridNotifiersImpl.h"
#include "Guild.h"
#include "Language.h"
2009-06-04 21:41:07 +02:00
#include "Player.h"
#include "SpellMgr.h"
2010-07-21 12:14:23 +02:00
#include "DisableMgr.h"
2010-08-07 17:58:45 +02:00
#include "ScriptMgr.h"
2009-07-01 18:36:03 -05:00
#include "MapManager.h"
2010-08-08 04:37:24 +02:00
#include "Battleground.h"
2009-12-25 15:53:37 +01:00
#include "Map.h"
2010-08-08 22:54:58 +06:00
#include "InstanceScript.h"
2012-01-27 02:09:40 +02:00
#include "Group.h"
2008-12-24 09:58:26 -06:00
2009-12-20 15:20:04 +01:00
namespace Trinity
2009-02-21 17:02:56 -06:00
{
class AchievementChatBuilder
{
public :
2011-11-07 11:18:00 -06:00
AchievementChatBuilder ( Player const & player , ChatMsg msgtype , int32 textId , uint32 ach_id )
: i_player ( player ), i_msgtype ( msgtype ), i_textId ( textId ), i_achievementId ( ach_id ) {}
2010-09-17 07:04:29 +02:00
void operator ()( WorldPacket & data , LocaleConstant loc_idx )
2009-02-21 17:02:56 -06:00
{
2011-04-29 20:47:02 +02:00
char const * text = sObjectMgr -> GetTrinityString ( i_textId , loc_idx );
2009-10-17 15:51:44 -07:00
2009-02-21 17:02:56 -06:00
data << uint8 ( i_msgtype );
data << uint32 ( LANG_UNIVERSAL );
data << uint64 ( i_player . GetGUID ());
data << uint32 ( 5 );
data << uint64 ( i_player . GetGUID ());
data << uint32 ( strlen ( text ) + 1 );
data << text ;
data << uint8 ( 0 );
data << uint32 ( i_achievementId );
}
2009-10-17 15:51:44 -07:00
2009-02-21 17:02:56 -06:00
private :
Player const & i_player ;
ChatMsg i_msgtype ;
int32 i_textId ;
uint32 i_achievementId ;
};
2009-12-20 15:20:04 +01:00
} // namespace Trinity
2009-02-21 17:02:56 -06:00
2009-04-08 16:24:34 -05:00
bool AchievementCriteriaData :: IsValid ( AchievementCriteriaEntry const * criteria )
{
2010-04-07 19:14:10 +02:00
if ( dataType >= MAX_ACHIEVEMENT_CRITERIA_DATA_TYPE )
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` for criteria (Entry: %u) has wrong data type (%u), ignored." , criteria -> ID , dataType );
2009-04-08 16:24:34 -05:00
return false ;
}
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
switch ( criteria -> type )
2009-04-08 16:24:34 -05:00
{
2009-06-07 20:54:23 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE :
2009-08-02 10:12:40 +08:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG :
2009-06-14 10:00:45 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING :
2011-04-30 12:41:14 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST : // only hardcoded list
2009-06-14 10:00:45 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL :
2009-06-01 21:51:34 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA :
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE :
2010-03-22 18:32:38 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL :
2009-08-02 10:12:40 +08:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL :
2009-04-29 18:42:53 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE :
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 :
2010-01-16 19:41:04 +03:00
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET :
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 :
2010-01-25 22:56:26 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT :
2010-08-07 18:31:06 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE :
2010-12-17 18:12:46 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL :
2011-04-30 12:41:14 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST : // only Children's Week achievements
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM : // only Children's Week achievements
2011-05-14 12:26:49 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS :
2011-12-10 19:46:54 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL :
2009-04-08 16:24:34 -05:00
break ;
default :
2011-06-19 13:51:14 +02:00
if ( dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT )
{
2012-08-27 15:06:59 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` has data for non-supported criteria type (Entry: %u Type: %u), ignored." , criteria -> ID , criteria -> type );
2011-06-19 13:51:14 +02:00
return false ;
}
break ;
2009-04-08 16:24:34 -05:00
}
2009-10-17 15:51:44 -07:00
2010-12-17 18:12:46 +01:00
switch ( dataType )
2009-04-08 16:24:34 -05:00
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE :
2009-06-01 21:51:34 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE :
2009-12-25 15:53:37 +01:00
case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT :
2009-04-08 16:24:34 -05:00
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE :
2011-04-28 22:57:08 +02:00
if ( ! creature . id || ! sObjectMgr -> GetCreatureTemplate ( creature . id ))
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_CREATURE (%u) has non-existing creature id in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , creature . id );
2009-04-08 16:24:34 -05:00
return false ;
}
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE :
2009-06-14 10:00:45 -05:00
if ( ! classRace . class_id && ! classRace . race_id )
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType );
2009-04-08 16:24:34 -05:00
return false ;
}
2010-04-07 23:25:02 +02:00
if ( classRace . class_id && (( 1 << ( classRace . class_id - 1 )) & CLASSMASK_ALL_PLAYABLE ) == 0 )
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , classRace . class_id );
2009-04-08 16:24:34 -05:00
return false ;
}
2010-04-07 23:25:02 +02:00
if ( classRace . race_id && (( 1 << ( classRace . race_id - 1 )) & RACEMASK_ALL_PLAYABLE ) == 0 )
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , classRace . race_id );
2009-04-08 16:24:34 -05:00
return false ;
}
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH :
2009-06-14 10:00:45 -05:00
if ( health . percent < 1 || health . percent > 100 )
2009-04-08 16:24:34 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_PLAYER_LESS_HEALTH (%u) has wrong percent value in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , health . percent );
2009-04-08 16:24:34 -05:00
return false ;
}
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA :
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA :
{
2011-07-26 23:09:28 +02:00
SpellInfo const * spellEntry = sSpellMgr -> GetSpellInfo ( aura . spell_id );
2009-06-14 10:00:45 -05:00
if ( ! spellEntry )
2009-04-08 16:34:38 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell id in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , ( dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA" ), dataType , aura . spell_id );
2009-04-08 16:34:38 -05:00
return false ;
}
2009-06-14 10:00:45 -05:00
if ( aura . effect_idx >= 3 )
2009-04-08 16:34:38 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has wrong spell effect index in value2 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , ( dataType == ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA ? "ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA" : "ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA" ), dataType , aura . effect_idx );
2009-04-08 16:34:38 -05:00
return false ;
}
2011-07-26 23:09:28 +02:00
if ( ! spellEntry -> Effects [ aura . effect_idx ]. ApplyAuraName )
2009-04-08 16:34:38 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type %s (%u) has non-aura spell effect (ID: %u Effect: %u), ignores." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , ( 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 );
2009-04-08 16:34:38 -05:00
return false ;
}
return true ;
}
2009-06-07 20:52:00 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL :
2010-08-21 23:40:53 +02:00
if ( level . minlevel > STRONG_MAX_LEVEL )
2009-06-07 20:52:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL (%u) has wrong minlevel in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , level . minlevel );
2009-06-07 20:52:00 -05:00
return false ;
}
return true ;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER :
2009-06-14 10:00:45 -05:00
if ( gender . gender > GENDER_NONE )
2009-06-07 20:52:00 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER (%u) has wrong gender in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , gender . gender );
2009-06-07 20:52:00 -05:00
return false ;
}
return true ;
2010-08-07 16:48:34 +02:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT :
if ( ! ScriptId )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT (%u) does not have ScriptName set, ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType );
2010-08-07 16:48:34 +02:00
return false ;
}
return true ;
2009-06-07 20:54:23 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT :
2009-06-14 10:00:45 -05:00
if ( map_players . maxcount <= 0 )
2009-06-07 20:54:23 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT (%u) has wrong max players count in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , map_players . maxcount );
2009-06-07 20:54:23 -05:00
return false ;
}
return true ;
2009-06-09 17:20:19 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM :
2009-06-14 10:00:45 -05:00
if ( team . team != ALLIANCE && team . team != HORDE )
2009-06-09 17:20:19 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM (%u) has unknown team in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , team . team );
2009-06-14 09:59:50 -05:00
return false ;
}
return true ;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK :
2010-04-07 19:14:10 +02:00
if ( drunk . state >= MAX_DRUNKEN )
2009-06-14 09:59:50 -05:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK (%u) has unknown drunken state in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , drunk . state );
2009-06-09 17:20:19 -05:00
return false ;
}
return true ;
2009-06-14 10:00:45 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY :
if ( ! sHolidaysStore . LookupEntry ( holiday . id ))
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY (%u) has unknown holiday in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , holiday . id );
2009-06-14 10:00:45 -05:00
return false ;
}
return true ;
2009-07-31 11:36:02 +08:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE :
2009-07-31 11:37:03 +08:00
return true ; // not check correctness node indexes
2010-03-22 18:32:38 +01:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM :
if ( equipped_item . item_quality >= MAX_ITEM_QUALITY )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_requirement` (Entry: %u Type: %u) for requirement ACHIEVEMENT_CRITERIA_REQUIRE_S_EQUIPED_ITEM (%u) has unknown quality state in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , equipped_item . item_quality );
2010-03-22 18:32:38 +01:00
return false ;
}
return true ;
2012-01-05 16:44:14 +01:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE :
if ( ! classRace . class_id && ! classRace . race_id )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) must not have 0 in either value field, ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType );
2012-01-05 16:44:14 +01:00
return false ;
}
if ( classRace . class_id && (( 1 << ( classRace . class_id - 1 )) & CLASSMASK_ALL_PLAYABLE ) == 0 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing class in value1 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , classRace . class_id );
2012-01-05 16:44:14 +01:00
return false ;
}
if ( classRace . race_id && (( 1 << ( classRace . race_id - 1 )) & RACEMASK_ALL_PLAYABLE ) == 0 )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) for data type ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE (%u) has non-existing race in value2 (%u), ignored." ,
2012-08-27 15:06:59 +02:00
criteria -> ID , criteria -> type , dataType , classRace . race_id );
2012-01-05 16:44:14 +01:00
return false ;
}
return true ;
2009-04-08 16:24:34 -05:00
default :
2012-08-27 15:06:59 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` (Entry: %u Type: %u) has data for non-supported data type (%u), ignored." , criteria -> ID , criteria -> type , dataType );
2009-04-08 16:24:34 -05:00
return false ;
}
}
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
bool AchievementCriteriaData :: Meets ( uint32 criteria_id , Player const * source , Unit const * target , uint32 miscValue1 /*= 0*/ ) const
2009-04-08 16:24:34 -05:00
{
2010-12-17 18:12:46 +01:00
switch ( dataType )
2009-04-08 16:24:34 -05:00
{
case ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE :
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_CREATURE :
2010-04-08 08:20:08 +02:00
if ( ! target || target -> GetTypeId () != TYPEID_UNIT )
2009-04-08 16:24:34 -05:00
return false ;
2009-06-07 20:54:23 -05:00
return target -> GetEntry () == creature . id ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_CLASS_RACE :
2009-10-18 18:38:46 -07:00
if ( ! target || target -> GetTypeId () != TYPEID_PLAYER )
2009-04-08 16:24:34 -05:00
return false ;
2010-04-07 19:14:10 +02:00
if ( classRace . class_id && classRace . class_id != target -> ToPlayer () -> getClass ())
2009-04-08 16:24:34 -05:00
return false ;
2010-04-07 19:14:10 +02:00
if ( classRace . race_id && classRace . race_id != target -> ToPlayer () -> getRace ())
2009-04-08 16:24:34 -05:00
return false ;
return true ;
2012-01-05 16:44:14 +01:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_PLAYER_CLASS_RACE :
if ( ! source || source -> GetTypeId () != TYPEID_PLAYER )
return false ;
if ( classRace . class_id && classRace . class_id != source -> ToPlayer () -> getClass ())
return false ;
if ( classRace . race_id && classRace . race_id != source -> ToPlayer () -> getRace ())
return false ;
return true ;
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_PLAYER_LESS_HEALTH :
2009-10-18 18:38:46 -07:00
if ( ! target || target -> GetTypeId () != TYPEID_PLAYER )
2009-04-08 16:24:34 -05:00
return false ;
2010-08-26 01:20:57 +06:00
return ! target -> HealthAbovePct ( health . percent );
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_AURA :
2011-04-29 20:47:02 +02:00
return source -> HasAuraEffect ( aura . spell_id , aura . effect_idx );
2009-04-08 16:34:38 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_AURA :
2011-04-29 20:47:02 +02:00
return target && target -> HasAuraEffect ( aura . spell_id , aura . effect_idx );
2009-06-01 21:51:34 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_VALUE :
2012-08-27 15:06:59 +02:00
return miscValue1 >= value . minvalue ;
2009-06-07 20:52:00 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_LEVEL :
if ( ! target )
return false ;
return target -> getLevel () >= level . minlevel ;
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_GENDER :
if ( ! target )
return false ;
return target -> getGender () == gender . gender ;
2010-08-07 16:48:34 +02:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT :
2010-12-22 21:25:23 +01:00
return sScriptMgr -> OnCriteriaCheck ( this , const_cast < Player *> ( source ), const_cast < Unit *> ( target ));
2009-06-07 20:54:23 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_MAP_PLAYER_COUNT :
return source -> GetMap () -> GetPlayersCountExceptGMs () <= map_players . maxcount ;
2009-06-09 17:20:19 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_T_TEAM :
if ( ! target || target -> GetTypeId () != TYPEID_PLAYER )
return false ;
2010-03-07 15:20:19 +01:00
return target -> ToPlayer () -> GetTeam () == team . team ;
2009-06-14 09:59:50 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_DRUNK :
2010-08-23 07:51:19 +02:00
return Player :: GetDrunkenstateByValue ( source -> GetDrunkValue ()) >= DrunkenState ( drunk . state );
2009-06-14 10:00:45 -05:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_HOLIDAY :
return IsHolidayActive ( HolidayIds ( holiday . id ));
2009-07-31 11:36:02 +08:00
case ACHIEVEMENT_CRITERIA_DATA_TYPE_BG_LOSS_TEAM_SCORE :
{
2010-08-08 04:37:24 +02:00
Battleground * bg = source -> GetBattleground ();
2010-04-07 19:14:10 +02:00
if ( ! bg )
2009-07-31 11:36:02 +08:00
return false ;
2012-10-04 12:49:58 +02:00
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 ;
2009-07-31 11:36:02 +08:00
}
2009-12-25 15:53:37 +01:00
case ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT :
2010-03-22 18:32:38 +01:00
{
2009-12-25 15:53:37 +01:00
if ( ! source -> IsInWorld ())
return false ;
Map * map = source -> GetMap ();
2010-04-20 21:55:47 +02:00
if ( ! map -> IsDungeon ())
2009-12-25 15:53:37 +01:00
{
2012-08-21 23:40:38 +01:00
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "Achievement system call ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT (%u) for achievement criteria %u for non-dungeon/non-raid map %u" ,
2009-12-25 15:53:37 +01:00
ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT , criteria_id , map -> GetId ());
return false ;
}
2010-12-17 18:12:46 +01:00
InstanceScript * instance = (( InstanceMap * ) map ) -> GetInstanceScript ();
if ( ! instance )
2009-12-25 15:53:37 +01:00
{
2012-08-21 23:40:38 +01:00
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "Achievement system call ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT (%u) for achievement criteria %u for map %u but map does not have a instance script" ,
2009-12-25 15:53:37 +01:00
ACHIEVEMENT_CRITERIA_DATA_INSTANCE_SCRIPT , criteria_id , map -> GetId ());
return false ;
}
2012-08-27 15:06:59 +02:00
return instance -> CheckAchievementCriteriaMeet ( criteria_id , source , target , miscValue1 );
2010-03-22 18:32:38 +01:00
}
case ACHIEVEMENT_CRITERIA_DATA_TYPE_S_EQUIPED_ITEM :
{
2012-08-27 15:06:59 +02:00
ItemTemplate const * pProto = sObjectMgr -> GetItemTemplate ( miscValue1 );
2010-03-22 18:32:38 +01:00
if ( ! pProto )
return false ;
return pProto -> ItemLevel >= equipped_item . item_level && pProto -> Quality >= equipped_item . item_quality ;
}
2010-12-17 18:12:46 +01:00
default :
break ;
2009-04-08 16:24:34 -05:00
}
return false ;
}
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
bool AchievementCriteriaDataSet :: Meets ( Player const * source , Unit const * target , uint32 miscValue /*= 0*/ ) const
2009-04-08 16:34:38 -05:00
{
2009-10-17 16:20:24 -07:00
for ( Storage :: const_iterator itr = storage . begin (); itr != storage . end (); ++ itr )
2012-08-27 15:06:59 +02:00
if ( ! itr -> Meets ( criteria_id , source , target , miscValue ))
2009-04-08 16:34:38 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:34:38 -05:00
return true ;
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
2012-09-18 11:33:09 +02:00
AchievementMgr < T >:: AchievementMgr ( T * owner ) : _owner ( owner ), _achievementPoints ( 0 ) {}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
AchievementMgr < T >::~ AchievementMgr ()
2008-12-24 09:58:26 -06:00
{
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: SendPacket ( WorldPacket * data ) const
2009-02-06 15:40:48 -06:00
{
2012-07-09 11:08:33 +02:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: SendPacket ( WorldPacket * data ) const
{
GetOwner () -> BroadcastPacket ( data );
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Player >:: SendPacket ( WorldPacket * data ) const
{
GetOwner () -> GetSession () -> SendPacket ( data );
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: RemoveCriteriaProgress ( const AchievementCriteriaEntry * entry )
{
CriteriaProgressMap :: iterator criteriaProgress = m_criteriaProgress . find ( entry -> ID );
if ( criteriaProgress == m_criteriaProgress . end ())
return ;
WorldPacket data ( SMSG_CRITERIA_DELETED , 4 );
data << uint32 ( entry -> ID );
SendPacket ( & data );
m_criteriaProgress . erase ( criteriaProgress );
}
template <>
void AchievementMgr < Guild >:: RemoveCriteriaProgress ( const AchievementCriteriaEntry * entry )
{
CriteriaProgressMap :: iterator criteriaProgress = m_criteriaProgress . find ( entry -> ID );
if ( criteriaProgress == m_criteriaProgress . end ())
return ;
2012-07-11 19:26:26 +02:00
ObjectGuid guid = GetOwner () -> GetGUID ();
2012-07-09 11:08:33 +02:00
WorldPacket data ( SMSG_GUILD_CRITERIA_DELETED , 4 + 8 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( guid [ 7 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 2 ]);
data . WriteByteSeq ( guid [ 3 ]);
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( guid [ 7 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( entry -> ID );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 5 ]);
data . WriteByteSeq ( guid [ 0 ]);
data . WriteByteSeq ( guid [ 6 ]);
2012-07-09 11:08:33 +02:00
SendPacket ( & data );
m_criteriaProgress . erase ( criteriaProgress );
2009-02-06 15:40:48 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
2012-08-27 15:06:59 +02:00
void AchievementMgr < T >:: ResetAchievementCriteria ( AchievementCriteriaTypes type , uint32 miscValue1 , uint32 miscValue2 , bool evenIfCriteriaComplete )
2009-04-23 22:07:37 -05:00
{
2012-09-18 11:33:09 +02:00
sLog -> outDebug ( LOG_FILTER_ACHIEVEMENTSYS , "ResetAchievementCriteria(%u, %u, %u)" , type , miscValue1 , miscValue2 );
2009-10-17 15:51:44 -07:00
2011-07-02 02:14:49 +02:00
// disable for gamemasters with GM-mode enabled
2012-07-09 11:08:33 +02:00
if ( GetOwner () -> isGameMaster ())
2009-04-23 22:07:37 -05:00
return ;
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
AchievementCriteriaEntryList const & achievementCriteriaList = sAchievementMgr -> GetAchievementCriteriaByType ( type );
2010-04-08 08:20:08 +02:00
for ( AchievementCriteriaEntryList :: const_iterator i = achievementCriteriaList . begin (); i != achievementCriteriaList . end (); ++ i )
2009-04-23 22:07:37 -05:00
{
2011-09-15 14:08:17 +02:00
AchievementCriteriaEntry const * achievementCriteria = ( * i );
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( achievementCriteria -> achievement );
2009-04-23 22:07:37 -05:00
if ( ! achievement )
continue ;
2009-10-17 15:51:44 -07:00
2010-08-07 18:31:06 +02:00
// don't update already completed criteria if not forced or achievement already complete
2011-12-12 18:19:26 +01:00
if (( IsCompletedCriteria ( achievementCriteria , achievement ) && ! evenIfCriteriaComplete ) || HasAchieved ( achievement -> ID ))
2009-04-23 22:07:37 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2010-08-07 18:31:06 +02:00
for ( uint8 j = 0 ; j < MAX_CRITERIA_REQUIREMENTS ; ++ j )
2012-08-27 15:06:59 +02:00
if ( achievementCriteria -> additionalRequirements [ j ]. additionalRequirement_type == miscValue1 &&
2011-03-26 05:33:46 +02:00
( ! achievementCriteria -> additionalRequirements [ j ]. additionalRequirement_value ||
2012-08-27 15:06:59 +02:00
achievementCriteria -> additionalRequirements [ j ]. additionalRequirement_value == miscValue2 ))
2010-08-07 18:31:06 +02:00
{
2010-08-13 13:48:59 +02:00
RemoveCriteriaProgress ( achievementCriteria );
2009-04-23 22:07:37 -05:00
break ;
2010-08-07 18:31:06 +02:00
}
2009-04-23 22:07:37 -05:00
}
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
2012-08-27 15:06:59 +02:00
void AchievementMgr < Guild >:: ResetAchievementCriteria ( AchievementCriteriaTypes /*type*/ , uint32 /*miscValue1*/ , uint32 /*miscValue2*/ , bool /*evenIfCriteriaComplete*/ )
2012-07-09 11:08:33 +02:00
{
// Not needed
}
template < class T >
void AchievementMgr < T >:: DeleteFromDB ( uint32 /*lowguid*/ )
{
}
template <>
void AchievementMgr < Player >:: DeleteFromDB ( uint32 lowguid )
2009-02-06 15:40:48 -06:00
{
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2012-05-30 08:01:02 +02:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_CHAR_ACHIEVEMENT );
stmt -> setUInt32 ( 0 , lowguid );
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_CHAR_ACHIEVEMENT_PROGRESS );
stmt -> setUInt32 ( 0 , lowguid );
trans -> Append ( stmt );
2010-08-21 03:19:25 +02:00
CharacterDatabase . CommitTransaction ( trans );
2009-02-06 15:40:48 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: DeleteFromDB ( uint32 lowguid )
{
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_ALL_GUILD_ACHIEVEMENTS );
stmt -> setUInt32 ( 0 , lowguid );
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_ALL_GUILD_ACHIEVEMENT_CRITERIA );
stmt -> setUInt32 ( 0 , lowguid );
trans -> Append ( stmt );
CharacterDatabase . CommitTransaction ( trans );
}
template < class T >
void AchievementMgr < T >:: SaveToDB ( SQLTransaction & /*trans*/ )
{
}
template <>
void AchievementMgr < Player >:: SaveToDB ( SQLTransaction & trans )
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! m_completedAchievements . empty ())
2008-12-24 09:58:26 -06:00
{
bool need_execute = false ;
std :: ostringstream ssdel ;
std :: ostringstream ssins ;
2010-04-08 08:20:08 +02:00
for ( CompletedAchievementMap :: iterator iter = m_completedAchievements . begin (); iter != m_completedAchievements . end (); ++ iter )
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! iter -> second . changed )
2008-12-24 09:58:26 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
/// first new/changed record prefix
2010-04-07 19:14:10 +02:00
if ( ! need_execute )
2008-12-24 09:58:26 -06:00
{
2012-07-09 11:08:33 +02:00
ssdel << "DELETE FROM character_achievement WHERE guid = " << GetOwner () -> GetGUIDLow () << " AND achievement IN (" ;
2008-12-24 09:58:26 -06:00
ssins << "INSERT INTO character_achievement (guid, achievement, date) VALUES " ;
need_execute = true ;
}
/// next new/changed record prefix
else
{
2011-07-29 14:18:28 +02:00
ssdel << ',' ;
ssins << ',' ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// new/changed record data
ssdel << iter -> first ;
2012-07-09 11:08:33 +02:00
ssins << '(' << GetOwner () -> GetGUIDLow () << ',' << iter -> first << ',' << uint64 ( iter -> second . date ) << ')' ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
/// mark as saved in db
iter -> second . changed = false ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( need_execute )
2008-12-24 09:58:26 -06:00
{
2011-09-29 22:35:00 +04:00
ssdel << ')' ;
2010-08-21 03:19:25 +02:00
trans -> Append ( ssdel . str (). c_str ());
trans -> Append ( ssins . str (). c_str ());
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! m_criteriaProgress . empty ())
2008-12-24 09:58:26 -06:00
{
/// prepare deleting and insert
2009-01-20 19:59:43 -06:00
bool need_execute_del = false ;
bool need_execute_ins = false ;
2008-12-24 09:58:26 -06:00
std :: ostringstream ssdel ;
std :: ostringstream ssins ;
2010-04-08 08:20:08 +02:00
for ( CriteriaProgressMap :: iterator iter = m_criteriaProgress . begin (); iter != m_criteriaProgress . end (); ++ iter )
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( ! iter -> second . changed )
2008-12-24 09:58:26 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// deleted data (including 0 progress state)
2008-12-24 09:58:26 -06:00
{
2009-01-20 19:59:43 -06:00
/// first new/changed record prefix (for any counter value)
2010-04-07 19:14:10 +02:00
if ( ! need_execute_del )
2009-01-20 19:59:43 -06:00
{
2012-07-09 11:08:33 +02:00
ssdel << "DELETE FROM character_achievement_progress WHERE guid = " << GetOwner () -> GetGUIDLow () << " AND criteria IN (" ;
2009-01-20 19:59:43 -06:00
need_execute_del = true ;
}
/// next new/changed record prefix
else
2011-07-29 14:18:28 +02:00
ssdel << ',' ;
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// new/changed record data
ssdel << iter -> first ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// store data only for real progress
2010-04-07 19:14:10 +02:00
if ( iter -> second . counter != 0 )
2008-12-24 09:58:26 -06:00
{
2009-01-20 19:59:43 -06:00
/// first new/changed record prefix
2010-04-07 19:14:10 +02:00
if ( ! need_execute_ins )
2009-01-20 19:59:43 -06:00
{
ssins << "INSERT INTO character_achievement_progress (guid, criteria, counter, date) VALUES " ;
need_execute_ins = true ;
}
/// next new/changed record prefix
else
2011-07-29 14:18:28 +02:00
ssins << ',' ;
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// new/changed record data
2012-07-09 11:08:33 +02:00
ssins << '(' << GetOwner () -> GetGUIDLow () << ',' << iter -> first << ',' << iter -> second . counter << ',' << iter -> second . date << ')' ;
2009-01-20 19:59:43 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
/// mark as updated in db
2008-12-24 09:58:26 -06:00
iter -> second . changed = false ;
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( need_execute_del ) // DELETE ... IN (.... _)_
2011-07-29 14:18:28 +02:00
ssdel << ')' ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( need_execute_del || need_execute_ins )
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( need_execute_del )
2010-08-21 03:19:25 +02:00
trans -> Append ( ssdel . str (). c_str ());
2010-04-07 19:14:10 +02:00
if ( need_execute_ins )
2010-08-21 03:19:25 +02:00
trans -> Append ( ssins . str (). c_str ());
2008-12-24 09:58:26 -06:00
}
}
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: SaveToDB ( SQLTransaction & trans )
{
PreparedStatement * stmt ;
std :: ostringstream guidstr ;
for ( CompletedAchievementMap :: const_iterator itr = m_completedAchievements . begin (); itr != m_completedAchievements . end (); ++ itr )
{
if ( ! itr -> second . changed )
continue ;
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_GUILD_ACHIEVEMENT );
stmt -> setUInt32 ( 0 , GetOwner () -> GetId ());
stmt -> setUInt16 ( 1 , itr -> first );
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_INS_GUILD_ACHIEVEMENT );
stmt -> setUInt32 ( 0 , GetOwner () -> GetId ());
stmt -> setUInt16 ( 1 , itr -> first );
stmt -> setUInt32 ( 2 , itr -> second . date );
for ( std :: set < uint64 >:: const_iterator gItr = itr -> second . guids . begin (); gItr != itr -> second . guids . end (); ++ gItr )
guidstr << GUID_LOPART ( * gItr ) << ',' ;
stmt -> setString ( 3 , guidstr . str ());
trans -> Append ( stmt );
guidstr . str ( "" );
}
for ( CriteriaProgressMap :: const_iterator itr = m_criteriaProgress . begin (); itr != m_criteriaProgress . end (); ++ itr )
{
if ( ! itr -> second . changed )
continue ;
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_GUILD_ACHIEVEMENT_CRITERIA );
stmt -> setUInt32 ( 0 , GetOwner () -> GetId ());
stmt -> setUInt16 ( 1 , itr -> first );
trans -> Append ( stmt );
stmt = CharacterDatabase . GetPreparedStatement ( CHAR_INS_GUILD_ACHIEVEMENT_CRITERIA );
stmt -> setUInt32 ( 0 , GetOwner () -> GetId ());
stmt -> setUInt16 ( 1 , itr -> first );
stmt -> setUInt32 ( 2 , itr -> second . counter );
stmt -> setUInt32 ( 3 , itr -> second . date );
stmt -> setUInt32 ( 4 , GUID_LOPART ( itr -> second . CompletedGUID ));
trans -> Append ( stmt );
}
}
template < class T >
void AchievementMgr < T >:: LoadFromDB ( PreparedQueryResult achievementResult , PreparedQueryResult criteriaResult )
{
}
template <>
void AchievementMgr < Player >:: LoadFromDB ( PreparedQueryResult achievementResult , PreparedQueryResult criteriaResult )
2008-12-24 09:58:26 -06:00
{
2010-04-07 19:14:10 +02:00
if ( achievementResult )
2008-12-24 09:58:26 -06:00
{
do
{
2010-09-25 17:10:00 +02:00
Field * fields = achievementResult -> Fetch ();
2011-01-28 15:34:53 +01:00
uint32 achievementid = fields [ 0 ]. GetUInt16 ();
2009-10-17 15:51:44 -07:00
2011-07-29 14:18:28 +02:00
// must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( achievementid );
2011-01-28 15:34:53 +01:00
if ( ! achievement )
2009-05-08 19:22:17 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2011-01-28 15:34:53 +01:00
CompletedAchievementData & ca = m_completedAchievements [ achievementid ];
2011-01-19 02:53:44 +01:00
ca . date = time_t ( fields [ 1 ]. GetUInt32 ());
2008-12-24 09:58:26 -06:00
ca . changed = false ;
2011-01-28 15:34:53 +01:00
2012-09-18 11:33:09 +02:00
_achievementPoints += achievement -> points ;
2011-01-28 15:34:53 +01:00
// title achievement rewards are retroactive
if ( AchievementReward const * reward = sAchievementMgr -> GetAchievementReward ( achievement ))
2012-07-09 11:08:33 +02:00
if ( uint32 titleId = reward -> titleId [ Player :: TeamForRace ( GetOwner () -> getRace ()) == ALLIANCE ? 0 : 1 ])
2011-01-28 15:34:53 +01:00
if ( CharTitlesEntry const * titleEntry = sCharTitlesStore . LookupEntry ( titleId ))
2012-09-17 23:49:13 +01:00
GetOwner () -> SetTitle ( titleEntry );
2011-01-28 15:34:53 +01:00
2012-08-27 15:06:59 +02:00
}
while ( achievementResult -> NextRow ());
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( criteriaResult )
2008-12-24 09:58:26 -06:00
{
2012-08-27 15:06:59 +02:00
time_t now = time ( NULL );
2008-12-24 09:58:26 -06:00
do
{
2010-09-25 17:10:00 +02:00
Field * fields = criteriaResult -> Fetch ();
2011-01-19 02:53:44 +01:00
uint32 id = fields [ 0 ]. GetUInt16 ();
2010-09-24 22:16:21 +02:00
uint32 counter = fields [ 1 ]. GetUInt32 ();
2011-01-19 02:53:44 +01:00
time_t date = time_t ( fields [ 2 ]. GetUInt32 ());
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntry const * criteria = sAchievementMgr -> GetAchievementCriteria ( id );
2009-05-08 19:22:17 -05:00
if ( ! criteria )
{
// we will remove not existed criteria for all characters
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "Non-existing achievement criteria %u data removed from table `character_achievement_progress`." , id );
2011-12-27 00:29:17 +01:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA );
stmt -> setUInt16 ( 0 , uint16 ( id ));
CharacterDatabase . Execute ( stmt );
2009-05-08 19:22:17 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
if ( criteria -> timeLimit && time_t ( date + criteria -> timeLimit ) < now )
2008-12-24 09:58:26 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
CriteriaProgress & progress = m_criteriaProgress [ id ];
progress . counter = counter ;
progress . date = date ;
progress . changed = false ;
2012-08-27 15:06:59 +02:00
}
while ( criteriaResult -> NextRow ());
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: LoadFromDB ( PreparedQueryResult achievementResult , PreparedQueryResult criteriaResult )
2008-12-24 09:58:26 -06:00
{
2012-07-09 11:08:33 +02:00
if ( achievementResult )
{
do
{
Field * fields = achievementResult -> Fetch ();
uint32 achievementid = fields [ 0 ]. GetUInt16 ();
// must not happen: cleanup at server startup in sAchievementMgr->LoadCompletedAchievements()
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( achievementid );
2012-07-09 11:08:33 +02:00
if ( ! achievement )
continue ;
CompletedAchievementData & ca = m_completedAchievements [ achievementid ];
ca . date = time_t ( fields [ 1 ]. GetUInt32 ());
2012-10-04 13:33:04 +02:00
Tokenizer guids ( fields [ 2 ]. GetString (), ' ' );
2012-07-09 11:08:33 +02:00
for ( uint32 i = 0 ; i < guids . size (); ++ i )
ca . guids . insert ( MAKE_NEW_GUID ( atol ( guids [ i ]), 0 , HIGHGUID_PLAYER ));
ca . changed = false ;
2012-09-18 11:33:09 +02:00
_achievementPoints += achievement -> points ;
2012-08-27 15:06:59 +02:00
}
while ( achievementResult -> NextRow ());
2012-07-09 11:08:33 +02:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
if ( criteriaResult )
{
time_t now = time ( NULL );
do
{
Field * fields = criteriaResult -> Fetch ();
uint32 id = fields [ 0 ]. GetUInt16 ();
uint32 counter = fields [ 1 ]. GetUInt32 ();
time_t date = time_t ( fields [ 2 ]. GetUInt32 ());
uint64 guid = fields [ 3 ]. GetUInt32 ();
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntry const * criteria = sAchievementMgr -> GetAchievementCriteria ( id );
2012-07-09 11:08:33 +02:00
if ( ! criteria )
{
// we will remove not existed criteria for all guilds
2012-08-27 15:06:59 +02:00
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "Non-existing achievement criteria %u data removed from table `guild_achievement_progress`." , id );
2012-07-09 11:08:33 +02:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_INVALID_ACHIEV_PROGRESS_CRITERIA );
stmt -> setUInt16 ( 0 , uint16 ( id ));
CharacterDatabase . Execute ( stmt );
continue ;
}
if ( criteria -> timeLimit && time_t ( date + criteria -> timeLimit ) < now )
continue ;
CriteriaProgress & progress = m_criteriaProgress [ id ];
progress . counter = counter ;
progress . date = date ;
progress . CompletedGUID = MAKE_NEW_GUID ( guid , 0 , HIGHGUID_PLAYER );
progress . changed = false ;
} while ( criteriaResult -> NextRow ());
}
}
template < class T >
void AchievementMgr < T >:: Reset ()
2012-07-11 23:27:00 +02:00
{
}
template <>
void AchievementMgr < Player >:: Reset ()
2012-07-09 11:08:33 +02:00
{
for ( CompletedAchievementMap :: const_iterator iter = m_completedAchievements . begin (); iter != m_completedAchievements . end (); ++ iter )
{
WorldPacket data ( SMSG_ACHIEVEMENT_DELETED , 4 );
data << uint32 ( iter -> first );
SendPacket ( & data );
}
for ( CriteriaProgressMap :: const_iterator iter = m_criteriaProgress . begin (); iter != m_criteriaProgress . end (); ++ iter )
{
WorldPacket data ( SMSG_CRITERIA_DELETED , 4 );
data << uint32 ( iter -> first );
SendPacket ( & data );
}
m_completedAchievements . clear ();
2012-09-18 11:33:09 +02:00
_achievementPoints = 0 ;
2012-07-09 11:08:33 +02:00
m_criteriaProgress . clear ();
2012-08-27 15:06:59 +02:00
DeleteFromDB ( GetOwner () -> GetGUIDLow ());
2012-07-09 11:08:33 +02:00
// re-fill data
2012-07-11 23:27:00 +02:00
CheckAllAchievementCriteria ( GetOwner ());
2012-07-09 11:08:33 +02:00
}
template <>
void AchievementMgr < Guild >:: Reset ()
{
2012-07-11 19:26:26 +02:00
ObjectGuid guid = GetOwner () -> GetGUID ();
2012-07-09 11:08:33 +02:00
for ( CompletedAchievementMap :: const_iterator iter = m_completedAchievements . begin (); iter != m_completedAchievements . end (); ++ iter )
{
WorldPacket data ( SMSG_GUILD_ACHIEVEMENT_DELETED , 4 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 4 ]);
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( guid [ 7 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( guid [ 6 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( iter -> first );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 5 ]);
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( guid [ 3 ]);
data . WriteByteSeq ( guid [ 6 ]);
data . WriteByteSeq ( guid [ 0 ]);
data . WriteByteSeq ( guid [ 7 ]);
2012-09-13 17:24:37 +01:00
data . AppendPackedTime ( iter -> second . date );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 2 ]);
2012-07-09 11:08:33 +02:00
SendPacket ( & data );
}
while ( ! m_criteriaProgress . empty ())
2012-08-27 15:06:59 +02:00
if ( AchievementCriteriaEntry const * criteria = sAchievementMgr -> GetAchievementCriteria ( m_criteriaProgress . begin () -> first ))
2012-07-09 11:08:33 +02:00
RemoveCriteriaProgress ( criteria );
2012-09-18 11:33:09 +02:00
_achievementPoints = 0 ;
2012-07-09 11:08:33 +02:00
m_completedAchievements . clear ();
2012-08-27 15:06:59 +02:00
DeleteFromDB ( GetOwner () -> GetId ());
2012-07-09 11:08:33 +02:00
}
template < class T >
void AchievementMgr < T >:: SendAchievementEarned ( AchievementEntry const * achievement ) const
{
2012-08-27 15:06:59 +02:00
// Don't send for achievements with ACHIEVEMENT_FLAG_HIDDEN
2011-03-04 12:11:20 +01:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_HIDDEN )
2010-04-27 22:22:13 +02:00
return ;
2012-08-27 15:06:59 +02:00
sLog -> outDebug ( LOG_FILTER_ACHIEVEMENTSYS , "AchievementMgr::SendAchievementEarned(%u)" , achievement -> ID );
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
if ( Guild * guild = sGuildMgr -> GetGuildById ( GetOwner () -> GetGuildId ()))
2008-12-24 09:58:26 -06:00
{
2012-07-09 11:08:33 +02:00
Trinity :: AchievementChatBuilder say_builder ( * GetOwner (), CHAT_MSG_GUILD_ACHIEVEMENT , LANG_ACHIEVEMENT_EARNED , achievement -> ID );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: AchievementChatBuilder > say_do ( say_builder );
2012-07-09 11:08:33 +02:00
guild -> BroadcastWorker ( say_do );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
if ( achievement -> flags & ( ACHIEVEMENT_FLAG_REALM_FIRST_KILL | ACHIEVEMENT_FLAG_REALM_FIRST_REACH ))
2008-12-24 09:58:26 -06:00
{
// broadcast realm first reached
2012-08-27 15:06:59 +02:00
WorldPacket data ( SMSG_SERVER_FIRST_ACHIEVEMENT , strlen ( GetOwner () -> GetName ()) + 1 + 8 + 4 + 4 );
2012-07-09 11:08:33 +02:00
data << GetOwner () -> GetName ();
data << uint64 ( GetOwner () -> GetGUID ());
2008-12-24 09:58:26 -06:00
data << uint32 ( achievement -> ID );
2009-02-21 17:02:56 -06:00
data << uint32 ( 0 ); // 1=link supplied string as player name, 0=display plain string
2010-12-23 23:25:44 +01:00
sWorld -> SendGlobalMessage ( & data );
2008-12-24 09:58:26 -06:00
}
2009-12-17 19:09:40 +01:00
// if player is in world he can tell his friends about new achievement
2012-07-09 11:08:33 +02:00
else if ( GetOwner () -> IsInWorld ())
2008-12-24 09:58:26 -06:00
{
2012-07-09 11:08:33 +02:00
CellCoord p = Trinity :: ComputeCellCoord ( GetOwner () -> GetPositionX (), GetOwner () -> GetPositionY ());
2009-10-17 15:51:44 -07:00
2009-02-21 17:02:56 -06:00
Cell cell ( p );
cell . SetNoCreate ();
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
Trinity :: AchievementChatBuilder say_builder ( * GetOwner (), CHAT_MSG_ACHIEVEMENT , LANG_ACHIEVEMENT_EARNED , achievement -> ID );
2009-12-20 15:20:04 +01:00
Trinity :: LocalizedPacketDo < Trinity :: AchievementChatBuilder > say_do ( say_builder );
2012-07-09 11:08:33 +02:00
Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: AchievementChatBuilder > > say_worker ( GetOwner (), sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), say_do );
2009-12-20 15:20:04 +01:00
TypeContainerVisitor < Trinity :: PlayerDistWorker < Trinity :: LocalizedPacketDo < Trinity :: AchievementChatBuilder > > , WorldTypeMapContainer > message ( say_worker );
2012-07-09 11:08:33 +02:00
cell . Visit ( p , message , * GetOwner () -> GetMap (), * GetOwner (), sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ));
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
WorldPacket data ( SMSG_ACHIEVEMENT_EARNED , 8 + 4 + 8 );
2012-07-09 11:08:33 +02:00
data . append ( GetOwner () -> GetPackGUID ());
2008-12-24 09:58:26 -06:00
data << uint32 ( achievement -> ID );
2012-09-13 16:38:18 +02:00
data . AppendPackedTime ( time ( NULL ));
2012-07-09 11:08:33 +02:00
data << uint32 ( 0 ); // does not notify player ingame
GetOwner () -> SendMessageToSetInRange ( & data , sWorld -> getFloatConfig ( CONFIG_LISTEN_RANGE_SAY ), true );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: SendAchievementEarned ( AchievementEntry const * achievement ) const
{
2012-07-11 19:26:26 +02:00
ObjectGuid guid = GetOwner () -> GetGUID ();
2012-07-09 11:08:33 +02:00
WorldPacket data ( SMSG_GUILD_ACHIEVEMENT_EARNED , 8 + 4 + 8 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( guid [ 7 ]);
data . WriteBit ( guid [ 4 ]);
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteByteSeq ( guid [ 2 ]);
2012-09-13 17:24:37 +01:00
data . AppendPackedTime ( time ( NULL ));
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 0 ]);
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( guid [ 3 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( achievement -> ID );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 7 ]);
data . WriteByteSeq ( guid [ 5 ]);
data . WriteByteSeq ( guid [ 6 ]);
2012-07-09 11:08:33 +02:00
SendPacket ( & data );
}
template < class T >
void AchievementMgr < T >:: SendCriteriaUpdate ( AchievementCriteriaEntry const * /*entry*/ , CriteriaProgress const * /*progress*/ , uint32 /*timeElapsed*/ , bool /*timedCompleted*/ ) const
{
}
template <>
void AchievementMgr < Player >:: SendCriteriaUpdate ( AchievementCriteriaEntry const * entry , CriteriaProgress const * progress , uint32 timeElapsed , bool timedCompleted ) const
2008-12-24 09:58:26 -06:00
{
2012-08-27 15:06:59 +02:00
WorldPacket data ( SMSG_CRITERIA_UPDATE , 8 + 4 + 8 );
2010-04-27 22:22:13 +02:00
data << uint32 ( entry -> ID );
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// the counter is packed like a packed Guid
data . appendPackGUID ( progress -> counter );
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
data . appendPackGUID ( GetOwner () -> GetGUID ());
2010-04-27 22:22:13 +02:00
if ( ! entry -> timeLimit )
data << uint32 ( 0 );
else
data << uint32 ( timedCompleted ? 0 : 1 ); // this are some flags, 1 is for keeping the counter at 0 in client
2012-09-13 16:38:18 +02:00
data . AppendPackedTime ( progress -> date );
2010-04-27 22:22:13 +02:00
data << uint32 ( timeElapsed ); // time elapsed in seconds
data << uint32 ( 0 ); // unk
2012-07-09 11:08:33 +02:00
SendPacket ( & data );
}
template <>
void AchievementMgr < Guild >:: SendCriteriaUpdate ( AchievementCriteriaEntry const * entry , CriteriaProgress const * progress , uint32 /*timeElapsed*/ , bool /*timedCompleted*/ ) const
{
//will send response to criteria progress request
WorldPacket data ( SMSG_GUILD_CRITERIA_DATA , 3 + 1 + 1 + 8 + 8 + 4 + 4 + 4 + 4 + 4 );
2012-07-11 19:26:26 +02:00
ObjectGuid counter = progress -> counter ; // for accessing every byte individually
ObjectGuid guid = progress -> CompletedGUID ;
2012-07-09 11:08:33 +02:00
data . WriteBits ( 1 , 21 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( counter [ 4 ]);
data . WriteBit ( counter [ 1 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( counter [ 3 ]);
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( counter [ 5 ]);
data . WriteBit ( counter [ 0 ]);
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( counter [ 2 ]);
data . WriteBit ( guid [ 7 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( counter [ 6 ]);
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( counter [ 7 ]);
data . WriteBit ( guid [ 4 ]);
2012-08-04 19:11:13 +01:00
data . FlushBits ();
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 5 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( progress -> date ); // unknown date
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( counter [ 3 ]);
data . WriteByteSeq ( counter [ 7 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( progress -> date ); // unknown date
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( counter [ 6 ]);
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( counter [ 4 ]);
data . WriteByteSeq ( guid [ 3 ]);
data . WriteByteSeq ( counter [ 0 ]);
data . WriteByteSeq ( guid [ 2 ]);
data . WriteByteSeq ( counter [ 1 ]);
data . WriteByteSeq ( guid [ 6 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( progress -> date ); // last update time (not packed!)
data << uint32 ( entry -> ID );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( counter [ 5 ]);
2012-07-09 11:08:33 +02:00
data << uint32 ( 0 );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 7 ]);
data . WriteByteSeq ( counter [ 2 ]);
data . WriteByteSeq ( guid [ 0 ]);
2012-07-09 11:08:33 +02:00
SendPacket ( & data );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
/**
* called at player login. The player might have fulfilled some achievements when the achievement system wasn't working yet
*/
2012-07-09 11:08:33 +02:00
template < class T >
2012-07-11 23:27:00 +02:00
void AchievementMgr < T >:: CheckAllAchievementCriteria ( Player * referencePlayer )
2008-12-24 09:58:26 -06:00
{
// suppress sending packets
2009-10-17 16:20:24 -07:00
for ( uint32 i = 0 ; i < ACHIEVEMENT_CRITERIA_TYPE_TOTAL ; ++ i )
2012-07-11 23:27:00 +02:00
UpdateAchievementCriteria ( AchievementCriteriaTypes ( i ), 0 , 0 , NULL , referencePlayer );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
static const uint32 achievIdByArenaSlot [ MAX_ARENA_SLOT ] = { 1057 , 1107 , 1108 };
2011-03-26 05:33:46 +02:00
static const uint32 achievIdForDungeon [][ 4 ] =
2009-03-06 15:21:44 -06:00
{
2011-04-29 20:47:02 +02:00
// ach_cr_id, is_dungeon, is_raid, is_heroic_dungeon
2009-03-06 15:21:44 -06:00
{ 321 , true , true , true },
{ 916 , false , true , false },
{ 917 , false , true , false },
{ 918 , true , false , false },
{ 2219 , false , false , true },
{ 0 , false , false , false }
};
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
// Helper function to avoid having to specialize template for a 800 line long function
template < typename T > static bool IsGuild () { return false ; }
2012-08-11 17:01:46 +02:00
template <> bool IsGuild < Guild > () { return true ; }
2012-07-09 11:08:33 +02:00
2008-12-24 09:58:26 -06:00
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
2012-07-09 11:08:33 +02:00
template < class T >
2012-08-27 15:06:59 +02:00
void AchievementMgr < T >:: UpdateAchievementCriteria ( AchievementCriteriaTypes type , uint32 miscValue1 /*= 0*/ , uint32 miscValue2 /*= 0*/ , Unit const * unit /*= NULL*/ , Player * referencePlayer /*= NULL*/ )
2008-12-24 09:58:26 -06:00
{
2012-08-27 15:06:59 +02:00
sLog -> outDebug ( LOG_FILTER_ACHIEVEMENTSYS , "UpdateAchievementCriteria(%u, %u, %u)" , type , miscValue1 , miscValue2 );
2009-10-17 15:51:44 -07:00
2011-07-02 02:14:49 +02:00
// disable for gamemasters with GM-mode enabled
2012-07-09 11:08:33 +02:00
if ( referencePlayer -> isGameMaster ())
2009-01-25 16:35:14 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-09-07 14:39:19 +02:00
// Lua_GetGuildLevelEnabled() is checked in achievement UI to display guild tab
if ( IsGuild < T > () && ! sWorld -> getBoolConfig ( CONFIG_GUILD_LEVELING_ENABLED ))
return ;
2012-07-09 11:08:33 +02:00
AchievementCriteriaEntryList const & achievementCriteriaList = sAchievementMgr -> GetAchievementCriteriaByType ( type , IsGuild < T > ());
2010-04-08 08:20:08 +02:00
for ( AchievementCriteriaEntryList :: const_iterator i = achievementCriteriaList . begin (); i != achievementCriteriaList . end (); ++ i )
2008-12-24 09:58:26 -06:00
{
2011-09-15 14:08:17 +02:00
AchievementCriteriaEntry const * achievementCriteria = ( * i );
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( achievementCriteria -> achievement );
2009-04-03 16:36:20 -06:00
if ( ! achievement )
2012-08-27 15:06:59 +02:00
{
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "UpdateAchievementCriteria: Achievement %u not found!" , achievementCriteria -> achievement );
2008-12-24 09:58:26 -06:00
continue ;
2012-08-27 15:06:59 +02:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
if ( ! CanUpdateCriteria ( achievementCriteria , achievement , miscValue1 , miscValue2 , unit , referencePlayer ))
2009-04-03 16:36:20 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2011-12-26 04:55:38 +02:00
// requirements not found in the dbc
if ( AchievementCriteriaDataSet const * data = sAchievementMgr -> GetCriteriaDataSet ( achievementCriteria ))
2012-07-09 11:08:33 +02:00
if ( ! data -> Meets ( referencePlayer , unit , miscValue1 ))
2011-12-26 04:55:38 +02:00
continue ;
2008-12-24 09:58:26 -06:00
switch ( type )
{
2009-03-05 09:22:43 -06:00
// std. case: increment at 1
2009-05-03 22:30:31 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS :
2009-05-05 14:50:06 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL :
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION :
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS : /* FIXME: for online player only currently */
2009-05-31 16:26:39 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED :
2009-05-05 14:49:15 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED :
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN :
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS :
2010-09-03 20:11:14 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS :
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_DEATH :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST :
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP :
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON :
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE :
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER :
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM :
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET :
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 :
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL :
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 :
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA :
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT :
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE :
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT :
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT :
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL :
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS :
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE :
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE :
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL :
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL :
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS :
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA :
2012-10-10 15:45:05 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA : // This also behaves like ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , 1 , referencePlayer , PROGRESS_ACCUMULATE );
2008-12-24 09:58:26 -06:00
break ;
2012-08-27 15:06:59 +02:00
// std case: increment at miscValue1
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS :
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS :
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL :
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY :
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS : /* FIXME: for online player only currently */
2009-04-23 22:07:04 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED :
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED :
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND :
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE :
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE :
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer , PROGRESS_ACCUMULATE );
2009-03-05 09:22:43 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE :
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE :
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY :
SetCriteriaProgress ( achievementCriteria , miscValue2 , referencePlayer , PROGRESS_ACCUMULATE );
break ;
// std case: high value at miscValue1
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD : /* FIXME: for online player only currently */
2009-04-23 22:07:04 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED :
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer , PROGRESS_HIGHEST );
2008-12-24 09:58:26 -06:00
break ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL :
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , referencePlayer -> getLevel (), referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL :
2012-07-09 11:08:33 +02:00
if ( uint32 skillvalue = referencePlayer -> GetBaseSkillValue ( achievementCriteria -> reach_skill_level . skillID ))
SetCriteriaProgress ( achievementCriteria , skillvalue , referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
2009-03-28 17:58:21 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL :
2012-07-09 11:08:33 +02:00
if ( uint32 maxSkillvalue = referencePlayer -> GetPureMaxSkillValue ( achievementCriteria -> learn_skill_level . skillID ))
SetCriteriaProgress ( achievementCriteria , maxSkillvalue , referencePlayer );
2009-03-28 17:58:21 -06:00
break ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT :
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetRewardedQuestCount (), referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
2010-06-14 18:33:46 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY :
{
2010-12-23 23:25:44 +01:00
time_t nextDailyResetTime = sWorld -> GetNextDailyQuestsResetTime ();
2010-06-14 18:33:46 +02:00
CriteriaProgress * progress = GetCriteriaProgress ( achievementCriteria );
2011-04-21 23:32:45 +02:00
if ( ! miscValue1 ) // Login case.
2010-06-14 18:33:46 +02:00
{
// reset if player missed one day.
if ( progress && progress -> date < ( nextDailyResetTime - 2 * DAY ))
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , 0 , referencePlayer , PROGRESS_SET );
2010-06-14 18:33:46 +02:00
continue ;
}
ProgressType progressType ;
2010-08-08 19:45:53 +02:00
if ( ! progress )
2010-06-14 18:33:46 +02:00
// 1st time. Start count.
progressType = PROGRESS_SET ;
else if ( progress -> date < ( nextDailyResetTime - 2 * DAY ))
2012-08-27 15:06:59 +02:00
// last progress is older than 2 days. Player missed 1 day => Restart count.
2010-06-14 18:33:46 +02:00
progressType = PROGRESS_SET ;
else if ( progress -> date < ( nextDailyResetTime - DAY ))
// last progress is between 1 and 2 days. => 1st time of the day.
progressType = PROGRESS_ACCUMULATE ;
else
// last progress is within the day before the reset => Already counted today.
continue ;
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , 1 , referencePlayer , progressType );
2010-06-14 18:33:46 +02:00
break ;
}
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE :
{
2011-07-08 10:54:46 +02:00
uint32 counter = 0 ;
2012-07-09 11:08:33 +02:00
const RewardedQuestSet & rewQuests = referencePlayer -> getRewardedQuests ();
2011-07-08 10:54:46 +02:00
for ( RewardedQuestSet :: const_iterator itr = rewQuests . begin (); itr != rewQuests . end (); ++ itr )
2008-12-24 09:58:26 -06:00
{
2010-12-26 04:16:18 +01:00
Quest const * quest = sObjectMgr -> GetQuestTemplate ( * itr );
if ( quest && quest -> GetZoneOrSort () >= 0 && uint32 ( quest -> GetZoneOrSort ()) == achievementCriteria -> complete_quests_in_zone . zoneID )
2011-07-08 10:54:46 +02:00
++ counter ;
2008-12-24 09:58:26 -06:00
}
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , counter , referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
}
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING :
// miscValue1 is the ingame fallheight*100 as stored in dbc
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer );
2009-01-20 19:59:43 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST :
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL :
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA :
case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP :
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT :
SetCriteriaProgress ( achievementCriteria , 1 , referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetBankBagSlotCount (), referencePlayer );
break ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION :
2009-03-06 15:21:44 -06:00
{
2012-08-27 15:06:59 +02:00
int32 reputation = referencePlayer -> GetReputationMgr (). GetReputation ( achievementCriteria -> gain_reputation . factionID );
if ( reputation > 0 )
SetCriteriaProgress ( achievementCriteria , reputation , referencePlayer );
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetReputationMgr (). GetExaltedFactionCount (), referencePlayer );
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS :
{
uint32 spellCount = 0 ;
for ( PlayerSpellMap :: const_iterator spellIter = referencePlayer -> GetSpellMap (). begin ();
spellIter != referencePlayer -> GetSpellMap (). end ();
++ spellIter )
2009-04-08 16:39:22 -05:00
{
2012-08-27 15:06:59 +02:00
SkillLineAbilityMapBounds bounds = sSpellMgr -> GetSkillLineAbilityMapBounds ( spellIter -> first );
for ( SkillLineAbilityMap :: const_iterator skillIter = bounds . first ; skillIter != bounds . second ; ++ skillIter )
2009-04-08 16:39:22 -05:00
{
2012-08-27 15:06:59 +02:00
if ( skillIter -> second -> skillId == achievementCriteria -> learn_skillline_spell . skillLine )
spellCount ++ ;
2009-04-08 16:39:22 -05:00
}
}
2012-08-27 15:06:59 +02:00
SetCriteriaProgress ( achievementCriteria , spellCount , referencePlayer );
2009-03-06 15:21:44 -06:00
break ;
}
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetReputationMgr (). GetReveredFactionCount (), referencePlayer );
break ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetReputationMgr (). GetHonoredFactionCount (), referencePlayer );
break ;
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetReputationMgr (). GetVisibleFactionCount (), referencePlayer );
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE :
2009-03-06 15:21:44 -06:00
{
2012-08-27 15:06:59 +02:00
uint32 spellCount = 0 ;
for ( PlayerSpellMap :: const_iterator spellIter = referencePlayer -> GetSpellMap (). begin ();
spellIter != referencePlayer -> GetSpellMap (). end ();
++ spellIter )
2009-03-06 15:21:44 -06:00
{
2012-08-27 15:06:59 +02:00
SkillLineAbilityMapBounds bounds = sSpellMgr -> GetSkillLineAbilityMapBounds ( spellIter -> first );
for ( SkillLineAbilityMap :: const_iterator skillIter = bounds . first ; skillIter != bounds . second ; ++ skillIter )
if ( skillIter -> second -> skillId == achievementCriteria -> learn_skill_line . skillLine )
spellCount ++ ;
2009-03-06 15:21:44 -06:00
}
2012-08-27 15:06:59 +02:00
SetCriteriaProgress ( achievementCriteria , spellCount , referencePlayer );
2009-03-06 15:21:44 -06:00
break ;
}
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetUInt32Value ( PLAYER_FIELD_LIFETIME_HONORABLE_KILLS ), referencePlayer );
2008-12-24 09:58:26 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED :
SetCriteriaProgress ( achievementCriteria , referencePlayer -> GetMoney (), referencePlayer , PROGRESS_HIGHEST );
2009-03-06 15:21:44 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS :
2011-04-21 23:32:45 +02:00
if ( ! miscValue1 )
2012-09-18 11:33:09 +02:00
SetCriteriaProgress ( achievementCriteria , _achievementPoints , referencePlayer , PROGRESS_SET );
2012-08-27 15:06:59 +02:00
else
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer , PROGRESS_ACCUMULATE );
2008-12-24 09:58:26 -06:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING :
2009-06-14 10:00:45 -05:00
{
2012-08-27 15:06:59 +02:00
uint32 reqTeamType = achievementCriteria -> highest_team_rating . teamtype ;
2011-04-21 23:32:45 +02:00
if ( miscValue1 )
2009-04-18 20:49:56 -05:00
{
2012-08-27 15:06:59 +02:00
if ( miscValue2 != reqTeamType )
2009-06-14 10:00:45 -05:00
continue ;
2012-08-27 15:06:59 +02:00
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer , PROGRESS_HIGHEST );
2009-04-18 20:49:56 -05:00
}
2012-08-27 15:06:59 +02:00
else // login case
2009-04-18 20:49:56 -05:00
{
2012-08-27 15:06:59 +02:00
for ( uint32 arena_slot = 0 ; arena_slot < MAX_ARENA_SLOT ; ++ arena_slot )
{
uint32 teamId = referencePlayer -> GetArenaTeamId ( arena_slot );
if ( ! teamId )
continue ;
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
ArenaTeam * team = sArenaTeamMgr -> GetArenaTeamById ( teamId );
if ( ! team || team -> GetType () != reqTeamType )
continue ;
2011-12-19 19:30:38 +02:00
2012-08-27 15:06:59 +02:00
SetCriteriaProgress ( achievementCriteria , team -> GetStats (). Rating , referencePlayer , PROGRESS_HIGHEST );
break ;
}
}
2010-01-16 19:41:04 +03:00
2009-03-05 09:22:43 -06:00
break ;
2010-01-16 19:41:04 +03:00
}
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING :
2009-09-11 13:20:38 -07:00
{
2012-08-27 15:06:59 +02:00
uint32 reqTeamType = achievementCriteria -> highest_personal_rating . teamtype ;
2010-12-17 18:12:46 +01:00
2011-04-21 23:32:45 +02:00
if ( miscValue1 )
2010-12-17 18:12:46 +01:00
{
2011-04-21 23:32:45 +02:00
if ( miscValue2 != reqTeamType )
2010-12-17 18:12:46 +01:00
continue ;
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer , PROGRESS_HIGHEST );
2010-12-17 18:12:46 +01:00
}
2012-08-27 15:06:59 +02:00
else // login case
2011-05-25 23:39:17 +02:00
{
for ( uint32 arena_slot = 0 ; arena_slot < MAX_ARENA_SLOT ; ++ arena_slot )
{
2012-07-09 11:08:33 +02:00
uint32 teamId = referencePlayer -> GetArenaTeamId ( arena_slot );
2011-05-25 23:39:17 +02:00
if ( ! teamId )
continue ;
ArenaTeam * team = sArenaTeamMgr -> GetArenaTeamById ( teamId );
if ( ! team || team -> GetType () != reqTeamType )
continue ;
2012-07-09 11:08:33 +02:00
if ( ArenaTeamMember const * member = team -> GetMember ( referencePlayer -> GetGUID ()))
2011-05-25 23:39:17 +02:00
{
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( achievementCriteria , member -> PersonalRating , referencePlayer , PROGRESS_HIGHEST );
2011-05-25 23:39:17 +02:00
break ;
}
}
2010-12-17 18:12:46 +01:00
}
break ;
}
2012-09-07 14:39:19 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL :
2012-09-18 11:33:09 +02:00
SetCriteriaProgress ( achievementCriteria , miscValue1 , referencePlayer );
2012-09-07 14:39:19 +02:00
break ;
2009-03-05 09:22:43 -06:00
// FIXME: not triggered in code as result, need to implement
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID :
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA :
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK :
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE :
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE :
2011-12-27 10:05:49 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS :
case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD :
case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL :
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS :
case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS :
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND :
case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING :
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD :
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD :
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD :
2012-08-17 10:25:29 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS :
case ACHIEVEMENT_CRITERIA_TYPE_UNK118 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK120 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK121 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK122 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK123 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK137 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK138 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK139 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK140 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK141 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK142 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK143 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK144 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK145 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK146 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK147 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK148 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK149 :
case ACHIEVEMENT_CRITERIA_TYPE_UNK150 :
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL :
break ; // Not implemented yet :(
2008-12-24 09:58:26 -06:00
}
2010-09-03 20:11:14 +02:00
2011-03-04 12:11:20 +01:00
if ( IsCompletedCriteria ( achievementCriteria , achievement ))
2012-07-09 11:08:33 +02:00
CompletedCriteriaFor ( achievement , referencePlayer );
2009-10-17 15:51:44 -07:00
2009-07-30 10:19:03 +08:00
// check again the completeness for SUMM and REQ COUNT achievements,
2009-04-11 23:13:00 -05:00
// as they don't depend on the completed criteria but on the sum of the progress of each individual criteria
if ( achievement -> flags & ACHIEVEMENT_FLAG_SUMM )
if ( IsCompletedAchievement ( achievement ))
2012-07-09 11:08:33 +02:00
CompletedAchievement ( achievement , referencePlayer );
2009-10-17 15:51:44 -07:00
2010-12-22 21:25:23 +01:00
if ( AchievementEntryList const * achRefList = sAchievementMgr -> GetAchievementByReferencedId ( achievement -> ID ))
2009-10-17 16:20:24 -07:00
for ( AchievementEntryList :: const_iterator itr = achRefList -> begin (); itr != achRefList -> end (); ++ itr )
2010-04-07 19:14:10 +02:00
if ( IsCompletedAchievement ( * itr ))
2012-07-09 11:08:33 +02:00
CompletedAchievement ( * itr , referencePlayer );
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
bool AchievementMgr < T >:: IsCompletedCriteria ( AchievementCriteriaEntry const * achievementCriteria , AchievementEntry const * achievement )
2008-12-24 09:58:26 -06:00
{
// counter can never complete
2010-04-07 19:14:10 +02:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_COUNTER )
2008-12-24 09:58:26 -06:00
return false ;
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( achievement -> flags & ( ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL ))
2008-12-24 09:58:26 -06:00
{
// someone on this realm has already completed that achievement
2010-12-22 21:25:23 +01:00
if ( sAchievementMgr -> IsRealmCompleted ( achievement ))
2008-12-24 09:58:26 -06:00
return false ;
}
2009-10-17 15:51:44 -07:00
2010-06-14 18:33:46 +02:00
CriteriaProgress const * progress = GetCriteriaProgress ( achievementCriteria );
if ( ! progress )
2008-12-24 09:58:26 -06:00
return false ;
2009-10-17 15:51:44 -07:00
2012-09-18 11:33:09 +02:00
switch ( AchievementCriteriaTypes ( achievementCriteria -> type ))
2008-12-24 09:58:26 -06:00
{
2009-07-31 11:36:02 +08:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG :
return progress -> counter >= achievementCriteria -> win_bg . winCount ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE :
return progress -> counter >= achievementCriteria -> kill_creature . creatureCount ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL :
2012-09-07 14:39:19 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL :
2009-03-05 09:22:43 -06:00
return progress -> counter >= achievementCriteria -> reach_level . level ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL :
return progress -> counter >= achievementCriteria -> reach_skill_level . skillLevel ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT :
return progress -> counter >= 1 ;
2009-01-02 11:03:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT :
return progress -> counter >= achievementCriteria -> complete_quest_count . totalQuestCount ;
2010-06-14 18:33:46 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY :
return progress -> counter >= achievementCriteria -> complete_daily_quest_daily . numberOfDays ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE :
return progress -> counter >= achievementCriteria -> complete_quests_in_zone . questCount ;
2009-05-06 16:38:58 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE :
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE :
return progress -> counter >= achievementCriteria -> healing_done . count ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST :
return progress -> counter >= achievementCriteria -> complete_daily_quest . questCount ;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING :
return progress -> counter >= achievementCriteria -> fall_without_dying . fallHeight ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST :
return progress -> counter >= 1 ;
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET :
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 :
return progress -> counter >= achievementCriteria -> be_spell_target . spellCount ;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL :
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 :
return progress -> counter >= achievementCriteria -> cast_spell . castCount ;
2010-08-07 18:31:06 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE :
return progress -> counter >= achievementCriteria -> bg_objective . completeCount ;
2010-12-17 18:12:46 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA :
return progress -> counter >= achievementCriteria -> honorable_kill_at_area . killCount ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL :
return progress -> counter >= 1 ;
2010-12-17 18:12:46 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL :
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL :
return progress -> counter >= achievementCriteria -> honorable_kill . killCount ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM :
return progress -> counter >= achievementCriteria -> own_item . itemCount ;
2009-06-01 21:51:34 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA :
return progress -> counter >= achievementCriteria -> win_rated_arena . count ;
2011-05-25 23:39:17 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING :
return progress -> counter >= achievementCriteria -> highest_personal_rating . PersonalRating ;
2009-05-06 16:38:58 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL :
return progress -> counter >= ( achievementCriteria -> learn_skill_level . skillLevel * 75 );
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM :
return progress -> counter >= achievementCriteria -> use_item . itemCount ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM :
return progress -> counter >= achievementCriteria -> loot_item . itemCount ;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA :
return progress -> counter >= 1 ;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT :
return progress -> counter >= achievementCriteria -> buy_bank_slot . numberOfSlots ;
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION :
return progress -> counter >= achievementCriteria -> gain_reputation . reputationAmount ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION :
return progress -> counter >= achievementCriteria -> gain_exalted_reputation . numberOfExaltedFactions ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP :
return progress -> counter >= achievementCriteria -> visit_barber . numberOfVisits ;
2010-01-24 16:26:33 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM :
2010-03-22 18:32:38 +01:00
return progress -> counter >= achievementCriteria -> equip_epic_item . count ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT :
return progress -> counter >= achievementCriteria -> roll_greed_on_loot . count ;
2009-05-06 16:38:58 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS :
return progress -> counter >= achievementCriteria -> hk_class . count ;
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE :
return progress -> counter >= achievementCriteria -> hk_race . count ;
2009-03-06 18:14:05 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE :
return progress -> counter >= achievementCriteria -> do_emote . count ;
2009-03-17 14:54:32 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM :
return progress -> counter >= achievementCriteria -> equip_item . count ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD :
return progress -> counter >= achievementCriteria -> quest_reward_money . goldInCopper ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY :
return progress -> counter >= achievementCriteria -> loot_money . goldInCopper ;
2009-04-03 16:37:06 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT :
return progress -> counter >= achievementCriteria -> use_gameobject . useCount ;
2010-08-13 13:48:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL :
return progress -> counter >= achievementCriteria -> special_pvp_kill . killCount ;
2009-04-18 20:49:56 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT :
return progress -> counter >= achievementCriteria -> fish_in_gameobject . lootCount ;
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS :
2009-04-20 20:33:43 -05:00
return progress -> counter >= achievementCriteria -> learn_skillline_spell . spellCount ;
2009-05-05 14:50:06 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL :
return progress -> counter >= achievementCriteria -> win_duel . duelCount ;
2009-05-06 16:38:58 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE :
return progress -> counter >= achievementCriteria -> loot_type . lootTypeCount ;
2009-04-20 20:33:43 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE :
return progress -> counter >= achievementCriteria -> learn_skill_line . spellCount ;
2010-08-06 14:56:41 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS :
return progress -> counter >= 9000 ;
2010-09-03 20:11:14 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS :
return progress -> counter >= achievementCriteria -> use_lfg . dungeonsComplete ;
2011-05-14 12:26:49 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS :
return progress -> counter >= achievementCriteria -> get_killing_blow . killCount ;
2011-11-27 00:29:44 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY :
return progress -> counter >= achievementCriteria -> currencyGain . count ;
2012-10-09 22:50:02 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA :
return achievementCriteria -> win_arena . count && progress -> counter >= achievementCriteria -> win_arena . count ;
2008-12-24 09:58:26 -06:00
// handle all statistic-only criteria here
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND :
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP :
2009-03-06 15:21:44 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_DEATH :
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON :
2008-12-24 09:58:26 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE :
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER :
2009-03-06 15:21:44 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM :
2010-12-17 18:12:46 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING :
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS :
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS :
2009-05-05 14:49:15 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS :
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL :
2009-05-05 14:50:06 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL :
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS :
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION :
2009-03-05 09:22:43 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD :
2009-05-05 14:48:48 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED :
2010-05-21 16:49:19 -03:00
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS :
2009-03-26 14:03:55 -06:00
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION :
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION :
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS :
2010-03-22 18:32:38 +01:00
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM :
2009-05-31 16:26:39 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED :
2009-05-05 14:49:15 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED :
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN :
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS :
2010-12-17 18:12:46 +01:00
default :
break ;
2008-12-24 09:58:26 -06:00
}
2012-09-18 11:33:09 +02:00
2008-12-24 09:58:26 -06:00
return false ;
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: CompletedCriteriaFor ( AchievementEntry const * achievement , Player * referencePlayer )
2008-12-24 09:58:26 -06:00
{
// counter can never complete
2010-04-07 19:14:10 +02:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_COUNTER )
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
// already completed and stored
2011-12-12 18:19:26 +01:00
if ( HasAchieved ( achievement -> ID ))
2009-04-03 16:36:20 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-04-05 17:05:15 -05:00
if ( IsCompletedAchievement ( achievement ))
2012-07-09 11:08:33 +02:00
CompletedAchievement ( achievement , referencePlayer );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
bool AchievementMgr < T >:: IsCompletedAchievement ( AchievementEntry const * entry )
2008-12-24 09:58:26 -06:00
{
2009-04-11 23:13:00 -05:00
// counter can never complete
2010-04-07 19:14:10 +02:00
if ( entry -> flags & ACHIEVEMENT_FLAG_COUNTER )
2009-04-11 23:13:00 -05:00
return false ;
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
// for achievement with referenced achievement criterias get from referenced and counter from self
2012-08-27 15:06:59 +02:00
uint32 achievementForTestId = entry -> refAchievement ? entry -> refAchievement : entry -> ID ;
uint32 achievementForTestCount = entry -> count ;
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntryList const * cList = sAchievementMgr -> GetAchievementCriteriaByAchievement ( achievementForTestId );
2010-04-07 19:14:10 +02:00
if ( ! cList )
2009-04-03 16:36:20 -06:00
return false ;
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:13:00 -05:00
// For SUMM achievements, we have to count the progress of each criteria of the achievement.
2012-08-27 15:06:59 +02:00
// Oddly, the target count is NOT contained in the achievement, but in each individual criteria
2009-04-11 23:13:00 -05:00
if ( entry -> flags & ACHIEVEMENT_FLAG_SUMM )
{
2009-10-17 16:20:24 -07:00
for ( AchievementCriteriaEntryList :: const_iterator itr = cList -> begin (); itr != cList -> end (); ++ itr )
2009-04-11 23:13:00 -05:00
{
AchievementCriteriaEntry const * criteria = * itr ;
2009-10-17 15:51:44 -07:00
2010-06-14 18:33:46 +02:00
CriteriaProgress const * progress = GetCriteriaProgress ( criteria );
if ( ! progress )
2009-04-11 23:13:00 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:13:00 -05:00
count += progress -> counter ;
2009-10-17 15:51:44 -07:00
2009-04-11 23:13:00 -05:00
// for counters, field4 contains the main count requirement
if ( count >= criteria -> raw . count )
return true ;
}
return false ;
}
2009-10-17 15:51:44 -07:00
2009-07-30 10:19:03 +08:00
// Default case - need complete all or
2009-04-11 23:13:00 -05:00
bool completed_all = true ;
2009-10-17 16:20:24 -07:00
for ( AchievementCriteriaEntryList :: const_iterator itr = cList -> begin (); itr != cList -> end (); ++ itr )
2008-12-24 09:58:26 -06:00
{
2009-04-03 16:36:20 -06:00
AchievementCriteriaEntry const * criteria = * itr ;
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
bool completed = IsCompletedCriteria ( criteria , entry );
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
// found an uncompleted criteria, but DONT return false yet - there might be a completed criteria with ACHIEVEMENT_CRITERIA_COMPLETE_FLAG_ALL
2010-04-07 19:14:10 +02:00
if ( completed )
2009-04-03 16:36:20 -06:00
++ count ;
else
completed_all = false ;
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
// completed as have req. count of completed criterias
2012-08-27 15:06:59 +02:00
if ( achievementForTestCount > 0 && achievementForTestCount <= count )
2009-04-03 16:36:20 -06:00
return true ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
// all criterias completed requirement
2012-08-27 15:06:59 +02:00
if ( completed_all && achievementForTestCount == 0 )
2009-04-03 16:36:20 -06:00
return true ;
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
return false ;
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template < class T >
CriteriaProgress * AchievementMgr < T >:: GetCriteriaProgress ( AchievementCriteriaEntry const * entry )
2010-06-14 18:33:46 +02:00
{
CriteriaProgressMap :: iterator iter = m_criteriaProgress . find ( entry -> ID );
if ( iter == m_criteriaProgress . end ())
return NULL ;
return & ( iter -> second );
}
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: SetCriteriaProgress ( AchievementCriteriaEntry const * entry , uint32 changeValue , Player * referencePlayer , ProgressType ptype )
2008-12-24 09:58:26 -06:00
{
2010-04-27 22:22:13 +02:00
// 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 ;
2012-09-18 11:33:09 +02:00
sLog -> outDebug ( LOG_FILTER_ACHIEVEMENTSYS , "SetCriteriaProgress(%u, %u) for (%s GUID: %u)" ,
entry -> ID , changeValue , GetLogNameForGuid ( GetOwner () -> GetGUID ()), GUID_LOPART ( GetOwner () -> GetGUID ()));
2009-10-17 15:51:44 -07:00
2010-06-14 18:33:46 +02:00
CriteriaProgress * progress = GetCriteriaProgress ( entry );
if ( ! progress )
2008-12-24 09:58:26 -06:00
{
2010-04-27 22:22:13 +02:00
// not create record for 0 counter but allow it for timed achievements
// we will need to send 0 progress to client to start the timer
if ( changeValue == 0 && ! entry -> timeLimit )
2009-01-20 19:59:43 -06:00
return ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
progress = & m_criteriaProgress [ entry -> ID ];
2009-03-05 09:22:43 -06:00
progress -> counter = changeValue ;
2008-12-24 09:58:26 -06:00
}
else
{
2009-04-27 18:42:35 -05:00
uint32 newValue = 0 ;
2010-12-17 18:12:46 +01:00
switch ( ptype )
2009-03-05 09:22:43 -06:00
{
case PROGRESS_SET :
newValue = changeValue ;
2009-04-03 16:39:21 -06:00
break ;
2009-03-05 09:22:43 -06:00
case PROGRESS_ACCUMULATE :
2009-03-06 18:14:05 -06:00
{
// avoid overflow
uint32 max_value = std :: numeric_limits < uint32 >:: max ();
newValue = max_value - progress -> counter > changeValue ? progress -> counter + changeValue : max_value ;
2009-04-03 16:39:21 -06:00
break ;
2009-03-06 18:14:05 -06:00
}
2009-03-05 09:22:43 -06:00
case PROGRESS_HIGHEST :
newValue = progress -> counter < changeValue ? changeValue : progress -> counter ;
2009-04-03 16:39:21 -06:00
break ;
2009-03-05 09:22:43 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-20 19:59:43 -06:00
// not update (not mark as changed) if counter will have same value
2010-04-27 22:22:13 +02:00
if ( progress -> counter == newValue && ! entry -> timeLimit )
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
progress -> counter = newValue ;
}
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
progress -> changed = true ;
2010-06-14 18:33:46 +02:00
progress -> date = time ( NULL ); // set the date to the latest update.
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( entry -> achievement );
2010-04-27 22:22:13 +02:00
uint32 timeElapsed = 0 ;
2012-07-09 11:08:33 +02:00
bool criteriaComplete = IsCompletedCriteria ( entry , achievement );
2010-04-27 22:22:13 +02:00
2010-04-07 19:14:10 +02:00
if ( entry -> timeLimit )
2008-12-24 09:58:26 -06:00
{
2010-04-27 22:22:13 +02:00
// Client expects this in packet
2010-07-12 00:30:17 +02:00
timeElapsed = entry -> timeLimit - ( timedIter -> second / IN_MILLISECONDS );
2010-04-27 22:22:13 +02:00
// Remove the timer, we wont need it anymore
2012-07-09 11:08:33 +02:00
if ( criteriaComplete )
2010-04-27 22:22:13 +02:00
m_timedAchievements . erase ( timedIter );
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
if ( criteriaComplete && achievement -> flags & ACHIEVEMENT_FLAG_SHOW_CRITERIA_MEMBERS && ! progress -> CompletedGUID )
progress -> CompletedGUID = referencePlayer -> GetGUID ();
2010-08-13 13:48:59 +02:00
2012-07-09 11:08:33 +02:00
SendCriteriaUpdate ( entry , progress , timeElapsed , criteriaComplete );
2010-08-13 13:48:59 +02:00
}
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: UpdateTimedAchievements ( uint32 timeDiff )
2010-04-27 22:22:13 +02:00
{
if ( ! m_timedAchievements . empty ())
{
for ( TimedAchievementMap :: iterator itr = m_timedAchievements . begin (); itr != m_timedAchievements . end ();)
{
// Time is up, remove timer and reset progress
if ( itr -> second <= timeDiff )
{
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntry const * entry = sAchievementMgr -> GetAchievementCriteria ( itr -> first );
2010-08-13 13:48:59 +02:00
RemoveCriteriaProgress ( entry );
2010-04-27 22:22:13 +02:00
m_timedAchievements . erase ( itr ++ );
}
else
{
itr -> second -= timeDiff ;
++ itr ;
}
}
}
}
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: StartTimedAchievement ( AchievementCriteriaTimedTypes /*type*/ , uint32 /*entry*/ , uint32 /*timeLost = 0*/ )
{
}
template <>
void AchievementMgr < Player >:: StartTimedAchievement ( AchievementCriteriaTimedTypes type , uint32 entry , uint32 timeLost /* = 0 */ )
2010-04-27 22:22:13 +02:00
{
2010-12-22 21:25:23 +01:00
AchievementCriteriaEntryList const & achievementCriteriaList = sAchievementMgr -> GetTimedAchievementCriteriaByType ( type );
2010-04-27 22:22:13 +02:00
for ( AchievementCriteriaEntryList :: const_iterator i = achievementCriteriaList . begin (); i != achievementCriteriaList . end (); ++ i )
{
2011-11-21 14:27:26 +01:00
if (( * i ) -> timedCriteriaMiscId != entry )
2010-04-27 22:22:13 +02:00
continue ;
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement (( * i ) -> achievement );
2010-04-27 22:22:13 +02:00
if ( m_timedAchievements . find (( * i ) -> ID ) == m_timedAchievements . end () && ! IsCompletedCriteria ( * i , achievement ))
{
// Start the timer
2010-08-12 13:38:31 +02:00
if (( * i ) -> timeLimit * IN_MILLISECONDS > timeLost )
{
m_timedAchievements [( * i ) -> ID ] = ( * i ) -> timeLimit * IN_MILLISECONDS - timeLost ;
2010-04-27 22:22:13 +02:00
2010-08-12 13:38:31 +02:00
// and at client too
2012-07-09 11:08:33 +02:00
SetCriteriaProgress ( * i , 0 , GetOwner (), PROGRESS_SET );
2010-08-12 13:38:31 +02:00
}
2010-04-27 22:22:13 +02:00
}
}
}
2012-07-09 11:08:33 +02:00
template < class T >
void AchievementMgr < T >:: RemoveTimedAchievement ( AchievementCriteriaTimedTypes type , uint32 entry )
2010-04-27 22:22:13 +02:00
{
2010-12-22 21:25:23 +01:00
AchievementCriteriaEntryList const & achievementCriteriaList = sAchievementMgr -> GetTimedAchievementCriteriaByType ( type );
2012-08-27 15:06:59 +02:00
for ( AchievementCriteriaEntryList :: const_iterator i = achievementCriteriaList . begin (); i != achievementCriteriaList . end (); ++ i )
2010-04-27 22:22:13 +02:00
{
2011-11-21 14:27:26 +01:00
if (( * i ) -> timedCriteriaMiscId != entry )
2010-04-27 22:22:13 +02:00
continue ;
TimedAchievementMap :: iterator timedIter = m_timedAchievements . find (( * i ) -> ID );
// We don't have timer for this achievement
if ( timedIter == m_timedAchievements . end ())
continue ;
2010-08-13 13:48:59 +02:00
// remove progress
RemoveCriteriaProgress ( * i );
2010-04-27 22:22:13 +02:00
// Remove the timer
m_timedAchievements . erase ( timedIter );
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2012-09-18 11:33:09 +02:00
template <>
void AchievementMgr < Player >:: CompletedAchievement ( AchievementEntry const * achievement , Player * referencePlayer )
2008-12-24 09:58:26 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outInfo ( LOG_FILTER_ACHIEVEMENTSYS , "AchievementMgr::CompletedAchievement(%u)" , achievement -> ID );
2009-10-17 15:51:44 -07:00
2011-07-02 02:14:49 +02:00
// disable for gamemasters with GM-mode enabled
2012-08-27 15:06:59 +02:00
if ( GetOwner () -> isGameMaster ())
2009-08-16 14:30:40 +02:00
return ;
2009-10-17 16:20:24 -07:00
2011-12-12 18:19:26 +01:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved ( achievement -> ID ))
2008-12-24 09:58:26 -06:00
return ;
2009-10-17 15:51:44 -07:00
2012-09-09 14:39:34 +02:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS )
if ( Guild * guild = sGuildMgr -> GetGuildById ( referencePlayer -> GetGuildId ()))
guild -> GetNewsLog (). AddNewEvent ( GUILD_NEWS_PLAYER_ACHIEVEMENT , time ( NULL ), referencePlayer -> GetGUID (), achievement -> flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER , achievement -> ID );
2012-07-09 11:08:33 +02:00
if ( ! GetOwner () -> GetSession () -> PlayerLoading ())
SendAchievementEarned ( achievement );
2012-05-30 08:01:02 +02:00
CompletedAchievementData & ca = m_completedAchievements [ achievement -> ID ];
2009-12-24 10:20:15 +01:00
ca . date = time ( NULL );
2008-12-24 09:58:26 -06:00
ca . changed = true ;
2009-10-17 15:51:44 -07:00
2008-12-24 09:58:26 -06:00
// don't insert for ACHIEVEMENT_FLAG_REALM_FIRST_KILL since otherwise only the first group member would reach that achievement
// TODO: where do set this instead?
2010-04-07 19:14:10 +02:00
if ( ! ( achievement -> flags & ACHIEVEMENT_FLAG_REALM_FIRST_KILL ))
2010-12-22 21:25:23 +01:00
sAchievementMgr -> SetRealmCompleted ( achievement );
2009-10-17 15:51:44 -07:00
2012-09-18 11:33:09 +02:00
_achievementPoints += achievement -> points ;
2012-07-24 15:29:49 +02:00
UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT , 0 , 0 , NULL , referencePlayer );
UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS , achievement -> points , 0 , NULL , referencePlayer );
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// reward items and titles if any
2010-12-22 21:25:23 +01:00
AchievementReward const * reward = sAchievementMgr -> GetAchievementReward ( achievement );
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// no rewards
2010-04-07 19:14:10 +02:00
if ( ! reward )
2009-01-06 13:55:14 -06:00
return ;
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// titles
2011-09-29 12:43:05 +02:00
//! Currently there's only one achievement that deals with gender-specific titles.
2011-09-28 16:26:15 +02:00
//! Since no common attributes were found, (not even in titleRewardFlags field)
2011-09-29 12:43:05 +02:00
//! we explicitly check by ID. Maybe in the future we could move the achievement_reward
2011-09-28 16:26:15 +02:00
//! condition fields to the condition system.
2012-07-09 11:08:33 +02:00
if ( uint32 titleId = reward -> titleId [ achievement -> ID == 1793 ? GetOwner () -> getGender () : ( GetOwner () -> GetTeam () == ALLIANCE ? 0 : 1 )])
2010-04-07 19:14:10 +02:00
if ( CharTitlesEntry const * titleEntry = sCharTitlesStore . LookupEntry ( titleId ))
2012-07-09 11:08:33 +02:00
GetOwner () -> SetTitle ( titleEntry );
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// mail
2010-04-07 19:14:10 +02:00
if ( reward -> sender )
2009-01-06 13:55:14 -06:00
{
2012-07-09 11:08:33 +02:00
Item * item = reward -> itemId ? Item :: CreateItem ( reward -> itemId , 1 , GetOwner ()) : NULL ;
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
int loc_idx = GetOwner () -> GetSession () -> GetSessionDbLocaleIndex ();
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// subject and text
std :: string subject = reward -> subject ;
std :: string text = reward -> text ;
2010-04-07 22:59:46 +02:00
if ( loc_idx >= 0 )
2009-01-06 13:55:14 -06:00
{
2010-12-22 21:25:23 +01:00
if ( AchievementRewardLocale const * loc = sAchievementMgr -> GetAchievementRewardLocale ( achievement ))
2008-12-24 09:58:26 -06:00
{
2011-08-04 15:14:15 +02:00
ObjectMgr :: GetLocaleString ( loc -> subject , loc_idx , subject );
ObjectMgr :: GetLocaleString ( loc -> text , loc_idx , text );
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2010-04-11 11:16:42 +04:00
MailDraft draft ( subject , text );
2009-12-17 13:07:38 +01:00
2010-08-21 03:19:25 +02:00
SQLTransaction trans = CharacterDatabase . BeginTransaction ();
2010-04-07 19:14:10 +02:00
if ( item )
2009-12-17 13:07:38 +01:00
{
// save new item before send
2010-08-21 03:19:25 +02:00
item -> SaveToDB ( trans ); // save for prevent lost at next mail load, if send fail then item will deleted
2009-12-17 13:07:38 +01:00
// item
draft . AddItem ( item );
}
2012-07-09 11:08:33 +02:00
draft . SendMailTo ( trans , GetOwner (), MailSender ( MAIL_CREATURE , reward -> sender ));
2010-08-21 03:19:25 +02:00
CharacterDatabase . CommitTransaction ( trans );
2008-12-24 09:58:26 -06:00
}
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: CompletedAchievement ( AchievementEntry const * achievement , Player * referencePlayer )
2008-12-24 09:58:26 -06:00
{
2012-08-27 15:06:59 +02:00
sLog -> outDebug ( LOG_FILTER_ACHIEVEMENTSYS , "AchievementMgr<Guild>::CompletedAchievement(%u)" , achievement -> ID );
2012-07-09 11:08:33 +02:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_COUNTER || HasAchieved ( achievement -> ID ))
return ;
2012-09-09 14:39:34 +02:00
if ( achievement -> flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_NEWS )
if ( Guild * guild = sGuildMgr -> GetGuildById ( referencePlayer -> GetGuildId ()))
guild -> GetNewsLog (). AddNewEvent ( GUILD_NEWS_GUILD_ACHIEVEMENT , time ( NULL ), 0 , achievement -> flags & ACHIEVEMENT_FLAG_SHOW_IN_GUILD_HEADER , achievement -> ID );
2012-07-09 11:08:33 +02:00
SendAchievementEarned ( achievement );
CompletedAchievementData & ca = m_completedAchievements [ achievement -> ID ];
ca . date = time ( NULL );
ca . changed = true ;
if ( achievement -> flags & ACHIEVEMENT_FLAG_SHOW_GUILD_MEMBERS )
{
if ( referencePlayer -> GetGuildId () == GetOwner () -> GetId ())
ca . guids . insert ( referencePlayer -> GetGUID ());
if ( Group const * group = referencePlayer -> GetGroup ())
for ( GroupReference const * ref = group -> GetFirstMember (); ref != NULL ; ref = ref -> next ())
if ( Player const * groupMember = ref -> getSource ())
if ( groupMember -> GetGuildId () == GetOwner () -> GetId ())
ca . guids . insert ( groupMember -> GetGUID ());
}
sAchievementMgr -> SetRealmCompleted ( achievement );
2012-09-18 11:33:09 +02:00
_achievementPoints += achievement -> points ;
2012-07-24 15:29:49 +02:00
UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT , 0 , 0 , NULL , referencePlayer );
UpdateAchievementCriteria ( ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS , achievement -> points , 0 , NULL , referencePlayer );
2012-07-09 11:08:33 +02:00
}
struct VisibleAchievementPred
{
bool operator ()( CompletedAchievementMap :: value_type const & val )
{
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( val . first );
2012-07-09 11:08:33 +02:00
return achievement && ! ( achievement -> flags & ACHIEVEMENT_FLAG_HIDDEN );
}
};
template < class T >
void AchievementMgr < T >:: SendAllAchievementData ( Player * /*receiver*/ ) const
{
VisibleAchievementPred isVisible ;
size_t numCriteria = m_criteriaProgress . size ();
size_t numAchievements = std :: count_if ( m_completedAchievements . begin (), m_completedAchievements . end (), isVisible );
ByteBuffer criteriaData ( numCriteria * ( 4 + 4 + 4 + 4 + 8 + 8 ));
2012-07-11 19:26:26 +02:00
ObjectGuid guid = GetOwner () -> GetGUID ();
ObjectGuid counter ;
2012-07-09 11:08:33 +02:00
WorldPacket data ( SMSG_ALL_ACHIEVEMENT_DATA , 4 + numAchievements * ( 4 + 4 ) + 4 + numCriteria * ( 4 + 4 + 4 + 4 + 8 + 8 ));
2012-07-12 21:09:17 +02:00
data . WriteBits ( numCriteria , 21 );
2012-07-09 11:08:33 +02:00
for ( CriteriaProgressMap :: const_iterator itr = m_criteriaProgress . begin (); itr != m_criteriaProgress . end (); ++ itr )
{
2012-07-12 21:09:17 +02:00
counter = uint64 ( itr -> second . counter );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 4 ]);
data . WriteBit ( counter [ 3 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( counter [ 0 ]);
data . WriteBit ( counter [ 6 ]);
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( counter [ 4 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( counter [ 7 ]);
data . WriteBit ( guid [ 7 ]);
2012-07-12 21:09:17 +02:00
data . WriteBits ( 0u , 2 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( counter [ 2 ]);
data . WriteBit ( counter [ 1 ]);
data . WriteBit ( counter [ 5 ]);
data . WriteBit ( guid [ 1 ]);
criteriaData . WriteByteSeq ( guid [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 5 ]);
criteriaData . WriteByteSeq ( counter [ 6 ]);
criteriaData . WriteByteSeq ( guid [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 6 ]);
criteriaData . WriteByteSeq ( counter [ 2 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( 0 ); // timer 2
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 2 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( itr -> first ); // criteria id
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 5 ]);
criteriaData . WriteByteSeq ( counter [ 0 ]);
criteriaData . WriteByteSeq ( counter [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 1 ]);
criteriaData . WriteByteSeq ( counter [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 0 ]);
criteriaData . WriteByteSeq ( guid [ 7 ]);
criteriaData . WriteByteSeq ( counter [ 7 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( 0 ); // timer 1
2012-09-13 17:24:37 +01:00
criteriaData . AppendPackedTime ( itr -> second . date ); // criteria date
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 1 ]);
2012-07-09 11:08:33 +02:00
}
data . WriteBits ( numAchievements , 23 );
2012-07-12 21:09:17 +02:00
data . FlushBits ();
2012-07-09 11:08:33 +02:00
data . append ( criteriaData );
for ( CompletedAchievementMap :: const_iterator itr = m_completedAchievements . begin (); itr != m_completedAchievements . end (); ++ itr )
{
if ( ! isVisible ( * itr ))
continue ;
data << uint32 ( itr -> first );
2012-09-13 18:29:32 +01:00
data . AppendPackedTime ( itr -> second . date );
2012-07-09 11:08:33 +02:00
}
SendPacket ( & data );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Guild >:: SendAllAchievementData ( Player * receiver ) const
2008-12-24 09:58:26 -06:00
{
2012-08-27 15:06:59 +02:00
WorldPacket data ( SMSG_GUILD_ACHIEVEMENT_DATA , m_completedAchievements . size () * ( 4 + 4 ) + 3 );
2012-07-09 11:08:33 +02:00
data . WriteBits ( m_completedAchievements . size (), 23 );
for ( CompletedAchievementMap :: const_iterator itr = m_completedAchievements . begin (); itr != m_completedAchievements . end (); ++ itr )
{
2012-09-13 18:29:32 +01:00
data . AppendPackedTime ( itr -> second . date );
2012-07-09 11:08:33 +02:00
data << uint32 ( itr -> first );
}
receiver -> GetSession () -> SendPacket ( & data );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
template <>
void AchievementMgr < Player >:: SendAchievementInfo ( Player * receiver , uint32 /*achievementId = 0 */ ) const
{
2012-07-11 19:26:26 +02:00
ObjectGuid guid = GetOwner () -> GetGUID ();
ObjectGuid counter ;
2012-07-09 11:08:33 +02:00
VisibleAchievementPred isVisible ;
size_t numCriteria = m_criteriaProgress . size ();
size_t numAchievements = std :: count_if ( m_completedAchievements . begin (), m_completedAchievements . end (), isVisible );
ByteBuffer criteriaData ( numCriteria * ( 0 ));
WorldPacket data ( SMSG_RESPOND_INSPECT_ACHIEVEMENTS , 1 + 8 + 3 + 3 + numAchievements * ( 4 + 4 ) + numCriteria * ( 0 ));
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 7 ]);
data . WriteBit ( guid [ 4 ]);
data . WriteBit ( guid [ 1 ]);
2012-07-09 11:08:33 +02:00
data . WriteBits ( numAchievements , 23 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( guid [ 3 ]);
2012-07-09 11:08:33 +02:00
data . WriteBits ( numCriteria , 21 );
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 2 ]);
2012-07-09 11:08:33 +02:00
for ( CriteriaProgressMap :: const_iterator itr = m_criteriaProgress . begin (); itr != m_criteriaProgress . end (); ++ itr )
{
2012-07-11 19:26:26 +02:00
counter = itr -> second . counter ;
data . WriteBit ( counter [ 5 ]);
data . WriteBit ( counter [ 3 ]);
data . WriteBit ( guid [ 1 ]);
data . WriteBit ( guid [ 4 ]);
data . WriteBit ( guid [ 2 ]);
data . WriteBit ( counter [ 6 ]);
data . WriteBit ( guid [ 0 ]);
data . WriteBit ( counter [ 4 ]);
data . WriteBit ( counter [ 1 ]);
data . WriteBit ( counter [ 2 ]);
data . WriteBit ( guid [ 3 ]);
data . WriteBit ( guid [ 7 ]);
2012-07-09 11:08:33 +02:00
data . WriteBits ( 0 , 2 ); // criteria progress flags
2012-07-11 19:26:26 +02:00
data . WriteBit ( counter [ 0 ]);
data . WriteBit ( guid [ 5 ]);
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( counter [ 7 ]);
2012-07-09 11:08:33 +02:00
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 4 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( 0 ); // timer 1
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 1 ]);
2012-09-14 11:30:21 +02:00
criteriaData . AppendPackedTime ( itr -> second . date );
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( counter [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 7 ]);
criteriaData . WriteByteSeq ( guid [ 5 ]);
criteriaData . WriteByteSeq ( counter [ 0 ]);
criteriaData . WriteByteSeq ( guid [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 2 ]);
criteriaData . WriteByteSeq ( guid [ 6 ]);
criteriaData . WriteByteSeq ( guid [ 7 ]);
criteriaData . WriteByteSeq ( counter [ 6 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( itr -> first );
criteriaData << uint32 ( 0 ); // timer 2
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( counter [ 1 ]);
criteriaData . WriteByteSeq ( counter [ 5 ]);
criteriaData . WriteByteSeq ( guid [ 0 ]);
criteriaData . WriteByteSeq ( counter [ 2 ]);
2012-07-09 11:08:33 +02:00
}
2012-07-11 19:26:26 +02:00
data . WriteBit ( guid [ 6 ]);
data . WriteBit ( guid [ 5 ]);
2012-07-12 21:09:17 +02:00
data . FlushBits ();
2012-07-09 11:08:33 +02:00
data . append ( criteriaData );
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 1 ]);
data . WriteByteSeq ( guid [ 6 ]);
data . WriteByteSeq ( guid [ 3 ]);
data . WriteByteSeq ( guid [ 0 ]);
data . WriteByteSeq ( guid [ 2 ]);
2012-07-09 11:08:33 +02:00
for ( CompletedAchievementMap :: const_iterator itr = m_completedAchievements . begin (); itr != m_completedAchievements . end (); ++ itr )
2008-12-24 09:58:26 -06:00
{
2012-07-09 11:08:33 +02:00
if ( ! isVisible ( * itr ))
2010-04-27 22:22:13 +02:00
continue ;
2012-07-09 11:08:33 +02:00
data << uint32 ( itr -> first );
2012-09-13 17:24:37 +01:00
data . AppendPackedTime ( itr -> second . date );
2008-12-24 09:58:26 -06:00
}
2009-10-17 15:51:44 -07:00
2012-07-11 19:26:26 +02:00
data . WriteByteSeq ( guid [ 7 ]);
data . WriteByteSeq ( guid [ 4 ]);
data . WriteByteSeq ( guid [ 5 ]);
2012-07-09 11:08:33 +02:00
receiver -> GetSession () -> SendPacket ( & data );
}
template <>
void AchievementMgr < Guild >:: SendAchievementInfo ( Player * receiver , uint32 achievementId /*= 0*/ ) const
{
//will send response to criteria progress request
AchievementCriteriaEntryList const * criteria = sAchievementMgr -> GetAchievementCriteriaByAchievement ( achievementId );
if ( ! criteria )
{
// send empty packet
WorldPacket data ( SMSG_GUILD_CRITERIA_DATA , 3 );
data . WriteBits ( 0 , 21 );
receiver -> GetSession () -> SendPacket ( & data );
return ;
}
2012-07-11 19:26:26 +02:00
ObjectGuid counter ;
ObjectGuid guid ;
2012-07-09 11:08:33 +02:00
uint32 numCriteria = 0 ;
ByteBuffer criteriaData ( criteria -> size () * ( 8 + 8 + 4 + 4 + 4 ));
ByteBuffer criteriaBits ( criteria -> size () * ( 8 + 8 ) / 8 );
for ( AchievementCriteriaEntryList :: const_iterator itr = criteria -> begin (); itr != criteria -> end (); ++ itr )
{
uint32 criteriaId = ( * itr ) -> ID ;
CriteriaProgressMap :: const_iterator progress = m_criteriaProgress . find ( criteriaId );
if ( progress == m_criteriaProgress . end ())
continue ;
++ numCriteria ;
2012-07-09 14:22:54 +02:00
}
criteriaBits . WriteBits ( numCriteria , 21 );
for ( AchievementCriteriaEntryList :: const_iterator itr = criteria -> begin (); itr != criteria -> end (); ++ itr )
{
uint32 criteriaId = ( * itr ) -> ID ;
CriteriaProgressMap :: const_iterator progress = m_criteriaProgress . find ( criteriaId );
if ( progress == m_criteriaProgress . end ())
continue ;
2012-07-11 19:26:26 +02:00
counter = progress -> second . counter ;
guid = progress -> second . CompletedGUID ;
criteriaBits . WriteBit ( counter [ 4 ]);
criteriaBits . WriteBit ( counter [ 1 ]);
criteriaBits . WriteBit ( guid [ 2 ]);
criteriaBits . WriteBit ( counter [ 3 ]);
criteriaBits . WriteBit ( guid [ 1 ]);
criteriaBits . WriteBit ( counter [ 5 ]);
criteriaBits . WriteBit ( counter [ 0 ]);
criteriaBits . WriteBit ( guid [ 3 ]);
criteriaBits . WriteBit ( counter [ 2 ]);
criteriaBits . WriteBit ( guid [ 7 ]);
criteriaBits . WriteBit ( guid [ 5 ]);
criteriaBits . WriteBit ( guid [ 0 ]);
criteriaBits . WriteBit ( counter [ 6 ]);
criteriaBits . WriteBit ( guid [ 6 ]);
criteriaBits . WriteBit ( counter [ 7 ]);
criteriaBits . WriteBit ( guid [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 5 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( progress -> second . date ); // unknown date
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( counter [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 7 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( progress -> second . date ); // unknown date
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( counter [ 6 ]);
criteriaData . WriteByteSeq ( guid [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 1 ]);
criteriaData . WriteByteSeq ( counter [ 4 ]);
criteriaData . WriteByteSeq ( guid [ 3 ]);
criteriaData . WriteByteSeq ( counter [ 0 ]);
criteriaData . WriteByteSeq ( guid [ 2 ]);
criteriaData . WriteByteSeq ( counter [ 1 ]);
criteriaData . WriteByteSeq ( guid [ 6 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( progress -> second . date ); // last update time (not packed!)
criteriaData << uint32 ( criteriaId );
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( counter [ 5 ]);
2012-07-09 11:08:33 +02:00
criteriaData << uint32 ( 0 );
2012-07-11 19:26:26 +02:00
criteriaData . WriteByteSeq ( guid [ 7 ]);
criteriaData . WriteByteSeq ( counter [ 2 ]);
criteriaData . WriteByteSeq ( guid [ 0 ]);
2012-07-09 11:08:33 +02:00
}
2012-07-09 14:22:54 +02:00
WorldPacket data ( SMSG_GUILD_CRITERIA_DATA , criteriaBits . size () + criteriaData . size ());
data . append ( criteriaBits );
2012-07-09 11:08:33 +02:00
if ( numCriteria )
data . append ( criteriaData );
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
receiver -> GetSession () -> SendPacket ( & data );
}
template < class T >
bool AchievementMgr < T >:: HasAchieved ( uint32 achievementId ) const
{
return m_completedAchievements . find ( achievementId ) != m_completedAchievements . end ();
}
template < class T >
bool AchievementMgr < T >:: CanUpdateCriteria ( AchievementCriteriaEntry const * criteria , AchievementEntry const * achievement , uint64 miscValue1 , uint64 miscValue2 , Unit const * unit , Player * referencePlayer )
{
if ( DisableMgr :: IsDisabledFor ( DISABLE_TYPE_ACHIEVEMENT_CRITERIA , criteria -> ID , NULL ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Disabled" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if ( achievement -> mapID != - 1 && referencePlayer -> GetMapId () != uint32 ( achievement -> mapID ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Wrong map" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if (( achievement -> requiredFaction == ACHIEVEMENT_FACTION_HORDE && referencePlayer -> GetTeam () != HORDE ) ||
( achievement -> requiredFaction == ACHIEVEMENT_FACTION_ALLIANCE && referencePlayer -> GetTeam () != ALLIANCE ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Wrong faction" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if ( IsCompletedCriteria ( criteria , achievement ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Is Completed" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if ( ! RequirementsSatisfied ( criteria , miscValue1 , miscValue2 , unit , referencePlayer ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Requirements not satisfied" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if ( ! AdditionalRequirementsSatisfied ( criteria , miscValue1 , miscValue2 , unit , referencePlayer ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Additional requirements not satisfied" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
if ( ! ConditionsSatisfied ( criteria , referencePlayer ))
{
sLog -> outTrace ( LOG_FILTER_ACHIEVEMENTSYS , "CanUpdateCriteria: %s (Id: %u Type %s) Conditions not satisfied" ,
criteria -> name , criteria -> ID , AchievementGlobalMgr :: GetCriteriaTypeString ( criteria -> type ));
return false ;
}
return true ;
}
template < class T >
bool AchievementMgr < T >:: ConditionsSatisfied ( AchievementCriteriaEntry const * criteria , Player * referencePlayer ) const
{
for ( uint32 i = 0 ; i < MAX_CRITERIA_REQUIREMENTS ; ++ i )
{
if ( ! criteria -> additionalRequirements [ i ]. additionalRequirement_type )
continue ;
switch ( criteria -> additionalRequirements [ i ]. additionalRequirement_type )
{
case ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP :
if ( referencePlayer -> GetMapId () != criteria -> additionalRequirements [ i ]. additionalRequirement_value )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_CONDITION_NOT_IN_GROUP :
if ( referencePlayer -> GetGroup ())
return false ;
break ;
default :
break ;
}
}
return true ;
}
template < class T >
bool AchievementMgr < T >:: RequirementsSatisfied ( AchievementCriteriaEntry const * achievementCriteria , uint64 miscValue1 , uint64 miscValue2 , Unit const * unit , Player * referencePlayer ) const
{
switch ( AchievementCriteriaTypes ( achievementCriteria -> type ))
{
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST :
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION :
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING :
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN :
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS :
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED :
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL :
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY :
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL :
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD :
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS :
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS :
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED :
2012-09-18 11:33:09 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL :
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED :
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL :
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_VISIT_BARBER_SHOP :
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL :
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA :
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS :
if ( ! miscValue1 )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY :
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT :
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE :
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS :
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION :
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION :
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING :
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING :
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS :
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL :
break ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT :
if ( m_completedAchievements . find ( achievementCriteria -> complete_achievement . linkedAchievement ) == m_completedAchievements . end ())
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG :
if ( ! miscValue1 || achievementCriteria -> win_bg . bgMapID != referencePlayer -> GetMapId ())
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE :
if ( ! miscValue1 || achievementCriteria -> kill_creature . creatureID != miscValue1 )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL :
// update at loading or specific skill update
if ( miscValue1 && miscValue1 != achievementCriteria -> reach_skill_level . skillID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL :
// update at loading or specific skill update
if ( miscValue1 && miscValue1 != achievementCriteria -> learn_skill_level . skillID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE :
if ( miscValue1 && miscValue1 != achievementCriteria -> complete_quests_in_zone . zoneID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND :
if ( ! miscValue1 || referencePlayer -> GetMapId () != achievementCriteria -> complete_battleground . mapID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP :
if ( ! miscValue1 || referencePlayer -> GetMapId () != achievementCriteria -> death_at_map . mapID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH :
{
if ( ! miscValue1 )
return false ;
// skip wrong arena achievements, if not achievIdByArenaSlot then normal total death counter
bool notfit = false ;
for ( int j = 0 ; j < MAX_ARENA_SLOT ; ++ j )
{
if ( achievIdByArenaSlot [ j ] == achievementCriteria -> achievement )
{
Battleground * bg = referencePlayer -> GetBattleground ();
if ( ! bg || ! bg -> isArena () || ArenaTeam :: GetSlotByType ( bg -> GetArenaType ()) != j )
notfit = true ;
break ;
}
}
if ( notfit )
return false ;
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON :
{
if ( ! miscValue1 )
return false ;
Map const * map = referencePlayer -> IsInWorld () ? referencePlayer -> GetMap () : sMapMgr -> FindMap ( referencePlayer -> GetMapId (), referencePlayer -> GetInstanceId ());
if ( ! map || ! map -> IsDungeon ())
return false ;
// search case
bool found = false ;
for ( int j = 0 ; achievIdForDungeon [ j ][ 0 ]; ++ j )
{
if ( achievIdForDungeon [ j ][ 0 ] == achievementCriteria -> achievement )
{
if ( map -> IsRaid ())
{
// if raid accepted (ignore difficulty)
if ( ! achievIdForDungeon [ j ][ 2 ])
break ; // for
}
else if ( referencePlayer -> GetDungeonDifficulty () == DUNGEON_DIFFICULTY_NORMAL )
{
// dungeon in normal mode accepted
if ( ! achievIdForDungeon [ j ][ 1 ])
break ; // for
}
else
{
// dungeon in heroic mode accepted
if ( ! achievIdForDungeon [ j ][ 3 ])
break ; // for
}
found = true ;
break ; // for
}
}
if ( ! found )
return false ;
//FIXME: work only for instances where max == min for players
if ((( InstanceMap * ) map ) -> GetMaxPlayers () != achievementCriteria -> death_in_dungeon . manLimit )
return false ;
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> killed_by_creature . creatureEntry )
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 ())
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM :
if ( ! miscValue1 || miscValue2 != achievementCriteria -> death_from . type )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST :
{
// if miscValues != 0, it contains the questID.
if ( miscValue1 )
{
if ( miscValue1 != achievementCriteria -> complete_quest . questID )
return false ;
}
else
{
// login case.
if ( ! referencePlayer -> GetQuestRewardStatus ( achievementCriteria -> complete_quest . questID ))
return false ;
}
if ( AchievementCriteriaDataSet const * data = sAchievementMgr -> GetCriteriaDataSet ( achievementCriteria ))
if ( ! data -> Meets ( referencePlayer , unit ))
return false ;
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET :
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> be_spell_target . spellID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL :
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> cast_spell . spellID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL :
if ( miscValue1 && miscValue1 != achievementCriteria -> learn_spell . spellID )
return false ;
if ( ! referencePlayer -> HasSpell ( achievementCriteria -> learn_spell . spellID ))
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 )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM :
if ( miscValue1 && achievementCriteria -> own_item . itemID != miscValue1 )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM :
if ( ! miscValue1 || achievementCriteria -> use_item . itemID != miscValue1 )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> own_item . itemID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA :
{
WorldMapOverlayEntry const * worldOverlayEntry = sWorldMapOverlayStore . LookupEntry ( achievementCriteria -> explore_area . areaReference );
if ( ! worldOverlayEntry )
break ;
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
bool matchFound = false ;
for ( int j = 0 ; j < MAX_WORLD_MAP_OVERLAY_AREA_IDX ; ++ j )
{
uint32 area_id = worldOverlayEntry -> areatableID [ j ];
if ( ! area_id ) // array have 0 only in empty tail
break ;
2010-03-15 04:37:28 +01:00
2012-08-27 15:06:59 +02:00
int32 exploreFlag = GetAreaFlagByAreaID ( area_id );
if ( exploreFlag < 0 )
continue ;
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
uint32 playerIndexOffset = uint32 ( exploreFlag ) / 32 ;
uint32 mask = 1 << ( uint32 ( exploreFlag ) % 32 );
2011-04-03 14:44:09 +02:00
2012-08-27 15:06:59 +02:00
if ( referencePlayer -> GetUInt32Value ( PLAYER_EXPLORED_ZONES_1 + playerIndexOffset ) & mask )
{
matchFound = true ;
break ;
}
}
2011-12-26 04:44:22 +02:00
2012-08-27 15:06:59 +02:00
if ( ! matchFound )
return false ;
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION :
if ( miscValue1 && miscValue1 != achievementCriteria -> gain_reputation . factionID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM :
// miscValue1 = itemid miscValue2 = itemSlot
if ( ! miscValue1 || miscValue2 != achievementCriteria -> equip_epic_item . itemSlot )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT :
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT :
{
// miscValue1 = itemid miscValue2 = diced value
if ( ! miscValue1 || miscValue2 != achievementCriteria -> roll_greed_on_loot . rollValue )
return false ;
2011-03-04 12:11:20 +01:00
2012-08-27 15:06:59 +02:00
ItemTemplate const * proto = sObjectMgr -> GetItemTemplate ( uint32 ( miscValue1 ));
if ( ! proto )
return false ;
break ;
}
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> do_emote . emoteID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE :
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE :
if ( ! miscValue1 )
return false ;
2011-03-04 12:11:20 +01:00
2012-08-27 15:06:59 +02:00
if ( achievementCriteria -> additionalRequirements [ 0 ]. additionalRequirement_type == ACHIEVEMENT_CRITERIA_CONDITION_BG_MAP )
{
if ( referencePlayer -> GetMapId () != achievementCriteria -> additionalRequirements [ 0 ]. additionalRequirement_value )
2011-03-04 12:11:20 +01:00
return false ;
2012-08-27 15:06:59 +02:00
// map specific case (BG in fact) expected player targeted damage/heal
if ( ! unit || unit -> GetTypeId () != TYPEID_PLAYER )
2011-03-04 12:11:20 +01:00
return false ;
2012-08-27 15:06:59 +02:00
}
break ;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM :
// miscValue1 = item_id
if ( ! miscValue1 || miscValue1 != achievementCriteria -> equip_item . itemID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> use_gameobject . goEntry )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> fish_in_gameobject . goEntry )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS :
if ( miscValue1 && miscValue1 != achievementCriteria -> learn_skillline_spell . skillLine )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM :
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM :
{
if ( ! miscValue1 )
return false ;
ItemTemplate const * proto = sObjectMgr -> GetItemTemplate ( miscValue1 );
if ( ! proto || proto -> Quality < ITEM_QUALITY_EPIC )
return false ;
break ;
2011-03-04 12:11:20 +01:00
}
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE :
if ( miscValue1 && miscValue1 != achievementCriteria -> learn_skill_line . skillLine )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> hk_class . classID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> hk_race . raceID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> bg_objective . objectiveId )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA :
if ( ! miscValue1 || miscValue1 != achievementCriteria -> honorable_kill_at_area . areaID )
return false ;
break ;
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY :
if ( ! miscValue1 || ! miscValue2 || int64 ( miscValue2 ) < 0
|| miscValue1 != achievementCriteria -> currencyGain . currency )
return false ;
break ;
2012-10-10 15:45:05 -05:00
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA :
if ( miscValue1 != achievementCriteria -> win_arena . mapID )
return false ;
break ;
2012-08-27 15:06:59 +02:00
default :
break ;
2011-03-04 12:11:20 +01:00
}
2012-08-27 15:06:59 +02:00
return true ;
}
2012-03-23 22:45:44 +01:00
2012-08-27 15:06:59 +02:00
template < class T >
bool AchievementMgr < T >:: AdditionalRequirementsSatisfied ( AchievementCriteriaEntry const * criteria , uint64 miscValue1 , uint64 /*miscValue2*/ , Unit const * unit , Player * referencePlayer ) const
{
for ( uint8 i = 0 ; i < MAX_ADDITIONAL_CRITERIA_CONDITIONS ; ++ i )
2011-12-26 04:44:22 +02:00
{
2012-08-27 15:06:59 +02:00
uint32 const reqType = criteria -> additionalConditionType [ i ];
uint32 const reqValue = criteria -> additionalConditionValue [ i ];
2011-03-04 12:11:20 +01:00
2012-08-27 15:06:59 +02:00
switch ( AchievementCriteriaAdditionalCondition ( reqType ))
2011-12-26 04:44:22 +02:00
{
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_ENTRY : // 4
if ( ! unit || unit -> GetEntry () != reqValue )
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_PLAYER : // 5
if ( ! unit || unit -> GetTypeId () != TYPEID_PLAYER )
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_DEAD : // 6
if ( ! unit || unit -> isAlive ())
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_ENEMY : // 7
if ( ! unit )
2011-12-26 04:44:22 +02:00
return false ;
2012-08-27 15:06:59 +02:00
if ( const Player * player = unit -> ToPlayer ())
if ( player -> GetTeam () == referencePlayer -> GetTeam ())
return false ;
2011-12-26 04:44:22 +02:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_HAS_AURA : // 8
if ( ! referencePlayer -> HasAura ( reqValue ))
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HAS_AURA : // 10
if ( ! unit || ! unit -> HasAura ( reqValue ))
2011-12-26 04:44:22 +02:00
return false ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_MUST_BE_MOUNTED : // 11
if ( ! unit || ! unit -> IsMounted ())
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_MIN : // 14
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_ITEM_QUALITY_EQUALS : // 15
{
// miscValue1 is itemid
ItemTemplate const * const item = sObjectMgr -> GetItemTemplate ( uint32 ( miscValue1 ));
if ( ! item || item -> Quality < reqValue )
2011-12-26 04:44:22 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
}
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAP_DIFFICULTY : // 20
if ( uint32 ( referencePlayer -> GetMap () -> GetDifficulty ()) != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_MAP : // 32
if ( referencePlayer -> GetMapId () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_ZONE : // 18
if ( referencePlayer -> GetZoneId () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_AREA : // 17
if ( referencePlayer -> GetAreaId () != reqValue )
return false ;
2012-01-27 02:09:40 +02:00
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_RACE : // 25
if ( referencePlayer -> getRace () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_CLASS : // 26
if ( referencePlayer -> getClass () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_RACE : // 27
if ( ! unit || unit -> GetTypeId () != TYPEID_PLAYER || unit -> getRace () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CLASS : // 28
if ( ! unit || unit -> GetTypeId () != TYPEID_PLAYER || unit -> getClass () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_MAX_GROUP_MEMBERS : // 29
if ( referencePlayer -> GetGroup () && referencePlayer -> GetGroup () -> GetMembersCount () >= reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_CREATURE_TYPE : // 30
{
if ( ! unit )
2012-01-27 02:09:40 +02:00
return false ;
2012-08-27 15:06:59 +02:00
Creature const * const creature = unit -> ToCreature ();
if ( ! creature || creature -> GetCreatureType () != reqValue )
2012-01-27 02:09:40 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
}
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TITLE_BIT_INDEX : // 38
// miscValue1 is title's bit index
if ( miscValue1 != reqValue )
2012-02-03 01:45:47 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_SOURCE_LEVEL : // 39
if ( referencePlayer -> getLevel () != reqValue )
2012-02-03 01:45:47 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_LEVEL : // 40
if ( ! unit || unit -> getLevel () != reqValue )
2012-02-03 01:45:47 +02:00
return false ;
break ;
2012-08-27 15:06:59 +02:00
case ACHIEVEMENT_CRITERIA_ADDITIONAL_CONDITION_TARGET_HEALTH_PERCENT_BELOW : // 46
if ( ! unit || unit -> GetHealthPct () >= reqValue )
2012-02-03 01:45:47 +02:00
return false ;
break ;
2011-12-26 04:44:22 +02:00
default :
break ;
}
}
2011-03-04 12:11:20 +01:00
return true ;
2010-04-27 22:22:13 +02:00
}
2012-08-27 15:06:59 +02:00
char const * AchievementGlobalMgr :: GetCriteriaTypeString ( uint32 type )
{
return GetCriteriaTypeString ( AchievementCriteriaTypes ( type ));
}
char const * AchievementGlobalMgr :: GetCriteriaTypeString ( AchievementCriteriaTypes type )
{
switch ( type )
{
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE :
return "KILL_CREATURE" ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG :
return "TYPE_WIN_BG" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ARCHAEOLOGY_PROJECTS :
return "COMPLETE_RESEARCH" ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_LEVEL :
return "REACH_LEVEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_SKILL_LEVEL :
return "REACH_SKILL_LEVEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_ACHIEVEMENT :
return "COMPLETE_ACHIEVEMENT" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST_COUNT :
return "COMPLETE_QUEST_COUNT" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY :
return "COMPLETE_DAILY_QUEST_DAILY" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_IN_ZONE :
return "COMPLETE_QUESTS_IN_ZONE" ;
case ACHIEVEMENT_CRITERIA_TYPE_CURRENCY :
return "CURRENCY" ;
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE :
return "DAMAGE_DONE" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST :
return "COMPLETE_DAILY_QUEST" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND :
return "COMPLETE_BATTLEGROUND" ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP :
return "DEATH_AT_MAP" ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH :
return "DEATH" ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON :
return "DEATH_IN_DUNGEON" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID :
return "COMPLETE_RAID" ;
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE :
return "KILLED_BY_CREATURE" ;
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER :
return "KILLED_BY_PLAYER" ;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING :
return "FALL_WITHOUT_DYING" ;
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM :
return "DEATHS_FROM" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST :
return "COMPLETE_QUEST" ;
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET :
return "BE_SPELL_TARGET" ;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL :
return "CAST_SPELL" ;
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE :
return "BG_OBJECTIVE_CAPTURE" ;
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA :
return "HONORABLE_KILL_AT_AREA" ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA :
return "WIN_ARENA" ;
case ACHIEVEMENT_CRITERIA_TYPE_PLAY_ARENA :
return "PLAY_ARENA" ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SPELL :
return "LEARN_SPELL" ;
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL :
return "HONORABLE_KILL" ;
case ACHIEVEMENT_CRITERIA_TYPE_OWN_ITEM :
return "OWN_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_ARENA :
return "WIN_RATED_ARENA" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_TEAM_RATING :
return "HIGHEST_TEAM_RATING" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_PERSONAL_RATING :
return "HIGHEST_PERSONAL_RATING" ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LEVEL :
return "LEARN_SKILL_LEVEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_USE_ITEM :
return "USE_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_ITEM :
return "LOOT_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_EXPLORE_AREA :
return "EXPLORE_AREA" ;
case ACHIEVEMENT_CRITERIA_TYPE_OWN_RANK :
return "OWN_RANK" ;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_BANK_SLOT :
return "BUY_BANK_SLOT" ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REPUTATION :
return "GAIN_REPUTATION" ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_EXALTED_REPUTATION :
return "GAIN_EXALTED_REPUTATION" ;
case ACHIEVEMENT_CRITERIA_TYPE_VISIT_BARBER_SHOP :
return "VISIT_BARBER_SHOP" ;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM :
return "EQUIP_EPIC_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED_ON_LOOT :
return "ROLL_NEED_ON_LOOT" ;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT :
return "GREED_ON_LOOT" ;
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS :
return "HK_CLASS" ;
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE :
return "HK_RACE" ;
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE :
return "DO_EMOTE" ;
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE :
return "HEALING_DONE" ;
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS :
return "GET_KILLING_BLOWS" ;
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM :
return "EQUIP_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_VENDORS :
return "MONEY_FROM_VENDORS" ;
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TALENTS :
return "GOLD_SPENT_FOR_TALENTS" ;
case ACHIEVEMENT_CRITERIA_TYPE_NUMBER_OF_TALENT_RESETS :
return "NUMBER_OF_TALENT_RESETS" ;
case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD :
return "MONEY_FROM_QUEST_REWARD" ;
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_TRAVELLING :
return "GOLD_SPENT_FOR_TRAVELLING" ;
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER :
return "GOLD_SPENT_AT_BARBER" ;
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL :
return "GOLD_SPENT_FOR_MAIL" ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY :
return "LOOT_MONEY" ;
case ACHIEVEMENT_CRITERIA_TYPE_USE_GAMEOBJECT :
return "USE_GAMEOBJECT" ;
case ACHIEVEMENT_CRITERIA_TYPE_BE_SPELL_TARGET2 :
return "BE_SPELL_TARGET2" ;
case ACHIEVEMENT_CRITERIA_TYPE_SPECIAL_PVP_KILL :
return "SPECIAL_PVP_KILL" ;
case ACHIEVEMENT_CRITERIA_TYPE_FISH_IN_GAMEOBJECT :
return "FISH_IN_GAMEOBJECT" ;
case ACHIEVEMENT_CRITERIA_TYPE_EARNED_PVP_TITLE :
return "EARNED_PVP_TITLE" ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS :
return "LEARN_SKILLLINE_SPELLS" ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_DUEL :
return "WIN_DUEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_LOSE_DUEL :
return "LOSE_DUEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE :
return "KILL_CREATURE_TYPE" ;
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_EARNED_BY_AUCTIONS :
return "GOLD_EARNED_BY_AUCTIONS" ;
case ACHIEVEMENT_CRITERIA_TYPE_CREATE_AUCTION :
return "CREATE_AUCTION" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_BID :
return "HIGHEST_AUCTION_BID" ;
case ACHIEVEMENT_CRITERIA_TYPE_WON_AUCTIONS :
return "WON_AUCTIONS" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_AUCTION_SOLD :
return "HIGHEST_AUCTION_SOLD" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_GOLD_VALUE_OWNED :
return "HIGHEST_GOLD_VALUE_OWNED" ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_REVERED_REPUTATION :
return "GAIN_REVERED_REPUTATION" ;
case ACHIEVEMENT_CRITERIA_TYPE_GAIN_HONORED_REPUTATION :
return "GAIN_HONORED_REPUTATION" ;
case ACHIEVEMENT_CRITERIA_TYPE_KNOWN_FACTIONS :
return "KNOWN_FACTIONS" ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_EPIC_ITEM :
return "LOOT_EPIC_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_RECEIVE_EPIC_ITEM :
return "RECEIVE_EPIC_ITEM" ;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_NEED :
return "ROLL_NEED" ;
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED :
return "ROLL_GREED" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_DEALT :
return "HIT_DEALT" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HIT_RECEIVED :
return "HIT_RECEIVED" ;
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_DAMAGE_RECEIVED :
return "TOTAL_DAMAGE_RECEIVED" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEAL_CASTED :
return "HIGHEST_HEAL_CASTED" ;
case ACHIEVEMENT_CRITERIA_TYPE_TOTAL_HEALING_RECEIVED :
return "TOTAL_HEALING_RECEIVED" ;
case ACHIEVEMENT_CRITERIA_TYPE_HIGHEST_HEALING_RECEIVED :
return "HIGHEST_HEALING_RECEIVED" ;
case ACHIEVEMENT_CRITERIA_TYPE_QUEST_ABANDONED :
return "QUEST_ABANDONED" ;
case ACHIEVEMENT_CRITERIA_TYPE_FLIGHT_PATHS_TAKEN :
return "FLIGHT_PATHS_TAKEN" ;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_TYPE :
return "LOOT_TYPE" ;
case ACHIEVEMENT_CRITERIA_TYPE_CAST_SPELL2 :
return "CAST_SPELL2" ;
case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILL_LINE :
return "LEARN_SKILL_LINE" ;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_HONORABLE_KILL :
return "EARN_HONORABLE_KILL" ;
case ACHIEVEMENT_CRITERIA_TYPE_ACCEPTED_SUMMONINGS :
return "ACCEPTED_SUMMONINGS" ;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_ACHIEVEMENT_POINTS :
return "EARN_ACHIEVEMENT_POINTS" ;
case ACHIEVEMENT_CRITERIA_TYPE_USE_LFD_TO_GROUP_WITH_PLAYERS :
return "USE_LFD_TO_GROUP_WITH_PLAYERS" ;
case ACHIEVEMENT_CRITERIA_TYPE_SPENT_GOLD_GUILD_REPAIRS :
return "SPENT_GOLD_GUILD_REPAIRS" ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_GUILD_LEVEL :
return "REACH_GUILD_LEVEL" ;
case ACHIEVEMENT_CRITERIA_TYPE_CRAFT_ITEMS_GUILD :
return "CRAFT_ITEMS_GUILD" ;
case ACHIEVEMENT_CRITERIA_TYPE_CATCH_FROM_POOL :
return "CATCH_FROM_POOL" ;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_BANK_SLOTS :
return "BUY_GUILD_BANK_SLOTS" ;
case ACHIEVEMENT_CRITERIA_TYPE_EARN_GUILD_ACHIEVEMENT_POINTS :
return "EARN_GUILD_ACHIEVEMENT_POINTS" ;
case ACHIEVEMENT_CRITERIA_TYPE_WIN_RATED_BATTLEGROUND :
return "WIN_RATED_BATTLEGROUND" ;
case ACHIEVEMENT_CRITERIA_TYPE_REACH_BG_RATING :
return "REACH_BG_RATING" ;
case ACHIEVEMENT_CRITERIA_TYPE_BUY_GUILD_TABARD :
return "BUY_GUILD_TABARD" ;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUESTS_GUILD :
return "COMPLETE_QUESTS_GUILD" ;
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILLS_GUILD :
return "HONORABLE_KILLS_GUILD" ;
case ACHIEVEMENT_CRITERIA_TYPE_KILL_CREATURE_TYPE_GUILD :
return "KILL_CREATURE_TYPE_GUILD" ;
default :
return "MISSING_TYPE" ;
}
return "" ;
}
2012-07-09 11:08:33 +02:00
template class AchievementMgr < Guild > ;
template class AchievementMgr < Player > ;
2011-03-04 12:11:20 +01:00
//==========================================================
2009-01-06 13:55:14 -06:00
void AchievementGlobalMgr :: LoadAchievementCriteriaList ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2010-04-07 23:25:02 +02:00
if ( sAchievementCriteriaStore . GetNumRows () == 0 )
2009-01-22 22:44:27 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outError ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 achievement criteria." );
2009-01-22 22:44:27 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2012-07-09 11:08:33 +02:00
uint32 criterias = 0 ;
uint32 guildCriterias = 0 ;
2009-04-03 16:36:20 -06:00
for ( uint32 entryId = 0 ; entryId < sAchievementCriteriaStore . GetNumRows (); ++ entryId )
2009-01-06 13:55:14 -06:00
{
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntry const * criteria = sAchievementMgr -> GetAchievementCriteria ( entryId );
2010-04-07 19:14:10 +02:00
if ( ! criteria )
2009-01-06 13:55:14 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( criteria -> achievement );
2012-07-09 11:08:33 +02:00
2012-08-27 15:06:59 +02:00
m_AchievementCriteriaListByAchievement [ criteria -> achievement ]. push_back ( criteria );
2010-04-27 22:22:13 +02:00
2012-07-09 11:08:33 +02:00
if ( achievement && achievement -> flags & ACHIEVEMENT_FLAG_GUILD )
2012-08-27 15:06:59 +02:00
++ guildCriterias , m_GuildAchievementCriteriasByType [ criteria -> type ]. push_back ( criteria );
2012-07-09 11:08:33 +02:00
else
2012-08-27 15:06:59 +02:00
++ criterias , m_AchievementCriteriasByType [ criteria -> type ]. push_back ( criteria );
2012-07-09 11:08:33 +02:00
2010-04-29 23:12:16 +02:00
if ( criteria -> timeLimit )
2011-11-21 14:27:26 +01:00
m_AchievementCriteriasByTimedType [ criteria -> timedCriteriaStartType ]. push_back ( criteria );
2009-01-06 13:55:14 -06:00
}
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u achievement criteria and %u guild achievement crieteria in %u ms" , criterias , guildCriterias , GetMSTimeDiffToNow ( oldMSTime ));
2009-01-06 13:55:14 -06:00
}
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
void AchievementGlobalMgr :: LoadAchievementReferenceList ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2010-04-07 23:25:02 +02:00
if ( sAchievementStore . GetNumRows () == 0 )
2009-04-03 16:36:20 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 achievement references." );
2009-04-03 16:36:20 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-12-19 17:06:33 +01:00
uint32 count = 0 ;
2009-04-03 16:36:20 -06:00
for ( uint32 entryId = 0 ; entryId < sAchievementStore . GetNumRows (); ++ entryId )
{
2012-08-27 15:06:59 +02:00
AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( entryId );
2010-04-07 19:14:10 +02:00
if ( ! achievement || ! achievement -> refAchievement )
2009-04-03 16:36:20 -06:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-03 16:36:20 -06:00
m_AchievementListByReferencedId [ achievement -> refAchievement ]. push_back ( achievement );
++ count ;
}
2009-10-17 15:51:44 -07:00
2012-06-18 19:05:25 +02:00
// Once Bitten, Twice Shy (10 player) - Icecrown Citadel
2012-08-27 15:06:59 +02:00
if ( AchievementEntry const * achievement = sAchievementMgr -> GetAchievement ( 4539 ))
2012-06-18 19:05:25 +02:00
const_cast < AchievementEntry *> ( achievement ) -> mapID = 631 ; // Correct map requirement (currently has Ulduar)
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u achievement references in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2009-04-08 16:24:34 -05:00
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:24:34 -05:00
void AchievementGlobalMgr :: LoadAchievementCriteriaData ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2009-04-08 16:27:00 -05:00
m_criteriaDataMap . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2010-09-11 21:10:54 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT criteria_id, type, value1, value2, ScriptName FROM achievement_criteria_data" );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! result )
2009-04-08 16:24:34 -05:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 additional achievement criteria data. DB table `achievement_criteria_data` is empty." );
2009-04-08 16:24:34 -05:00
return ;
}
2009-10-17 15:51:44 -07:00
2010-12-19 17:06:33 +01:00
uint32 count = 0 ;
2009-04-08 16:24:34 -05:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-04-08 16:24:34 -05:00
uint32 criteria_id = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
AchievementCriteriaEntry const * criteria = sAchievementMgr -> GetAchievementCriteria ( criteria_id );
2009-10-17 15:51:44 -07:00
2009-04-08 16:24:34 -05:00
if ( ! criteria )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` has data for non-existing criteria (Entry: %u), ignore." , criteria_id );
2009-04-08 16:24:34 -05:00
continue ;
}
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint32 dataType = fields [ 1 ]. GetUInt8 ();
2010-09-24 22:16:21 +02:00
const char * scriptName = fields [ 4 ]. GetCString ();
2010-08-07 16:48:34 +02:00
uint32 scriptId = 0 ;
2010-08-09 10:56:59 +02:00
if ( strcmp ( scriptName , "" )) // not empty
2010-08-07 16:48:34 +02:00
{
if ( dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_SCRIPT )
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_criteria_data` has ScriptName set for non-scripted data type (Entry: %u, type %u), useless data." , criteria_id , dataType );
2010-08-07 16:48:34 +02:00
else
2010-12-22 21:25:23 +01:00
scriptId = sObjectMgr -> GetScriptId ( scriptName );
2010-08-07 16:48:34 +02:00
}
AchievementCriteriaData data ( dataType , fields [ 2 ]. GetUInt32 (), fields [ 3 ]. GetUInt32 (), scriptId );
2009-10-17 15:51:44 -07:00
2009-06-07 20:54:23 -05:00
if ( ! data . IsValid ( criteria ))
2009-04-08 16:24:34 -05:00
continue ;
2009-10-17 15:51:44 -07:00
2009-04-08 16:34:38 -05:00
// this will allocate empty data set storage
AchievementCriteriaDataSet & dataSet = m_criteriaDataMap [ criteria_id ];
2010-01-16 19:41:04 +03:00
dataSet . SetCriteriaId ( criteria_id );
2009-10-17 15:51:44 -07:00
2009-04-08 16:34:38 -05:00
// add real data only for not NONE data types
2009-06-07 20:54:23 -05:00
if ( data . dataType != ACHIEVEMENT_CRITERIA_DATA_TYPE_NONE )
2009-04-08 16:34:38 -05:00
dataSet . Add ( data );
2009-10-17 15:51:44 -07:00
2009-04-08 16:34:38 -05:00
// counting data by and data types
2009-04-08 16:24:34 -05:00
++ count ;
2010-12-19 17:06:33 +01:00
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u additional achievement criteria data in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2009-04-03 16:36:20 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
void AchievementGlobalMgr :: LoadCompletedAchievements ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2010-09-11 21:10:54 +02:00
QueryResult result = CharacterDatabase . Query ( "SELECT achievement FROM character_achievement GROUP BY achievement" );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! result )
2009-01-22 22:44:27 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 completed achievements. DB table `character_achievement` is empty." );
2009-01-06 13:55:14 -06:00
return ;
2009-01-22 22:44:27 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2012-05-30 08:01:02 +02:00
uint16 achievementId = fields [ 0 ]. GetUInt16 ();
2012-08-27 15:06:59 +02:00
const AchievementEntry * achievement = sAchievementMgr -> GetAchievement ( achievementId );
2011-12-13 00:17:01 +02:00
if ( ! achievement )
2009-05-08 19:22:17 -05:00
{
2011-12-27 00:29:17 +01:00
// Remove non existent achievements from all characters
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_ACHIEVEMENTSYS , "Non-existing achievement %u data removed from table `character_achievement`." , achievementId );
2011-12-27 00:29:17 +01:00
PreparedStatement * stmt = CharacterDatabase . GetPreparedStatement ( CHAR_DEL_INVALID_ACHIEVMENT );
stmt -> setUInt16 ( 0 , uint16 ( achievementId ));
CharacterDatabase . Execute ( stmt );
2009-05-08 19:22:17 -05:00
continue ;
}
2011-12-13 00:17:01 +02:00
else if ( achievement -> flags & ( ACHIEVEMENT_FLAG_REALM_FIRST_REACH | ACHIEVEMENT_FLAG_REALM_FIRST_KILL ))
2011-12-27 00:29:17 +01:00
m_allCompletedAchievements . insert ( achievementId );
2012-08-27 15:06:59 +02:00
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %lu completed achievements in %u ms" , ( unsigned long ) m_allCompletedAchievements . size (), GetMSTimeDiffToNow ( oldMSTime ));
2009-01-06 13:55:14 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
void AchievementGlobalMgr :: LoadRewards ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2009-04-08 16:27:00 -05:00
m_achievementRewards . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2012-08-27 15:06:59 +02:00
// 0 1 2 3 4 5 6
2010-09-11 21:10:54 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT entry, title_A, title_H, item, sender, subject, text FROM achievement_reward" );
2009-10-17 15:51:44 -07:00
2010-04-07 19:14:10 +02:00
if ( ! result )
2009-01-06 13:55:14 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outError ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 achievement rewards. DB table `achievement_reward` is empty." );
2009-01-06 13:55:14 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-04-08 16:27:00 -05:00
uint32 count = 0 ;
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-01-06 13:55:14 -06:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2012-08-27 15:06:59 +02:00
const AchievementEntry * pAchievement = GetAchievement ( entry );
2010-03-11 23:25:04 +01:00
if ( ! pAchievement )
2009-01-06 13:55:14 -06:00
{
2012-08-27 15:06:59 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` has wrong achievement (Entry: %u), ignored." , entry );
2009-01-06 13:55:14 -06:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
AchievementReward reward ;
reward . titleId [ 0 ] = fields [ 1 ]. GetUInt32 ();
reward . titleId [ 1 ] = fields [ 2 ]. GetUInt32 ();
reward . itemId = fields [ 3 ]. GetUInt32 ();
reward . sender = fields [ 4 ]. GetUInt32 ();
2010-09-24 22:16:21 +02:00
reward . subject = fields [ 5 ]. GetString ();
reward . text = fields [ 6 ]. GetString ();
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
// must be title or mail at least
if ( ! reward . titleId [ 0 ] && ! reward . titleId [ 1 ] && ! reward . sender )
{
2012-08-27 15:06:59 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) does not have title or item reward data, ignored." , entry );
2009-01-06 13:55:14 -06:00
continue ;
}
2009-10-17 15:51:44 -07:00
2011-03-04 12:11:20 +01:00
if ( pAchievement -> requiredFaction == ACHIEVEMENT_FACTION_ANY && (( reward . titleId [ 0 ] == 0 ) != ( reward . titleId [ 1 ] == 0 )))
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) has title (A: %u H: %u) for only one team." , entry , reward . titleId [ 0 ], reward . titleId [ 1 ]);
2010-03-11 23:25:04 +01:00
2009-01-06 13:55:14 -06:00
if ( reward . titleId [ 0 ])
{
CharTitlesEntry const * titleEntry = sCharTitlesStore . LookupEntry ( reward . titleId [ 0 ]);
if ( ! titleEntry )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_A`, set to 0" , entry , reward . titleId [ 0 ]);
2009-01-06 13:55:14 -06:00
reward . titleId [ 0 ] = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
if ( reward . titleId [ 1 ])
{
CharTitlesEntry const * titleEntry = sCharTitlesStore . LookupEntry ( reward . titleId [ 1 ]);
if ( ! titleEntry )
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) has invalid title id (%u) in `title_H`, set to 0" , entry , reward . titleId [ 1 ]);
2009-01-06 13:55:14 -06:00
reward . titleId [ 1 ] = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
//check mail data before item for report including wrong item case
if ( reward . sender )
{
2011-04-28 22:57:08 +02:00
if ( ! sObjectMgr -> GetCreatureTemplate ( reward . sender ))
2009-01-06 13:55:14 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) has invalid creature entry %u as sender, mail reward skipped." , entry , reward . sender );
2009-01-06 13:55:14 -06:00
reward . sender = 0 ;
}
}
else
{
if ( reward . itemId )
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) does not have sender data but has item reward, item will not be rewarded." , entry );
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
if ( ! reward . subject . empty ())
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) does not have sender data but has mail subject." , entry );
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
if ( ! reward . text . empty ())
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) does not have sender data but has mail text." , entry );
2009-01-06 13:55:14 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
if ( reward . itemId )
{
2011-04-28 22:42:33 +02:00
if ( ! sObjectMgr -> GetItemTemplate ( reward . itemId ))
2009-01-06 13:55:14 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `achievement_reward` (Entry: %u) has invalid item id %u, reward mail will not contain item." , entry , reward . itemId );
2009-01-06 13:55:14 -06:00
reward . itemId = 0 ;
}
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
m_achievementRewards [ entry ] = reward ;
2009-04-08 16:27:00 -05:00
++ count ;
2010-12-19 17:06:33 +01:00
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %u achievement rewards in %u ms" , count , GetMSTimeDiffToNow ( oldMSTime ));
2009-01-06 13:55:14 -06:00
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
void AchievementGlobalMgr :: LoadRewardLocales ()
{
2010-12-19 17:06:33 +01:00
uint32 oldMSTime = getMSTime ();
2009-01-06 13:55:14 -06:00
m_achievementRewardLocales . clear (); // need for reload case
2009-10-17 15:51:44 -07:00
2011-04-29 20:47:02 +02:00
QueryResult result = WorldDatabase . Query ( "SELECT entry, subject_loc1, text_loc1, subject_loc2, text_loc2, subject_loc3, text_loc3, subject_loc4, text_loc4, "
"subject_loc5, text_loc5, subject_loc6, text_loc6, subject_loc7, text_loc7, subject_loc8, text_loc8"
2010-12-19 17:06:33 +01:00
" FROM locales_achievement_reward" );
2009-10-17 15:51:44 -07:00
2010-01-01 14:19:29 -06:00
if ( ! result )
2009-01-06 13:55:14 -06:00
{
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded 0 achievement reward locale strings. DB table `locales_achievement_reward` is empty" );
2009-01-06 13:55:14 -06:00
return ;
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
do
{
2011-09-15 14:08:17 +02:00
Field * fields = result -> Fetch ();
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
uint32 entry = fields [ 0 ]. GetUInt32 ();
2009-10-17 15:51:44 -07:00
2010-04-07 23:25:02 +02:00
if ( m_achievementRewards . find ( entry ) == m_achievementRewards . end ())
2009-01-06 13:55:14 -06:00
{
2012-08-03 14:20:18 +02:00
sLog -> outError ( LOG_FILTER_SQL , "Table `locales_achievement_reward` (Entry: %u) has locale strings for non-existing achievement reward." , entry );
2009-01-06 13:55:14 -06:00
continue ;
}
2009-10-17 15:51:44 -07:00
2009-01-06 13:55:14 -06:00
AchievementRewardLocale & data = m_achievementRewardLocales [ entry ];
2009-10-17 15:51:44 -07:00
2010-09-28 08:21:51 +03:00
for ( int i = 1 ; i < TOTAL_LOCALES ; ++ i )
2009-01-06 13:55:14 -06:00
{
2010-08-27 00:57:49 +06:00
LocaleConstant locale = ( LocaleConstant ) i ;
2011-08-04 15:14:15 +02:00
ObjectMgr :: AddLocaleString ( fields [ 1 + 2 * ( i - 1 )]. GetString (), locale , data . subject );
ObjectMgr :: AddLocaleString ( fields [ 1 + 2 * ( i - 1 ) + 1 ]. GetString (), locale , data . text );
2009-01-06 13:55:14 -06:00
}
2012-08-27 15:06:59 +02:00
}
while ( result -> NextRow ());
2009-10-17 15:51:44 -07:00
2012-08-16 20:17:29 +01:00
sLog -> outInfo ( LOG_FILTER_SERVER_LOADING , ">> Loaded %lu achievement reward locale strings in %u ms" , ( unsigned long ) m_achievementRewardLocales . size (), GetMSTimeDiffToNow ( oldMSTime ));
2009-01-06 13:55:14 -06:00
}
2012-08-27 15:06:59 +02:00
AchievementEntry const * AchievementGlobalMgr :: GetAchievement ( uint32 achievementId ) const
{
return sAchievementStore . LookupEntry ( achievementId );
}
AchievementCriteriaEntry const * AchievementGlobalMgr :: GetAchievementCriteria ( uint32 criteriaId ) const
{
return sAchievementCriteriaStore . LookupEntry ( criteriaId );
}