[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);

Author: VladimirMangos

--HG--
branch : trunk
This commit is contained in:
megamage
2009-03-06 18:14:05 -06:00
parent 7915fd768a
commit c2261e3502
7 changed files with 78 additions and 41 deletions
+3 -1
View File
@@ -1,3 +1,5 @@
DELETE FROM mangos_string WHERE entry = 726; ALTER TABLE db_version CHANGE COLUMN required_7382_01_mangos_creature_template required_7388_01_mangos_mangos_string bit;
DELETE FROM mangos_string WHERE entry IN (750,751);
INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); INSERT INTO mangos_string VALUES (750,'Not enough players. This game will close in %u mins.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); INSERT INTO mangos_string VALUES (751,'Not enough players. This game will close in %u seconds.',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL);
+32 -2
View File
@@ -730,6 +730,31 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE); SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break; 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: case ACHIEVEMENT_CRITERIA_TYPE_LEARN_SKILLLINE_SPELLS:
{ {
uint32 spellCount = 0; uint32 spellCount = 0;
@@ -798,7 +823,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM: case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_EPIC_ITEM:
case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS: case ACHIEVEMENT_CRITERIA_TYPE_HK_CLASS:
case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE: case ACHIEVEMENT_CRITERIA_TYPE_HK_RACE:
case ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE:
case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE: case ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS: case ACHIEVEMENT_CRITERIA_TYPE_GET_KILLING_BLOWS:
case ACHIEVEMENT_CRITERIA_TYPE_EQUIP_ITEM: 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_NEED_ON_LOOT:
case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT: case ACHIEVEMENT_CRITERIA_TYPE_ROLL_GREED_ON_LOOT:
return progress->counter >= achievementCriteria->roll_greed_on_loot.count; 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: case ACHIEVEMENT_CRITERIA_TYPE_MONEY_FROM_QUEST_REWARD:
return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper; return progress->counter >= achievementCriteria->quest_reward_money.goldInCopper;
case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY: case ACHIEVEMENT_CRITERIA_TYPE_LOOT_MONEY:
@@ -1024,8 +1050,12 @@ void AchievementMgr::SetCriteriaProgress(AchievementCriteriaEntry const* entry,
newValue = changeValue; newValue = changeValue;
break; break;
case PROGRESS_ACCUMULATE: case PROGRESS_ACCUMULATE:
newValue = progress->counter + changeValue; {
// avoid overflow
uint32 max_value = std::numeric_limits<uint32>::max();
newValue = max_value - progress->counter > changeValue ? progress->counter + changeValue : max_value;
break; break;
}
case PROGRESS_HIGHEST: case PROGRESS_HIGHEST:
newValue = progress->counter < changeValue ? changeValue : progress->counter; newValue = progress->counter < changeValue ? changeValue : progress->counter;
break; break;
+5 -7
View File
@@ -524,8 +524,11 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
} }
EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote); EmotesTextEntry const *em = sEmotesTextStore.LookupEntry(text_emote);
if (em) if (!em)
{ return;
GetPlayer()->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DO_EMOTE, text_emote, 0, unit);
uint32 emote_anim = em->textid; uint32 emote_anim = em->textid;
WorldPacket data; WorldPacket data;
@@ -548,20 +551,15 @@ void WorldSession::HandleTextEmoteOpcode( WorldPacket & recv_data )
data << emoteNum; data << emoteNum;
data << (uint32)namlen; data << (uint32)namlen;
if( namlen > 1 ) if( namlen > 1 )
{
data.append(nam, namlen); data.append(nam, namlen);
}
else else
{
data << (uint8)0x00; data << (uint8)0x00;
}
GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true); GetPlayer()->SendMessageToSetInRange(&data,sWorld.getConfig(CONFIG_LISTEN_RANGE_TEXTEMOTE),true);
//Send scripted event call //Send scripted event call
if (pCreature && Script) if (pCreature && Script)
Script->ReceiveEmote(GetPlayer(),pCreature,text_emote); Script->ReceiveEmote(GetPlayer(),pCreature,text_emote);
}
} }
void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data ) void WorldSession::HandleChatIgnoredOpcode(WorldPacket& recv_data )
+5
View File
@@ -20645,3 +20645,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);
}
+1
View File
@@ -2181,6 +2181,7 @@ class TRINITY_DLL_SPEC Player : public Unit
void AddRunePower(uint8 index); void AddRunePower(uint8 index);
void InitRunes(); void InitRunes();
AchievementMgr& GetAchievementMgr() { return m_achievementMgr; } 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(uint32 bitIndex);
bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); } bool HasTitle(CharTitlesEntry const* title) { return HasTitle(title->bit_index); }
void SetTitle(CharTitlesEntry const* title); void SetTitle(CharTitlesEntry const* title);
+2 -1
View File
@@ -359,7 +359,8 @@ struct AchievementCriteriaEntry
// TODO: where is the information about the target stored? // TODO: where is the information about the target stored?
struct struct
{ {
uint32 emoteID; // 3 uint32 emoteID; // 3 enum TextEmotes
uint32 count; // 4 count of emotes, always required special target or requirements
} do_emote; } do_emote;
// ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13 // ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE = 13
// ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55 // ACHIEVEMENT_CRITERIA_TYPE_HEALING_DONE = 55
+1 -1
View File
@@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__ #ifndef __REVISION_NR_H__
#define __REVISION_NR_H__ #define __REVISION_NR_H__
#define REVISION_NR "7389" #define REVISION_NR "7391"
#endif // __REVISION_NR_H__ #endif // __REVISION_NR_H__