From 22817dd6a1619f47be545e2f8b34566bd113a13d Mon Sep 17 00:00:00 2001 From: elsid Date: Fri, 15 Nov 2024 01:25:40 +0100 Subject: [PATCH] Use normalized path for correctMeshPath --- apps/openmw/mwlua/types/activator.cpp | 6 ++-- apps/openmw/mwlua/types/apparatus.cpp | 6 ++-- apps/openmw/mwlua/types/armor.cpp | 5 +-- apps/openmw/mwlua/types/book.cpp | 8 ++--- apps/openmw/mwlua/types/clothing.cpp | 5 +-- apps/openmw/mwlua/types/container.cpp | 6 ++-- apps/openmw/mwlua/types/creature.cpp | 7 +++-- apps/openmw/mwlua/types/door.cpp | 8 ++--- apps/openmw/mwlua/types/ingredient.cpp | 6 ++-- apps/openmw/mwlua/types/light.cpp | 5 +-- apps/openmw/mwlua/types/lockpick.cpp | 5 +-- apps/openmw/mwlua/types/misc.cpp | 6 ++-- apps/openmw/mwlua/types/modelproperty.hpp | 21 +++++++++++++ apps/openmw/mwlua/types/npc.cpp | 7 +++-- apps/openmw/mwlua/types/potion.cpp | 5 +-- apps/openmw/mwlua/types/probe.cpp | 5 +-- apps/openmw/mwlua/types/repair.cpp | 5 +-- apps/openmw/mwlua/types/static.cpp | 5 +-- apps/openmw/mwlua/types/terminal.cpp | 6 ++-- apps/openmw/mwlua/types/weapon.cpp | 5 +-- apps/openmw/mwmechanics/activespells.cpp | 8 +++-- apps/openmw/mwmechanics/actors.cpp | 4 +-- apps/openmw/mwmechanics/character.cpp | 11 ++++--- apps/openmw/mwmechanics/spellcasting.cpp | 31 ++++++++++--------- apps/openmw/mwmechanics/spelleffects.cpp | 17 +++++++--- apps/openmw/mwmechanics/summoning.cpp | 4 ++- apps/openmw/mwrender/actoranimation.cpp | 2 +- apps/openmw/mwrender/esm4npcanimation.cpp | 2 +- apps/openmw/mwrender/npcanimation.cpp | 15 +++++---- apps/openmw/mwworld/cellpreloader.cpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/projectilemanager.cpp | 6 ++-- apps/openmw/mwworld/worldimp.cpp | 6 ++-- components/misc/resourcehelpers.cpp | 7 ++--- components/misc/resourcehelpers.hpp | 4 +-- .../integration_tests/test_lua_api/test.lua | 4 +-- 36 files changed, 155 insertions(+), 102 deletions(-) create mode 100644 apps/openmw/mwlua/types/modelproperty.hpp diff --git a/apps/openmw/mwlua/types/activator.cpp b/apps/openmw/mwlua/types/activator.cpp index e1c923d31a..a366256899 100644 --- a/apps/openmw/mwlua/types/activator.cpp +++ b/apps/openmw/mwlua/types/activator.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -49,9 +51,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Activator& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Activator& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property([](const ESM::Activator& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Activator& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/apparatus.cpp b/apps/openmw/mwlua/types/apparatus.cpp index d26f146096..c9953d87ad 100644 --- a/apps/openmw/mwlua/types/apparatus.cpp +++ b/apps/openmw/mwlua/types/apparatus.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -39,9 +41,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Apparatus& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Apparatus& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property([](const ESM::Apparatus& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Apparatus& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/armor.cpp b/apps/openmw/mwlua/types/armor.cpp index f26949c358..0acb517dbe 100644 --- a/apps/openmw/mwlua/types/armor.cpp +++ b/apps/openmw/mwlua/types/armor.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -96,8 +98,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Armor& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Armor& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Armor& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["icon"] = sol::readonly_property([vfs](const ESM::Armor& rec) -> std::string { return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); }); diff --git a/apps/openmw/mwlua/types/book.cpp b/apps/openmw/mwlua/types/book.cpp index f869971b9b..b133a90c3a 100644 --- a/apps/openmw/mwlua/types/book.cpp +++ b/apps/openmw/mwlua/types/book.cpp @@ -1,13 +1,14 @@ #include "types.hpp" -#include -#include +#include "modelproperty.hpp" #include #include #include #include #include +#include +#include #include #include "apps/openmw/mwbase/environment.hpp" @@ -104,8 +105,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Book& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Book& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property( [](const ESM::Book& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); record["icon"] = sol::readonly_property([vfs](const ESM::Book& rec) -> std::string { diff --git a/apps/openmw/mwlua/types/clothing.cpp b/apps/openmw/mwlua/types/clothing.cpp index 778beee97a..0085f05198 100644 --- a/apps/openmw/mwlua/types/clothing.cpp +++ b/apps/openmw/mwlua/types/clothing.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -91,8 +93,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Clothing& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Clothing& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Clothing& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["icon"] = sol::readonly_property([vfs](const ESM::Clothing& rec) -> std::string { return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); }); diff --git a/apps/openmw/mwlua/types/container.cpp b/apps/openmw/mwlua/types/container.cpp index 67c2c5c65c..9d3821ca48 100644 --- a/apps/openmw/mwlua/types/container.cpp +++ b/apps/openmw/mwlua/types/container.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -49,9 +51,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Container& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Container& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property([](const ESM::Container& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Container& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/creature.cpp b/apps/openmw/mwlua/types/creature.cpp index a171f147e6..4ebc658eb9 100644 --- a/apps/openmw/mwlua/types/creature.cpp +++ b/apps/openmw/mwlua/types/creature.cpp @@ -1,6 +1,8 @@ +#include "types.hpp" + #include "../stats.hpp" #include "actor.hpp" -#include "types.hpp" +#include "modelproperty.hpp" #include #include @@ -37,8 +39,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Creature& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Creature& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Creature& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Creature& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/door.cpp b/apps/openmw/mwlua/types/door.cpp index 7133690640..58a53a7124 100644 --- a/apps/openmw/mwlua/types/door.cpp +++ b/apps/openmw/mwlua/types/door.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include "../localscripts.hpp" #include @@ -107,8 +109,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Door& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Door& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property( [](const ESM::Door& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); record["openSound"] = sol::readonly_property( @@ -145,8 +146,7 @@ namespace MWLua record["id"] = sol::readonly_property( [](const ESM4::Door& rec) -> std::string { return ESM::RefId(rec.mId).serializeText(); }); record["name"] = sol::readonly_property([](const ESM4::Door& rec) -> std::string { return rec.mFullName; }); - record["model"] = sol::readonly_property( - [](const ESM4::Door& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["isAutomatic"] = sol::readonly_property( [](const ESM4::Door& rec) -> bool { return rec.mDoorFlags & ESM4::Door::Flag_AutomaticDoor; }); } diff --git a/apps/openmw/mwlua/types/ingredient.cpp b/apps/openmw/mwlua/types/ingredient.cpp index e05dc2bdb8..8e52a82b19 100644 --- a/apps/openmw/mwlua/types/ingredient.cpp +++ b/apps/openmw/mwlua/types/ingredient.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -31,9 +33,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Ingredient& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Ingredient& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property([](const ESM::Ingredient& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Ingredient& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/light.cpp b/apps/openmw/mwlua/types/light.cpp index 788f6d3e4e..41a0bf8d4a 100644 --- a/apps/openmw/mwlua/types/light.cpp +++ b/apps/openmw/mwlua/types/light.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -90,8 +92,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Light& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Light& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Light& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["icon"] = sol::readonly_property([vfs](const ESM::Light& rec) -> std::string { return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); }); diff --git a/apps/openmw/mwlua/types/lockpick.cpp b/apps/openmw/mwlua/types/lockpick.cpp index be25d855ec..3f41c65df2 100644 --- a/apps/openmw/mwlua/types/lockpick.cpp +++ b/apps/openmw/mwlua/types/lockpick.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -30,8 +32,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Lockpick& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Lockpick& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Lockpick& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Lockpick& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/misc.cpp b/apps/openmw/mwlua/types/misc.cpp index 2695abff9b..ef89464a2c 100644 --- a/apps/openmw/mwlua/types/misc.cpp +++ b/apps/openmw/mwlua/types/misc.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -81,9 +83,7 @@ namespace MWLua record["id"] = sol::readonly_property( [](const ESM::Miscellaneous& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Miscellaneous& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property([](const ESM::Miscellaneous& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); record["mwscript"] = sol::readonly_property([](const ESM::Miscellaneous& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); diff --git a/apps/openmw/mwlua/types/modelproperty.hpp b/apps/openmw/mwlua/types/modelproperty.hpp new file mode 100644 index 0000000000..7bb473ad81 --- /dev/null +++ b/apps/openmw/mwlua/types/modelproperty.hpp @@ -0,0 +1,21 @@ +#ifndef OPENMW_APPS_OPENMW_MWLUA_TYPES_MODELPROPERTY_H +#define OPENMW_APPS_OPENMW_MWLUA_TYPES_MODELPROPERTY_H + +#include +#include + +#include +#include + +namespace MWLua +{ + template + void addModelProperty(sol::usertype& recordType) + { + recordType["model"] = sol::readonly_property([](const T& recordValue) -> std::string { + return Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(recordValue.mModel)).value(); + }); + } +} + +#endif diff --git a/apps/openmw/mwlua/types/npc.cpp b/apps/openmw/mwlua/types/npc.cpp index c0cfbc90db..7cfcf6d704 100644 --- a/apps/openmw/mwlua/types/npc.cpp +++ b/apps/openmw/mwlua/types/npc.cpp @@ -1,6 +1,8 @@ -#include "actor.hpp" #include "types.hpp" +#include "actor.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -93,8 +95,7 @@ namespace MWLua = sol::readonly_property([](const ESM::NPC& rec) -> int { return (int)rec.mNpdt.mDisposition; }); record["head"] = sol::readonly_property([](const ESM::NPC& rec) -> std::string { return rec.mHead.serializeText(); }); - record["model"] = sol::readonly_property( - [](const ESM::NPC& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["isEssential"] = sol::readonly_property([](const ESM::NPC& rec) -> bool { return rec.mFlags & ESM::NPC::Essential; }); record["isMale"] = sol::readonly_property([](const ESM::NPC& rec) -> bool { return rec.isMale(); }); diff --git a/apps/openmw/mwlua/types/potion.cpp b/apps/openmw/mwlua/types/potion.cpp index 4ba3351cc4..4d04c8bb13 100644 --- a/apps/openmw/mwlua/types/potion.cpp +++ b/apps/openmw/mwlua/types/potion.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -76,8 +78,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Potion& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Potion& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Potion& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["icon"] = sol::readonly_property([vfs](const ESM::Potion& rec) -> std::string { return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); }); diff --git a/apps/openmw/mwlua/types/probe.cpp b/apps/openmw/mwlua/types/probe.cpp index 7ce269744f..4467f6617a 100644 --- a/apps/openmw/mwlua/types/probe.cpp +++ b/apps/openmw/mwlua/types/probe.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -30,8 +32,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Probe& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Probe& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Probe& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property( [](const ESM::Probe& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); record["icon"] = sol::readonly_property([vfs](const ESM::Probe& rec) -> std::string { diff --git a/apps/openmw/mwlua/types/repair.cpp b/apps/openmw/mwlua/types/repair.cpp index e44bdddd04..af95d187a8 100644 --- a/apps/openmw/mwlua/types/repair.cpp +++ b/apps/openmw/mwlua/types/repair.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -30,8 +32,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Repair& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Repair& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Repair& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["mwscript"] = sol::readonly_property( [](const ESM::Repair& rec) -> sol::optional { return LuaUtil::serializeRefId(rec.mScript); }); record["icon"] = sol::readonly_property([vfs](const ESM::Repair& rec) -> std::string { diff --git a/apps/openmw/mwlua/types/static.cpp b/apps/openmw/mwlua/types/static.cpp index b624db0276..7a4c0866eb 100644 --- a/apps/openmw/mwlua/types/static.cpp +++ b/apps/openmw/mwlua/types/static.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -24,7 +26,6 @@ namespace MWLua = [](const ESM::Static& rec) -> std::string { return "ESM3_Static[" + rec.mId.toDebugString() + "]"; }; record["id"] = sol::readonly_property([](const ESM::Static& rec) -> std::string { return rec.mId.serializeText(); }); - record["model"] = sol::readonly_property( - [](const ESM::Static& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); } } diff --git a/apps/openmw/mwlua/types/terminal.cpp b/apps/openmw/mwlua/types/terminal.cpp index 58a3170b0b..8abd52da74 100644 --- a/apps/openmw/mwlua/types/terminal.cpp +++ b/apps/openmw/mwlua/types/terminal.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -33,8 +35,6 @@ namespace MWLua record["resultText"] = sol::readonly_property([](const ESM4::Terminal& rec) -> std::string { return rec.mResultText; }); record["name"] = sol::readonly_property([](const ESM4::Terminal& rec) -> std::string { return rec.mFullName; }); - record["model"] = sol::readonly_property([](const ESM4::Terminal& rec) -> std::string { - return Misc::ResourceHelpers::correctMeshPath(rec.mModel); - }); + addModelProperty(record); } } diff --git a/apps/openmw/mwlua/types/weapon.cpp b/apps/openmw/mwlua/types/weapon.cpp index 51795cffc1..d5c52c8c4f 100644 --- a/apps/openmw/mwlua/types/weapon.cpp +++ b/apps/openmw/mwlua/types/weapon.cpp @@ -1,5 +1,7 @@ #include "types.hpp" +#include "modelproperty.hpp" + #include #include #include @@ -129,8 +131,7 @@ namespace MWLua record["id"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mId.serializeText(); }); record["name"] = sol::readonly_property([](const ESM::Weapon& rec) -> std::string { return rec.mName; }); - record["model"] = sol::readonly_property( - [](const ESM::Weapon& rec) -> std::string { return Misc::ResourceHelpers::correctMeshPath(rec.mModel); }); + addModelProperty(record); record["icon"] = sol::readonly_property([vfs](const ESM::Weapon& rec) -> std::string { return Misc::ResourceHelpers::correctIconPath(rec.mIcon, vfs); }); diff --git a/apps/openmw/mwmechanics/activespells.cpp b/apps/openmw/mwmechanics/activespells.cpp index b624b104ed..3cee16f29f 100644 --- a/apps/openmw/mwmechanics/activespells.cpp +++ b/apps/openmw/mwmechanics/activespells.cpp @@ -367,8 +367,12 @@ namespace MWMechanics ESM::RefId::stringRefId("VFX_Reflect")); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr); if (animation && !reflectStatic->mModel.empty()) - animation->addEffect(Misc::ResourceHelpers::correctMeshPath(reflectStatic->mModel), - ESM::MagicEffect::indexToName(ESM::MagicEffect::Reflect), false); + { + const VFS::Path::Normalized reflectStaticModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(reflectStatic->mModel)); + animation->addEffect( + reflectStaticModel, ESM::MagicEffect::indexToName(ESM::MagicEffect::Reflect), false); + } caster.getClass().getCreatureStats(caster).getActiveSpells().addSpell(*reflected); } if (removedSpell) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 401ba0ae86..bb3273981d 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -214,7 +214,7 @@ namespace const ESM::Static* const fx = world->getStore().get().search(ESM::RefId::stringRefId("VFX_Soul_Trap")); if (fx != nullptr) - world->spawnEffect(VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(fx->mModel)), "", + world->spawnEffect(Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(fx->mModel)), "", creature.getRefData().getPosition().asVec3()); MWBase::Environment::get().getSoundManager()->playSound3D( @@ -1806,7 +1806,7 @@ namespace MWMechanics ESM::RefId::stringRefId("VFX_Summon_End")); if (fx) MWBase::Environment::get().getWorld()->spawnEffect( - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(fx->mModel)), "", + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(fx->mModel)), "", ptr.getRefData().getPosition().asVec3()); // Remove the summoned creature's summoned creatures as well diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index ed4eb9e0ec..da3f3dbeec 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1590,13 +1590,16 @@ namespace MWMechanics const ESM::Static* castStatic = world->getStore().get().find(ESM::RefId::stringRefId("VFX_Hands")); + const VFS::Path::Normalized castStaticModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(castStatic->mModel)); + if (mAnimation->getNode("Bip01 L Hand")) - mAnimation->addEffect(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel), - "", false, "Bip01 L Hand", effect->mParticle); + mAnimation->addEffect( + castStaticModel.value(), "", false, "Bip01 L Hand", effect->mParticle); if (mAnimation->getNode("Bip01 R Hand")) - mAnimation->addEffect(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel), - "", false, "Bip01 R Hand", effect->mParticle); + mAnimation->addEffect( + castStaticModel.value(), "", false, "Bip01 R Hand", effect->mParticle); } // first effect used for casting animation const ESM::ENAMstruct& firstEffect = effects->front().mData; diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 1d847a4129..dd3892e2d9 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -72,12 +72,12 @@ namespace MWMechanics { if (effectInfo.mData.mRange == ESM::RT_Target) world->spawnEffect( - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel)), texture, + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(areaStatic->mModel)), texture, mHitPosition, 1.0f); continue; } else - world->spawnEffect(VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(areaStatic->mModel)), + world->spawnEffect(Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(areaStatic->mModel)), texture, mHitPosition, static_cast(effectInfo.mData.mArea * 2)); // Play explosion sound (make sure to use NoTrack, since we will delete the projectile now) @@ -487,7 +487,7 @@ namespace MWMechanics void CastSpell::playSpellCastingEffects(const std::vector& effects) const { const MWWorld::ESMStore& store = *MWBase::Environment::get().getESMStore(); - std::vector addedEffects; + std::vector addedEffects; for (const ESM::IndexedENAMstruct& effectData : effects) { @@ -500,17 +500,18 @@ namespace MWMechanics else castStatic = store.get().find(ESM::RefId::stringRefId("VFX_DefaultCast")); + VFS::Path::Normalized castStaticModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(castStatic->mModel)); + // check if the effect was already added - if (std::find(addedEffects.begin(), addedEffects.end(), - Misc::ResourceHelpers::correctMeshPath(castStatic->mModel)) - != addedEffects.end()) + if (std::find(addedEffects.begin(), addedEffects.end(), castStaticModel) != addedEffects.end()) continue; MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(mCaster); if (animation) { - animation->addEffect(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel), - ESM::MagicEffect::indexToName(effect->mIndex), false, {}, effect->mParticle); + animation->addEffect(castStaticModel.value(), ESM::MagicEffect::indexToName(effect->mIndex), false, {}, + effect->mParticle); } else { @@ -539,15 +540,13 @@ namespace MWMechanics scale *= npcScaleVec.z(); } scale = std::max(scale, 1.f); - MWBase::Environment::get().getWorld()->spawnEffect( - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel)), - effect->mParticle, pos, scale); + MWBase::Environment::get().getWorld()->spawnEffect(castStaticModel, effect->mParticle, pos, scale); } if (animation && !mCaster.getClass().isActor()) animation->addSpellCastGlow(effect->getColor()); - addedEffects.push_back(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel)); + addedEffects.push_back(std::move(castStaticModel)); MWBase::SoundManager* sndMgr = MWBase::Environment::get().getSoundManager(); if (!effect->mCastSound.empty()) @@ -584,8 +583,12 @@ namespace MWMechanics { // Don't play particle VFX unless the effect is new or it should be looping. if (playNonLooping || loop) - anim->addEffect(Misc::ResourceHelpers::correctMeshPath(castStatic->mModel), - ESM::MagicEffect::indexToName(magicEffect.mIndex), loop, {}, magicEffect.mParticle); + { + const VFS::Path::Normalized castStaticModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(castStatic->mModel)); + anim->addEffect(castStaticModel.value(), ESM::MagicEffect::indexToName(magicEffect.mIndex), loop, {}, + magicEffect.mParticle); + } } } } diff --git a/apps/openmw/mwmechanics/spelleffects.cpp b/apps/openmw/mwmechanics/spelleffects.cpp index 96044ebc5b..7035c7f61c 100644 --- a/apps/openmw/mwmechanics/spelleffects.cpp +++ b/apps/openmw/mwmechanics/spelleffects.cpp @@ -286,8 +286,13 @@ namespace const ESM::Static* absorbStatic = esmStore.get().find(ESM::RefId::stringRefId("VFX_Absorb")); MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(target); if (animation && !absorbStatic->mModel.empty()) - animation->addEffect(Misc::ResourceHelpers::correctMeshPath(absorbStatic->mModel), - ESM::MagicEffect::indexToName(ESM::MagicEffect::SpellAbsorption), false); + { + const VFS::Path::Normalized absorbStaticModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(absorbStatic->mModel)); + animation->addEffect( + absorbStaticModel.value(), ESM::MagicEffect::indexToName(ESM::MagicEffect::SpellAbsorption), false); + } + int spellCost = 0; if (const ESM::Spell* spell = esmStore.get().search(spellParams.getSourceSpellId())) { @@ -455,8 +460,12 @@ namespace MWMechanics anim->removeEffect(ESM::MagicEffect::indexToName(effect.mEffectId)); const ESM::Static* fx = world->getStore().get().search(ESM::RefId::stringRefId("VFX_Summon_end")); - if (fx) - anim->addEffect(Misc::ResourceHelpers::correctMeshPath(fx->mModel), ""); + if (fx != nullptr) + { + const VFS::Path::Normalized fxModel + = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(fx->mModel)); + anim->addEffect(fxModel.value(), ""); + } } } else if (caster == getPlayer()) diff --git a/apps/openmw/mwmechanics/summoning.cpp b/apps/openmw/mwmechanics/summoning.cpp index e4b9e953aa..78d4976040 100644 --- a/apps/openmw/mwmechanics/summoning.cpp +++ b/apps/openmw/mwmechanics/summoning.cpp @@ -105,7 +105,9 @@ namespace MWMechanics const ESM::Static* fx = world->getStore().get().search(ESM::RefId::stringRefId("VFX_Summon_Start")); if (fx) - anim->addEffect(Misc::ResourceHelpers::correctMeshPath(fx->mModel), "", false); + anim->addEffect( + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(fx->mModel)).value(), "", + false); } } catch (std::exception& e) diff --git a/apps/openmw/mwrender/actoranimation.cpp b/apps/openmw/mwrender/actoranimation.cpp index 73582aa15a..9d68bf9bbd 100644 --- a/apps/openmw/mwrender/actoranimation.cpp +++ b/apps/openmw/mwrender/actoranimation.cpp @@ -131,7 +131,7 @@ namespace MWRender if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor) return std::string(); if (!bodypart->mModel.empty()) - return Misc::ResourceHelpers::correctMeshPath(bodypart->mModel); + return Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bodypart->mModel)).value(); } } } diff --git a/apps/openmw/mwrender/esm4npcanimation.cpp b/apps/openmw/mwrender/esm4npcanimation.cpp index 3bff588343..d0b54adb8f 100644 --- a/apps/openmw/mwrender/esm4npcanimation.cpp +++ b/apps/openmw/mwrender/esm4npcanimation.cpp @@ -53,7 +53,7 @@ namespace MWRender if (model.empty()) return; mResourceSystem->getSceneManager()->getInstance( - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(model)), mObjectRoot.get()); + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(model)), mObjectRoot.get()); } template diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 58bd3734ee..c14eee27e4 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -78,7 +78,7 @@ namespace const ESM::BodyPart* bodyPart = sVampireMapping[thisCombination]; if (!bodyPart) return std::string(); - return Misc::ResourceHelpers::correctMeshPath(bodyPart->mModel); + return Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bodyPart->mModel)).value(); } } @@ -463,7 +463,7 @@ namespace MWRender { const ESM::BodyPart* bp = store.get().search(headName); if (bp) - mHeadModel = Misc::ResourceHelpers::correctMeshPath(bp->mModel); + mHeadModel = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bp->mModel)); else Log(Debug::Warning) << "Warning: Failed to load body part '" << headName << "'"; } @@ -472,7 +472,7 @@ namespace MWRender { const ESM::BodyPart* bp = store.get().search(hairName); if (bp) - mHairModel = Misc::ResourceHelpers::correctMeshPath(bp->mModel); + mHairModel = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bp->mModel)); else Log(Debug::Warning) << "Warning: Failed to load body part '" << hairName << "'"; } @@ -501,7 +501,7 @@ namespace MWRender bool isCustomModel = false; if (!is1stPerson && !isWerewolf && !mNpc->mModel.empty()) { - VFS::Path::Normalized model = Misc::ResourceHelpers::correctMeshPath(mNpc->mModel); + VFS::Path::Normalized model = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(mNpc->mModel)); isCustomModel = !isDefaultActorSkeleton(model); smodel = Misc::ResourceHelpers::correctActorModelPath(model, mResourceSystem->getVFS()); } @@ -648,8 +648,7 @@ namespace MWRender { const ESM::Light* light = part.get()->mBase; addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(light->mModel)), false, nullptr, - true); + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(light->mModel)), false, nullptr, true); if (mObjectParts[ESM::PRT_Shield]) addExtraLight(mObjectParts[ESM::PRT_Shield]->getNode()->asGroup(), SceneUtil::LightCommon(*light)); } @@ -669,7 +668,7 @@ namespace MWRender { if (const ESM::BodyPart* bodypart = parts[part]) addOrReplaceIndividualPart(static_cast(part), -1, 1, - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(bodypart->mModel))); + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bodypart->mModel))); } } @@ -899,7 +898,7 @@ namespace MWRender if (bodypart) addOrReplaceIndividualPart(static_cast(part.mPart), group, priority, - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(bodypart->mModel)), enchantedGlow, + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(bodypart->mModel)), enchantedGlow, glowColor); else reserveIndividualPart((ESM::PartReferenceType)part.mPart, group, priority); diff --git a/apps/openmw/mwworld/cellpreloader.cpp b/apps/openmw/mwworld/cellpreloader.cpp index e54e9d84df..5540982f26 100644 --- a/apps/openmw/mwworld/cellpreloader.cpp +++ b/apps/openmw/mwworld/cellpreloader.cpp @@ -116,7 +116,7 @@ namespace MWWorld try { const VFS::Manager& vfs = *mSceneManager->getVFS(); - mesh = Misc::ResourceHelpers::correctMeshPath(path); + mesh = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(path)); mesh = Misc::ResourceHelpers::correctActorModelPath(mesh, &vfs); if (!vfs.exists(mesh)) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index a1eec196eb..26100551e8 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -315,7 +315,7 @@ namespace MWWorld { std::string_view model = getModel(ptr); if (!model.empty()) - return Misc::ResourceHelpers::correctMeshPath(model); + return Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(model)); return {}; } diff --git a/apps/openmw/mwworld/projectilemanager.cpp b/apps/openmw/mwworld/projectilemanager.cpp index 382453e713..b019dabdfe 100644 --- a/apps/openmw/mwworld/projectilemanager.cpp +++ b/apps/openmw/mwworld/projectilemanager.cpp @@ -222,7 +222,7 @@ namespace MWWorld attachTo->accept(findVisitor); if (findVisitor.mFoundNode) mResourceSystem->getSceneManager()->getInstance( - VFS::Path::toNormalized(Misc::ResourceHelpers::correctMeshPath(weapon->mModel)), + Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized(weapon->mModel)), findVisitor.mFoundNode); } } @@ -330,8 +330,8 @@ namespace MWWorld // shape if (state.mIdMagic.size() > 1) { - model = Misc::ResourceHelpers::correctMeshPath( - MWBase::Environment::get().getESMStore()->get().find(state.mIdMagic[1])->mModel); + model = Misc::ResourceHelpers::correctMeshPath(VFS::Path::Normalized( + MWBase::Environment::get().getESMStore()->get().find(state.mIdMagic[1])->mModel)); } state.mProjectileId = mPhysics->addProjectile(caster, pos, model, true); state.mToDelete = false; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index a86af4c920..cfbf8311ee 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3682,8 +3682,10 @@ namespace MWWorld if (texture.empty()) texture = Fallback::Map::getString("Blood_Texture_0"); - VFS::Path::Normalized model(Misc::ResourceHelpers::correctMeshPath(std::string{ - Fallback::Map::getString("Blood_Model_" + std::to_string(Misc::Rng::rollDice(3))) } /*[0, 2]*/)); + // [0, 2] + const int number = Misc::Rng::rollDice(3); + const VFS::Path::Normalized model = Misc::ResourceHelpers::correctMeshPath( + VFS::Path::Normalized(Fallback::Map::getString("Blood_Model_" + std::to_string(number)))); mRendering->spawnEffect(model, texture, worldPosition, 1.0f, false); } diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp index 383f69439a..5279e2ad23 100644 --- a/components/misc/resourcehelpers.cpp +++ b/components/misc/resourcehelpers.cpp @@ -167,11 +167,10 @@ std::string Misc::ResourceHelpers::correctMaterialPath(std::string_view resPath, return correctResourcePath({ { "materials" } }, resPath, vfs); } -std::string Misc::ResourceHelpers::correctMeshPath(std::string_view resPath) +VFS::Path::Normalized Misc::ResourceHelpers::correctMeshPath(VFS::Path::NormalizedView resPath) { - std::string res = "meshes\\"; - res.append(resPath); - return res; + static constexpr VFS::Path::NormalizedView prefix("meshes"); + return prefix / resPath; } VFS::Path::Normalized Misc::ResourceHelpers::correctSoundPath(VFS::Path::NormalizedView resPath) diff --git a/components/misc/resourcehelpers.hpp b/components/misc/resourcehelpers.hpp index ba1609edb6..9aaa89a861 100644 --- a/components/misc/resourcehelpers.hpp +++ b/components/misc/resourcehelpers.hpp @@ -36,8 +36,8 @@ namespace Misc VFS::Path::Normalized correctActorModelPath(VFS::Path::NormalizedView resPath, const VFS::Manager* vfs); std::string correctMaterialPath(std::string_view resPath, const VFS::Manager* vfs); - // Adds "meshes\\". - std::string correctMeshPath(std::string_view resPath); + // Prepends "meshes/". + VFS::Path::Normalized correctMeshPath(VFS::Path::NormalizedView resPath); // Prepends "sound/". VFS::Path::Normalized correctSoundPath(VFS::Path::NormalizedView resPath); diff --git a/scripts/data/integration_tests/test_lua_api/test.lua b/scripts/data/integration_tests/test_lua_api/test.lua index 82f3468494..78f2d956f7 100644 --- a/scripts/data/integration_tests/test_lua_api/test.lua +++ b/scripts/data/integration_tests/test_lua_api/test.lua @@ -158,7 +158,7 @@ local function testRecordCreation() radius = 30, color = 5, name = "TestLight", - model = "meshes\\marker_door.dae" + model = "meshes/marker_door.dae" } local draft = types.Light.createRecordDraft(newLight) local record = world.createRecord(draft) @@ -287,7 +287,7 @@ end local function testRecordModelProperty() initPlayer() local player = world.players[1] - testing.expectEqual(types.NPC.record(player).model, 'meshes\\basicplayer.dae') + testing.expectEqual(types.NPC.record(player).model, 'meshes/basicplayer.dae') end tests = {