Implement some death related achievements

* ACHIEVEMENT_CRITERIA_TYPE_DEATH (normal and arena types counting)
    * ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON (instance types by man limit counting)
      Note: need fixed for cases when max allowed players different from recommended count.
    * ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM (environment damage sources by types)

    Fixed:
    * ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER
       - self-kill counting as death from players
       - same team player kill in opposition kills counter.

    Also cleanup in Player::EnvironmentalDamage use DBCStructure.h comment.

Author: VladimirMangos

--HG--
branch : trunk
This commit is contained in:
megamage
2009-03-06 15:21:44 -06:00
parent 2e0af6e37b
commit 50b3095312
4 changed files with 203 additions and 84 deletions
+108 -4
View File
@@ -27,6 +27,7 @@
#include "GameEvent.h"
#include "World.h"
#include "SpellMgr.h"
#include "ArenaTeam.h"
#include "ProgressBar.h"
#include "GridNotifiersImpl.h"
#include "CellImpl.h"
@@ -374,6 +375,18 @@ void AchievementMgr::CheckAllAchievementCriteria()
UpdateAchievementCriteria(AchievementCriteriaTypes(i));
}
static const uint32 achievIdByArenaSlot[MAX_ARENA_SLOT] = { 1057, 1107, 1108 };
static const uint32 achievIdForDangeon[][4] =
{
// ach_cr_id,is_dungeon,is_raid,is_heroic_dungeon
{ 321, true, true, true },
{ 916, false, true, false },
{ 917, false, true, false },
{ 918, true, false, false },
{ 2219, false, false, true },
{ 0, false, false, false }
};
/**
* this function will be called whenever the user might have done a criteria relevant action
*/
@@ -408,7 +421,6 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
{
// std. case: increment at 1
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST:
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
@@ -493,6 +505,79 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
{
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
// skip wrong arena achievements, if not achievIdByArenaSlot then normal totla death counter
bool notfit = false;
for(int i = 0; i < MAX_ARENA_SLOT; ++i)
{
if(achievIdByArenaSlot[i] == achievement->ID)
{
BattleGround* bg = GetPlayer()->GetBattleGround();
if(!bg || ArenaTeam::GetSlotByType(bg->GetArenaType())!=i)
notfit = true;
break;
}
}
if(notfit)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
{
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
Map const* map = GetPlayer()->GetMap();
if(!map->IsDungeon())
continue;
// search case
bool found = false;
for(int i = 0; achievIdForDangeon[i][0]; ++i)
{
if(achievIdForDangeon[i][0] == achievement->ID)
{
if(map->IsRaid())
{
// if raid accepted (ignore difficulty)
if(!achievIdForDangeon[i][2])
break; // for
}
else if(GetPlayer()->GetDifficulty()==DIFFICULTY_NORMAL)
{
// dungeon in normal mode accepted
if(!achievIdForDangeon[i][1])
break; // for
}
else
{
// dungeon in heroic mode accepted
if(!achievIdForDangeon[i][3])
break; // for
}
found = true;
break; // for
}
}
if(!found)
continue;
//FIXME: work only for instances where max==min for players
if(((InstanceMap*)map)->GetMaxPlayers() != achievementCriteria->death_in_dungeon.manLimit)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
@@ -501,6 +586,17 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
// if team check required: must kill by opposition faction
if(achievement->ID==318 && miscvalue2==GetPlayer()->GetTeam())
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_FALL_WITHOUT_DYING:
{
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
@@ -518,6 +614,14 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
SetCriteriaProgress(achievementCriteria, miscvalue1);
break;
}
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
// AchievementMgr::UpdateAchievementCriteria might also be called on login - skip in this case
if(!miscvalue1)
continue;
if(miscvalue2 != achievementCriteria->death_from.type)
continue;
SetCriteriaProgress(achievementCriteria, 1, PROGRESS_ACCUMULATE);
break;
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST:
if(GetPlayer()->GetQuestRewardStatus(achievementCriteria->complete_quest.questID))
SetCriteriaProgress(achievementCriteria, 1);
@@ -680,10 +784,7 @@ void AchievementMgr::UpdateAchievementCriteria(AchievementCriteriaTypes type, ui
case ACHIEVEMENT_CRITERIA_TYPE_WIN_BG:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_DAILY_QUEST_DAILY:
case ACHIEVEMENT_CRITERIA_TYPE_DAMAGE_DONE:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON:
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID:
case ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM:
case ACHIEVEMENT_CRITERIA_TYPE_BG_OBJECTIVE_CAPTURE:
case ACHIEVEMENT_CRITERIA_TYPE_HONORABLE_KILL_AT_AREA:
case ACHIEVEMENT_CRITERIA_TYPE_WIN_ARENA:
@@ -836,8 +937,11 @@ bool AchievementMgr::IsCompletedCriteria(AchievementCriteriaEntry const* achieve
// handle all statistic-only criteria here
case ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_BATTLEGROUND:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP:
case ACHIEVEMENT_CRITERIA_TYPE_DEATH:
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_GOLD_SPENT_FOR_TALENTS:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_AT_BARBER:
case ACHIEVEMENT_CRITERIA_TYPE_GOLD_SPENT_FOR_MAIL:
+11 -3
View File
@@ -898,6 +898,9 @@ void Player::StopMirrorTimer(MirrorTimerType Type)
void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 damage)
{
if(!isAlive() || isGameMaster())
return;
WorldPacket data(SMSG_ENVIRONMENTALDAMAGELOG, (21));
data << (uint64)guid;
data << (uint8)(type!=DAMAGE_FALL_TO_VOID ? type : DAMAGE_FALL);
@@ -908,7 +911,9 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
DealDamage(this, damage, NULL, SELF_DAMAGE, SPELL_SCHOOL_MASK_NORMAL, NULL, false);
if(type==DAMAGE_FALL && !isAlive()) // DealDamage not apply item durability loss at self damage
if(!isAlive())
{
if(type==DAMAGE_FALL) // DealDamage not apply item durability loss at self damage
{
DEBUG_LOG("We are fall to death, loosing 10 percents durability");
DurabilityLossAll(0.10f,false);
@@ -916,6 +921,9 @@ void Player::EnvironmentalDamage(uint64 guid, EnviromentalDamage type, uint32 da
WorldPacket data(SMSG_DURABILITY_DAMAGE_DEATH, 0);
GetSession()->SendPacket(&data);
}
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM, 1, type);
}
}
void Player::HandleDrowning()
@@ -998,8 +1006,6 @@ void Player::HandleLava()
uint64 guid = GetGUID();
uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage
// if not gamemaster then deal damage
if ( !isGameMaster() )
EnvironmentalDamage(guid, DAMAGE_LAVA, damage);
m_breathTimer = 1*IN_MILISECONDS;
@@ -1385,6 +1391,8 @@ void Player::setDeathState(DeathState s)
if(!ressSpellId)
ressSpellId = GetResurrectionSpellId();
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_AT_MAP, 1);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH, 1);
GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON, 1);
}
Unit::setDeathState(s);
+5 -4
View File
@@ -728,6 +728,7 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
if (pVictim->GetTypeId() == TYPEID_UNIT && !((Creature*)pVictim)->isPet() && !((Creature*)pVictim)->hasLootRecipient())
((Creature*)pVictim)->SetLootRecipient(this);
if (health <= damage)
{
DEBUG_LOG("DealDamage: victim just died");
@@ -809,8 +810,8 @@ uint32 Unit::DealDamage(Unit *pVictim, uint32 damage, CleanDamage const* cleanDa
{
if (GetTypeId() == TYPEID_UNIT)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
else if(GetTypeId() == TYPEID_PLAYER)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1);
else if(GetTypeId() == TYPEID_PLAYER && pVictim != this)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ((Player*)this)->GetTeam());
}
// 10% durability loss on death
@@ -12487,8 +12488,8 @@ void Unit::Kill(Unit *pVictim, bool durabilityLoss)
{
if (GetTypeId() == TYPEID_UNIT)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_CREATURE, GetEntry());
else if(GetTypeId() == TYPEID_PLAYER)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1);
else if(GetTypeId() == TYPEID_PLAYER && pVictim != this)
((Player*)pVictim)->GetAchievementMgr().UpdateAchievementCriteria(ACHIEVEMENT_CRITERIA_TYPE_KILLED_BY_PLAYER, 1, ((Player*)this)->GetTeam());
}
}
+8 -2
View File
@@ -151,6 +151,12 @@ struct AchievementCriteriaEntry
uint32 mapID; // 3
} death_at_map;
// ACHIEVEMENT_CRITERIA_TYPE_DEATH_IN_DUNGEON = 18
struct
{
uint32 manLimit; // 3
} death_in_dungeon;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_RAID = 19
struct
{
@@ -173,8 +179,8 @@ struct AchievementCriteriaEntry
// ACHIEVEMENT_CRITERIA_TYPE_DEATHS_FROM = 26
struct
{
uint32 type; // 0 - fatigue, 1 - drowning, 2 - falling, 3 - ??, 5 - fire and lava
} deaths;
uint32 type; // 3, see enum EnviromentalDamage
} death_from;
// ACHIEVEMENT_CRITERIA_TYPE_COMPLETE_QUEST = 27
struct