diff --git a/dGame/dCinema/Recorder.cpp b/dGame/dCinema/Recorder.cpp index 2345f244..ce07355e 100644 --- a/dGame/dCinema/Recorder.cpp +++ b/dGame/dCinema/Recorder.cpp @@ -46,15 +46,15 @@ void Recorder::Act(Entity* actor, Play* variables) { LOG("Acting %d steps", m_Records.size()); // Loop through all records - ActingDispatch(actor, 0, variables); + ActingDispatch(actor, m_Records, 0, variables); } -void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { - if (index >= m_Records.size()) { +void Recorder::ActingDispatch(Entity* actor, const std::vector& records, size_t index, Play* variables) { + if (index >= records.size()) { return; } - auto* record = m_Records[index]; + auto* record = records[index]; // Check if the record is a fork auto* forkRecord = dynamic_cast(record); @@ -64,7 +64,7 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (forkRecord) { if (variables == nullptr) { // Skip the fork - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); return; } @@ -86,11 +86,11 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (success) { // Find the success record - for (auto i = 0; i < m_Records.size(); ++i) { - auto* record = m_Records[i]; + for (auto i = 0; i < records.size(); ++i) { + auto* record = records[i]; if (record->m_Name == forkRecord->success) { - ActingDispatch(actor, i, variables); + ActingDispatch(actor, records, i, variables); return; } } @@ -101,11 +101,11 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { } else { // Find the failure record - for (auto i = 0; i < m_Records.size(); ++i) { - auto* record = m_Records[i]; + for (auto i = 0; i < records.size(); ++i) { + auto* record = records[i]; if (record->m_Name == forkRecord->failure) { - ActingDispatch(actor, i, variables); + ActingDispatch(actor, records, i, variables); return; } } @@ -121,11 +121,11 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (jumpRecord) { // Find the jump record - for (auto i = 0; i < m_Records.size(); ++i) { - auto* record = m_Records[i]; + for (auto i = 0; i < records.size(); ++i) { + auto* record = records[i]; if (record->m_Name == jumpRecord->label) { - ActingDispatch(actor, i, variables); + ActingDispatch(actor, records, i, variables); return; } } @@ -141,13 +141,13 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (setVariableRecord) { if (variables == nullptr) { // Skip the set variable - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); return; } variables->variables[setVariableRecord->variable] = setVariableRecord->value; - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records,index + 1, variables); return; } @@ -157,38 +157,38 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (barrierRecord) { if (variables == nullptr) { // Skip the barrier - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); return; } auto actionTaken = std::make_shared(false); - variables->SetupBarrier(barrierRecord->signal, [this, actor, index, variables, actionTaken]() { + variables->SetupBarrier(barrierRecord->signal, [actor, records, index, variables, actionTaken]() { if (*actionTaken) { return; } *actionTaken = true; - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); }); if (barrierRecord->timeout <= 0.0001f) { return; } - Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(barrierRecord->timeout, [this, barrierRecord, actor, index, variables, actionTaken]() { + Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(barrierRecord->timeout, [barrierRecord, records, actor, index, variables, actionTaken]() { if (*actionTaken) { return; } *actionTaken = true; - for (auto i = 0; i < m_Records.size(); ++i) { - auto* record = m_Records[i]; + for (auto i = 0; i < records.size(); ++i) { + auto* record = records[i]; if (record->m_Name == barrierRecord->timeoutLabel) { - ActingDispatch(actor, i, variables); + ActingDispatch(actor, records, i, variables); return; } } @@ -232,30 +232,30 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { if (playerProximityRecord) { if (variables == nullptr) { // Skip the player proximity record - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); return; } auto actionTaken = std::make_shared(false); - PlayerProximityDispatch(actor, index, variables, actionTaken); + PlayerProximityDispatch(actor, records, index, variables, actionTaken); if (playerProximityRecord->timeout <= 0.0f) { return; } - Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(playerProximityRecord->timeout, [this, playerProximityRecord, actor, index, variables, actionTaken]() { + Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(playerProximityRecord->timeout, [playerProximityRecord, actor, records, index, variables, actionTaken]() { if (*actionTaken) { return; } *actionTaken = true; - for (auto i = 0; i < m_Records.size(); ++i) { - auto* record = m_Records[i]; + for (auto i = 0; i < records.size(); ++i) { + auto* record = records[i]; if (record->m_Name == playerProximityRecord->timeoutLabel) { - ActingDispatch(actor, i, variables); + ActingDispatch(actor, records, i, variables); return; } } @@ -264,15 +264,24 @@ void Recorder::ActingDispatch(Entity* actor, size_t index, Play* variables) { return; } - actor->AddCallbackTimer(delay, [this, actor, index, variables]() { - ActingDispatch(actor, index + 1, variables); + // Check if the record is a coroutine record + auto* coroutineRecord = dynamic_cast(record); + + if (coroutineRecord) { + actor->AddCallbackTimer(delay, [actor, coroutineRecord, index, variables]() { + ActingDispatch(actor, coroutineRecord->records, 0, variables); + }); + } + + actor->AddCallbackTimer(delay, [actor, records, index, variables]() { + ActingDispatch(actor, records, index + 1, variables); }); record->Act(actor); } -void Cinema::Recording::Recorder::PlayerProximityDispatch(Entity* actor, size_t index, Play* variables, std::shared_ptr actionTaken) { - auto* record = dynamic_cast(m_Records[index]); +void Cinema::Recording::Recorder::PlayerProximityDispatch(Entity* actor, const std::vector& records, size_t index, Play* variables, std::shared_ptr actionTaken) { + auto* record = dynamic_cast(records[index]); auto* player = Game::entityManager->GetEntity(variables->player); if (player == nullptr || record == nullptr) { @@ -291,16 +300,78 @@ void Cinema::Recording::Recorder::PlayerProximityDispatch(Entity* actor, size_t *actionTaken = true; - ActingDispatch(actor, index + 1, variables); + ActingDispatch(actor, records, index + 1, variables); return; } - Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(1.0f, [this, actor, index, variables, actionTaken]() { - PlayerProximityDispatch(actor, index, variables, actionTaken); + Game::entityManager->GetZoneControlEntity()->AddCallbackTimer(1.0f, [actor, records, index, variables, actionTaken]() { + PlayerProximityDispatch(actor, records, index, variables, actionTaken); }); } +void Cinema::Recording::Recorder::LoadRecords(tinyxml2::XMLElement* root, std::vector& records) { + + for (auto* element = root->FirstChildElement(); element; element = element->NextSiblingElement()) { + std::string name = element->Name(); + + if (!element->Attribute("t")) { + element->SetAttribute("t", 0.0f); + } + + // If the name does not end with Record, add it + if (name.find("Record") == std::string::npos) { + name += "Record"; + } + + Record* record = nullptr; + + if (name == "MovementRecord") { + record = new MovementRecord(); + } else if (name == "SpeakRecord") { + record = new SpeakRecord(); + } else if (name == "AnimationRecord") { + record = new AnimationRecord(); + } else if (name == "EquipRecord") { + record = new EquipRecord(); + } else if (name == "UnequipRecord") { + record = new UnequipRecord(); + } else if (name == "ClearEquippedRecord") { + record = new ClearEquippedRecord(); + } else if (name == "ForkRecord") { + record = new ForkRecord(); + } else if (name == "WaitRecord") { + record = new WaitRecord(); + } else if (name == "JumpRecord") { + record = new JumpRecord(); + } else if (name == "SetVariableRecord") { + record = new SetVariableRecord(); + } else if (name == "BarrierRecord") { + record = new BarrierRecord(); + } else if (name == "SignalRecord") { + record = new SignalRecord(); + } else if (name == "ConcludeRecord") { + record = new ConcludeRecord(); + } else if (name == "PlayerProximityRecord") { + record = new PlayerProximityRecord(); + } else if (name == "VisibilityRecord") { + record = new VisibilityRecord(); + } else if (name == "PlayEffectRecord") { + record = new PlayEffectRecord(); + } else if (name == "CoroutineRecord") { + record = new CoroutineRecord(); + } + + record->Deserialize(element); + records.push_back(record); + + if (element->Attribute("name")) { + records.back()->m_Name = element->Attribute("name"); + } + } + +} + Entity* Recorder::ActFor(Entity* actorTemplate, Entity* player, Play* variables) { EntityInfo info; info.lot = actorTemplate->GetLOT(); @@ -682,83 +753,7 @@ Recorder* Recorder::LoadFromFile(const std::string& filename) { Recorder* recorder = new Recorder(); - for (auto* element = root->FirstChildElement(); element; element = element->NextSiblingElement()) { - const std::string name = element->Name(); - - if (!element->Attribute("t")) { - element->SetAttribute("t", 0.0f); - } - - if (name == "MovementRecord") { - MovementRecord* record = new MovementRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "SpeakRecord") { - SpeakRecord* record = new SpeakRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "AnimationRecord") { - AnimationRecord* record = new AnimationRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "EquipRecord") { - EquipRecord* record = new EquipRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "UnequipRecord") { - UnequipRecord* record = new UnequipRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "ClearEquippedRecord") { - ClearEquippedRecord* record = new ClearEquippedRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "ForkRecord") { - ForkRecord* record = new ForkRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "WaitRecord") { - WaitRecord* record = new WaitRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "JumpRecord") { - JumpRecord* record = new JumpRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "SetVariableRecord") { - SetVariableRecord* record = new SetVariableRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "BarrierRecord") { - BarrierRecord* record = new BarrierRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "SignalRecord") { - SignalRecord* record = new SignalRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "ConcludeRecord") { - ConcludeRecord* record = new ConcludeRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "PlayerProximityRecord") { - PlayerProximityRecord* record = new PlayerProximityRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "VisibilityRecord") { - VisibilityRecord* record = new VisibilityRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } else if (name == "PlayEffectRecord") { - PlayEffectRecord* record = new PlayEffectRecord(); - record->Deserialize(element); - recorder->m_Records.push_back(record); - } - - if (element->Attribute("name")) { - recorder->m_Records.back()->m_Name = element->Attribute("name"); - } - } + LoadRecords(root, recorder->m_Records); return recorder; } @@ -1066,3 +1061,14 @@ void Cinema::Recording::PlayEffectRecord::Deserialize(tinyxml2::XMLElement* elem m_Delay = element->DoubleAttribute("t"); } + +void Cinema::Recording::CoroutineRecord::Act(Entity* actor) { + +} + +void Cinema::Recording::CoroutineRecord::Serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent) { +} + +void Cinema::Recording::CoroutineRecord::Deserialize(tinyxml2::XMLElement* element) { + Recorder::LoadRecords(element, records); +} diff --git a/dGame/dCinema/Recorder.h b/dGame/dCinema/Recorder.h index e113a430..abcd7dc0 100644 --- a/dGame/dCinema/Recorder.h +++ b/dGame/dCinema/Recorder.h @@ -25,6 +25,54 @@ public: std::string m_Name; }; +class Recorder +{ +public: + Recorder(); + + ~Recorder(); + + void AddRecord(Record* record); + + void Act(Entity* actor, Play* variables = nullptr); + + Entity* ActFor(Entity* actorTemplate, Entity* player, Play* variables = nullptr); + + void StopActingFor(Entity* actor, Entity* actorTemplate, LWOOBJID playerID); + + bool IsRecording() const; + + void SaveToFile(const std::string& filename); + + float GetDuration() const; + + static Recorder* LoadFromFile(const std::string& filename); + + static void AddRecording(LWOOBJID actorID, Recorder* recorder); + + static void StartRecording(LWOOBJID actorID); + + static void StopRecording(LWOOBJID actorID); + + static Recorder* GetRecorder(LWOOBJID actorID); + + static void RegisterEffectForActor(LWOOBJID actorID, const int32_t& effectId); + + static void LoadRecords(tinyxml2::XMLElement* root, std::vector& records); + + static void ActingDispatch(Entity* actor, const std::vector& records, size_t index, Play* variables); + + static void PlayerProximityDispatch(Entity* actor, const std::vector& records, size_t index, Play* variables, std::shared_ptr actionTaken); + +private: + std::vector m_Records; + + bool m_IsRecording; + + std::chrono::milliseconds m_StartTime; + + std::chrono::milliseconds m_LastRecordTime; +}; class MovementRecord : public Record { @@ -299,51 +347,19 @@ public: void Deserialize(tinyxml2::XMLElement* element) override; }; -class Recorder +class CoroutineRecord : public Record { public: - Recorder(); + std::vector records; - ~Recorder(); + CoroutineRecord() = default; - void AddRecord(Record* record); + void Act(Entity* actor) override; - void Act(Entity* actor, Play* variables = nullptr); - - Entity* ActFor(Entity* actorTemplate, Entity* player, Play* variables = nullptr); - - void StopActingFor(Entity* actor, Entity* actorTemplate, LWOOBJID playerID); - - bool IsRecording() const; - - void SaveToFile(const std::string& filename); - - float GetDuration() const; + void Serialize(tinyxml2::XMLDocument& document, tinyxml2::XMLElement* parent) override; - static Recorder* LoadFromFile(const std::string& filename); - - static void AddRecording(LWOOBJID actorID, Recorder* recorder); - - static void StartRecording(LWOOBJID actorID); - - static void StopRecording(LWOOBJID actorID); - - static Recorder* GetRecorder(LWOOBJID actorID); - - static void RegisterEffectForActor(LWOOBJID actorID, const int32_t& effectId); - -private: - void ActingDispatch(Entity* actor, size_t index, Play* variables); - - void PlayerProximityDispatch(Entity* actor, size_t index, Play* variables, std::shared_ptr actionTaken); - - std::vector m_Records; - - bool m_IsRecording; - - std::chrono::milliseconds m_StartTime; - - std::chrono::milliseconds m_LastRecordTime; + void Deserialize(tinyxml2::XMLElement* element) override; }; + } \ No newline at end of file