1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-03-23 19:20:56 +00:00

ESM::Dialogue Lua bindings 4

This commit is contained in:
trav5 2024-04-20 15:47:34 +02:00
parent d14fc1d28c
commit 3bb7bf1a4a

View File

@ -1,10 +1,10 @@
#include "dialoguebindings.hpp" #include "dialoguebindings.hpp"
#include <algorithm>
#include "apps/openmw/mwbase/environment.hpp" #include "apps/openmw/mwbase/environment.hpp"
#include "apps/openmw/mwworld/esmstore.hpp" #include "apps/openmw/mwworld/esmstore.hpp"
#include "apps/openmw/mwworld/store.hpp" #include "apps/openmw/mwworld/store.hpp"
#include "context.hpp" #include "context.hpp"
#include "object.hpp" #include "object.hpp"
#include <algorithm>
#include <components/esm3/loaddial.hpp> #include <components/esm3/loaddial.hpp>
#include <components/lua/luastate.hpp> #include <components/lua/luastate.hpp>
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
@ -25,19 +25,23 @@ namespace
} }
return nullptr; return nullptr;
} }
public: public:
FilteredDialogueStore() FilteredDialogueStore()
: mDialogueStore{MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>()} : mDialogueStore{ MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>() }
{} {
}
class FilteredDialogueIterator class FilteredDialogueIterator
{ {
using DecoratedIterator = MWWorld::Store<ESM::Dialogue>::iterator; using DecoratedIterator = MWWorld::Store<ESM::Dialogue>::iterator;
DecoratedIterator mIter; DecoratedIterator mIter;
public: public:
FilteredDialogueIterator(const DecoratedIterator& decoratedIterator) FilteredDialogueIterator(const DecoratedIterator& decoratedIterator)
: mIter{decoratedIterator} : mIter{ decoratedIterator }
{} {
}
FilteredDialogueIterator& operator++() FilteredDialogueIterator& operator++()
{ {
@ -60,7 +64,7 @@ namespace
bool operator==(const FilteredDialogueIterator& x) const { return mIter == x.mIter; } bool operator==(const FilteredDialogueIterator& x) const { return mIter == x.mIter; }
bool operator!=(const FilteredDialogueIterator& x) const { return not (*this == x); } bool operator!=(const FilteredDialogueIterator& x) const { return not(*this == x); }
const ESM::Dialogue& operator*() const { return *mIter; } const ESM::Dialogue& operator*() const { return *mIter; }
@ -88,12 +92,13 @@ namespace
size_t getSize() const size_t getSize() const
{ {
return std::count_if(mDialogueStore.begin(), mDialogueStore.end(), [this](const auto& d) { return d.mType == filter; }); return std::count_if(
mDialogueStore.begin(), mDialogueStore.end(), [this](const auto& d) { return d.mType == filter; });
} }
iterator begin() const iterator begin() const
{ {
iterator result{mDialogueStore.begin()}; iterator result{ mDialogueStore.begin() };
while (result != end() and result->mType != filter) while (result != end() and result->mType != filter)
{ {
std::advance(result, 1); std::advance(result, 1);
@ -101,10 +106,7 @@ namespace
return result; return result;
} }
iterator end() const iterator end() const { return iterator{ mDialogueStore.end() }; }
{
return iterator{mDialogueStore.end()};
}
}; };
template <ESM::Dialogue::Type filter> template <ESM::Dialogue::Type filter>
@ -114,29 +116,26 @@ namespace
table["record"] = sol::overload( table["record"] = sol::overload(
[](const MWLua::Object& obj) -> const ESM::Dialogue* { return obj.ptr().get<ESM::Dialogue>()->mBase; }, [](const MWLua::Object& obj) -> const ESM::Dialogue* { return obj.ptr().get<ESM::Dialogue>()->mBase; },
[](std::string_view id) -> const ESM::Dialogue* [](std::string_view id) -> const ESM::Dialogue* {
{
return StoreT{}.search(ESM::RefId::deserializeText(Misc::StringUtils::lowerCase(id))); return StoreT{}.search(ESM::RefId::deserializeText(Misc::StringUtils::lowerCase(id)));
}); });
sol::state_view& lua = context.mLua->sol(); sol::state_view& lua = context.mLua->sol();
sol::usertype<StoreT> storeBindingsClass = lua.new_usertype<StoreT>("ESM3_Dialogue_Type" + std::to_string(filter) + " Store"); sol::usertype<StoreT> storeBindingsClass
storeBindingsClass[sol::meta_function::to_string] = [](const StoreT& store) = lua.new_usertype<StoreT>("ESM3_Dialogue_Type" + std::to_string(filter) + " Store");
{ storeBindingsClass[sol::meta_function::to_string] = [](const StoreT& store) {
return "{" + std::to_string(store.getSize()) + " ESM3_Dialogue_Type" + std::to_string(filter) + " records}"; return "{" + std::to_string(store.getSize()) + " ESM3_Dialogue_Type" + std::to_string(filter) + " records}";
}; };
storeBindingsClass[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); }; storeBindingsClass[sol::meta_function::length] = [](const StoreT& store) { return store.getSize(); };
storeBindingsClass[sol::meta_function::index] = sol::overload( storeBindingsClass[sol::meta_function::index] = sol::overload(
[](const StoreT& store, size_t index) -> const ESM::Dialogue* [](const StoreT& store, size_t index) -> const ESM::Dialogue* {
{
if (index == 0 or index > store.getSize()) if (index == 0 or index > store.getSize())
{ {
return nullptr; return nullptr;
} }
return store.at(index - 1); return store.at(index - 1);
}, },
[](const StoreT& store, std::string_view id) -> const ESM::Dialogue* [](const StoreT& store, std::string_view id) -> const ESM::Dialogue* {
{
return store.search(ESM::RefId::deserializeText(Misc::StringUtils::lowerCase(id))); return store.search(ESM::RefId::deserializeText(Misc::StringUtils::lowerCase(id)));
}); });
storeBindingsClass[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>(); storeBindingsClass[sol::meta_function::ipairs] = lua["ipairsForArray"].template get<sol::function>();
@ -151,7 +150,7 @@ namespace
const ESM::Dialogue* getDialogueRecord() const const ESM::Dialogue* getDialogueRecord() const
{ {
const auto& dialogueStore{MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>()}; const auto& dialogueStore{ MWBase::Environment::get().getESMStore()->get<ESM::Dialogue>() };
return dialogueStore.search(mDialogueRecordId); return dialogueStore.search(mDialogueRecordId);
} }
}; };
@ -159,20 +158,14 @@ namespace
void prepareBindingsForDialogueRecord(sol::state_view& lua) void prepareBindingsForDialogueRecord(sol::state_view& lua)
{ {
auto recordBindingsClass = lua.new_usertype<ESM::Dialogue>("ESM3_Dialogue"); auto recordBindingsClass = lua.new_usertype<ESM::Dialogue>("ESM3_Dialogue");
recordBindingsClass[sol::meta_function::to_string] = [lua](const ESM::Dialogue& rec) -> sol::object recordBindingsClass[sol::meta_function::to_string] = [lua](const ESM::Dialogue& rec) -> sol::object {
{
return sol::make_object(lua, "ESM3_Dialogue[" + rec.mId.toDebugString() + "]"); return sol::make_object(lua, "ESM3_Dialogue[" + rec.mId.toDebugString() + "]");
}; };
recordBindingsClass["id"] = sol::readonly_property([lua](const ESM::Dialogue& rec) recordBindingsClass["id"] = sol::readonly_property(
{ [lua](const ESM::Dialogue& rec) { return sol::make_object(lua, rec.mId.serializeText()); });
return sol::make_object(lua, rec.mId.serializeText()); recordBindingsClass["name"]
}); = sol::readonly_property([lua](const ESM::Dialogue& rec) { return sol::make_object(lua, rec.mStringId); });
recordBindingsClass["name"] = sol::readonly_property([lua](const ESM::Dialogue& rec) recordBindingsClass["questName"] = sol::readonly_property([lua](const ESM::Dialogue& rec) -> sol::object {
{
return sol::make_object(lua, rec.mStringId);
});
recordBindingsClass["questName"] = sol::readonly_property([lua](const ESM::Dialogue& rec) -> sol::object
{
if (rec.mType != ESM::Dialogue::Type::Journal) if (rec.mType != ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
@ -186,36 +179,34 @@ namespace
} }
return sol::nil; return sol::nil;
}); });
recordBindingsClass["infos"] = sol::readonly_property([lua](const ESM::Dialogue& rec) recordBindingsClass["infos"]
{ = sol::readonly_property([lua](const ESM::Dialogue& rec) { return DialogueInfos{ rec.mId }; });
return DialogueInfos{rec.mId};
});
} }
void prepareBindingsForDialogueRecordInfoList(sol::state_view& lua) void prepareBindingsForDialogueRecordInfoList(sol::state_view& lua)
{ {
auto recordInfosBindingsClass = lua.new_usertype<DialogueInfos>("ESM3_Dialogue_Infos"); auto recordInfosBindingsClass = lua.new_usertype<DialogueInfos>("ESM3_Dialogue_Infos");
recordInfosBindingsClass[sol::meta_function::to_string] = [lua](const DialogueInfos& store) -> sol::object recordInfosBindingsClass[sol::meta_function::to_string] = [lua](const DialogueInfos& store) -> sol::object {
{
if (const ESM::Dialogue* dialogueRecord = store.getDialogueRecord()) if (const ESM::Dialogue* dialogueRecord = store.getDialogueRecord())
{ {
return sol::make_object(lua, "{" + std::to_string(dialogueRecord->mInfo.size()) + " ESM3_Dialogue[" + dialogueRecord->mId.toDebugString() + "] info elements}"); return sol::make_object(lua,
"{" + std::to_string(dialogueRecord->mInfo.size()) + " ESM3_Dialogue["
+ dialogueRecord->mId.toDebugString() + "] info elements}");
} }
return sol::nil; return sol::nil;
}; };
recordInfosBindingsClass[sol::meta_function::length] = [](const DialogueInfos& store) recordInfosBindingsClass[sol::meta_function::length] = [](const DialogueInfos& store) {
{
const ESM::Dialogue* dialogueRecord = store.getDialogueRecord(); const ESM::Dialogue* dialogueRecord = store.getDialogueRecord();
return dialogueRecord ? dialogueRecord->mInfo.size() : 0; return dialogueRecord ? dialogueRecord->mInfo.size() : 0;
}; };
recordInfosBindingsClass[sol::meta_function::index] = [](const DialogueInfos& store, size_t index) -> const ESM::DialInfo* recordInfosBindingsClass[sol::meta_function::index]
{ = [](const DialogueInfos& store, size_t index) -> const ESM::DialInfo* {
const ESM::Dialogue* dialogueRecord = store.getDialogueRecord(); const ESM::Dialogue* dialogueRecord = store.getDialogueRecord();
if (not dialogueRecord or index == 0 or index > dialogueRecord->mInfo.size()) if (not dialogueRecord or index == 0 or index > dialogueRecord->mInfo.size())
{ {
return nullptr; return nullptr;
} }
ESM::Dialogue::InfoContainer::const_iterator iter{dialogueRecord->mInfo.cbegin()}; ESM::Dialogue::InfoContainer::const_iterator iter{ dialogueRecord->mInfo.cbegin() };
std::advance(iter, index - 1); std::advance(iter, index - 1);
return &(*iter); return &(*iter);
}; };
@ -227,141 +218,137 @@ namespace
{ {
auto recordInfoBindingsClass = lua.new_usertype<ESM::DialInfo>("ESM3_Dialogue_Info"); auto recordInfoBindingsClass = lua.new_usertype<ESM::DialInfo>("ESM3_Dialogue_Info");
recordInfoBindingsClass[sol::meta_function::to_string] = [lua](const ESM::DialInfo& rec) recordInfoBindingsClass[sol::meta_function::to_string] = [lua](const ESM::DialInfo& rec) {
{
return sol::make_object(lua, "ESM3_Dialogue_Info[" + rec.mId.toDebugString() + "]"); return sol::make_object(lua, "ESM3_Dialogue_Info[" + rec.mId.toDebugString() + "]");
}; };
recordInfoBindingsClass["id"] = sol::readonly_property([lua](const ESM::DialInfo& rec) recordInfoBindingsClass["id"] = sol::readonly_property(
{ [lua](const ESM::DialInfo& rec) { return sol::make_object(lua, rec.mId.serializeText()); });
return sol::make_object(lua, rec.mId.serializeText()); recordInfoBindingsClass["text"]
}); = sol::readonly_property([lua](const ESM::DialInfo& rec) { return sol::make_object(lua, rec.mResponse); });
recordInfoBindingsClass["text"] = sol::readonly_property([lua](const ESM::DialInfo& rec) recordInfoBindingsClass["questStage"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
{
return sol::make_object(lua, rec.mResponse);
});
recordInfoBindingsClass["questStage"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object
{
if (rec.mData.mType != ESM::Dialogue::Type::Journal) if (rec.mData.mType != ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
return sol::make_object(lua, rec.mData.mJournalIndex); return sol::make_object(lua, rec.mData.mJournalIndex);
}); });
recordInfoBindingsClass["questFinished"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["questFinished"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType != ESM::Dialogue::Type::Journal) if (rec.mData.mType != ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
return sol::make_object(lua, rec.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Finished); return sol::make_object(lua, rec.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Finished);
}); });
recordInfoBindingsClass["questRestart"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["questRestart"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType != ESM::Dialogue::Type::Journal) if (rec.mData.mType != ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
return sol::make_object(lua, rec.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Restart); return sol::make_object(lua, rec.mQuestStatus == ESM::DialInfo::QuestStatus::QS_Restart);
}); });
recordInfoBindingsClass["filterActorId"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorId"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mActor.serializeText(); const auto result = rec.mActor.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorRace"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorRace"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mRace.serializeText(); const auto result = rec.mRace.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorClass"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorClass"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mClass.serializeText(); const auto result = rec.mClass.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorFaction"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorFaction"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mFaction.serializeText(); const auto result = rec.mFaction.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorFactionRank"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorFactionRank"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mData.mRank; const auto result = rec.mData.mRank;
return result == -1 ? sol::nil : sol::make_object(lua, result); return result == -1 ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorCell"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorCell"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mCell.serializeText(); const auto result = rec.mCell.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterActorDisposition"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorDisposition"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
return sol::make_object(lua, rec.mData.mDisposition); return sol::make_object(lua, rec.mData.mDisposition);
}); });
recordInfoBindingsClass["filterActorGender"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterActorGender"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mData.mGender; const auto result = rec.mData.mGender;
return result == -1 ? sol::nil : sol::make_object(lua, result); return result == -1 ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterPlayerFaction"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterPlayerFaction"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mPcFaction.serializeText(); const auto result = rec.mPcFaction.serializeText();
return result.empty() ? sol::nil : sol::make_object(lua, result); return result.empty() ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["filterPlayerFactionRank"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["filterPlayerFactionRank"]
{ = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
if (rec.mData.mType == ESM::Dialogue::Type::Journal) if (rec.mData.mType == ESM::Dialogue::Type::Journal)
{ {
return sol::nil; return sol::nil;
} }
const auto result = rec.mData.mPCrank; const auto result = rec.mData.mPCrank;
return result == -1 ? sol::nil : sol::make_object(lua, result); return result == -1 ? sol::nil : sol::make_object(lua, result);
}); });
recordInfoBindingsClass["sound"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object recordInfoBindingsClass["sound"] = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
{
if (rec.mData.mType == ESM::Dialogue::Type::Journal or rec.mSound == "") if (rec.mData.mType == ESM::Dialogue::Type::Journal or rec.mSound == "")
{ {
return sol::nil; return sol::nil;
} }
return sol::make_object(lua, Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normalized(rec.mSound)).value()); return sol::make_object(
lua, Misc::ResourceHelpers::correctSoundPath(VFS::Path::Normalized(rec.mSound)).value());
}); });
// // mResultScript TODO recordInfoBindingsClass["resultScript"]
// // mSelects TODO = sol::readonly_property([lua](const ESM::DialInfo& rec) -> sol::object {
return rec.mResultScript.empty() ? sol::nil : sol::make_object(lua, rec.mResultScript);
});
} }
void prepareBindingsForDialogueRecords(sol::state_view& lua) void prepareBindingsForDialogueRecords(sol::state_view& lua)