Fix 'The Undying' and 'The Immortal' achievements.

This commit is contained in:
Giuseppe Montesanto
2012-01-01 04:34:14 +01:00
parent ea7b0b064d
commit bf73409f49
8 changed files with 174 additions and 88 deletions

View File

@@ -0,0 +1,29 @@
-- The Undying
DELETE FROM `disables` WHERE `sourceType` = 4 AND `entry` IN (13237, 13238, 13239, 13240, 7617); -- Enable criteria
DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (13237, 13238, 13239, 13240, 7617); -- Enable instance script execution for achievement criteria
INSERT INTO `achievement_criteria_data` VALUES
(13237, 12, 0, 0, ''),
(13237, 18, 0, 0, ''),
(13238, 12, 0, 0, ''),
(13238, 18, 0, 0, ''),
(13239, 12, 0, 0, ''),
(13239, 18, 0, 0, ''),
(13240, 12, 0, 0, ''),
(13240, 18, 0, 0, ''),
(7617, 12, 0, 0, ''),
(7617, 18, 0, 0, '');
-- The Immortal
DELETE FROM `disables` WHERE `sourceType` = 4 AND `entry` IN (13233, 13234, 13235, 13236, 7616); -- Enable criteria
DELETE FROM `achievement_criteria_data` WHERE `criteria_id` IN (13233, 13234, 13235, 13236, 7616); -- Enable instance script execution for achievement criteria
INSERT INTO `achievement_criteria_data` VALUES
(13233, 12, 1, 0, ''),
(13233, 18, 0, 0, ''),
(13234, 12, 1, 0, ''),
(13234, 18, 0, 0, ''),
(13235, 12, 1, 0, ''),
(13235, 18, 0, 0, ''),
(13236, 12, 1, 0, ''),
(13236, 18, 0, 0, ''),
(7616, 12, 1, 0, ''),
(7616, 18, 0, 0, '');

View File

@@ -1507,9 +1507,6 @@ void Creature::setDeathState(DeathState s)
if (m_formation && m_formation->getLeader() == this)
m_formation->FormationReset(true);
if (ZoneScript* zoneScript = GetZoneScript())
zoneScript->OnCreatureDeath(this);
if ((canFly() || IsFlying()) && FallGround())
return;

View File

@@ -12750,6 +12750,10 @@ void Unit::setDeathState(DeathState s)
// do not why since in IncreaseMaxHealth currenthealth is checked
SetHealth(0);
SetPower(getPowerType(), 0);
// players in instance don't have ZoneScript, but they have InstanceScript
if (ZoneScript* zoneScript = GetZoneScript() ? GetZoneScript() : (ZoneScript*)GetInstanceScript())
zoneScript->OnUnitDeath(this);
}
else if (s == JUST_ALIVED)
RemoveFlag (UNIT_FIELD_FLAGS, UNIT_FLAG_SKINNABLE); // clear skinnable for creature and player (at battleground)

View File

@@ -37,7 +37,7 @@ class ZoneScript
virtual void OnGameObjectCreate(GameObject* /*go*/) {}
virtual void OnGameObjectRemove(GameObject* /*go*/) {}
virtual void OnCreatureDeath(Creature* /*creature*/) {}
virtual void OnUnitDeath(Unit* /*unit*/) {}
//All-purpose data storage 64 bit
virtual uint64 GetData64(uint32 /*DataId*/) { return 0; }

View File

@@ -335,8 +335,12 @@ class instance_icecrown_citadel : public InstanceMapScript
return entry;
}
void OnCreatureDeath(Creature* creature)
void OnUnitDeath(Unit* unit)
{
Creature* creature = unit->ToCreature();
if (!creature)
return;
switch (creature->GetEntry())
{
case NPC_YMIRJAR_BATTLE_MAIDEN:

View File

@@ -121,24 +121,24 @@ public:
LoadMinionData(minionData);
}
std::set<uint64> HeiganEruptionGUID[4];
uint64 GothikGateGUID;
uint64 HorsemenChestGUID;
uint64 SapphironGUID;
uint64 uiFaerlina;
uint64 uiThane;
uint64 uiLady;
uint64 uiBaron;
uint64 uiSir;
std::set<uint64> heiganEruptionGUID[4];
uint64 gothikGateGUID;
uint64 horsemenChestGUID;
uint64 sapphironGUID;
uint64 faerlinaGUID;
uint64 thaneGUID;
uint64 ladyGUID;
uint64 baronGUID;
uint64 sirGUID;
uint64 uiThaddius;
uint64 uiHeigan;
uint64 uiFeugen;
uint64 uiStalagg;
uint64 thaddiusGUID;
uint64 heiganGUID;
uint64 feugenGUID;
uint64 stalaggGUID;
uint64 uiKelthuzad;
uint64 uiKelthuzadTrigger;
uint64 uiPortals[4];
uint64 kelthuzadGUID;
uint64 kelthuzadTriggerGUID;
uint64 portalsGUID[4];
uint32 AbominationCount;
@@ -147,41 +147,46 @@ public:
time_t minHorsemenDiedTime;
time_t maxHorsemenDiedTime;
uint32 playerDied;
void Initialize()
{
GothikGateGUID = 0;
HorsemenChestGUID = 0;
SapphironGUID = 0;
uiFaerlina = 0;
uiThane = 0;
uiLady = 0;
uiBaron = 0;
uiSir = 0;
uiThaddius = 0;
uiHeigan = 0;
uiFeugen = 0;
uiStalagg = 0;
uiKelthuzad = 0;
uiKelthuzadTrigger = 0;
gothikGateGUID = 0;
horsemenChestGUID = 0;
sapphironGUID = 0;
faerlinaGUID = 0;
thaneGUID = 0;
ladyGUID = 0;
baronGUID = 0;
sirGUID = 0;
thaddiusGUID = 0;
heiganGUID = 0;
feugenGUID = 0;
stalaggGUID = 0;
kelthuzadGUID = 0;
kelthuzadTriggerGUID = 0;
memset(uiPortals, 0, sizeof(uiPortals));
playerDied = 0;
gothikDoorState = GO_STATE_ACTIVE;
memset(portalsGUID, 0, sizeof(portalsGUID));
}
void OnCreatureCreate(Creature* creature)
{
switch (creature->GetEntry())
{
case 15989: SapphironGUID = creature->GetGUID(); return;
case 15953: uiFaerlina = creature->GetGUID(); return;
case 16064: uiThane = creature->GetGUID(); return;
case 16065: uiLady = creature->GetGUID(); return;
case 30549: uiBaron = creature->GetGUID(); return;
case 16063: uiSir = creature->GetGUID(); return;
case 15928: uiThaddius = creature->GetGUID(); return;
case 15936: uiHeigan = creature->GetGUID(); return;
case 15930: uiFeugen = creature->GetGUID(); return;
case 15929: uiStalagg = creature->GetGUID(); return;
case 15990: uiKelthuzad = creature->GetGUID(); return;
case 15989: sapphironGUID = creature->GetGUID(); return;
case 15953: faerlinaGUID = creature->GetGUID(); return;
case 16064: thaneGUID = creature->GetGUID(); return;
case 16065: ladyGUID = creature->GetGUID(); return;
case 30549: baronGUID = creature->GetGUID(); return;
case 16063: sirGUID = creature->GetGUID(); return;
case 15928: thaddiusGUID = creature->GetGUID(); return;
case 15936: heiganGUID = creature->GetGUID(); return;
case 15930: feugenGUID = creature->GetGUID(); return;
case 15929: stalaggGUID = creature->GetGUID(); return;
case 15990: kelthuzadGUID = creature->GetGUID(); return;
}
AddMinion(creature, true);
@@ -197,7 +202,7 @@ public:
if (go->GetGOInfo()->displayId == 6785 || go->GetGOInfo()->displayId == 1287)
{
uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY());
HeiganEruptionGUID[section].insert(go->GetGUID());
heiganEruptionGUID[section].insert(go->GetGUID());
return;
}
@@ -205,29 +210,29 @@ public:
switch (go->GetEntry())
{
case GO_GOTHIK_GATE:
GothikGateGUID = go->GetGUID();
gothikGateGUID = go->GetGUID();
go->SetGoState(gothikDoorState);
break;
case GO_HORSEMEN_CHEST:
HorsemenChestGUID = go->GetGUID();
horsemenChestGUID = go->GetGUID();
break;
case GO_HORSEMEN_CHEST_HERO:
HorsemenChestGUID = go->GetGUID();
horsemenChestGUID = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL01:
uiPortals[0] = go->GetGUID();
portalsGUID[0] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL02:
uiPortals[1] = go->GetGUID();
portalsGUID[1] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL03:
uiPortals[2] = go->GetGUID();
portalsGUID[2] = go->GetGUID();
break;
case GO_KELTHUZAD_PORTAL04:
uiPortals[3] = go->GetGUID();
portalsGUID[3] = go->GetGUID();
break;
case GO_KELTHUZAD_TRIGGER:
uiKelthuzadTrigger = go->GetGUID();
kelthuzadTriggerGUID = go->GetGUID();
break;
default:
break;
@@ -242,16 +247,16 @@ public:
{
uint32 section = GetEruptionSection(go->GetPositionX(), go->GetPositionY());
HeiganEruptionGUID[section].erase(go->GetGUID());
heiganEruptionGUID[section].erase(go->GetGUID());
return;
}
switch (go->GetEntry())
{
case GO_BIRTH:
if (SapphironGUID)
if (sapphironGUID)
{
if (Creature* pSapphiron = instance->GetCreature(SapphironGUID))
if (Creature* pSapphiron = instance->GetCreature(sapphironGUID))
pSapphiron->AI()->DoAction(DATA_SAPPHIRON_BIRTH);
return;
}
@@ -263,6 +268,15 @@ public:
AddDoor(go, false);
}
void OnUnitDeath(Unit* unit)
{
if (unit->GetTypeId() == TYPEID_PLAYER && IsEncounterInProgress())
{
playerDied = 1;
SaveToDB();
}
}
void SetData(uint32 id, uint32 value)
{
switch (id)
@@ -271,11 +285,10 @@ public:
HeiganErupt(value);
break;
case DATA_GOTHIK_GATE:
if (GameObject* gothikGate = instance->GetGameObject(GothikGateGUID))
if (GameObject* gothikGate = instance->GetGameObject(gothikGateGUID))
gothikGate->SetGoState(GOState(value));
gothikDoorState = GOState(value);
break;
case DATA_HORSEMEN0:
case DATA_HORSEMEN1:
case DATA_HORSEMEN2:
@@ -319,35 +332,35 @@ public:
switch (id)
{
case DATA_FAERLINA:
return uiFaerlina;
return faerlinaGUID;
case DATA_THANE:
return uiThane;
return thaneGUID;
case DATA_LADY:
return uiLady;
return ladyGUID;
case DATA_BARON:
return uiBaron;
return baronGUID;
case DATA_SIR:
return uiSir;
return sirGUID;
case DATA_THADDIUS:
return uiThaddius;
return thaddiusGUID;
case DATA_HEIGAN:
return uiHeigan;
return heiganGUID;
case DATA_FEUGEN:
return uiFeugen;
return feugenGUID;
case DATA_STALAGG:
return uiStalagg;
return stalaggGUID;
case DATA_KELTHUZAD:
return uiKelthuzad;
return kelthuzadGUID;
case DATA_KELTHUZAD_PORTAL01:
return uiPortals[0];
return portalsGUID[0];
case DATA_KELTHUZAD_PORTAL02:
return uiPortals[1];
return portalsGUID[1];
case DATA_KELTHUZAD_PORTAL03:
return uiPortals[2];
return portalsGUID[2];
case DATA_KELTHUZAD_PORTAL04:
return uiPortals[3];
return portalsGUID[3];
case DATA_KELTHUZAD_TRIGGER:
return uiKelthuzadTrigger;
return kelthuzadTriggerGUID;
}
return 0;
}
@@ -359,7 +372,7 @@ public:
if (id == BOSS_HORSEMEN && state == DONE)
{
if (GameObject* pHorsemenChest = instance->GetGameObject(HorsemenChestGUID))
if (GameObject* pHorsemenChest = instance->GetGameObject(horsemenChestGUID))
pHorsemenChest->SetRespawnTime(pHorsemenChest->GetRespawnDelay());
}
@@ -373,7 +386,7 @@ public:
if (i == section)
continue;
for (std::set<uint64>::const_iterator itr = HeiganEruptionGUID[i].begin(); itr != HeiganEruptionGUID[i].end(); ++itr)
for (std::set<uint64>::const_iterator itr = heiganEruptionGUID[i].begin(); itr != heiganEruptionGUID[i].end(); ++itr)
{
if (GameObject* pHeiganEruption = instance->GetGameObject(*itr))
{
@@ -384,6 +397,21 @@ public:
}
}
// This Function is called in CheckAchievementCriteriaMeet and CheckAchievementCriteriaMeet is called before SetBossState(bossId, DONE),
// so to check if all bosses are done the checker must exclude 1 boss, the last done, if there is at most 1 encouter in progress when is
// called this function then all bosses are done. The one boss that check is the boss that calls this function, so it is dead.
bool AreAllEncoutersDone()
{
uint32 numBossAlive = 0;
for (uint32 i = 0; i < MAX_BOSS_NUMBER; ++i)
if (GetBossState(i) != DONE)
numBossAlive++;
if (numBossAlive > 1)
return false;
return true;
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target = NULL*/, uint32 /*miscvalue1 = 0*/)
{
switch (criteria_id)
@@ -396,12 +424,22 @@ public:
if (Difficulty(instance->GetSpawnMode()) == RAID_DIFFICULTY_25MAN_NORMAL && (maxHorsemenDiedTime - minHorsemenDiedTime) < 15)
return true;
return false;
case 13233: // Criteria for achievement 2186: The Immortal (25-man)
// TODO.
break;
case 13237: // Criteria for achievement 2187: The Undying (10-man)
// TODO.
break;
// Difficulty checks are done on DB.
// Criteria for achievement 2186: The Immortal (25-man)
case 13233: // The Four Horsemen
case 13234: // Maexxna
case 13235: // Thaddius
case 13236: // Loatheb
case 7616: // Kel'Thuzad
// Criteria for achievement 2187: The Undying (10-man)
case 13237: // The Four Horsemen
case 13238: // Maexxna
case 13239: // Loatheb
case 13240: // Thaddius
case 7617: // Kel'Thuzad
if (AreAllEncoutersDone() && !playerDied)
return true;
return false;
}
return false;
}
@@ -409,16 +447,22 @@ public:
std::string GetSaveData()
{
std::ostringstream saveStream;
saveStream << GetBossSaveData() << ' ' << gothikDoorState;
saveStream << GetBossSaveData() << gothikDoorState << ' ' << playerDied;
return saveStream.str();
}
void Load(const char * data)
{
std::istringstream loadStream(LoadBossState(data));
uint32 buff;
uint32 temp, buff, buff2;
for (uint32 i = 0; i < MAX_BOSS_NUMBER; ++i)
loadStream >> temp;
loadStream >> buff;
gothikDoorState = GOState(buff);
loadStream >> buff2;
playerDied = buff2;
}
};

View File

@@ -58,8 +58,12 @@ public:
gameObjectList.clear();
}
void OnCreatureDeath(Creature* creature)
void OnUnitDeath(Unit* unit)
{
Creature* creature = unit->ToCreature();
if (!creature)
return;
if (creature->GetEntry() != NPC_CENTRIFUGE_CONSTRUCT)
return;

View File

@@ -358,8 +358,12 @@ class instance_ulduar : public InstanceMapScript
}
}
void OnCreatureDeath(Creature* creature)
void OnUnitDeath(Unit* unit)
{
Creature* creature = unit->ToCreature();
if (!creature)
return;
switch (creature->GetEntry())
{
case NPC_CORRUPTED_SERVITOR: