From c622cfc2450a9b5fc02280aa9109d8c8951aaf6a Mon Sep 17 00:00:00 2001 From: trav5 Date: Mon, 15 Apr 2024 22:01:41 +0200 Subject: [PATCH] ESM::Dialogue Lua bindings 1 --- apps/openmw/CMakeLists.txt | 2 +- apps/openmw/mwlua/corebindings.cpp | 3 +- apps/openmw/mwlua/dialoguebindings.cpp | 133 +++++++++++++++++++++++++ apps/openmw/mwlua/dialoguebindings.hpp | 12 +++ 4 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 apps/openmw/mwlua/dialoguebindings.cpp create mode 100644 apps/openmw/mwlua/dialoguebindings.hpp diff --git a/apps/openmw/CMakeLists.txt b/apps/openmw/CMakeLists.txt index c9bfa87648..c71ad38665 100644 --- a/apps/openmw/CMakeLists.txt +++ b/apps/openmw/CMakeLists.txt @@ -62,7 +62,7 @@ add_openmw_dir (mwscript add_openmw_dir (mwlua luamanagerimp object objectlists userdataserializer luaevents engineevents objectvariant context menuscripts globalscripts localscripts playerscripts luabindings objectbindings cellbindings - mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings + mwscriptbindings camerabindings vfsbindings uibindings soundbindings inputbindings nearbybindings dialoguebindings postprocessingbindings stats recordstore debugbindings corebindings worldbindings worker magicbindings factionbindings classbindings itemdata inputprocessor animationbindings birthsignbindings racebindings markupbindings types/types types/door types/item types/actor types/container types/lockable types/weapon types/npc diff --git a/apps/openmw/mwlua/corebindings.cpp b/apps/openmw/mwlua/corebindings.cpp index b212d4d01c..a0ce98eaaf 100644 --- a/apps/openmw/mwlua/corebindings.cpp +++ b/apps/openmw/mwlua/corebindings.cpp @@ -23,6 +23,7 @@ #include "luaevents.hpp" #include "magicbindings.hpp" #include "soundbindings.hpp" +#include "dialoguebindings.hpp" #include "stats.hpp" namespace MWLua @@ -98,7 +99,7 @@ namespace MWLua api["stats"] = initCoreStatsBindings(context); api["factions"] = initCoreFactionBindings(context); - + api["dialogue"] = initCoreDialogueBindings(context); api["l10n"] = LuaUtil::initL10nLoader(lua->sol(), MWBase::Environment::get().getL10nManager()); const MWWorld::Store* gmstStore = &MWBase::Environment::get().getESMStore()->get(); diff --git a/apps/openmw/mwlua/dialoguebindings.cpp b/apps/openmw/mwlua/dialoguebindings.cpp new file mode 100644 index 0000000000..4021b2ba54 --- /dev/null +++ b/apps/openmw/mwlua/dialoguebindings.cpp @@ -0,0 +1,133 @@ +#include "dialoguebindings.hpp" +#include "context.hpp" +#include "recordstore.hpp" +#include "apps/openmw/mwworld/store.hpp" +#include +#include +#include +#include + +namespace +{ + sol::table prepareJournalRecord(sol::state_view& lua, const ESM::Dialogue& mwDialogue) + { + const auto dialogueRecordId = mwDialogue.mId.serializeText(); + sol::table result(lua, sol::create); + result["text"] = mwDialogue.mStringId; + + sol::table preparedInfos(lua, sol::create); + unsigned index = 1; + for (const auto& mwDialogueInfo : mwDialogue.mInfo) + { + if (mwDialogueInfo.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Name) + { + result["questName"] = mwDialogueInfo.mResponse; + continue; + } + sol::table infoElement(lua, sol::create); + infoElement["id"] = (dialogueRecordId + '#' + mwDialogueInfo.mId.serializeText()); + infoElement["text"] = mwDialogueInfo.mResponse; + infoElement["questStage"] = mwDialogueInfo.mData.mJournalIndex; + infoElement["questFinished"] = (mwDialogueInfo.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Finished); + infoElement["questRestart"] = (mwDialogueInfo.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Restart); + preparedInfos[index++] = infoElement; + } + + result["infos"] = LuaUtil::makeStrictReadOnly(preparedInfos); + return result; + } + + sol::table prepareNonJournalRecord(sol::state_view& lua, const ESM::Dialogue& mwDialogue) + { + const auto dialogueRecordId = mwDialogue.mId.serializeText(); + sol::table result(lua, sol::create); + result["text"] = mwDialogue.mStringId; + + sol::table preparedInfos(lua, sol::create); + unsigned index = 1; + for (const auto& mwDialogueInfo : mwDialogue.mInfo) + { + sol::table infoElement(lua, sol::create); + infoElement["id"] = (dialogueRecordId + '#' + mwDialogueInfo.mId.serializeText()); + infoElement["text"] = mwDialogueInfo.mResponse; + infoElement["actorId"] = mwDialogueInfo.mActor.serializeText(); + infoElement["actorRace"] = mwDialogueInfo.mRace.serializeText(); + infoElement["actorClass"] = mwDialogueInfo.mClass.serializeText(); + infoElement["actorFaction"] = mwDialogueInfo.mFaction.serializeText(); + if (mwDialogueInfo.mData.mRank != -1) + { + infoElement["actorFactionRank"] = mwDialogueInfo.mData.mRank; + } + infoElement["actorCell"] = mwDialogueInfo.mClass.serializeText(); + infoElement["actorDisposition"] = mwDialogueInfo.mData.mDisposition; + if (mwDialogueInfo.mData.mGender != ESM::DialInfo::Gender::NA) + { + infoElement["actorGender"] = mwDialogueInfo.mData.mGender; + } + infoElement["playerFaction"] = mwDialogueInfo.mPcFaction.serializeText(); + if (mwDialogueInfo.mData.mPCrank != -1) + { + infoElement["playerFactionRank"] = mwDialogueInfo.mData.mPCrank; + } + if (not mwDialogueInfo.mSound.empty()) + { + infoElement["sound"] = Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normalized(mwDialogueInfo.mSound)).value(); + } + //mResultScript TODO + //mSelects TODO + preparedInfos[index++] = infoElement; + } + + result["infos"] = LuaUtil::makeStrictReadOnly(preparedInfos); + return result; + } +} + +namespace MWLua +{ + + sol::table initCoreDialogueBindings(const Context& context) + { + sol::state_view& lua = context.mLua->sol(); + sol::table api(lua, sol::create); + + const MWWorld::Store& mwDialogueStore = MWBase::Environment::get().getESMStore()->get(); + + sol::table journalRecordsByQuestId(lua, sol::create); + sol::table topicRecordsByTopicId(lua, sol::create); + sol::table voiceRecordsById(lua, sol::create); + sol::table greetingRecordsById(lua, sol::create); + sol::table persuasionRecordsById(lua, sol::create); + for (const auto& mwDialogue : mwDialogueStore) + { + const auto dialogueRecordId = mwDialogue.mId.serializeText(); + if (mwDialogue.mType == ESM::Dialogue::Type::Journal) + { + journalRecordsByQuestId[dialogueRecordId] = prepareJournalRecord(lua, mwDialogue); + } + else if (mwDialogue.mType == ESM::Dialogue::Type::Topic) + { + topicRecordsByTopicId[dialogueRecordId] = prepareNonJournalRecord(lua, mwDialogue); + } + else if (mwDialogue.mType == ESM::Dialogue::Type::Voice) + { + voiceRecordsById[dialogueRecordId] = prepareNonJournalRecord(lua, mwDialogue); + } + else if (mwDialogue.mType == ESM::Dialogue::Type::Greeting) + { + greetingRecordsById[dialogueRecordId] = prepareNonJournalRecord(lua, mwDialogue); + } + else if (mwDialogue.mType == ESM::Dialogue::Type::Persuasion) + { + persuasionRecordsById[dialogueRecordId] = prepareNonJournalRecord(lua, mwDialogue); + } + } + api["journalRecords"] = LuaUtil::makeStrictReadOnly(journalRecordsByQuestId); + api["topicRecords"] = LuaUtil::makeStrictReadOnly(topicRecordsByTopicId); + api["voiceRecords"] = LuaUtil::makeStrictReadOnly(voiceRecordsById); + api["greetingRecords"] = LuaUtil::makeStrictReadOnly(greetingRecordsById); + api["persuasionRecords"] = LuaUtil::makeStrictReadOnly(persuasionRecordsById); + + return LuaUtil::makeReadOnly(api); + } +} diff --git a/apps/openmw/mwlua/dialoguebindings.hpp b/apps/openmw/mwlua/dialoguebindings.hpp new file mode 100644 index 0000000000..6909418e96 --- /dev/null +++ b/apps/openmw/mwlua/dialoguebindings.hpp @@ -0,0 +1,12 @@ +#ifndef MWLUA_DIALOGUEBINDINGS_H +#define MWLUA_DIALOGUEBINDINGS_H + +#include + +namespace MWLua +{ + struct Context; + sol::table initCoreDialogueBindings(const Context&); +} + +#endif // MWLUA_DIALOGUEBINDINGS_H