Core/Scripts: Save instance data in JSON format

This commit is contained in:
Shauren
2020-01-03 21:55:45 +01:00
parent 9b924522d0
commit 76be303351
40 changed files with 742 additions and 1220 deletions

View File

@@ -0,0 +1 @@
DELETE FROM `areatrigger_scripts` WHERE `ScriptName`='at_icc_start_blood_quickening';

View File

@@ -27,6 +27,7 @@
#include "Group.h"
#include "InstancePackets.h"
#include "InstanceScenario.h"
#include "InstanceScriptData.h"
#include "LFGMgr.h"
#include "Log.h"
#include "Map.h"
@@ -35,11 +36,11 @@
#include "Player.h"
#include "RBAC.h"
#include "ScriptReloadMgr.h"
#include "SmartEnum.h"
#include "SpellMgr.h"
#include "World.h"
#include "WorldSession.h"
#include "WorldStateMgr.h"
#include <sstream>
#include <cstdarg>
#ifdef TRINITY_API_USE_DYNAMIC_LINKING
@@ -83,17 +84,6 @@ void InstanceScript::SaveToDB()
{
if (InstanceScenario* scenario = instance->GetInstanceScenario())
scenario->SaveToDB();
std::string data = GetSaveData();
if (data.empty())
return;
CharacterDatabasePreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_UPD_INSTANCE_DATA);
stmt->setUInt32(0, GetCompletedEncounterMask());
stmt->setString(1, data);
stmt->setUInt32(2, _entranceId);
stmt->setUInt32(3, instance->GetInstanceId());
CharacterDatabase.Execute(stmt);
}
bool InstanceScript::IsEncounterInProgress() const
@@ -171,9 +161,7 @@ GameObject* InstanceScript::GetGameObject(uint32 type)
void InstanceScript::SetHeaders(std::string const& dataHeaders)
{
for (char header : dataHeaders)
if (isalpha(header))
headers.push_back(header);
headers = dataHeaders;
}
void InstanceScript::LoadBossBoundaries(BossBoundaryData const& data)
@@ -451,8 +439,8 @@ bool InstanceScript::SetBossState(uint32 id, EncounterState state)
bossInfo->state = state;
SaveToDB();
if (state == DONE && dungeonEncounter)
instance->UpdateInstanceLock(dungeonEncounter, { id, state });
if (dungeonEncounter)
instance->UpdateInstanceLock({ dungeonEncounter, id, state });
}
for (uint32 type = 0; type < MAX_DOOR_TYPES; ++type)
@@ -493,12 +481,11 @@ void InstanceScript::Load(char const* data)
OUT_LOAD_INST_DATA(data);
std::istringstream loadStream(data);
if (ReadSaveDataHeaders(loadStream))
InstanceScriptDataReader reader(*this);
if (reader.Load(data) == InstanceScriptDataReader::Result::Ok)
{
ReadSaveDataBossStates(loadStream);
ReadSaveDataMore(loadStream);
UpdateSpawnGroups();
AfterDataLoad();
}
else
OUT_LOAD_INST_DATA_FAIL;
@@ -506,86 +493,39 @@ void InstanceScript::Load(char const* data)
OUT_LOAD_INST_DATA_COMPLETE;
}
bool InstanceScript::ReadSaveDataHeaders(std::istringstream& data)
{
for (char header : headers)
{
char buff;
data >> buff;
if (header != buff)
return false;
}
return true;
}
void InstanceScript::ReadSaveDataBossStates(std::istringstream& data)
{
uint32 bossId = 0;
for (; bossId < bosses.size(); ++bossId)
{
uint32 buff;
data >> buff;
if (buff == IN_PROGRESS || buff == FAIL || buff == SPECIAL)
buff = NOT_STARTED;
if (buff < TO_BE_DECIDED)
SetBossState(bossId, EncounterState(buff));
}
UpdateSpawnGroups();
}
std::string InstanceScript::GetSaveData()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
InstanceScriptDataWriter writer(*this);
WriteSaveDataHeaders(saveStream);
WriteSaveDataBossStates(saveStream);
WriteSaveDataMore(saveStream);
writer.FillData();
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
return writer.GetString();
}
std::string InstanceScript::UpdateSaveData(std::string const& oldData, UpdateSaveDataEvent const& event)
std::string InstanceScript::UpdateBossStateSaveData(std::string const& oldData, UpdateBossStateSaveDataEvent const& event)
{
if (!instance->GetMapDifficulty()->IsUsingEncounterLocks())
return GetSaveData();
std::size_t position = (headers.size() + event.BossId) * 2;
std::string newData = oldData;
if (position >= oldData.length())
{
// Initialize blank data
std::ostringstream saveStream;
WriteSaveDataHeaders(saveStream);
for (std::size_t i = 0; i < bosses.size(); ++i)
saveStream << uint32(NOT_STARTED) << ' ';
WriteSaveDataMore(saveStream);
newData = saveStream.str();
}
newData[position] = uint32(event.NewState) + '0';
return newData;
InstanceScriptDataWriter writer(*this);
writer.FillDataFrom(oldData);
writer.SetBossState(event);
return writer.GetString();
}
void InstanceScript::WriteSaveDataHeaders(std::ostringstream& data)
std::string InstanceScript::UpdateAdditionalSaveData(std::string const& oldData, UpdateAdditionalSaveDataEvent const& event)
{
for (char header : headers)
data << header << ' ';
}
if (!instance->GetMapDifficulty()->IsUsingEncounterLocks())
return GetSaveData();
void InstanceScript::WriteSaveDataBossStates(std::ostringstream& data)
{
for (BossInfo const& bossInfo : bosses)
data << uint32(bossInfo.state) << ' ';
InstanceScriptDataWriter writer(*this);
writer.FillDataFrom(oldData);
writer.SetAdditionalData(event);
return writer.GetString();
}
void InstanceScript::HandleGameObject(ObjectGuid guid, bool open, GameObject* go /*= nullptr*/)
@@ -935,26 +875,9 @@ void InstanceScript::UpdatePhasing()
});
}
/*static*/ char const* InstanceScript::GetBossStateName(uint8 state)
char const* InstanceScript::GetBossStateName(uint8 state)
{
// See enum EncounterState in InstanceScript.h
switch (state)
{
case NOT_STARTED:
return "NOT_STARTED";
case IN_PROGRESS:
return "IN_PROGRESS";
case FAIL:
return "FAIL";
case DONE:
return "DONE";
case SPECIAL:
return "SPECIAL";
case TO_BE_DECIDED:
return "TO_BE_DECIDED";
default:
return "INVALID";
}
return EnumUtils::ToConstant(EncounterState(state));
}
void InstanceScript::UpdateCombatResurrection(uint32 diff)
@@ -1012,6 +935,19 @@ uint32 InstanceScript::GetCombatResurrectionChargeInterval() const
return interval;
}
PersistentInstanceScriptValueBase::PersistentInstanceScriptValueBase(InstanceScript& instance, char const* name, std::variant<int64, double> value)
: _instance(instance), _name(name), _value(std::move(value))
{
_instance.RegisterPersistentScriptValue(this);
}
PersistentInstanceScriptValueBase::~PersistentInstanceScriptValueBase() = default;
void PersistentInstanceScriptValueBase::NotifyValueChanged()
{
_instance.instance->UpdateInstanceLock(CreateEvent());
}
bool InstanceHasScript(WorldObject const* obj, char const* scriptName)
{
if (InstanceMap* instance = obj->GetMap()->ToInstanceMap())

View File

@@ -22,9 +22,9 @@
#include "Common.h"
#include "Duration.h"
#include <array>
#include <iosfwd>
#include <map>
#include <set>
#include <variant>
#define OUT_SAVE_INST_DATA TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d)", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
#define OUT_SAVE_INST_DATA_COMPLETE TC_LOG_DEBUG("scripts", "Saving Instance Data for Instance %s (Map %d, Instance Id %d) completed.", instance->GetMapName(), instance->GetId(), instance->GetInstanceId())
@@ -37,6 +37,7 @@ class Creature;
class GameObject;
class InstanceMap;
class ModuleReference;
class PersistentInstanceScriptValueBase;
class Player;
class Unit;
struct DungeonEncounterEntry;
@@ -154,12 +155,21 @@ struct MinionInfo
BossInfo* bossInfo;
};
struct UpdateSaveDataEvent
struct UpdateBossStateSaveDataEvent
{
DungeonEncounterEntry const* DungeonEncounter;
uint32 BossId;
EncounterState NewState;
};
struct UpdateAdditionalSaveDataEvent
{
explicit UpdateAdditionalSaveDataEvent(char const* key, std::variant<int64, double> value) : Key(key), Value(value) { }
char const* Key;
std::variant<int64, double> Value;
};
typedef std::multimap<uint32 /*entry*/, DoorInfo> DoorInfoMap;
typedef std::pair<DoorInfoMap::const_iterator, DoorInfoMap::const_iterator> DoorInfoMapBounds;
@@ -180,14 +190,13 @@ class TC_GAME_API InstanceScript : public ZoneScript
// if we're starting without any saved instance data
virtual void Create();
// if we're loading existing instance save data
virtual void Load(char const* data);
void Load(char const* data);
// When save is needed, this function generates the data
virtual std::string GetSaveData();
std::string GetSaveData();
virtual std::string UpdateSaveData(std::string const& oldData, UpdateSaveDataEvent const& event);
void SaveToDB();
std::string UpdateBossStateSaveData(std::string const& oldData, UpdateBossStateSaveDataEvent const& event);
std::string UpdateAdditionalSaveData(std::string const& oldData, UpdateAdditionalSaveDataEvent const& event);
virtual void Update(uint32 /*diff*/) { }
void UpdateCombatResurrection(uint32 diff);
@@ -307,6 +316,10 @@ class TC_GAME_API InstanceScript : public ZoneScript
uint8 GetCombatResurrectionCharges() const { return _combatResurrectionCharges; }
uint32 GetCombatResurrectionChargeInterval() const;
void RegisterPersistentScriptValue(PersistentInstanceScriptValueBase* value) { _persistentScriptValues.push_back(value); }
std::string const& GetHeader() const { return headers; }
std::vector<PersistentInstanceScriptValueBase*>& GetPersistentScriptValues() { return _persistentScriptValues; }
protected:
void SetHeaders(std::string const& dataHeaders);
void SetBossNumber(uint32 number) { bosses.resize(number); }
@@ -337,13 +350,8 @@ class TC_GAME_API InstanceScript : public ZoneScript
// Pay very much attention at how the returned BossInfo data is modified to avoid issues.
BossInfo* GetBossInfo(uint32 id);
// Instance Load and Save
bool ReadSaveDataHeaders(std::istringstream& data);
void ReadSaveDataBossStates(std::istringstream& data);
virtual void ReadSaveDataMore(std::istringstream& /*data*/) { }
void WriteSaveDataHeaders(std::ostringstream& data);
void WriteSaveDataBossStates(std::ostringstream& data);
virtual void WriteSaveDataMore(std::ostringstream& /*data*/) { }
// Override this function to validate all additional data loads
virtual void AfterDataLoad() { }
bool _SkipCheckRequiredBosses(Player const* player = nullptr) const;
@@ -352,8 +360,11 @@ class TC_GAME_API InstanceScript : public ZoneScript
void LoadDungeonEncounterData(uint32 bossId, std::array<uint32, MAX_DUNGEON_ENCOUNTERS_PER_BOSS> const& dungeonEncounterIds);
void UpdateEncounterState(EncounterCreditType type, uint32 creditEntry, Unit* source);
std::vector<char> headers;
void SaveToDB();
std::string headers;
std::vector<BossInfo> bosses;
std::vector<PersistentInstanceScriptValueBase*> _persistentScriptValues;
DoorInfoMap doors;
MinionInfoMap minions;
ObjectInfoMap _creatureInfo;
@@ -376,4 +387,75 @@ class TC_GAME_API InstanceScript : public ZoneScript
friend class debug_commandscript;
};
class TC_GAME_API PersistentInstanceScriptValueBase
{
protected:
PersistentInstanceScriptValueBase(InstanceScript& instance, char const* name, std::variant<int64, double> value);
public:
virtual ~PersistentInstanceScriptValueBase();
char const* GetName() const { return _name; }
UpdateAdditionalSaveDataEvent CreateEvent() const
{
return UpdateAdditionalSaveDataEvent(_name, _value);
}
void LoadValue(int64 value)
{
_value.emplace<int64>(value);
}
void LoadValue(double value)
{
_value.emplace<double>(value);
}
protected:
void NotifyValueChanged();
InstanceScript& _instance;
char const* _name;
std::variant<int64, double> _value;
};
template<typename T>
class PersistentInstanceScriptValue : public PersistentInstanceScriptValueBase
{
public:
PersistentInstanceScriptValue(InstanceScript& instance, char const* name, T value = {})
: PersistentInstanceScriptValueBase(instance, name, WrapValue(value))
{
}
operator T() const
{
return std::visit([](auto v) { return static_cast<T>(v); }, _value);
}
PersistentInstanceScriptValue& operator=(T value)
{
_value = WrapValue(value);
NotifyValueChanged();
return *this;
}
void LoadValue(T value)
{
_value = WrapValue(value);
}
private:
static std::variant<int64, double> WrapValue(T value)
{
if constexpr (std::is_integral_v<T> || std::is_enum_v<T>)
return int64(value);
else if constexpr (std::is_floating_point_v<T>)
return double(value);
else
return {};
}
};
#endif // TRINITY_INSTANCE_DATA_H

View File

@@ -0,0 +1,270 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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/>.
*/
#include "InstanceScriptData.h"
#include "DB2Stores.h"
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
#include "World.h"
#include <rapidjson/pointer.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/writer.h>
#include <rapidjson/error/en.h>
namespace
{
std::string const HeadersKey = "Header";
std::string const BossStatesSaveDataKey = "BossStates";
std::string const MoreSaveDataKey = "AdditionalData";
}
InstanceScriptDataReader::Result InstanceScriptDataReader::Load(char const* data)
{
/*
Expected JSON
{
"Header": "HEADER_STRING_SET_BY_SCRIPT",
"BossStates": [0,2,0,...] // indexes are boss ids, values are EncounterState
"AdditionalData: { // optional
"ExtraKey1": 123
"AnotherExtraKey": 2.0
}
}
*/
if (_doc.Parse(data).HasParseError())
{
TC_LOG_ERROR("scripts.data.load", "JSON parser error %s at " SZFMTD " while loading data for instance %u [%u-%s | %u-%s]",
rapidjson::GetParseError_En(_doc.GetParseError()), _doc.GetErrorOffset(),
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::MalformedJson;
}
if (!_doc.IsObject())
{
TC_LOG_ERROR("scripts.data.load", "Root JSON value is not an object for instance %u [%u-%s | %u-%s]",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::RootIsNotAnObject;
}
Result result = ParseHeader();
if (result != Result::Ok)
return result;
result = ParseBossStates();
if (result != Result::Ok)
return result;
result = ParseAdditionalData();
if (result != Result::Ok)
return result;
return Result::Ok;
}
InstanceScriptDataReader::Result InstanceScriptDataReader::ParseHeader()
{
auto headerItr = _doc.FindMember(HeadersKey);
if (headerItr == _doc.MemberEnd())
{
TC_LOG_ERROR("scripts.data.load", "Missing data header for instance %u [%u-%s | %u-%s]",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::MissingHeader;
}
if (headerItr->value != _instance.GetHeader())
{
TC_LOG_ERROR("scripts.data.load", "Incorrect data header for instance %u [%u-%s | %u-%s], expected \"%s\" got \"%s\"",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName(),
_instance.GetHeader().c_str(), headerItr->value.IsString() ? headerItr->value.GetString() : "");
return Result::UnexpectedHeader;
}
return Result::Ok;
}
InstanceScriptDataReader::Result InstanceScriptDataReader::ParseBossStates()
{
auto bossStatesItr = _doc.FindMember(BossStatesSaveDataKey);
if (bossStatesItr == _doc.MemberEnd())
{
TC_LOG_ERROR("scripts.data.load", "Missing boss states for instance %u [%u-%s | %u-%s]",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::MissingBossStates;
}
if (!bossStatesItr->value.IsArray())
{
TC_LOG_ERROR("scripts.data.load", "Boss states is not an array for instance %u [%u-%s | %u-%s]",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::BossStatesIsNotAnObject;
}
for (uint32 bossId = 0; bossId < bossStatesItr->value.Size(); ++bossId)
{
if (bossId >= _instance.GetEncounterCount())
{
TC_LOG_ERROR("scripts.data.load", "Boss states has entry for boss with higher id (%u) than number of bosses (%u) for instance %u [%u-%s | %u-%s]",
bossId, _instance.GetEncounterCount(), GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::UnknownBoss;
}
auto& bossState = bossStatesItr->value[bossId];
if (!bossState.IsNumber())
{
TC_LOG_ERROR("scripts.data.load", "Boss state for boss (%u) is not a number for instance %u [%u-%s | %u-%s]",
bossId, GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::BossStateIsNotAnObject;
}
EncounterState state = EncounterState(bossState.GetInt());
if (state == IN_PROGRESS || state == FAIL || state == SPECIAL)
state = NOT_STARTED;
if (state < TO_BE_DECIDED)
_instance.SetBossState(bossId, state);
}
return Result::Ok;
}
InstanceScriptDataReader::Result InstanceScriptDataReader::ParseAdditionalData()
{
auto moreDataItr = _doc.FindMember(MoreSaveDataKey);
if (moreDataItr == _doc.MemberEnd())
return Result::Ok;
if (!moreDataItr->value.IsObject())
{
TC_LOG_ERROR("scripts.data.load", "Additional data is not an object for instance %u [%u-%s | %u-%s]",
GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::AdditionalDataIsNotAnObject;
}
for (PersistentInstanceScriptValueBase* value : _instance.GetPersistentScriptValues())
{
auto valueItr = moreDataItr->value.FindMember(value->GetName());
if (valueItr != moreDataItr->value.MemberEnd() && !valueItr->value.IsNull())
{
if (!valueItr->value.IsNumber())
{
TC_LOG_ERROR("scripts.data.load", "Additional data value for key %s is not a number for instance %u [%u-%s | %u-%s]",
value->GetName(), GetInstanceId(), GetMapId(), GetMapName(), GetDifficultyId(), GetDifficultyName());
return Result::AdditionalDataUnexpectedValueType;
}
if (valueItr->value.IsDouble())
value->LoadValue(valueItr->value.GetDouble());
else
value->LoadValue(valueItr->value.GetInt64());
}
}
return Result::Ok;
}
uint32 InstanceScriptDataReader::GetInstanceId() const { return _instance.instance->GetInstanceId(); }
uint32 InstanceScriptDataReader::GetMapId() const { return _instance.instance->GetId(); }
char const* InstanceScriptDataReader::GetMapName() const { return _instance.instance->GetMapName(); }
uint32 InstanceScriptDataReader::GetDifficultyId() const { return uint32(_instance.instance->GetDifficultyID()); }
char const* InstanceScriptDataReader::GetDifficultyName() const { return sDifficultyStore.AssertEntry(_instance.instance->GetDifficultyID())->Name[sWorld->GetDefaultDbcLocale()]; }
std::string InstanceScriptDataWriter::GetString()
{
rapidjson::StringBuffer buffer;
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
_doc.Accept(writer);
return std::string(buffer.GetString(), buffer.GetSize());
}
void InstanceScriptDataWriter::FillData(bool withValues)
{
_doc.SetObject();
_doc.AddMember(rapidjson::StringRef(HeadersKey), _instance.GetHeader(), _doc.GetAllocator());
rapidjson::Value bossStates(rapidjson::kArrayType);
for (uint32 bossId = 0; bossId < _instance.GetEncounterCount(); ++bossId)
{
rapidjson::Value bossStateValue(rapidjson::kNumberType);
bossStateValue.SetInt(withValues ? _instance.GetBossState(bossId) : NOT_STARTED);
bossStates.PushBack(bossStateValue.Move(), _doc.GetAllocator());
}
_doc.AddMember(rapidjson::StringRef(BossStatesSaveDataKey), bossStates.Move(), _doc.GetAllocator());
if (!_instance.GetPersistentScriptValues().empty())
{
rapidjson::Value moreData(rapidjson::kObjectType);
for (PersistentInstanceScriptValueBase* additionalValue : _instance.GetPersistentScriptValues())
{
if (withValues)
{
UpdateAdditionalSaveDataEvent data = additionalValue->CreateEvent();
std::visit([&](auto v)
{
moreData.AddMember(rapidjson::StringRef(data.Key), rapidjson::Value(v), _doc.GetAllocator());
}, data.Value);
}
else
moreData.AddMember(rapidjson::StringRef(additionalValue->GetName()), rapidjson::Value(), _doc.GetAllocator());
}
_doc.AddMember(rapidjson::StringRef(MoreSaveDataKey), moreData.Move(), _doc.GetAllocator());
}
}
void InstanceScriptDataWriter::FillDataFrom(std::string const& data)
{
if (_doc.Parse(data).HasParseError())
FillData(false);
}
void InstanceScriptDataWriter::SetBossState(UpdateBossStateSaveDataEvent const& data)
{
std::string bossIdKey = Trinity::StringFormat("%u", data.BossId);
rapidjson::Pointer::Token tokens[] =
{
{ BossStatesSaveDataKey.c_str(), uint32(BossStatesSaveDataKey.length()), rapidjson::kPointerInvalidIndex },
{ bossIdKey.c_str(), uint32(bossIdKey.length()), rapidjson::kPointerInvalidIndex }
};
rapidjson::Pointer ptr(tokens, std::size(tokens));
// jsonptr("/BossStates/BossId")
rapidjson::Value stateValue(rapidjson::kNumberType);
stateValue.SetInt(data.NewState);
rapidjson::SetValueByPointer(_doc, ptr, stateValue.Move());
}
void InstanceScriptDataWriter::SetAdditionalData(UpdateAdditionalSaveDataEvent const& data)
{
rapidjson::Pointer::Token tokens[] =
{
{ MoreSaveDataKey.c_str(), uint32(MoreSaveDataKey.length()), rapidjson::kPointerInvalidIndex },
{ data.Key, uint32(strlen(data.Key)), rapidjson::kPointerInvalidIndex }
};
rapidjson::Pointer ptr(tokens, std::size(tokens));
// jsonptr("/AdditionalData/CustomValueName")
std::visit([&](auto v)
{
rapidjson::SetValueByPointer(_doc, ptr, v);
}, data.Value);
}

View File

@@ -0,0 +1,86 @@
/*
* This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
*
* 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/>.
*/
#ifndef InstanceScriptData_h__
#define InstanceScriptData_h__
#include "Errors.h" // rapidjson depends on WPAssert
#include <rapidjson/document.h>
#include <string>
class InstanceScript;
struct UpdateBossStateSaveDataEvent;
struct UpdateAdditionalSaveDataEvent;
class InstanceScriptDataReader
{
public:
enum class Result
{
Ok,
MalformedJson,
RootIsNotAnObject,
MissingHeader,
UnexpectedHeader,
MissingBossStates,
BossStatesIsNotAnObject,
UnknownBoss,
BossStateIsNotAnObject,
MissingBossState,
BossStateValueIsNotANumber,
AdditionalDataIsNotAnObject,
AdditionalDataUnexpectedValueType
};
InstanceScriptDataReader(InstanceScript& instance) : _instance(instance) { }
Result Load(char const* data);
private:
Result ParseHeader();
Result ParseBossStates();
Result ParseAdditionalData();
// logging helpers
uint32 GetInstanceId() const;
uint32 GetMapId() const;
char const* GetMapName() const;
uint32 GetDifficultyId() const;
char const* GetDifficultyName() const;
InstanceScript& _instance;
rapidjson::Document _doc;
};
class InstanceScriptDataWriter
{
public:
InstanceScriptDataWriter(InstanceScript& instance) : _instance(instance) { }
std::string GetString();
void FillData(bool withValues = true);
void FillDataFrom(std::string const& data);
void SetBossState(UpdateBossStateSaveDataEvent const& data);
void SetAdditionalData(UpdateAdditionalSaveDataEvent const& data);
private:
InstanceScript& _instance;
rapidjson::Document _doc;
};
#endif // InstanceScriptData_h__

View File

@@ -3014,13 +3014,11 @@ std::string const& InstanceMap::GetScriptName() const
return sObjectMgr->GetScriptName(i_script_id);
}
void InstanceMap::UpdateInstanceLock(DungeonEncounterEntry const* dungeonEncounter, UpdateSaveDataEvent const& updateSaveDataEvent)
void InstanceMap::UpdateInstanceLock(UpdateBossStateSaveDataEvent const& updateSaveDataEvent)
{
if (i_instanceLock)
{
uint32 instanceCompletedEncounters = i_instanceLock->GetData()->CompletedEncountersMask;
if (dungeonEncounter)
instanceCompletedEncounters |= 1u << dungeonEncounter->Bit;
uint32 instanceCompletedEncounters = i_instanceLock->GetData()->CompletedEncountersMask | (1u << updateSaveDataEvent.DungeonEncounter->Bit);
MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
@@ -3028,7 +3026,7 @@ void InstanceMap::UpdateInstanceLock(DungeonEncounterEntry const* dungeonEncount
if (entries.IsInstanceIdBound())
sInstanceLockMgr.UpdateSharedInstanceLock(trans,
{ GetInstanceId(), i_data->GetSaveData(), instanceCompletedEncounters, dungeonEncounter });
{ GetInstanceId(), i_data->GetSaveData(), instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter });
for (MapReference& mapReference : m_mapRefManager)
{
@@ -3045,7 +3043,52 @@ void InstanceMap::UpdateInstanceLock(DungeonEncounterEntry const* dungeonEncount
bool isNewLock = !playerLock || !playerLock->GetData()->CompletedEncountersMask || playerLock->IsExpired();
InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
{ GetInstanceId(), i_data->UpdateSaveData(oldData ? *oldData : "", updateSaveDataEvent), instanceCompletedEncounters, dungeonEncounter });
{ GetInstanceId(), i_data->UpdateBossStateSaveData(oldData ? *oldData : "", updateSaveDataEvent), instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter });
if (isNewLock)
{
WorldPackets::Instance::InstanceSaveCreated data;
data.Gm = player->IsGameMaster();
player->SendDirectMessage(data.Write());
player->GetSession()->SendCalendarRaidLockoutAdded(newLock);
}
}
CharacterDatabase.CommitTransaction(trans);
}
}
void InstanceMap::UpdateInstanceLock(UpdateAdditionalSaveDataEvent const& updateSaveDataEvent)
{
if (i_instanceLock)
{
uint32 instanceCompletedEncounters = i_instanceLock->GetData()->CompletedEncountersMask;
MapDb2Entries entries{ GetEntry(), GetMapDifficulty() };
CharacterDatabaseTransaction trans = CharacterDatabase.BeginTransaction();
if (entries.IsInstanceIdBound())
sInstanceLockMgr.UpdateSharedInstanceLock(trans,
{ GetInstanceId(), i_data->GetSaveData(), instanceCompletedEncounters, nullptr });
for (MapReference& mapReference : m_mapRefManager)
{
Player* player = mapReference.GetSource();
// never instance bind GMs with GM mode enabled
if (player->IsGameMaster())
continue;
InstanceLock const* playerLock = sInstanceLockMgr.FindActiveInstanceLock(player->GetGUID(), entries);
std::string const* oldData = nullptr;
if (playerLock)
oldData = &playerLock->GetData()->Data;
bool isNewLock = !playerLock || !playerLock->GetData()->CompletedEncountersMask || playerLock->IsExpired();
InstanceLock const* newLock = sInstanceLockMgr.UpdateInstanceLockForPlayer(trans, player->GetGUID(), entries,
{ GetInstanceId(), i_data->UpdateAdditionalSaveData(oldData ? *oldData : "", updateSaveDataEvent), instanceCompletedEncounters, nullptr });
if (isNewLock)
{

View File

@@ -65,7 +65,6 @@ class Weather;
class WorldObject;
class WorldPacket;
struct DungeonEncounterEntry;
struct UpdateSaveDataEvent;
struct MapDifficultyEntry;
struct MapEntry;
struct Position;
@@ -73,6 +72,8 @@ struct ScriptAction;
struct ScriptInfo;
struct SmoothPhasingInfo;
struct SummonPropertiesEntry;
struct UpdateAdditionalSaveDataEvent;
struct UpdateBossStateSaveDataEvent;
class Transport;
enum Difficulty : uint8;
enum WeatherState : uint32;
@@ -814,7 +815,8 @@ class TC_GAME_API InstanceMap : public Map
InstanceScenario const* GetInstanceScenario() const { return i_scenario; }
void SetInstanceScenario(InstanceScenario* scenario) { i_scenario = scenario; }
InstanceLock const* GetInstanceLock() const { return i_instanceLock; }
void UpdateInstanceLock(DungeonEncounterEntry const* dungeonEncounter, UpdateSaveDataEvent const& updateSaveDataEvent);
void UpdateInstanceLock(UpdateBossStateSaveDataEvent const& updateSaveDataEvent);
void UpdateInstanceLock(UpdateAdditionalSaveDataEvent const& updateSaveDataEvent);
void CreateInstanceLockForPlayer(Player* player);
void UnloadAll() override;
EnterState CannotEnter(Player* player) override;

View File

@@ -164,23 +164,23 @@ public:
static bool HandleInstanceSaveDataCommand(ChatHandler* handler)
{
Player* player = handler->GetSession()->GetPlayer();
InstanceMap* map = player->GetMap()->ToInstanceMap();
if (!map)
{
handler->PSendSysMessage(LANG_NOT_DUNGEON);
handler->SetSentErrorMessage(true);
return false;
}
//Player* player = handler->GetSession()->GetPlayer();
//InstanceMap* map = player->GetMap()->ToInstanceMap();
//if (!map)
//{
// handler->PSendSysMessage(LANG_NOT_DUNGEON);
// handler->SetSentErrorMessage(true);
// return false;
//}
if (!map->GetInstanceScript())
{
handler->PSendSysMessage(LANG_NO_INSTANCE_DATA);
handler->SetSentErrorMessage(true);
return false;
}
//if (!map->GetInstanceScript())
//{
// handler->PSendSysMessage(LANG_NO_INSTANCE_DATA);
// handler->SetSentErrorMessage(true);
// return false;
//}
map->GetInstanceScript()->SaveToDB();
//map->GetInstanceScript()->SaveToDB();
return true;
}

View File

@@ -22,7 +22,6 @@
#include "Log.h"
#include "Map.h"
#include "ScriptedCreature.h"
#include <sstream>
#define TIMER_TOMBOFTHESEVEN 15000
#define MAX_ENCOUNTER 6
@@ -84,7 +83,7 @@ public:
instance_blackrock_depths_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
memset(&encounter, 0, sizeof(encounter));
SetBossNumber(MAX_ENCOUNTER);
BarAleCount = 0;
GhostKillCount = 0;
@@ -92,9 +91,6 @@ public:
TombEventCounter = 0;
}
uint32 encounter[MAX_ENCOUNTER];
std::string str_data;
ObjectGuid EmperorGUID;
ObjectGuid PhalanxGUID;
ObjectGuid MagmusGUID;
@@ -210,44 +206,30 @@ public:
switch (type)
{
case TYPE_RING_OF_LAW:
encounter[0] = data;
SetBossState(0, EncounterState(data));
break;
case TYPE_VAULT:
encounter[1] = data;
SetBossState(1, EncounterState(data));
break;
case TYPE_BAR:
if (data == SPECIAL)
++BarAleCount;
else
encounter[2] = data;
SetBossState(2, EncounterState(data));
break;
case TYPE_TOMB_OF_SEVEN:
encounter[3] = data;
SetBossState(3, EncounterState(data));
break;
case TYPE_LYCEUM:
encounter[4] = data;
SetBossState(4, EncounterState(data));
break;
case TYPE_IRON_HALL:
encounter[5] = data;
SetBossState(5, EncounterState(data));
break;
case DATA_GHOSTKILL:
GhostKillCount += data;
break;
}
if (data == DONE || GhostKillCount >= TOMB_OF_SEVEN_BOSS_NUM)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << encounter[0] << ' ' << encounter[1] << ' ' << encounter[2] << ' '
<< encounter[3] << ' ' << encounter[4] << ' ' << encounter[5] << ' ' << GhostKillCount;
str_data = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 type) const override
@@ -255,20 +237,20 @@ public:
switch (type)
{
case TYPE_RING_OF_LAW:
return encounter[0];
return GetBossState(0);
case TYPE_VAULT:
return encounter[1];
return GetBossState(1);
case TYPE_BAR:
if (encounter[2] == IN_PROGRESS && BarAleCount == 3)
if (GetBossState(2) == IN_PROGRESS && BarAleCount == 3)
return SPECIAL;
else
return encounter[2];
return GetBossState(2);
case TYPE_TOMB_OF_SEVEN:
return encounter[3];
return GetBossState(3);
case TYPE_LYCEUM:
return encounter[4];
return GetBossState(4);
case TYPE_IRON_HALL:
return encounter[5];
return GetBossState(5);
case DATA_GHOSTKILL:
return GhostKillCount;
}
@@ -319,36 +301,6 @@ public:
return ObjectGuid::Empty;
}
std::string GetSaveData() override
{
return str_data;
}
void Load(char const* in) override
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> encounter[0] >> encounter[1] >> encounter[2] >> encounter[3]
>> encounter[4] >> encounter[5] >> GhostKillCount;
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (encounter[i] == IN_PROGRESS)
encounter[i] = NOT_STARTED;
if (GhostKillCount > 0 && GhostKillCount < TOMB_OF_SEVEN_BOSS_NUM)
GhostKillCount = 0;//reset tomb of seven event
if (GhostKillCount >= TOMB_OF_SEVEN_BOSS_NUM)
GhostKillCount = TOMB_OF_SEVEN_BOSS_NUM;
OUT_LOAD_INST_DATA_COMPLETE;
}
void TombOfSevenEvent()
{
if (GhostKillCount < TOMB_OF_SEVEN_BOSS_NUM && !TombBossGUIDs[TombEventCounter].IsEmpty())

View File

@@ -172,7 +172,7 @@ class instance_molten_core : public InstanceMapScript
return true;
}
void ReadSaveDataMore(std::istringstream& /*data*/) override
void AfterDataLoad() override
{
if (CheckMajordomoExecutus())
_executusSchedule = true;

View File

@@ -21,7 +21,6 @@
#include "gnomeregan.h"
#include "InstanceScript.h"
#include "Map.h"
#include <sstream>
class instance_gnomeregan : public InstanceMapScript
{

View File

@@ -161,7 +161,7 @@ class instance_scholomance : public InstanceMapScript
instance->SummonCreature(NPC_DARKMASTER_GANDLING, GandlingLoc);
}
void ReadSaveDataMore(std::istringstream& /*data*/) override
void AfterDataLoad() override
{
CheckToSpawnGandling();
}

View File

@@ -30,7 +30,6 @@ EndScriptData */
#include "Map.h"
#include "ScriptedCreature.h"
#include "TemporarySummon.h"
#include <sstream>
#define MAX_ENCOUNTER 4
@@ -84,15 +83,12 @@ public:
instance_shadowfang_keep_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
SetBossNumber(MAX_ENCOUNTER);
uiPhase = 0;
uiTimer = 0;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string str_data;
ObjectGuid uiAshGUID;
ObjectGuid uiAdaGUID;
ObjectGuid uiArchmageArugalGUID;
@@ -120,17 +116,17 @@ public:
{
case GO_COURTYARD_DOOR:
DoorCourtyardGUID = go->GetGUID();
if (m_auiEncounter[0] == DONE)
if (GetBossState(0) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_SORCERER_DOOR:
DoorSorcererGUID = go->GetGUID();
if (m_auiEncounter[2] == DONE)
if (GetBossState(2) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_ARUGAL_DOOR:
DoorArugalGUID = go->GetGUID();
if (m_auiEncounter[3] == DONE)
if (GetBossState(3) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
}
@@ -155,12 +151,12 @@ public:
case TYPE_FREE_NPC:
if (data == DONE)
DoUseDoorOrButton(DoorCourtyardGUID);
m_auiEncounter[0] = data;
SetBossState(0, EncounterState(data));
break;
case TYPE_RETHILGORE:
if (data == DONE)
DoSpeech();
m_auiEncounter[1] = data;
SetBossState(1, EncounterState(data));
break;
case TYPE_FENRUS:
switch (data)
@@ -173,27 +169,14 @@ public:
DoUseDoorOrButton(DoorSorcererGUID);
break;
}
m_auiEncounter[2] = data;
SetBossState(2, EncounterState(data));
break;
case TYPE_NANDOS:
if (data == DONE)
DoUseDoorOrButton(DoorArugalGUID);
m_auiEncounter[3] = data;
SetBossState(3, EncounterState(data));
break;
}
if (data == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' ' << m_auiEncounter[3];
str_data = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
uint32 GetData(uint32 type) const override
@@ -201,44 +184,17 @@ public:
switch (type)
{
case TYPE_FREE_NPC:
return m_auiEncounter[0];
return GetBossState(0);
case TYPE_RETHILGORE:
return m_auiEncounter[1];
return GetBossState(1);
case TYPE_FENRUS:
return m_auiEncounter[2];
return GetBossState(2);
case TYPE_NANDOS:
return m_auiEncounter[3];
return GetBossState(3);
}
return 0;
}
std::string GetSaveData() override
{
return str_data;
}
void Load(char const* in) override
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void Update(uint32 uiDiff) override
{
if (GetData(TYPE_FENRUS) != DONE)

View File

@@ -34,7 +34,6 @@ EndScriptData */
#include "MotionMaster.h"
#include "Player.h"
#include "stratholme.h"
#include <sstream>
enum InstanceEvents
{
@@ -60,9 +59,7 @@ class instance_stratholme : public InstanceMapScript
instance_stratholme_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
EncounterState[i] = NOT_STARTED;
SetBossNumber(MAX_ENCOUNTER);
for (uint8 i = 0; i < 5; ++i)
IsSilverHandDead[i] = false;
@@ -71,7 +68,6 @@ class instance_stratholme : public InstanceMapScript
scarletsKilled = 0;
}
uint32 EncounterState[MAX_ENCOUNTER];
uint8 scarletsKilled;
bool IsSilverHandDead[5];
@@ -126,7 +122,7 @@ class instance_stratholme : public InstanceMapScript
bool StartSlaugtherSquare()
{
//change to DONE when crystals implemented
if (EncounterState[1] == IN_PROGRESS && EncounterState[2] == IN_PROGRESS && EncounterState[3] == IN_PROGRESS)
if (GetBossState(1) == IN_PROGRESS && GetBossState(2) == IN_PROGRESS && GetBossState(3) == IN_PROGRESS)
{
HandleGameObject(portGauntletGUID, true);
HandleGameObject(portSlaugtherGUID, true);
@@ -254,9 +250,9 @@ class instance_stratholme : public InstanceMapScript
switch (data)
{
case IN_PROGRESS:
if (EncounterState[0] == IN_PROGRESS || EncounterState[0] == FAIL)
if (GetBossState(0) == IN_PROGRESS || GetBossState(0) == FAIL)
break;
EncounterState[0] = data;
SetBossState(0, EncounterState(data));
events.ScheduleEvent(EVENT_BARON_RUN, 45min);
TC_LOG_DEBUG("scripts", "Instance Stratholme: Baron run in progress.");
break;
@@ -264,10 +260,10 @@ class instance_stratholme : public InstanceMapScript
DoRemoveAurasDueToSpellOnPlayers(SPELL_BARON_ULTIMATUM);
if (Creature* ysida = instance->GetCreature(ysidaGUID))
ysida->CastSpell(ysida, SPELL_PERM_FEIGN_DEATH, true);
EncounterState[0] = data;
SetBossState(0, EncounterState(data));
break;
case DONE:
EncounterState[0] = data;
SetBossState(0, EncounterState(data));
if (Creature* ysida = instance->GetCreature(ysidaGUID))
{
@@ -303,7 +299,7 @@ class instance_stratholme : public InstanceMapScript
}
break;
case TYPE_BARONESS:
EncounterState[1] = data;
SetBossState(1, EncounterState(data));
if (data == IN_PROGRESS)
{
HandleGameObject(ziggurat1GUID, true);
@@ -312,7 +308,7 @@ class instance_stratholme : public InstanceMapScript
}
break;
case TYPE_NERUB:
EncounterState[2] = data;
SetBossState(2, EncounterState(data));
if (data == IN_PROGRESS)
{
HandleGameObject(ziggurat2GUID, true);
@@ -321,7 +317,7 @@ class instance_stratholme : public InstanceMapScript
}
break;
case TYPE_PALLID:
EncounterState[3] = data;
SetBossState(3, EncounterState(data));
if (data == IN_PROGRESS)
{
HandleGameObject(ziggurat3GUID, true);
@@ -362,7 +358,7 @@ class instance_stratholme : public InstanceMapScript
events.ScheduleEvent(EVENT_SLAUGHTER_SQUARE, 1min);
TC_LOG_DEBUG("scripts", "Instance Stratholme: Slaugther event will continue in 1 minute.");
}
EncounterState[4] = data;
SetBossState(4, EncounterState(data));
break;
case TYPE_BARON:
if (data == IN_PROGRESS)
@@ -383,7 +379,7 @@ class instance_stratholme : public InstanceMapScript
SetData(TYPE_BARON_RUN, DONE);
}
EncounterState[5] = data;
SetBossState(5, EncounterState(data));
break;
case TYPE_SH_AELMAR:
IsSilverHandDead[0] = (data) ? true : false;
@@ -401,46 +397,6 @@ class instance_stratholme : public InstanceMapScript
IsSilverHandDead[4] = (data) ? true : false;
break;
}
if (data == DONE)
SaveToDB();
}
std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << EncounterState[0] << ' ' << EncounterState[1] << ' ' << EncounterState[2] << ' '
<< EncounterState[3] << ' ' << EncounterState[4] << ' ' << EncounterState[5];
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(char const* in) override
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> EncounterState[0] >> EncounterState[1] >> EncounterState[2] >> EncounterState[3]
>> EncounterState[4] >> EncounterState[5];
// Do not reset 1, 2 and 3. they are not set to done, yet .
if (EncounterState[0] == IN_PROGRESS)
EncounterState[0] = NOT_STARTED;
if (EncounterState[4] == IN_PROGRESS)
EncounterState[4] = NOT_STARTED;
if (EncounterState[5] == IN_PROGRESS)
EncounterState[5] = NOT_STARTED;
OUT_LOAD_INST_DATA_COMPLETE;
}
uint32 GetData(uint32 type) const override
@@ -452,17 +408,17 @@ class instance_stratholme : public InstanceMapScript
return 1;
return 0;
case TYPE_BARON_RUN:
return EncounterState[0];
return GetBossState(0);
case TYPE_BARONESS:
return EncounterState[1];
return GetBossState(1);
case TYPE_NERUB:
return EncounterState[2];
return GetBossState(2);
case TYPE_PALLID:
return EncounterState[3];
return GetBossState(3);
case TYPE_RAMSTEIN:
return EncounterState[4];
return GetBossState(4);
case TYPE_BARON:
return EncounterState[5];
return GetBossState(5);
}
return 0;
}

View File

@@ -32,7 +32,6 @@ EndScriptData */
#include "MotionMaster.h"
#include "ObjectAccessor.h"
#include "uldaman.h"
#include <sstream>
enum Spells
{
@@ -64,21 +63,12 @@ class instance_uldaman : public InstanceMapScript
instance_uldaman_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
SetBossNumber(MAX_ENCOUNTER);
ironayaSealDoorTimer = 27000; //animation time
keystoneCheck = false;
}
bool IsEncounterInProgress() const override
{
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] == IN_PROGRESS)
return true;
return false;
}
ObjectGuid archaedasGUID;
ObjectGuid ironayaGUID;
ObjectGuid whoWokeuiArchaedasGUID;
@@ -99,9 +89,6 @@ class instance_uldaman : public InstanceMapScript
GuidVector earthenGuardians;
GuidVector archaedasWallMinions; // minions lined up around the wall
uint32 m_auiEncounter[MAX_ENCOUNTER];
std::string str_data;
void OnGameObjectCreate(GameObject* go) override
{
switch (go->GetEntry())
@@ -109,14 +96,14 @@ class instance_uldaman : public InstanceMapScript
case GO_ALTAR_OF_THE_KEEPER_TEMPLE_DOOR: // lock the door
altarOfTheKeeperTempleDoor = go->GetGUID();
if (m_auiEncounter[0] == DONE)
if (GetBossState(0) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_ARCHAEDAS_TEMPLE_DOOR:
archaedasTempleDoor = go->GetGUID();
if (m_auiEncounter[0] == DONE)
if (GetBossState(0) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
@@ -125,21 +112,21 @@ class instance_uldaman : public InstanceMapScript
go->ReplaceAllFlags(GO_FLAG_IN_USE | GO_FLAG_NODESPAWN);
ancientVaultDoor = go->GetGUID();
if (m_auiEncounter[1] == DONE)
if (GetBossState(1) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_IRONAYA_SEAL_DOOR:
ironayaSealDoor = go->GetGUID();
if (m_auiEncounter[2] == DONE)
if (GetBossState(2) == DONE)
HandleGameObject(ObjectGuid::Empty, true, go);
break;
case GO_KEYSTONE:
keystoneGUID = go->GetGUID();
if (m_auiEncounter[2] == DONE)
if (GetBossState(2) == DONE)
{
HandleGameObject(ObjectGuid::Empty, true, go);
go->SetFlag(GO_FLAG_INTERACT_COND);
@@ -345,13 +332,13 @@ class instance_uldaman : public InstanceMapScript
switch (type)
{
case DATA_ALTAR_DOORS:
m_auiEncounter[0] = data;
SetBossState(0, EncounterState(data));
if (data == DONE)
SetDoor(altarOfTheKeeperTempleDoor, true);
break;
case DATA_ANCIENT_DOOR:
m_auiEncounter[1] = data;
SetBossState(1, EncounterState(data));
if (data == DONE) //archeadas defeat
{
SetDoor(archaedasTempleDoor, true); //re open enter door
@@ -360,7 +347,7 @@ class instance_uldaman : public InstanceMapScript
break;
case DATA_IRONAYA_DOOR:
m_auiEncounter[2] = data;
SetBossState(2, EncounterState(data));
break;
case DATA_STONE_KEEPERS:
@@ -371,7 +358,7 @@ class instance_uldaman : public InstanceMapScript
switch (data)
{
case NOT_STARTED:
if (m_auiEncounter[0] == DONE) //if players opened the doors
if (GetBossState(0) == DONE) //if players opened the doors
SetDoor(archaedasTempleDoor, true);
RespawnMinions();
@@ -391,19 +378,6 @@ class instance_uldaman : public InstanceMapScript
keystoneCheck = true;
break;
}
if (data == DONE)
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2];
str_data = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
}
}
void SetGuidData(uint32 type, ObjectGuid data) override
@@ -416,33 +390,6 @@ class instance_uldaman : public InstanceMapScript
}
}
std::string GetSaveData() override
{
return str_data;
}
void Load(char const* in) override
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
{
if (m_auiEncounter[i] == IN_PROGRESS)
m_auiEncounter[i] = NOT_STARTED;
}
OUT_LOAD_INST_DATA_COMPLETE;
}
void OnCreatureCreate(Creature* creature) override
{
switch (creature->GetEntry())
@@ -467,7 +414,7 @@ class instance_uldaman : public InstanceMapScript
case 7228: // Ironaya
ironayaGUID = creature->GetGUID();
if (m_auiEncounter[2] != DONE)
if (GetBossState(2) != DONE)
SetFrozenState (creature);
break;

View File

@@ -22,7 +22,6 @@
#include "Map.h"
#include "ScriptedCreature.h"
#include "zulaman.h"
#include <sstream>
class instance_zulaman : public InstanceMapScript
{
@@ -31,7 +30,8 @@ class instance_zulaman : public InstanceMapScript
struct instance_zulaman_InstanceScript : public InstanceScript
{
instance_zulaman_InstanceScript(InstanceMap* map) : InstanceScript(map)
instance_zulaman_InstanceScript(InstanceMap* map) : InstanceScript(map),
ZulAmanState(*this, "TimedRunState", NOT_STARTED)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
@@ -146,7 +146,6 @@ class instance_zulaman : public InstanceMapScript
events.ScheduleEvent(EVENT_UPDATE_ZULAMAN_TIMER, 1min);
SpeedRunTimer = 15;
ZulAmanState = data;
SaveToDB();
}
break;
}
@@ -240,7 +239,6 @@ class instance_zulaman : public InstanceMapScript
switch (eventId)
{
case EVENT_UPDATE_ZULAMAN_TIMER:
SaveToDB();
DoUpdateWorldState(WORLD_STATE_ZULAMAN_TIMER, --SpeedRunTimer);
if (SpeedRunTimer)
events.ScheduleEvent(EVENT_UPDATE_ZULAMAN_TIMER, 1min);
@@ -257,24 +255,13 @@ class instance_zulaman : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << ZulAmanState << ' '
<< SpeedRunTimer << ' '
<< ZulAmanBossCount;
}
void ReadSaveDataMore(std::istringstream& data) override
{
data >> ZulAmanState;
data >> SpeedRunTimer;
data >> ZulAmanBossCount;
if (ZulAmanState == IN_PROGRESS && SpeedRunTimer && SpeedRunTimer <= 15)
// Speed run cannot be resumed after reset/crash
if (ZulAmanState != NOT_STARTED)
{
events.ScheduleEvent(EVENT_UPDATE_ZULAMAN_TIMER, 1min);
DoUpdateWorldState(WORLD_STATE_ZULAMAN_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ZULAMAN_TIMER, SpeedRunTimer);
SpeedRunTimer = 0;
ZulAmanState.LoadValue(FAIL);
}
}
@@ -291,7 +278,7 @@ class instance_zulaman : public InstanceMapScript
ObjectGuid StrangeGongGUID;
ObjectGuid MasiveGateGUID;
uint32 SpeedRunTimer;
uint32 ZulAmanState;
PersistentInstanceScriptValue<uint32> ZulAmanState;
uint32 ZulAmanBossCount;
};

View File

@@ -30,7 +30,6 @@ EndScriptData */
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
#include <sstream>
/* Battle of Mount Hyjal encounters:
0 - Rage Winterchill event
@@ -157,12 +156,10 @@ public:
case DATA_ALLIANCE_RETREAT:
allianceRetreat = data;
HandleGameObject(HordeGate, true);
SaveToDB();
break;
case DATA_HORDE_RETREAT:
hordeRetreat = data;
HandleGameObject(ElfGate, true);
SaveToDB();
break;
case DATA_RAIDDAMAGE:
RaidDamage += data;
@@ -206,16 +203,6 @@ public:
return true;
}
void ReadSaveDataMore(std::istringstream& loadStream) override
{
loadStream >> allianceRetreat >> hordeRetreat >> RaidDamage;
}
void WriteSaveDataMore(std::ostringstream& saveStream) override
{
saveStream << allianceRetreat << ' ' << hordeRetreat << ' ' << RaidDamage;
}
uint32 GetData(uint32 type) const override
{
switch (type)
@@ -228,6 +215,14 @@ public:
return 0;
}
void AfterDataLoad() override
{
if (GetBossState(DATA_ANETHERON) == DONE)
allianceRetreat = 1;
if (GetBossState(DATA_AZGALOR) == DONE)
hordeRetreat = 1;
}
protected:
GuidList m_uiAncientGemGUID;
ObjectGuid HordeGate;

View File

@@ -265,7 +265,11 @@ class instance_culling_of_stratholme : public InstanceMapScript
struct instance_culling_of_stratholme_InstanceMapScript : public InstanceScript
{
instance_culling_of_stratholme_InstanceMapScript(InstanceMap* map) : InstanceScript(map), _currentState(JUST_STARTED), _infiniteGuardianTimeout(0), _waveCount(0), _currentSpawnLoc(0)
instance_culling_of_stratholme_InstanceMapScript(InstanceMap* map) : InstanceScript(map),
_currentState(*this, "currentState", JUST_STARTED),
_infiniteGuardianTimeout(*this, "infiniteGuardianTimeout", 0),
_waveCount(0),
_currentSpawnLoc(0)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
@@ -275,30 +279,16 @@ class instance_culling_of_stratholme : public InstanceMapScript
_plagueCrates.reserve(NUM_PLAGUE_CRATES);
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << _currentState << ' ' << _infiniteGuardianTimeout;
}
void ReadSaveDataMore(std::istringstream& data) override
{
// read current instance progress from save data, then regress to the previous stable state
uint32 state = JUST_STARTED;
time_t infiniteGuardianTime = 0;
data >> state;
data >> infiniteGuardianTime; // UNIX timestamp
COSProgressStates loadState = GetStableStateFor(COSProgressStates(state));
COSProgressStates loadState = GetStableStateFor(_currentState);
SetInstanceProgress(loadState, true);
if (infiniteGuardianTime)
{
_infiniteGuardianTimeout = infiniteGuardianTime;
if (_infiniteGuardianTimeout)
events.ScheduleEvent(EVENT_GUARDIAN_TICK, 0s);
}
time_t timediff = (infiniteGuardianTime - GameTime::GetGameTime());
if (!infiniteGuardianTime)
time_t timediff = (_infiniteGuardianTimeout - GameTime::GetGameTime());
if (!_infiniteGuardianTimeout)
timediff = -1;
TC_LOG_DEBUG("scripts.cos", "instance_culling_of_stratholme::ReadSaveDataMore: Loaded with state %u and guardian timeout at %zu minutes %zu seconds from now", (uint32)loadState, timediff / MINUTE, timediff % MINUTE);
@@ -752,8 +742,6 @@ class instance_culling_of_stratholme : public InstanceMapScript
SpawnInfiniteCorruptor();
events.RescheduleEvent(EVENT_RESPAWN_ARTHAS, 1s);
}
SaveToDB();
}
private:
@@ -791,9 +779,9 @@ class instance_culling_of_stratholme : public InstanceMapScript
}
EventMap events;
COSProgressStates _currentState;
PersistentInstanceScriptValue<COSProgressStates> _currentState;
std::unordered_map<uint32, uint32> _currentWorldStates;
time_t _infiniteGuardianTimeout;
PersistentInstanceScriptValue<time_t> _infiniteGuardianTimeout;
// Generic
ObjectGuid _chromieGUID;

View File

@@ -167,7 +167,7 @@ public:
return ObjectGuid::Empty;
}
void ReadSaveDataMore(std::istringstream&) override
void AfterDataLoad() override
{
if (GetBossState(DATA_LIEUTENANT_DRAKE) == DONE)
mBarrelCount = 5;

View File

@@ -22,7 +22,6 @@
#include "halls_of_origination.h"
#include "InstanceScript.h"
#include "Map.h"
#include <sstream>
DoorData const doorData[] =
{
@@ -201,16 +200,10 @@ class instance_halls_of_origination : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << _deadElementals;
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 deadElementals;
data >> deadElementals;
IncreaseDeadElementals(deadElementals);
if (GetBossState(BOSS_ANRAPHET) == DONE)
IncreaseDeadElementals(4);
}
protected:

View File

@@ -28,7 +28,6 @@ EndScriptData */
#include "Log.h"
#include "Map.h"
#include "wailing_caverns.h"
#include <sstream>
#define MAX_ENCOUNTER 9
@@ -47,13 +46,11 @@ public:
instance_wailing_caverns_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
{
SetHeaders(DataHeader);
memset(&m_auiEncounter, 0, sizeof(m_auiEncounter));
SetBossNumber(MAX_ENCOUNTER);
yelled = false;
}
uint32 m_auiEncounter[MAX_ENCOUNTER];
bool yelled;
ObjectGuid NaralexGUID;
@@ -67,33 +64,32 @@ public:
{
switch (type)
{
case TYPE_LORD_COBRAHN: m_auiEncounter[0] = data;break;
case TYPE_LORD_PYTHAS: m_auiEncounter[1] = data;break;
case TYPE_LADY_ANACONDRA: m_auiEncounter[2] = data;break;
case TYPE_LORD_SERPENTIS: m_auiEncounter[3] = data;break;
case TYPE_NARALEX_EVENT: m_auiEncounter[4] = data;break;
case TYPE_NARALEX_PART1: m_auiEncounter[5] = data;break;
case TYPE_NARALEX_PART2: m_auiEncounter[6] = data;break;
case TYPE_NARALEX_PART3: m_auiEncounter[7] = data;break;
case TYPE_MUTANUS_THE_DEVOURER: m_auiEncounter[8] = data;break;
case TYPE_LORD_COBRAHN: SetBossState(0, EncounterState(data));break;
case TYPE_LORD_PYTHAS: SetBossState(1, EncounterState(data));break;
case TYPE_LADY_ANACONDRA: SetBossState(2, EncounterState(data));break;
case TYPE_LORD_SERPENTIS: SetBossState(3, EncounterState(data));break;
case TYPE_NARALEX_EVENT: SetBossState(4, EncounterState(data));break;
case TYPE_NARALEX_PART1: SetBossState(5, EncounterState(data));break;
case TYPE_NARALEX_PART2: SetBossState(6, EncounterState(data));break;
case TYPE_NARALEX_PART3: SetBossState(7, EncounterState(data));break;
case TYPE_MUTANUS_THE_DEVOURER: SetBossState(8, EncounterState(data));break;
case TYPE_NARALEX_YELLED: yelled = true; break;
}
if (data == DONE)SaveToDB();
}
uint32 GetData(uint32 type) const override
{
switch (type)
{
case TYPE_LORD_COBRAHN: return m_auiEncounter[0];
case TYPE_LORD_PYTHAS: return m_auiEncounter[1];
case TYPE_LADY_ANACONDRA: return m_auiEncounter[2];
case TYPE_LORD_SERPENTIS: return m_auiEncounter[3];
case TYPE_NARALEX_EVENT: return m_auiEncounter[4];
case TYPE_NARALEX_PART1: return m_auiEncounter[5];
case TYPE_NARALEX_PART2: return m_auiEncounter[6];
case TYPE_NARALEX_PART3: return m_auiEncounter[7];
case TYPE_MUTANUS_THE_DEVOURER: return m_auiEncounter[8];
case TYPE_LORD_COBRAHN: return GetBossState(0);
case TYPE_LORD_PYTHAS: return GetBossState(1);
case TYPE_LADY_ANACONDRA: return GetBossState(2);
case TYPE_LORD_SERPENTIS: return GetBossState(3);
case TYPE_NARALEX_EVENT: return GetBossState(4);
case TYPE_NARALEX_PART1: return GetBossState(5);
case TYPE_NARALEX_PART2: return GetBossState(6);
case TYPE_NARALEX_PART3: return GetBossState(7);
case TYPE_MUTANUS_THE_DEVOURER: return GetBossState(8);
case TYPE_NARALEX_YELLED: return yelled;
}
return 0;
@@ -104,41 +100,6 @@ public:
if (data == DATA_NARALEX)return NaralexGUID;
return ObjectGuid::Empty;
}
std::string GetSaveData() override
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
saveStream << m_auiEncounter[0] << ' ' << m_auiEncounter[1] << ' ' << m_auiEncounter[2] << ' '
<< m_auiEncounter[3] << ' ' << m_auiEncounter[4] << ' ' << m_auiEncounter[5] << ' '
<< m_auiEncounter[6] << ' ' << m_auiEncounter[7] << ' ' << m_auiEncounter[8];
OUT_SAVE_INST_DATA_COMPLETE;
return saveStream.str();
}
void Load(char const* in) override
{
if (!in)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(in);
std::istringstream loadStream(in);
loadStream >> m_auiEncounter[0] >> m_auiEncounter[1] >> m_auiEncounter[2] >> m_auiEncounter[3]
>> m_auiEncounter[4] >> m_auiEncounter[5] >> m_auiEncounter[6] >> m_auiEncounter[7] >> m_auiEncounter[8];
for (uint8 i = 0; i < MAX_ENCOUNTER; ++i)
if (m_auiEncounter[i] != DONE)
m_auiEncounter[i] = NOT_STARTED;
OUT_LOAD_INST_DATA_COMPLETE;
}
};
};

View File

@@ -21,7 +21,6 @@
#include "InstanceScript.h"
#include "Map.h"
#include "ScriptMgr.h"
#include <sstream>
DoorData const doorData[] =
{
@@ -128,15 +127,13 @@ class instance_ahnkahet : public InstanceMapScript
return 0;
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << SpheresState[0] << ' ' << SpheresState[1];
}
void ReadSaveDataMore(std::istringstream& data) override
{
data >> SpheresState[0];
data >> SpheresState[1];
if (GetBossState(DATA_PRINCE_TALDARAM) == DONE)
{
SpheresState[0] = IN_PROGRESS;
SpheresState[1] = IN_PROGRESS;
}
}
protected:

View File

@@ -30,7 +30,6 @@ EndScriptData */
#include "MotionMaster.h"
#include "Player.h"
#include "trial_of_the_champion.h"
#include <sstream>
constexpr uint32 ToCEncounterCount = 4;
@@ -46,12 +45,11 @@ public:
struct instance_trial_of_the_champion_InstanceMapScript : public InstanceScript
{
instance_trial_of_the_champion_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
instance_trial_of_the_champion_InstanceMapScript(InstanceMap* map) : InstanceScript(map),
uiMovementDone(*this, "uiMovementDone"), uiGrandChampionsDeaths(*this, "uiGrandChampionsDeaths")
{
SetHeaders(DataHeader);
SetBossNumber(ToCEncounterCount);
uiMovementDone = 0;
uiGrandChampionsDeaths = 0;
uiArgentSoldierDeaths = 0;
teamInInstance = 0;
@@ -59,8 +57,8 @@ public:
}
uint32 teamInInstance;
uint16 uiMovementDone;
uint16 uiGrandChampionsDeaths;
PersistentInstanceScriptValue<uint16> uiMovementDone;
PersistentInstanceScriptValue<uint16> uiGrandChampionsDeaths;
uint8 uiArgentSoldierDeaths;
ObjectGuid uiAnnouncerGUID;
@@ -165,7 +163,7 @@ public:
}
else if (state == DONE)
{
++uiGrandChampionsDeaths;
uiGrandChampionsDeaths = uiGrandChampionsDeaths + 1;
if (uiGrandChampionsDeaths == 3)
{
if (Creature* pAnnouncer = instance->GetCreature(uiAnnouncerGUID))
@@ -227,10 +225,10 @@ public:
}
}
break;
case BOSS_BLACK_KNIGHT:
SetBossState(BOSS_BLACK_KNIGHT, EncounterState(uiData));
break;
}
if (uiData == DONE)
SaveToDB();
}
uint32 GetData(uint32 uiData) const override
@@ -274,16 +272,6 @@ public:
break;
}
}
void WriteSaveDataMore(std::ostringstream& stream) override
{
stream << uiGrandChampionsDeaths << ' ' << uiMovementDone;
}
void ReadSaveDataMore(std::istringstream& stream) override
{
stream >> uiGrandChampionsDeaths >> uiMovementDone;
}
};
};

View File

@@ -21,7 +21,7 @@
#include "CreatureAIImpl.h"
#define ToCScriptName "instance_trial_of_the_champion"
#define DataHeader "TC"
#define DataHeader "TCv0.1"
enum TCData
{

View File

@@ -25,7 +25,6 @@
#include "ScriptedCreature.h"
#include "TemporarySummon.h"
#include "trial_of_the_crusader.h"
#include <sstream>
// ToDo: Remove magic numbers of events
@@ -107,7 +106,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
LoadBossBoundaries(boundaries);
LoadObjectData(creatureData, gameObjectData);
LoadDoorData(doorData);
TrialCounter = 50;
EventStage = 0;
NorthrendBeasts = NOT_STARTED;
NorthrendBeastsCount = 4;
@@ -118,7 +116,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
SnoboldCount = 0;
MistressOfPainCount = 0;
PlayerDeathCount = 0;
NeedSave = false;
CrusadersSpecialState = false;
TributeToDedicatedInsanity = false; // NYI, set to true when implement it
DoUpdateWorldState(UPDATE_STATE_UI_SHOW, instance->IsHeroic() ? 1 : 0);
@@ -140,15 +137,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
snoboldGUIDS.push_back(creature->GetGUID());
}
// Summon prevention to heroic modes
uint32 GetCreatureEntry(ObjectGuid::LowType /*guidLow*/, CreatureData const* data) override
{
if (!TrialCounter)
return 0;
return data->id;
}
void OnGameObjectCreate(GameObject* go) override
{
InstanceScript::OnGameObjectCreate(go);
@@ -241,46 +229,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
case DONE:
{
EventStage = 6000;
uint32 tributeChest = 0;
if (instance->GetDifficultyID() == DIFFICULTY_10_HC)
{
if (TrialCounter >= 50)
tributeChest = GO_TRIBUTE_CHEST_10H_99;
else
{
if (TrialCounter >= 45)
tributeChest = GO_TRIBUTE_CHEST_10H_50;
else
{
if (TrialCounter >= 25)
tributeChest = GO_TRIBUTE_CHEST_10H_45;
else
tributeChest = GO_TRIBUTE_CHEST_10H_25;
}
}
}
else if (instance->GetDifficultyID() == DIFFICULTY_25_HC)
{
if (TrialCounter >= 50)
tributeChest = GO_TRIBUTE_CHEST_25H_99;
else
{
if (TrialCounter >= 45)
tributeChest = GO_TRIBUTE_CHEST_25H_50;
else
{
if (TrialCounter >= 25)
tributeChest = GO_TRIBUTE_CHEST_25H_45;
else
tributeChest = GO_TRIBUTE_CHEST_25H_25;
}
}
}
if (tributeChest)
if (Creature* tirion = GetCreature(DATA_FORDRING))
if (GameObject* chest = tirion->SummonGameObject(tributeChest, 805.62f, 134.87f, 142.16f, 3.27f, QuaternionData::fromEulerAnglesZYX(3.27f, 0.0f, 0.0f), 7_days))
chest->SetRespawnTime(chest->GetRespawnDelay());
break;
}
default:
@@ -296,26 +244,9 @@ class instance_trial_of_the_crusader : public InstanceMapScript
TC_LOG_DEBUG("scripts", "[ToCr] BossState(type %u) %u = state %u;", type, GetBossState(type), state);
if (state == FAIL)
{
if (instance->IsHeroic())
{
--TrialCounter;
// decrease attempt counter at wipe
DoUpdateWorldState(UPDATE_STATE_UI_COUNT, TrialCounter);
// if theres no more attemps allowed
if (!TrialCounter)
{
if (Creature* anubarak = GetCreature(DATA_ANUBARAK))
anubarak->DespawnOrUnsummon();
}
}
NeedSave = true;
EventStage = (type == DATA_NORTHREND_BEASTS ? 666 : 0);
state = NOT_STARTED;
}
if (state == DONE || NeedSave)
Save();
}
return true;
}
@@ -354,10 +285,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
{
switch (type)
{
case TYPE_COUNTER:
TrialCounter = data;
data = DONE;
break;
case TYPE_EVENT:
EventStage = data;
data = NOT_STARTED;
@@ -440,10 +367,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
{
switch (type)
{
case DATA_TEAM:
return Team;
case TYPE_COUNTER:
return TrialCounter;
case TYPE_EVENT:
return EventStage;
case TYPE_NORTHREND_BEASTS:
@@ -563,60 +486,6 @@ class instance_trial_of_the_crusader : public InstanceMapScript
}
}
void Save()
{
OUT_SAVE_INST_DATA;
std::ostringstream saveStream;
for (uint8 i = 0; i < EncounterCount; ++i)
saveStream << GetBossState(i) << ' ';
saveStream << TrialCounter << ' '
<< PlayerDeathCount << ' '
<< uint32(TributeToDedicatedInsanity ? 1 : 0);
SaveDataBuffer = saveStream.str();
SaveToDB();
OUT_SAVE_INST_DATA_COMPLETE;
NeedSave = false;
}
std::string GetSaveData() override
{
return SaveDataBuffer;
}
void Load(char const* strIn) override
{
if (!strIn)
{
OUT_LOAD_INST_DATA_FAIL;
return;
}
OUT_LOAD_INST_DATA(strIn);
std::istringstream loadStream(strIn);
uint32 tmpState;
for (uint8 i = 0; i < EncounterCount; ++i)
{
loadStream >> tmpState;
if (tmpState == IN_PROGRESS || tmpState > SPECIAL)
tmpState = NOT_STARTED;
SetBossState(i, EncounterState(tmpState));
}
loadStream >> TrialCounter;
loadStream >> PlayerDeathCount;
loadStream >> tmpState;
TributeToDedicatedInsanity = tmpState != 0;
EventStage = 0;
OUT_LOAD_INST_DATA_COMPLETE;
}
bool CheckAchievementCriteriaMeet(uint32 criteria_id, Player const* /*source*/, Unit const* /*target*/, uint32 /*miscvalue1*/) override
{
switch (criteria_id)
@@ -633,7 +502,7 @@ class instance_trial_of_the_crusader : public InstanceMapScript
case THREE_SIXTY_PAIN_SPIKE_25_PLAYER_HEROIC:
return MistressOfPainCount >= 2;
case A_TRIBUTE_TO_DEDICATED_INSANITY:
return false/*TrialCounter == 50 && TributeToDedicatedInsanity*/;
return false; // no longer obtainable
default:
break;
}
@@ -642,14 +511,11 @@ class instance_trial_of_the_crusader : public InstanceMapScript
}
protected:
uint32 TrialCounter;
uint32 EventStage;
uint32 EventTimer;
uint32 NorthrendBeasts;
uint32 Team;
bool NeedSave;
bool CrusadersSpecialState;
std::string SaveDataBuffer;
GuidVector snoboldGUIDS;
// Achievement stuff

View File

@@ -24,7 +24,6 @@
#include "ScriptMgr.h"
#include "TemporarySummon.h"
#include "Transport.h"
#include <sstream>
Position const JainaSpawnPos = { 5236.659f, 1929.894f, 707.7781f, 0.8726646f }; // Jaina Spawn Position
Position const SylvanasSpawnPos = { 5236.667f, 1929.906f, 707.7781f, 0.8377581f }; // Sylvanas Spawn Position (sniffed)
@@ -457,8 +456,6 @@ class instance_halls_of_reflection : public InstanceMapScript
default:
break;
}
SaveToDB();
}
void SetGuidData(uint32 type, ObjectGuid data) override
@@ -728,31 +725,16 @@ class instance_halls_of_reflection : public InstanceMapScript
return ObjectGuid::Empty;
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << _introState << ' ' << _frostswornGeneralState << ' ' << _quelDelarState;
}
if (GetBossState(DATA_FALRIC) == DONE)
{
_introState = DONE;
_quelDelarState = DONE;
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 temp = 0;
data >> temp;
if (temp == DONE)
SetData(DATA_INTRO_EVENT, DONE);
else
SetData(DATA_INTRO_EVENT, NOT_STARTED);
data >> temp;
if (temp == DONE)
SetData(DATA_FROSTSWORN_GENERAL, DONE);
else
SetData(DATA_FROSTSWORN_GENERAL, NOT_STARTED);
data >> temp;
if (temp == DONE)
SetData(DATA_QUEL_DELAR_EVENT, DONE);
else
SetData(DATA_QUEL_DELAR_EVENT, NOT_STARTED);
if (GetBossState(DATA_THE_LICH_KING_ESCAPE) == DONE)
_frostswornGeneralState = DONE;
}
private:

View File

@@ -23,7 +23,6 @@
#include "gundrak.h"
#include "Map.h"
#include "ScriptMgr.h"
#include <sstream>
DoorData const doorData[] =
{
@@ -242,25 +241,14 @@ class instance_gundrak : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << uint32(SladRanStatueState) << ' ';
data << uint32(DrakkariColossusStatueState) << ' ';
data << uint32(MoorabiStatueState) << ' ';
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 temp;
data >> temp;
SladRanStatueState = GOState(temp);
data >> temp;
DrakkariColossusStatueState = GOState(temp);
data >> temp;
MoorabiStatueState = GOState(temp);
if (GetBossState(DATA_SLAD_RAN) == DONE)
SladRanStatueState = GO_STATE_DESTROYED;
if (GetBossState(DATA_DRAKKARI_COLOSSUS) == DONE)
DrakkariColossusStatueState = GO_STATE_DESTROYED;
if (GetBossState(DATA_MOORABI) == DONE)
MoorabiStatueState = GO_STATE_DESTROYED;
if (IsBridgeReady())
Events.ScheduleEvent(DATA_BRIDGE, TIMER_STATUE_ACTIVATION);
@@ -314,7 +302,6 @@ class instance_gundrak : public InstanceMapScript
ToggleGameObject(type, GO_STATE_DESTROYED);
ToggleGameObject(DATA_TRAPDOOR, GO_STATE_READY);
ToggleGameObject(DATA_COLLISION, GO_STATE_ACTIVE);
SaveToDB();
return;
default:
return;
@@ -329,8 +316,6 @@ class instance_gundrak : public InstanceMapScript
if (IsBridgeReady())
Events.ScheduleEvent(DATA_BRIDGE, TIMER_STATUE_ACTIVATION);
SaveToDB();
}
}

View File

@@ -69,7 +69,6 @@ enum Spells
SPELL_TWILIGHT_BLOODBOLT = 71446,
SPELL_INCITE_TERROR = 73070,
SPELL_BLOODBOLT_WHIRL = 71772,
SPELL_ANNIHILATE = 71322,
SPELL_CLEAR_ALL_STATUS_AILMENTS = 70939,
// Blood Infusion
@@ -125,12 +124,10 @@ enum Points
POINT_CENTER = 1,
POINT_AIR = 2,
POINT_GROUND = 3,
POINT_MINCHAR = 4,
};
Position const centerPos = {4595.7090f, 2769.4190f, 400.6368f, 0.000000f};
Position const airPos = {4595.7090f, 2769.4190f, 422.3893f, 0.000000f};
Position const mincharPos = {4629.3711f, 2782.6089f, 424.6390f, 0.000000f};
bool IsVampire(Unit const* unit)
{
@@ -150,8 +147,6 @@ struct boss_blood_queen_lana_thel : public BossAI
void Initialize()
{
_offtankGUID.Clear();
_creditBloodQuickening = false;
_killMinchar = false;
}
void Reset() override
@@ -188,7 +183,6 @@ struct boss_blood_queen_lana_thel : public BossAI
DoCast(me, SPELL_SHROUD_OF_SORROW, true);
DoCast(me, SPELL_FRENZIED_BLOODTHIRST_VISUAL, true);
DoCastSelf(SPELL_CLEAR_ALL_STATUS_AILMENTS, true);
_creditBloodQuickening = instance->GetData(DATA_BLOOD_QUICKENING_STATE) == IN_PROGRESS;
}
void JustDied(Unit* /*killer*/) override
@@ -200,22 +194,6 @@ struct boss_blood_queen_lana_thel : public BossAI
DoCastAOE(SPELL_BLOOD_INFUSION_CREDIT, true);
CleanAuras();
// Blah, credit the quest
if (_creditBloodQuickening)
{
instance->SetData(DATA_BLOOD_QUICKENING_STATE, DONE);
if (Player* player = me->GetLootRecipient())
player->RewardPlayerAndGroupAtEvent(Is25ManRaid() ? NPC_INFILTRATOR_MINCHAR_BQ_25 : NPC_INFILTRATOR_MINCHAR_BQ, player);
if (Creature* minchar = me->FindNearestCreature(NPC_INFILTRATOR_MINCHAR_BQ, 200.0f))
{
minchar->SetEmoteState(EMOTE_ONESHOT_NONE);
minchar->SetAnimTier(AnimTier::Ground);
minchar->SetCanFly(false);
minchar->RemoveAllAuras();
minchar->GetMotionMaster()->MoveCharge(4629.3711f, 2782.6089f, 401.5301f, SPEED_CHARGE / 3.0f);
}
}
}
void CleanAuras()
@@ -232,38 +210,15 @@ struct boss_blood_queen_lana_thel : public BossAI
instance->DoRemoveAurasDueToSpellOnPlayers(PRESENCE_OF_THE_DARKFALLEN);
}
void DoAction(int32 action) override
{
if (action != ACTION_KILL_MINCHAR)
return;
if (instance->GetBossState(DATA_BLOOD_QUEEN_LANA_THEL) == IN_PROGRESS)
_killMinchar = true;
else
{
me->SetDisableGravity(true);
me->GetMotionMaster()->MovePoint(POINT_MINCHAR, mincharPos);
}
}
void EnterEvadeMode(EvadeReason why) override
{
if (!_EnterEvadeMode(why))
return;
CleanAuras();
if (_killMinchar)
{
_killMinchar = false;
me->SetDisableGravity(true);
me->GetMotionMaster()->MovePoint(POINT_MINCHAR, mincharPos);
}
else
{
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
me->AddUnitState(UNIT_STATE_EVADE);
me->GetMotionMaster()->MoveTargetedHome();
Reset();
}
void JustReachedHome() override
@@ -323,12 +278,6 @@ struct boss_blood_queen_lana_thel : public BossAI
AttackStart(victim);
events.ScheduleEvent(EVENT_BLOOD_MIRROR, 2500ms, EVENT_GROUP_CANCELLABLE);
break;
case POINT_MINCHAR:
DoCast(me, SPELL_ANNIHILATE, true);
// already in evade mode
me->GetMotionMaster()->MoveTargetedHome();
Reset();
break;
default:
break;
}
@@ -508,8 +457,6 @@ private:
GuidSet _vampires;
GuidSet _bloodboltedPlayers;
ObjectGuid _offtankGUID;
bool _creditBloodQuickening;
bool _killMinchar;
};
// helper for shortened code

View File

@@ -1501,9 +1501,6 @@ class at_sindragosa_lair : public AreaTriggerScript
if (!instance->GetData(DATA_SINDRAGOSA_FROSTWYRMS) && !instance->GetGuidData(DATA_SINDRAGOSA) && instance->GetBossState(DATA_SINDRAGOSA) != DONE)
{
if (player->GetMap()->IsHeroic() && !instance->GetData(DATA_HEROIC_ATTEMPTS))
return true;
player->GetMap()->LoadGrid(SindragosaSpawnPos.GetPositionX(), SindragosaSpawnPos.GetPositionY());
if (Creature* sindragosa = player->GetMap()->SummonCreature(NPC_SINDRAGOSA, SindragosaSpawnPos))
sindragosa->AI()->DoAction(ACTION_START_FROSTWYRM);

View File

@@ -1559,20 +1559,6 @@ class at_icc_shutdown_traps : public AreaTriggerScript
}
};
class at_icc_start_blood_quickening : public AreaTriggerScript
{
public:
at_icc_start_blood_quickening() : AreaTriggerScript("at_icc_start_blood_quickening") { }
bool OnTrigger(Player* player, AreaTriggerEntry const* /*areaTrigger*/) override
{
if (InstanceScript* instance = player->GetInstanceScript())
if (instance->GetData(DATA_BLOOD_QUICKENING_STATE) == NOT_STARTED)
instance->SetData(DATA_BLOOD_QUICKENING_STATE, IN_PROGRESS);
return true;
}
};
class at_icc_nerubar_broodkeeper : public OnlyOnceAreaTriggerScript
{
public:
@@ -1627,6 +1613,5 @@ void AddSC_icecrown_citadel()
// AreaTriggers
new at_icc_saurfang_portal();
new at_icc_shutdown_traps();
new at_icc_start_blood_quickening();
new at_icc_nerubar_broodkeeper();
}

View File

@@ -23,7 +23,7 @@
#include "SpellScript.h"
#define ICCScriptName "instance_icecrown_citadel"
#define DataHeader "IC"
#define DataHeader "ICCv1"
uint32 const EncounterCount = 13;
@@ -103,8 +103,6 @@ enum ICDataTypes
DATA_RIMEFANG = 25,
DATA_COLDFLAME_JETS = 26,
DATA_TEAM_IN_INSTANCE = 27,
DATA_BLOOD_QUICKENING_STATE = 28,
DATA_HEROIC_ATTEMPTS = 29,
DATA_CROK_SCOURGEBANE = 30,
DATA_CAPTAIN_ARNATH = 31,
DATA_CAPTAIN_BRANDON = 32,
@@ -499,9 +497,6 @@ enum ICSharedActions
ACTION_ROTFACE_DEATH = -366272,
ACTION_CHANGE_PHASE = -366780,
// Blood-Queen Lana'thel
ACTION_KILL_MINCHAR = -379550,
// Frostwing Halls gauntlet event
ACTION_VRYKUL_DEATH = 37129,

View File

@@ -29,7 +29,6 @@
#include "TemporarySummon.h"
#include "Transport.h"
#include "TransportMgr.h"
#include <sstream>
#include <unordered_set>
enum EventIds
@@ -46,7 +45,6 @@ enum EventIds
enum TimedEvents
{
EVENT_UPDATE_EXECUTION_TIME = 1,
EVENT_QUAKE_SHATTER = 2,
EVENT_REBUILD_PLATFORM = 3,
EVENT_RESPAWN_GUNSHIP = 4
@@ -122,27 +120,6 @@ DungeonEncounterData const encounters[] =
{ DATA_THE_LICH_KING, {{ 1106 }} }
};
// this doesnt have to only store questgivers, also can be used for related quest spawns
struct WeeklyQuest
{
uint32 creatureEntry;
uint32 questId[2]; // 10 and 25 man versions
};
// when changing the content, remember to update SetData, DATA_BLOOD_QUICKENING_STATE case for NPC_ALRIN_THE_AGILE index
WeeklyQuest const WeeklyQuestData[WeeklyNPCs] =
{
{ NPC_INFILTRATOR_MINCHAR, { QUEST_DEPROGRAMMING_10, QUEST_DEPROGRAMMING_25 } }, // Deprogramming
{ NPC_KOR_KRON_LIEUTENANT, { QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 } }, // Securing the Ramparts
{ NPC_ROTTING_FROST_GIANT_10, { QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 } }, // Securing the Ramparts
{ NPC_ROTTING_FROST_GIANT_25, { QUEST_SECURING_THE_RAMPARTS_10, QUEST_SECURING_THE_RAMPARTS_25 } }, // Securing the Ramparts
{ NPC_ALCHEMIST_ADRIANNA, { QUEST_RESIDUE_RENDEZVOUS_10, QUEST_RESIDUE_RENDEZVOUS_25 } }, // Residue Rendezvous
{ NPC_ALRIN_THE_AGILE, { QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 } }, // Blood Quickening
{ NPC_INFILTRATOR_MINCHAR_BQ, { QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 } }, // Blood Quickening
{ NPC_MINCHAR_BEAM_STALKER, { QUEST_BLOOD_QUICKENING_10, QUEST_BLOOD_QUICKENING_25 } }, // Blood Quickening
{ NPC_VALITHRIA_DREAMWALKER_QUEST, { QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_10, QUEST_RESPITE_FOR_A_TORNMENTED_SOUL_25 } } // Respite for a Tormented Soul
};
// NPCs spawned at Light's Hammer on Lich King dead
Position const JainaSpawnPos = { -48.65278f, 2211.026f, 27.98586f, 3.124139f };
Position const MuradinSpawnPos = { -47.34549f, 2208.087f, 27.98586f, 3.106686f };
@@ -163,11 +140,6 @@ class instance_icecrown_citadel : public InstanceMapScript
LoadDungeonEncounterData(encounters);
LoadBossBoundaries(boundaries);
LoadDoorData(doorData);
HeroicAttempts = MaxHeroicAttempts;
ColdflameJetsState = NOT_STARTED;
UpperSpireTeleporterActiveState = NOT_STARTED;
BloodQuickeningState = NOT_STARTED;
BloodQuickeningMinutes = 0;
BloodPrinceIntro = 1;
SindragosaIntro = 1;
IsBonedEligible = true;
@@ -358,22 +330,7 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_INFILTRATOR_MINCHAR_BQ:
case NPC_MINCHAR_BEAM_STALKER:
case NPC_VALITHRIA_DREAMWALKER_QUEST:
{
for (uint8 questIndex = 0; questIndex < WeeklyNPCs; ++questIndex)
{
if (WeeklyQuestData[questIndex].creatureEntry == entry)
{
uint8 diffIndex = instance->Is25ManRaid() ? 1 : 0;
if (!sQuestPoolMgr->IsQuestActive(WeeklyQuestData[questIndex].questId[diffIndex]))
return 0;
break;
}
}
if (entry == NPC_KOR_KRON_LIEUTENANT && GetData(DATA_TEAM_IN_INSTANCE) == ALLIANCE)
return NPC_SKYBREAKER_LIEUTENANT;
break;
}
return 0;
case NPC_HORDE_GUNSHIP_CANNON:
case NPC_ORGRIMS_HAMMER_CREW:
case NPC_SKY_REAVER_KORM_BLACKSCAR:
@@ -487,9 +444,6 @@ class instance_icecrown_citadel : public InstanceMapScript
case NPC_RIMEFANG:
case NPC_SPINESTALKER:
{
if (instance->IsHeroic() && !HeroicAttempts)
return;
if (GetBossState(DATA_SINDRAGOSA) == DONE)
return;
@@ -747,10 +701,6 @@ class instance_icecrown_citadel : public InstanceMapScript
return UpperSpireTeleporterActiveState;
case DATA_TEAM_IN_INSTANCE:
return instance->GetTeamInInstance();
case DATA_BLOOD_QUICKENING_STATE:
return BloodQuickeningState;
case DATA_HEROIC_ATTEMPTS:
return HeroicAttempts;
case DATA_BLOOD_PRINCE_COUNCIL_INTRO:
return BloodPrinceIntro;
case DATA_SINDRAGOSA_INTRO:
@@ -838,25 +788,6 @@ class instance_icecrown_citadel : public InstanceMapScript
return ObjectGuid::Empty;
}
void HandleHeroicAttempts()
{
if (HeroicAttempts)
{
--HeroicAttempts;
DoUpdateWorldState(WORLDSTATE_ATTEMPTS_REMAINING, HeroicAttempts);
}
if (!HeroicAttempts)
{
for (ObjectGuid const& bossGuid : { ProfessorPutricideGUID, BloodQueenLanaThelGUID, SindragosaGUID, TheLichKingGUID })
{
if (Creature* boss = instance->GetCreature(bossGuid))
if (boss->IsAlive())
boss->DespawnOrUnsummon();
}
}
}
bool SetBossState(uint32 type, EncounterState state) override
{
if (!InstanceScript::SetBossState(type, state))
@@ -973,32 +904,22 @@ class instance_icecrown_citadel : public InstanceMapScript
break;
case DATA_PROFESSOR_PUTRICIDE:
HandleGameObject(PlagueSigilGUID, state != DONE);
if (instance->IsHeroic() && state == FAIL)
HandleHeroicAttempts();
else if (state == DONE)
if (state == DONE)
CheckLichKingAvailability();
break;
case DATA_BLOOD_QUEEN_LANA_THEL:
HandleGameObject(BloodwingSigilGUID, state != DONE);
if (instance->IsHeroic() && state == FAIL)
HandleHeroicAttempts();
else if (state == DONE)
if (state == DONE)
CheckLichKingAvailability();
break;
case DATA_VALITHRIA_DREAMWALKER:
if (state == DONE)
{
if (sQuestPoolMgr->IsQuestActive(WeeklyQuestData[8].questId[instance->Is25ManRaid() ? 1 : 0]))
instance->SummonCreature(NPC_VALITHRIA_DREAMWALKER_QUEST, ValithriaSpawnPos);
if (GameObject* teleporter = instance->GetGameObject(TeleporterSindragosaGUID))
SetTeleporterState(teleporter, true);
}
break;
case DATA_SINDRAGOSA:
HandleGameObject(FrostwingSigilGUID, state != DONE);
if (instance->IsHeroic() && state == FAIL)
HandleHeroicAttempts();
else if (state == DONE)
if (state == DONE)
CheckLichKingAvailability();
break;
case DATA_THE_LICH_KING:
@@ -1011,9 +932,7 @@ class instance_icecrown_citadel : public InstanceMapScript
if (GameObject* platform = instance->GetGameObject(ArthasPlatformGUID))
platform->SetFarVisible(state == IN_PROGRESS);
if (instance->IsHeroic() && state == FAIL)
HandleHeroicAttempts();
else if (state == DONE)
if (state == DONE)
{
if (GameObject* bolvar = instance->GetGameObject(FrozenBolvarGUID))
bolvar->SetRespawnTime(7 * DAY);
@@ -1065,48 +984,12 @@ class instance_icecrown_citadel : public InstanceMapScript
break;
case DATA_COLDFLAME_JETS:
ColdflameJetsState = data;
if (ColdflameJetsState == DONE)
SaveToDB();
break;
case DATA_BLOOD_QUICKENING_STATE:
{
// skip if nothing changes
if (BloodQuickeningState == data)
break;
// 5 is the index of Blood Quickening
if (!sQuestPoolMgr->IsQuestActive(WeeklyQuestData[5].questId[instance->Is25ManRaid() ? 1 : 0]))
break;
switch (data)
{
case IN_PROGRESS:
Events.ScheduleEvent(EVENT_UPDATE_EXECUTION_TIME, 1min);
BloodQuickeningMinutes = 30;
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_EXECUTION_TIME, BloodQuickeningMinutes);
break;
case DONE:
Events.CancelEvent(EVENT_UPDATE_EXECUTION_TIME);
BloodQuickeningMinutes = 0;
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
break;
default:
break;
}
BloodQuickeningState = data;
SaveToDB();
break;
}
case DATA_UPPERSPIRE_TELE_ACT:
UpperSpireTeleporterActiveState = data;
if (UpperSpireTeleporterActiveState == DONE)
{
if (GameObject* go = instance->GetGameObject(TeleporterUpperSpireGUID))
SetTeleporterState(go, true);
SaveToDB();
}
break;
case DATA_BLOOD_PRINCE_COUNCIL_INTRO:
BloodPrinceIntro = data;
@@ -1343,36 +1226,18 @@ class instance_icecrown_citadel : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << HeroicAttempts << ' '
<< ColdflameJetsState << ' '
<< BloodQuickeningState << ' '
<< BloodQuickeningMinutes << ' '
<< UpperSpireTeleporterActiveState;
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 temp = 0;
data >> HeroicAttempts;
data >> temp;
ColdflameJetsState = temp == DONE ? DONE : NOT_STARTED;
data >> temp;
BloodQuickeningState = temp == DONE ? DONE : NOT_STARTED;
data >> BloodQuickeningMinutes;
data >> temp;
UpperSpireTeleporterActiveState = temp == DONE ? DONE : NOT_STARTED;
if (GetBossState(DATA_DEATHBRINGER_SAURFANG) == DONE)
{
ColdflameJetsState = DONE;
UpperSpireTeleporterActiveState = DONE;
}
}
void Update(uint32 diff) override
{
if (BloodQuickeningState != IN_PROGRESS && GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL)
if (GetBossState(DATA_THE_LICH_KING) != IN_PROGRESS && GetBossState(DATA_ICECROWN_GUNSHIP_BATTLE) != FAIL)
return;
Events.Update(diff);
@@ -1381,25 +1246,6 @@ class instance_icecrown_citadel : public InstanceMapScript
{
switch (eventId)
{
case EVENT_UPDATE_EXECUTION_TIME:
{
--BloodQuickeningMinutes;
if (BloodQuickeningMinutes)
{
Events.ScheduleEvent(EVENT_UPDATE_EXECUTION_TIME, 1min);
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 1);
DoUpdateWorldState(WORLDSTATE_EXECUTION_TIME, BloodQuickeningMinutes);
}
else
{
BloodQuickeningState = DONE;
DoUpdateWorldState(WORLDSTATE_SHOW_TIMER, 0);
if (Creature* bq = instance->GetCreature(BloodQueenLanaThelGUID))
bq->AI()->DoAction(ACTION_KILL_MINCHAR);
}
SaveToDB();
break;
}
case EVENT_QUAKE_SHATTER:
{
if (GameObject* platform = instance->GetGameObject(ArthasPlatformGUID))
@@ -1552,9 +1398,6 @@ class instance_icecrown_citadel : public InstanceMapScript
std::unordered_set<ObjectGuid::LowType> FrostwyrmGUIDs;
std::unordered_set<ObjectGuid::LowType> SpinestalkerTrash;
std::unordered_set<ObjectGuid::LowType> RimefangTrash;
uint32 BloodQuickeningState;
uint32 HeroicAttempts;
uint16 BloodQuickeningMinutes;
uint8 BloodPrinceIntro;
uint8 SindragosaIntro;
bool IsBonedEligible;

View File

@@ -124,8 +124,6 @@ class instance_naxxramas : public InstanceMapScript
hadSapphironBirth = false;
CurrentWingTaunt = SAY_KELTHUZAD_FIRST_WING_TAUNT;
playerDied = false;
}
void OnCreatureCreate(Creature* creature) override
@@ -250,12 +248,6 @@ class instance_naxxramas : public InstanceMapScript
void OnUnitDeath(Unit* unit) override
{
if (!playerDied && unit->IsPlayer() && IsEncounterInProgress())
{
playerDied = true;
SaveToDB();
}
if (Creature* creature = unit->ToCreature())
if (creature->GetEntry() == NPC_BIGGLESWORTH)
{
@@ -544,26 +536,12 @@ class instance_naxxramas : public InstanceMapScript
case 13239: // Loatheb
case 13240: // Thaddius
case 7617: // Kel'Thuzad
if (AreAllEncountersDone() && !playerDied)
return true;
return false;
}
return false;
}
void WriteSaveDataMore(std::ostringstream& data) override
{
data << uint32(playerDied ? 1 : 0);
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 tmpState;
data >> tmpState;
playerDied = tmpState != 0;
}
protected:
/* The Arachnid Quarter */
// Anub'rekhan
@@ -608,9 +586,6 @@ class instance_naxxramas : public InstanceMapScript
bool hadSapphironBirth;
uint8 CurrentWingTaunt;
/* The Immortal / The Undying */
bool playerDied;
EventMap events;
};

View File

@@ -152,9 +152,6 @@ enum Events
EVENT_OUTRO_9,
EVENT_OUTRO_10,
EVENT_OUTRO_11,
EVENT_DESPAWN_ALGALON_1,
EVENT_DESPAWN_ALGALON_2,
EVENT_DESPAWN_ALGALON_3,
// Living Constellation
EVENT_ARCANE_BARRAGE
@@ -334,18 +331,6 @@ struct boss_algalon_the_observer : public BossAI
events.CancelEvent(EVENT_RESUME_UPDATING);
events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1s + 500ms);
break;
case EVENT_DESPAWN_ALGALON:
events.Reset();
events.SetPhase(PHASE_ROLE_PLAY);
if (me->IsInCombat())
events.ScheduleEvent(EVENT_ASCEND_TO_THE_HEAVENS, 1ms);
events.ScheduleEvent(EVENT_DESPAWN_ALGALON_1, 5s);
events.ScheduleEvent(EVENT_DESPAWN_ALGALON_2, 17s);
events.ScheduleEvent(EVENT_DESPAWN_ALGALON_3, 26s);
me->DespawnOrUnsummon(34s);
me->SetUnitFlag(UNIT_FLAG_UNINTERACTIBLE);
me->SetImmuneToNPC(true);
break;
case ACTION_INIT_ALGALON:
_firstPull = false;
me->SetImmuneToPC(false);
@@ -385,7 +370,6 @@ struct boss_algalon_the_observer : public BossAI
DoZoneInCombat();
introDelay = 26500ms;
summons.DespawnEntry(NPC_AZEROTH);
instance->SetData(EVENT_DESPAWN_ALGALON, 0);
events.ScheduleEvent(EVENT_START_COMBAT, 16s);
}
@@ -687,15 +671,6 @@ struct boss_algalon_the_observer : public BossAI
DoCastSelf(SPELL_TELEPORT);
me->DespawnOrUnsummon(1s + 200ms);
break;
case EVENT_DESPAWN_ALGALON_1:
Talk(SAY_ALGALON_DESPAWN_1);
break;
case EVENT_DESPAWN_ALGALON_2:
Talk(SAY_ALGALON_DESPAWN_2);
break;
case EVENT_DESPAWN_ALGALON_3:
Talk(SAY_ALGALON_DESPAWN_3);
break;
default:
break;
}

View File

@@ -27,7 +27,6 @@
#include "ScriptMgr.h"
#include "TemporarySummon.h"
#include "Vehicle.h"
#include <sstream>
static BossBoundaryData const boundaries =
{
@@ -168,7 +167,6 @@ class instance_ulduar : public InstanceMapScript
LoadMinionData(minionData);
LoadObjectData(creatureData, objectData);
_algalonTimer = 61;
_maxArmorItemLevel = 0;
_maxWeaponItemLevel = 0;
TeamInInstance = 0;
@@ -183,7 +181,7 @@ class instance_ulduar : public InstanceMapScript
IsDriveMeCrazyEligible = true;
_algalonSummoned = false;
_summonAlgalon = false;
_CoUAchivePlayerDeathMask = 0;
_algalonFirstIntro = true;
memset(_summonObservationRingKeeper, 0, sizeof(_summonObservationRingKeeper));
memset(_summonYSKeeper, 0, sizeof(_summonYSKeeper));
@@ -234,7 +232,7 @@ class instance_ulduar : public InstanceMapScript
{
_summonAlgalon = false;
TempSummon* algalon = instance->SummonCreature(NPC_ALGALON, AlgalonLandPos);
if (_algalonTimer && _algalonTimer <= 60)
if (!_algalonFirstIntro)
algalon->AI()->DoAction(ACTION_INIT_ALGALON);
else
algalon->SetImmuneToPC(false);
@@ -349,28 +347,24 @@ class instance_ulduar : public InstanceMapScript
case NPC_FREYA_YS:
KeeperGUIDs[0] = creature->GetGUID();
_summonYSKeeper[0] = false;
SaveToDB();
++keepersCount;
DoUpdateWorldState(WORLD_STATE_YOGG_SARON_KEEPERS, keepersCount);
break;
case NPC_HODIR_YS:
KeeperGUIDs[1] = creature->GetGUID();
_summonYSKeeper[1] = false;
SaveToDB();
++keepersCount;
DoUpdateWorldState(WORLD_STATE_YOGG_SARON_KEEPERS, keepersCount);
break;
case NPC_THORIM_YS:
KeeperGUIDs[2] = creature->GetGUID();
_summonYSKeeper[2] = false;
SaveToDB();
++keepersCount;
DoUpdateWorldState(WORLD_STATE_YOGG_SARON_KEEPERS, keepersCount);
break;
case NPC_MIMIRON_YS:
KeeperGUIDs[3] = creature->GetGUID();
_summonYSKeeper[3] = false;
SaveToDB();
++keepersCount;
DoUpdateWorldState(WORLD_STATE_YOGG_SARON_KEEPERS, keepersCount);
break;
@@ -526,19 +520,6 @@ class instance_ulduar : public InstanceMapScript
void OnUnitDeath(Unit* unit) override
{
// Champion/Conqueror of Ulduar
if (unit->GetTypeId() == TYPEID_PLAYER)
{
for (uint8 i = 0; i < DATA_ALGALON; ++i)
{
if (GetBossState(i) == IN_PROGRESS)
{
_CoUAchivePlayerDeathMask |= (1 << i);
SaveToDB();
}
}
}
Creature* creature = unit->ToCreature();
if (!creature)
return;
@@ -690,10 +671,6 @@ class instance_ulduar : public InstanceMapScript
case DATA_ALGALON:
if (state == DONE)
{
_events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
_events.CancelEvent(EVENT_DESPAWN_ALGALON);
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_algalonTimer = 61;
if (GameObject* gift = GetGameObject(DATA_GIFT_OF_THE_OBSERVER))
gift->SetRespawnTime(gift->GetRespawnDelay());
// get item level (recheck weapons)
@@ -707,6 +684,7 @@ class instance_ulduar : public InstanceMapScript
}
else if (state == IN_PROGRESS)
{
_algalonFirstIntro = false;
// get item level (armor cannot be swapped in combat)
Map::PlayerList const& players = instance->GetPlayers();
for (Map::PlayerList::const_iterator itr = players.begin(); itr != players.end(); ++itr)
@@ -747,7 +725,6 @@ class instance_ulduar : public InstanceMapScript
if (data >= 2 && GetBossState(DATA_FLAME_LEVIATHAN) == NOT_STARTED)
{
_events.ScheduleEvent(EVENT_LEVIATHAN_BREAK_DOOR, 5s);
SaveToDB();
}
break;
case DATA_HODIR_RARE_CACHE:
@@ -768,13 +745,6 @@ class instance_ulduar : public InstanceMapScript
case DATA_DRIVE_ME_CRAZY:
IsDriveMeCrazyEligible = data ? true : false;
break;
case EVENT_DESPAWN_ALGALON:
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, 60);
_algalonTimer = 60;
_events.ScheduleEvent(EVENT_DESPAWN_ALGALON, 1h);
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 1min);
break;
case DATA_ALGALON_SUMMON_STATE:
_algalonSummoned = true;
break;
@@ -883,94 +853,49 @@ class instance_ulduar : public InstanceMapScript
return IsDriveMeCrazyEligible;
case CRITERIA_C_O_U_LEVIATHAN_10:
case CRITERIA_C_O_U_LEVIATHAN_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_FLAME_LEVIATHAN)) == 0;
case CRITERIA_C_O_U_IGNIS_10:
case CRITERIA_C_O_U_IGNIS_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_IGNIS)) == 0;
case CRITERIA_C_O_U_RAZORSCALE_10:
case CRITERIA_C_O_U_RAZORSCALE_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_RAZORSCALE)) == 0;
case CRITERIA_C_O_U_XT002_10:
case CRITERIA_C_O_U_XT002_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_XT002)) == 0;
case CRITERIA_C_O_U_IRON_COUNCIL_10:
case CRITERIA_C_O_U_IRON_COUNCIL_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_ASSEMBLY_OF_IRON)) == 0;
case CRITERIA_C_O_U_KOLOGARN_10:
case CRITERIA_C_O_U_KOLOGARN_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_KOLOGARN)) == 0;
case CRITERIA_C_O_U_AURIAYA_10:
case CRITERIA_C_O_U_AURIAYA_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_AURIAYA)) == 0;
case CRITERIA_C_O_U_HODIR_10:
case CRITERIA_C_O_U_HODIR_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_HODIR)) == 0;
case CRITERIA_C_O_U_THORIM_10:
case CRITERIA_C_O_U_THORIM_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_THORIM)) == 0;
case CRITERIA_C_O_U_FREYA_10:
case CRITERIA_C_O_U_FREYA_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_FREYA)) == 0;
case CRITERIA_C_O_U_MIMIRON_10:
case CRITERIA_C_O_U_MIMIRON_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_MIMIRON)) == 0;
case CRITERIA_C_O_U_VEZAX_10:
case CRITERIA_C_O_U_VEZAX_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_VEZAX)) == 0;
case CRITERIA_C_O_U_YOGG_SARON_10:
case CRITERIA_C_O_U_YOGG_SARON_25:
return (_CoUAchivePlayerDeathMask & (1 << DATA_YOGG_SARON)) == 0;
return false;
}
return false;
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
data << ColossusData << ' ' << _algalonTimer << ' ' << uint32(_algalonSummoned ? 1 : 0);
if (GetBossState(DATA_FLAME_LEVIATHAN) == DONE)
SetData(DATA_COLOSSUS, DONE);
for (uint8 i = 0; i < 4; ++i)
data << ' ' << uint32(!KeeperGUIDs[i].IsEmpty() ? 1 : 0);
data << ' ' << _CoUAchivePlayerDeathMask;
}
void ReadSaveDataMore(std::istringstream& data) override
{
uint32 tempState;
data >> tempState;
SetData(DATA_COLOSSUS, tempState);
data >> _algalonTimer;
data >> tempState;
_algalonSummoned = tempState != 0;
if (_algalonSummoned && GetBossState(DATA_ALGALON) != DONE)
{
_summonAlgalon = true;
if (_algalonTimer && _algalonTimer <= 60)
{
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 1min);
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 1);
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, _algalonTimer);
}
}
for (uint8 i = 0; i < 4; ++i)
{
data >> tempState;
_summonYSKeeper[i] = tempState != 0;
}
if (GetBossState(DATA_FREYA) == DONE && !_summonYSKeeper[0])
if (GetBossState(DATA_FREYA) == DONE)
_summonObservationRingKeeper[0] = true;
if (GetBossState(DATA_HODIR) == DONE && !_summonYSKeeper[1])
if (GetBossState(DATA_HODIR) == DONE)
_summonObservationRingKeeper[1] = true;
if (GetBossState(DATA_THORIM) == DONE && !_summonYSKeeper[2])
if (GetBossState(DATA_THORIM) == DONE)
_summonObservationRingKeeper[2] = true;
if (GetBossState(DATA_MIMIRON) == DONE && !_summonYSKeeper[3])
if (GetBossState(DATA_MIMIRON) == DONE)
_summonObservationRingKeeper[3] = true;
data >> _CoUAchivePlayerDeathMask;
}
void Update(uint32 diff) override
@@ -984,19 +909,6 @@ class instance_ulduar : public InstanceMapScript
{
switch (eventId)
{
case EVENT_UPDATE_ALGALON_TIMER:
SaveToDB();
DoUpdateWorldState(WORLD_STATE_ALGALON_DESPAWN_TIMER, --_algalonTimer);
if (_algalonTimer)
_events.ScheduleEvent(EVENT_UPDATE_ALGALON_TIMER, 1min);
else
{
DoUpdateWorldState(WORLD_STATE_ALGALON_TIMER_ENABLED, 0);
_events.CancelEvent(EVENT_UPDATE_ALGALON_TIMER);
if (Creature* algalon = GetCreature(DATA_ALGALON))
algalon->AI()->DoAction(EVENT_DESPAWN_ALGALON);
}
break;
case EVENT_DESPAWN_LEVIATHAN_VEHICLES:
// Eject all players from vehicles and make them untargetable.
// They will be despawned after a while
@@ -1054,14 +966,13 @@ class instance_ulduar : public InstanceMapScript
private:
EventMap _events;
uint32 _algalonTimer;
bool _summonAlgalon;
bool _algalonSummoned;
bool _algalonFirstIntro;
bool _summonObservationRingKeeper[4];
bool _summonYSKeeper[4];
uint32 _maxArmorItemLevel;
uint32 _maxWeaponItemLevel;
uint32 _CoUAchivePlayerDeathMask;
};
InstanceScript* GetInstanceScript(InstanceMap* map) const override

View File

@@ -477,8 +477,8 @@ enum UlduarAchievementData
{
// FL Achievement boolean
DATA_UNBROKEN = 29052906, // 2905, 2906 are achievement IDs,
MAX_HERALD_ARMOR_ITEMLEVEL = 226,
MAX_HERALD_WEAPON_ITEMLEVEL = 232
MAX_HERALD_ARMOR_ITEMLEVEL = 35,
MAX_HERALD_WEAPON_ITEMLEVEL = 35
};
enum UlduarSharedSpells
@@ -489,8 +489,6 @@ enum UlduarSharedSpells
enum UlduarEvents
{
EVENT_DESPAWN_ALGALON = 1,
EVENT_UPDATE_ALGALON_TIMER = 2,
ACTION_INIT_ALGALON = 6,
EVENT_DESPAWN_LEVIATHAN_VEHICLES = 7,
EVENT_LEVIATHAN_BREAK_DOOR = 8

View File

@@ -20,7 +20,6 @@
#include "GameObject.h"
#include "InstanceScript.h"
#include "utgarde_keep.h"
#include <sstream>
DoorData const doorData[] =
{
@@ -166,9 +165,6 @@ class instance_utgarde_keep : public InstanceMapScript
HandleGameObject(Forges[i].BellowGUID, data != NOT_STARTED);
HandleGameObject(Forges[i].FireGUID, data != NOT_STARTED);
Forges[i].Event = data;
if (data == DONE)
SaveToDB();
break;
}
default:
@@ -176,16 +172,11 @@ class instance_utgarde_keep : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
for (uint8 i = 0; i < 3; ++i)
data << Forges[i].Event << ' ';
}
void ReadSaveDataMore(std::istringstream& data) override
{
for (uint8 i = 0; i < 3; ++i)
data >> Forges[i].Event;
if (GetBossState(DATA_PRINCE_KELESETH) == DONE)
for (uint8 i = 0; i < 3; ++i)
Forges[i].Event = DONE;
}
protected:

View File

@@ -26,7 +26,6 @@
#include "TaskScheduler.h"
#include "ScriptMgr.h"
#include "TemporarySummon.h"
#include <sstream>
/*
* TODO:
@@ -197,16 +196,15 @@ class instance_violet_hold : public InstanceMapScript
struct instance_violet_hold_InstanceMapScript : public InstanceScript
{
instance_violet_hold_InstanceMapScript(InstanceMap* map) : InstanceScript(map)
instance_violet_hold_InstanceMapScript(InstanceMap* map) : InstanceScript(map),
FirstBossId(*this, "FirstBossId", 0),
SecondBossId(*this, "SecondBossId", 0)
{
SetHeaders(DataHeader);
SetBossNumber(EncounterCount);
LoadObjectData(creatureData, gameObjectData);
LoadMinionData(minionData);
FirstBossId = 0;
SecondBossId = 0;
DoorIntegrity = 100;
WaveCount = 0;
EventState = NOT_STARTED;
@@ -794,17 +792,6 @@ class instance_violet_hold : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
{
data << FirstBossId << ' ' << SecondBossId;
}
void ReadSaveDataMore(std::istringstream& data) override
{
data >> FirstBossId;
data >> SecondBossId;
}
bool CheckWipe() const
{
Map::PlayerList const& players = instance->GetPlayers();
@@ -943,8 +930,8 @@ class instance_violet_hold : public InstanceMapScript
static uint8 const ActivationCrystalCount = 5;
ObjectGuid ActivationCrystalGUIDs[ActivationCrystalCount];
uint32 FirstBossId;
uint32 SecondBossId;
PersistentInstanceScriptValue<uint32> FirstBossId;
PersistentInstanceScriptValue<uint32> SecondBossId;
uint8 DoorIntegrity;
uint8 WaveCount;

View File

@@ -26,12 +26,10 @@ EndScriptData */
#include "GameObject.h"
#include "GameObjectAI.h"
#include "InstanceScript.h"
#include "Log.h"
#include "Map.h"
#include "Player.h"
#include "serpent_shrine.h"
#include "TemporarySummon.h"
#include <sstream>
#define MAX_ENCOUNTER 6
@@ -285,7 +283,6 @@ class instance_serpent_shrine : public InstanceMapScript
case DATA_TRASH:
if (data == 1 && TrashCount < MIN_KILLS)
++TrashCount;//+1 died
SaveToDB();
break;
case DATA_WATER:
Water = data;
@@ -350,16 +347,6 @@ class instance_serpent_shrine : public InstanceMapScript
return 0;
}
void WriteSaveDataMore(std::ostringstream& stream) override
{
stream << TrashCount;
}
void ReadSaveDataMore(std::istringstream& stream) override
{
stream >> TrashCount;
}
private:
ObjectGuid LurkerBelow;
ObjectGuid Sharkkis;

View File

@@ -30,7 +30,6 @@ EndScriptData */
#include "shattered_halls.h"
#include "SpellAuras.h"
#include "TemporarySummon.h"
#include <sstream>
DoorData const doorData[] =
{
@@ -118,7 +117,6 @@ class instance_shattered_halls : public InstanceMapScript
executionTimer = 55 * MINUTE * IN_MILLISECONDS;
DoCastSpellOnPlayers(SPELL_KARGATH_EXECUTIONER_1);
executionerGUID = creature->GetGUID();
SaveToDB();
break;
case NPC_CAPTAIN_ALINA:
case NPC_CAPTAIN_BONESHATTER:
@@ -153,7 +151,6 @@ class instance_shattered_halls : public InstanceMapScript
{
DoCastSpellOnPlayers(SPELL_REMOVE_KARGATH_EXECUTIONER);
executionTimer = 0;
SaveToDB();
}
break;
case DATA_KARGATH:
@@ -185,47 +182,11 @@ class instance_shattered_halls : public InstanceMapScript
}
}
void WriteSaveDataMore(std::ostringstream& data) override
void AfterDataLoad() override
{
if (!instance->IsHeroic())
return;
data << uint32(executed) << ' '
<< executionTimer << ' ';
}
void ReadSaveDataMore(std::istringstream& data) override
{
if (!instance->IsHeroic())
return;
uint32 readbuff;
data >> readbuff;
executed = uint8(readbuff);
data >> readbuff;
if (executed > VictimCount)
{
executed = VictimCount;
executionTimer = 0;
return;
}
if (!readbuff)
return;
Creature* executioner = nullptr;
instance->LoadGrid(Executioner.GetPositionX(), Executioner.GetPositionY());
if (Creature* kargath = instance->GetCreature(kargathGUID))
if (executionerGUID.IsEmpty())
executioner = kargath->SummonCreature(NPC_SHATTERED_EXECUTIONER, Executioner);
if (executioner)
for (uint8 i = executed; i < VictimCount; ++i)
executioner->SummonCreature(executionerVictims[i](GetData(DATA_TEAM_IN_INSTANCE)), executionerVictims[i].GetPos());
executionTimer = readbuff;
// timed events are not resumable after reset/crash
executed = VictimCount;
executionTimer = 0;
}
uint32 GetData(uint32 type) const override
@@ -266,8 +227,6 @@ class instance_shattered_halls : public InstanceMapScript
if (Creature* executioner = instance->GetCreature(executionerGUID))
executioner->AI()->SetData(DATA_PRISONERS_EXECUTED, executed);
SaveToDB();
}
else
executionTimer -= diff;