From 8da2cf888c10aad3cbcf73489279f632192f0fb1 Mon Sep 17 00:00:00 2001 From: VladimirMangos Date: Fri, 6 Mar 2009 22:21:35 +0300 Subject: [PATCH] [7391] Prevent achievement counter overflow, implement ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE generic support. Before overflow has been possible at 4294967295 lols for example. ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE in many cases require check special conditions and targets. For this allow call it from scripts: * Add Player::UpdateAchievementCriteria functiona ccessable from scripts * In emote case it allowed call in form player->UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote_id, achievement_id, target_unit_ptr); --- src/game/AchievementMgr.cpp | 34 ++++++++++++++++++-- src/game/ChatHandler.cpp | 64 ++++++++++++++++++-------------------- src/game/Player.cpp | 5 +++ src/game/Player.h | 1 + src/shared/Database/DBCStructure.h | 3 +- src/shared/revision_nr.h | 2 +- 6 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/game/AchievementMgr.cpp b/src/game/AchievementMgr.cpp index b06a2f1c7..0f61962ce 100644 --- a/src/game/AchievementMgr.cpp +++ b/src/game/AchievementMgr.cpp @@ -730,6 +730,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); break; } + case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: + { + // miscvalue1 = emote + // miscvalue2 = achievement->ID for special requirement + if(!miscvalue1) + continue; + if(miscvalue1 != achievementCriteria->do_emote.emoteID) + continue; + if(achievementCriteria->do_emote.count) + { + // harcoded case + if(achievement->ID==247) + { + if (!unit || unit->GetTypeId() != TYPEID_PLAYER || + unit->isAlive() || ((Player*)unit)->GetDeathTimer() == 0) + continue; + } + // expected as scripted case + else if(!miscvalue2 || !achievement->ID != miscvalue2) + continue; + } + + SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); + break; + } case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS: { uint32 spellCount = 0; @@ -798,7 +823,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS: case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: - case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: @@ -927,6 +951,8 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve 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; + case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE: + return progress->counter >= achievementCriteria->do_emote.count; case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD: return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: @@ -1024,8 +1050,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry, newValue = changeValue; break; case PROGRESS_ACCUMULATE: - newValue = progress->counter + changeValue; + { + // avoid overflow + uint32 max_value = std::numeric_limits::max(); + newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value; break; + } case PROGRESS_HIGHEST: newValue = progress->counter < changeValue ? changeValue : progress->counter; break; diff --git a/src/game/ChatHandler.cpp b/src/game/ChatHandler.cpp index ea5061001..0edfd30c8 100644 --- a/src/game/ChatHandler.cpp +++ b/src/game/ChatHandler.cpp @@ -522,44 +522,42 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data ) } EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); - if (em) - { - uint32 emote_anim = em->textid; + if (!em) + return; - WorldPacket data; + GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit); - switch(emote_anim) - { - case EMOTE_STATE_SLEEP: - case EMOTE_STATE_SIT: - case EMOTE_STATE_KNEEL: - case EMOTE_ONESHOT_NONE: - break; - default: - GetPlayer()->HandleEmoteCommand(emote_anim); - break; - } + uint32 emote_anim = em->textid; - data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); - data << GetPlayer()->GetGUID(); - data << (uint32)text_emote; - data << emoteNum; - data << (uint32)namlen; - if( namlen > 1 ) - { - data.append(nam, namlen); - } - else - { - data << (uint8)0x00; - } - - GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); + WorldPacket data; - //Send scripted event call - if (pCreature && Script) - Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); + switch(emote_anim) + { + case EMOTE_STATE_SLEEP: + case EMOTE_STATE_SIT: + case EMOTE_STATE_KNEEL: + case EMOTE_ONESHOT_NONE: + break; + default: + GetPlayer()->HandleEmoteCommand(emote_anim); + break; } + + data.Initialize(SMSG_TEXT_EMOTE, (20+namlen)); + data << GetPlayer()->GetGUID(); + data << (uint32)text_emote; + data << emoteNum; + data << (uint32)namlen; + if( namlen > 1 ) + data.append(nam, namlen); + else + data << (uint8)0x00; + + GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); + + //Send scripted event call + if (pCreature && Script) + Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); } void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) diff --git a/src/game/Player.cpp b/src/game/Player.cpp index e42f8d1e8..ead51d937 100644 --- a/src/game/Player.cpp +++ b/src/game/Player.cpp @@ -19869,3 +19869,8 @@ void Player::HandleFall(MovementInfo const& movementInfo) } } } + +void Player::UpdateAchievementCriteria( AchievementCriteriaTypes type, uint32 miscvalue1/*=0*/, uint32 miscvalue2/*=0*/, Unit *unit/*=NULL*/, uint32 time/*=0*/ ) +{ + GetAchievementMgr().UpdateAchievementCriteria(type, miscvalue1,miscvalue2,unit,time); +} \ No newline at end of file diff --git a/src/game/Player.h b/src/game/Player.h index f616108cd..69ac16476 100644 --- a/src/game/Player.h +++ b/src/game/Player.h @@ -2149,6 +2149,7 @@ class MANGOS_DLL_SPEC Player : public Unit void AddRunePower(uint8 index); void InitRunes(); AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } + void UpdateAchievementCriteria(AchievementCriteriaTypes type, uint32 miscvalue1=0, uint32 miscvalue2=0, Unit *unit=NULL, uint32 time=0); bool HasTitle(uint32 bitIndex); bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } void SetTitle(CharTitlesEntry const* title); diff --git a/src/shared/Database/DBCStructure.h b/src/shared/Database/DBCStructure.h index 60d354863..bcb1d22b6 100644 --- a/src/shared/Database/DBCStructure.h +++ b/src/shared/Database/DBCStructure.h @@ -356,7 +356,8 @@ struct AchievementCriteriaEntry // TODO: where is the information about the target stored? struct { - uint32 emoteID; // 3 + uint32 emoteID; // 3 enum TextEmotes + uint32 count; // 4 count of emotes, always required special target or requirements } do_emote; // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 8fc9ed7d7..5b2bf5927 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "7390" + #define REVISION_NR "7391" #endif // __REVISION_NR_H__ -- 2.11.4.GIT