mirror of
https://github.com/OpenMW/openmw.git
synced 2025-10-14 15:56:34 +00:00
Merge branch 'master' of https://gitlab.com/OpenMW/openmw
This commit is contained in:
commit
8e76a0ab06
146 changed files with 928 additions and 499 deletions
|
@ -108,8 +108,8 @@ Coverity:
|
|||
- ccache/
|
||||
variables:
|
||||
CCACHE_SIZE: 2G
|
||||
CC: clang-12
|
||||
CXX: clang++-12
|
||||
CC: clang
|
||||
CXX: clang++
|
||||
CMAKE_BUILD_TYPE: Debug
|
||||
CMAKE_CXX_FLAGS_DEBUG: -O0
|
||||
before_script:
|
||||
|
@ -125,18 +125,34 @@ Coverity:
|
|||
- ccache -z -M "${CCACHE_SIZE}"
|
||||
- CI/before_script.linux.sh
|
||||
- cov-analysis-linux64-*/bin/cov-configure --template --comptype prefix --compiler ccache
|
||||
# Remove the specific targets and build everything once we can do it under 3h
|
||||
- cov-analysis-linux64-*/bin/cov-build --dir cov-int cmake --build build -- -j $(nproc)
|
||||
- ccache -svv
|
||||
after_script:
|
||||
- tar cfz cov-int.tar.gz cov-int
|
||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
||||
--form file=@cov-int.tar.gz --form version="$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA"
|
||||
--form description="CI_COMMIT_SHORT_SHA / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
||||
- echo "OPENMW_JOB_ID=$CI_JOB_ID" >> build.env
|
||||
artifacts:
|
||||
expire_in: 1 day
|
||||
paths:
|
||||
- /builds/OpenMW/openmw/cov-int/build-log.txt
|
||||
- /builds/OpenMW/openmw/cov-int.tar.gz
|
||||
reports:
|
||||
dotenv: build.env
|
||||
|
||||
Coverity_Upload:
|
||||
image: ubuntu:24.04
|
||||
stage: build
|
||||
rules:
|
||||
- if: $CI_PIPELINE_SOURCE == "schedule"
|
||||
before_script:
|
||||
- CI/install_debian_deps.sh coverity_upload
|
||||
script:
|
||||
- echo "$CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/$OPENMW_JOB_ID/artifacts/cov-int.tar.gz"
|
||||
- curl https://scan.coverity.com/builds?project=$COVERITY_SCAN_PROJECT_NAME
|
||||
--form token=$COVERITY_SCAN_TOKEN --form email=$GITLAB_USER_EMAIL
|
||||
--form version="$CI_COMMIT_REF_NAME:$CI_COMMIT_SHORT_SHA"
|
||||
--form description="CI_COMMIT_SHORT_SHA / $CI_COMMIT_TITLE / $CI_COMMIT_REF_NAME:$CI_PIPELINE_ID"
|
||||
--form url="$CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/$OPENMW_JOB_ID/artifacts/cov-int.tar.gz"
|
||||
needs:
|
||||
- Coverity
|
||||
|
||||
Ubuntu_GCC:
|
||||
extends: .Ubuntu
|
||||
|
|
|
@ -11,7 +11,8 @@ print_help() {
|
|||
declare -rA GROUPED_DEPS=(
|
||||
[gcc]="binutils gcc build-essential cmake ccache curl unzip git pkg-config mold"
|
||||
[clang]="binutils clang make cmake ccache curl unzip git pkg-config mold"
|
||||
[coverity]="binutils clang-12 make cmake ccache curl unzip git pkg-config"
|
||||
[coverity]="binutils clang make cmake ccache curl unzip git pkg-config file"
|
||||
[coverity_upload]="curl"
|
||||
[gcc_preprocess]="
|
||||
binutils
|
||||
build-essential
|
||||
|
|
|
@ -82,7 +82,7 @@ message(STATUS "Configuring OpenMW...")
|
|||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 50)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
set(OPENMW_LUA_API_REVISION 85)
|
||||
set(OPENMW_LUA_API_REVISION 87)
|
||||
set(OPENMW_POSTPROCESSING_API_REVISION 3)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
|
|
@ -638,8 +638,9 @@ CUSTOM: customdata.lua
|
|||
sol::object deserialized = LuaUtil::deserialize(lua.sol(), data2.mScripts[0].mData, &serializer1);
|
||||
EXPECT_TRUE(deserialized.is<sol::table>());
|
||||
sol::table table = deserialized;
|
||||
for (const auto& [key, value] : table)
|
||||
if (!table.empty())
|
||||
{
|
||||
const auto [key, value] = *table.cbegin();
|
||||
EXPECT_TRUE(key.is<ESM::RefNum>());
|
||||
EXPECT_TRUE(value.is<ESM::RefNum>());
|
||||
EXPECT_EQ(key.as<ESM::RefNum>(), (ESM::RefNum{ 42, 34 }));
|
||||
|
|
|
@ -215,8 +215,6 @@ int main(int argc, char** argv)
|
|||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
@ -291,6 +291,7 @@ bool Launcher::SettingsPage::loadSettings()
|
|||
}
|
||||
}
|
||||
loadSettingBool(Settings::sound().mCameraListener, *cameraListenerCheckBox);
|
||||
dopplerSpinBox->setValue(Settings::sound().mDopplerFactor);
|
||||
}
|
||||
|
||||
// Interface Changes
|
||||
|
@ -485,6 +486,8 @@ void Launcher::SettingsPage::saveSettings()
|
|||
|
||||
const bool cCameraListener = cameraListenerCheckBox->checkState() != Qt::Unchecked;
|
||||
Settings::sound().mCameraListener.set(cCameraListener);
|
||||
|
||||
Settings::sound().mDopplerFactor.set(dopplerSpinBox->value());
|
||||
}
|
||||
|
||||
// Interface Changes
|
||||
|
|
|
@ -1224,6 +1224,51 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="dopplerLabel">
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>Controls the strength of the Doppler effect. Zero means it is completely disabled.</p><p>The Doppler effect increases or decreases the pitch of sounds relative to the velocity of the sound source and the listener.</p></body></html></string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Doppler Factor</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="dopplerSpinBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>283</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>1.000000000000000</double>
|
||||
</property>
|
||||
<property name="singleStep">
|
||||
<double>0.010000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.250000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer>
|
||||
<property name="orientation">
|
||||
|
|
|
@ -59,14 +59,13 @@ namespace CSMWorld
|
|||
|
||||
const Record<ESM::LandTexture>* IdCollection<ESM::LandTexture>::searchRecord(std::uint16_t index, int plugin) const
|
||||
{
|
||||
auto found = mIndices.find({ plugin, index });
|
||||
if (found != mIndices.end())
|
||||
{
|
||||
int index = searchId(found->second);
|
||||
if (index != -1)
|
||||
return &getRecord(index);
|
||||
}
|
||||
return nullptr;
|
||||
const auto it = mIndices.find({ plugin, index });
|
||||
if (it == mIndices.end())
|
||||
return nullptr;
|
||||
const int recordIndex = searchId(it->second);
|
||||
if (recordIndex == -1)
|
||||
return nullptr;
|
||||
return &getRecord(recordIndex);
|
||||
}
|
||||
|
||||
const std::string* IdCollection<ESM::LandTexture>::getLandTexture(std::uint16_t index, int plugin) const
|
||||
|
|
|
@ -5,7 +5,8 @@
|
|||
#include <future>
|
||||
#include <system_error>
|
||||
|
||||
#include <osgDB/WriteFile>
|
||||
#include <osgDB/ReaderWriter>
|
||||
#include <osgDB/Registry>
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
|
||||
#include <SDL.h>
|
||||
|
@ -28,7 +29,6 @@
|
|||
|
||||
#include <components/compiler/extensions0.hpp>
|
||||
|
||||
#include <components/stereo/multiview.hpp>
|
||||
#include <components/stereo/stereomanager.hpp>
|
||||
|
||||
#include <components/sceneutil/glextensions.hpp>
|
||||
|
|
|
@ -75,6 +75,7 @@ namespace MWBase
|
|||
const MWRender::AnimPriority& priority, int blendMask, bool autodisable, float speedmult,
|
||||
std::string_view start, std::string_view stop, float startpoint, uint32_t loops, bool loopfallback)
|
||||
= 0;
|
||||
virtual void jailTimeServed(const MWWorld::Ptr& actor, int days) = 0;
|
||||
virtual void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) = 0;
|
||||
virtual void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) = 0;
|
||||
virtual void onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon,
|
||||
|
|
|
@ -234,6 +234,8 @@ namespace MWBase
|
|||
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater)
|
||||
= 0;
|
||||
|
||||
virtual void setListenerVel(const osg::Vec3f& vel) = 0;
|
||||
|
||||
virtual void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) = 0;
|
||||
|
||||
void setSimulationTimeScale(float scale) { mSimulationTimeScale = scale; }
|
||||
|
|
|
@ -496,6 +496,8 @@ namespace MWBase
|
|||
virtual float getSunVisibility() const = 0;
|
||||
virtual float getSunPercentage() const = 0;
|
||||
|
||||
virtual float getPhysicsFrameRateDt() const = 0;
|
||||
|
||||
virtual bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) = 0;
|
||||
|
||||
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <components/misc/strings/format.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -86,46 +87,6 @@ namespace MWGui
|
|||
|
||||
// We should not worsen corprus when in prison
|
||||
player.getClass().getCreatureStats(player).getActiveSpells().skipWorsenings(mDays * 24);
|
||||
|
||||
const auto& skillStore = MWBase::Environment::get().getESMStore()->get<ESM::Skill>();
|
||||
std::set<const ESM::Skill*> skills;
|
||||
for (int day = 0; day < mDays; ++day)
|
||||
{
|
||||
auto& prng = MWBase::Environment::get().getWorld()->getPrng();
|
||||
const ESM::Skill* skill = skillStore.searchRandom({}, prng);
|
||||
skills.insert(skill);
|
||||
|
||||
MWMechanics::SkillValue& value = player.getClass().getNpcStats(player).getSkill(skill->mId);
|
||||
if (skill->mId == ESM::Skill::Security || skill->mId == ESM::Skill::Sneak)
|
||||
value.setBase(std::min(100.f, value.getBase() + 1));
|
||||
else
|
||||
value.setBase(std::max(0.f, value.getBase() - 1));
|
||||
}
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting>& gmst
|
||||
= MWBase::Environment::get().getESMStore()->get<ESM::GameSetting>();
|
||||
|
||||
std::string message;
|
||||
if (mDays == 1)
|
||||
message = gmst.find("sNotifyMessage42")->mValue.getString();
|
||||
else
|
||||
message = gmst.find("sNotifyMessage43")->mValue.getString();
|
||||
|
||||
message = Misc::StringUtils::format(message, mDays);
|
||||
|
||||
for (const ESM::Skill* skill : skills)
|
||||
{
|
||||
int skillValue = player.getClass().getNpcStats(player).getSkill(skill->mId).getBase();
|
||||
std::string skillMsg = gmst.find("sNotifyMessage44")->mValue.getString();
|
||||
if (skill->mId == ESM::Skill::Sneak || skill->mId == ESM::Skill::Security)
|
||||
skillMsg = gmst.find("sNotifyMessage39")->mValue.getString();
|
||||
|
||||
skillMsg = Misc::StringUtils::format(skillMsg, skill->mName, skillValue);
|
||||
message += "\n" + skillMsg;
|
||||
}
|
||||
|
||||
std::vector<std::string> buttons;
|
||||
buttons.emplace_back("#{Interface:OK}");
|
||||
MWBase::Environment::get().getWindowManager()->interactiveMessageBox(message, buttons);
|
||||
MWBase::Environment::get().getLuaManager()->jailTimeServed(player, mDays);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -775,12 +775,10 @@ namespace MWGui
|
|||
, mGlobalMapRender(std::make_unique<MWRender::GlobalMap>(localMapRender->getRoot(), workQueue))
|
||||
, mEditNoteDialog()
|
||||
{
|
||||
static bool registered = false;
|
||||
if (!registered)
|
||||
{
|
||||
[[maybe_unused]] static const bool registered = [] {
|
||||
MyGUI::FactoryManager::getInstance().registerFactory<MarkerWidget>("Widget");
|
||||
registered = true;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
|
||||
mEditNoteDialog.setVisible(false);
|
||||
mEditNoteDialog.eventOkClicked += MyGUI::newDelegate(this, &MapWindow::onNoteEditOk);
|
||||
|
|
|
@ -587,6 +587,7 @@ namespace MWGui
|
|||
getWidget(mAvailableEffectsList, "AvailableEffects");
|
||||
getWidget(mUsedEffectsView, "UsedEffects");
|
||||
getWidget(mPriceLabel, "PriceLabel");
|
||||
getWidget(mPlayerGold, "PlayerGold");
|
||||
getWidget(mBuyButton, "BuyButton");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
|
||||
|
@ -613,6 +614,10 @@ namespace MWGui
|
|||
mPtr = actor;
|
||||
mNameEdit->setCaption({});
|
||||
|
||||
MWWorld::Ptr player = MWMechanics::getPlayer();
|
||||
int playerGold = player.getClass().getContainerStore(player).count(MWWorld::ContainerStore::sGoldId);
|
||||
mPlayerGold->setCaptionWithReplacing(MyGUI::utility::toString(playerGold));
|
||||
|
||||
startEditing();
|
||||
}
|
||||
|
||||
|
|
|
@ -190,6 +190,7 @@ namespace MWGui
|
|||
MyGUI::Button* mBuyButton;
|
||||
MyGUI::Button* mCancelButton;
|
||||
MyGUI::TextBox* mPriceLabel;
|
||||
MyGUI::TextBox* mPlayerGold;
|
||||
|
||||
ESM::Spell mSpell;
|
||||
};
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace MWGui
|
|||
: WindowBase("openmw_trainingwindow.layout")
|
||||
{
|
||||
getWidget(mTrainingOptions, "TrainingOptions");
|
||||
getWidget(mCancelButton, "CancelButton");
|
||||
getWidget(mCancelButton, "OkButton");
|
||||
getWidget(mPlayerGold, "PlayerGold");
|
||||
|
||||
mCancelButton->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onCancelButtonClicked);
|
||||
|
@ -123,14 +123,14 @@ namespace MWGui
|
|||
MyGUI::Button* button = mTrainingOptions->createWidget<MyGUI::Button>(price <= playerGold
|
||||
? "SandTextButton"
|
||||
: "SandTextButtonDisabled", // can't use setEnabled since that removes tooltip
|
||||
MyGUI::IntCoord(5, 5 + i * lineHeight, mTrainingOptions->getWidth() - 10, lineHeight),
|
||||
MyGUI::IntCoord(4, 3 + i * lineHeight, mTrainingOptions->getWidth() - 10, lineHeight),
|
||||
MyGUI::Align::Default);
|
||||
|
||||
button->setUserData(skills[i].first);
|
||||
button->eventMouseButtonClick += MyGUI::newDelegate(this, &TrainingWindow::onTrainingSelected);
|
||||
|
||||
button->setCaptionWithReplacing(
|
||||
MyGUI::TextIterator::toTagsString(skill->mName) + " - " + MyGUI::utility::toString(price));
|
||||
MyGUI::TextIterator::toTagsString(skill->mName) + " - " + MyGUI::utility::toString(price) + "#{sgp}");
|
||||
|
||||
button->setSize(button->getTextSize().width + 12, button->getSize().height);
|
||||
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
#include "animationbindings.hpp"
|
||||
|
||||
#include <components/esm3/loadmgef.hpp>
|
||||
#include <components/esm3/loadstat.hpp>
|
||||
#include <components/lua/asyncpackage.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/utilpackage.hpp>
|
||||
#include <components/misc/finitenumbers.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
@ -15,11 +9,8 @@
|
|||
|
||||
#include "../mwmechanics/character.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
#include "objectvariant.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
|
||||
#include "idcollectionbindings.hpp"
|
||||
#include "types/types.hpp"
|
||||
#include "recordstore.hpp"
|
||||
|
||||
namespace sol
|
||||
{
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initBirthSignRecordBindings(const Context& context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "cellbindings.hpp"
|
||||
|
||||
#include <components/esm/esmbridge.hpp>
|
||||
|
||||
#include <components/esm3/loadacti.hpp>
|
||||
#include <components/esm3/loadalch.hpp>
|
||||
#include <components/esm3/loadappa.hpp>
|
||||
|
@ -27,7 +25,6 @@
|
|||
#include <components/esm4/loadammo.hpp>
|
||||
#include <components/esm4/loadarmo.hpp>
|
||||
#include <components/esm4/loadbook.hpp>
|
||||
#include <components/esm4/loadcell.hpp>
|
||||
#include <components/esm4/loadclot.hpp>
|
||||
#include <components/esm4/loadcont.hpp>
|
||||
#include <components/esm4/loaddoor.hpp>
|
||||
|
@ -38,7 +35,6 @@
|
|||
#include <components/esm4/loadligh.hpp>
|
||||
#include <components/esm4/loadmisc.hpp>
|
||||
#include <components/esm4/loadmstt.hpp>
|
||||
#include <components/esm4/loadrefr.hpp>
|
||||
#include <components/esm4/loadscol.hpp>
|
||||
#include <components/esm4/loadstat.hpp>
|
||||
#include <components/esm4/loadtree.hpp>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#ifndef MWLUA_CELLBINDINGS_H
|
||||
#define MWLUA_CELLBINDINGS_H
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void initCellBindingsForLocalScripts(const Context&);
|
||||
void initCellBindingsForGlobalScripts(const Context&);
|
||||
struct Context;
|
||||
|
||||
void initCellBindingsForLocalScripts(const Context& context);
|
||||
void initCellBindingsForGlobalScripts(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_CELLBINDINGS_H
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include <components/lua/luastate.hpp>
|
||||
|
||||
#include "idcollectionbindings.hpp"
|
||||
#include "types/types.hpp"
|
||||
#include "recordstore.hpp"
|
||||
|
||||
namespace sol
|
||||
{
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initClassRecordBindings(const Context& context);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <stdexcept>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
#include <components/esm3/loadfact.hpp>
|
||||
#include <components/lua/l10n.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/serialization.hpp>
|
||||
|
@ -20,6 +19,7 @@
|
|||
#include "../mwworld/datetimemanager.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "coremwscriptbindings.hpp"
|
||||
#include "dialoguebindings.hpp"
|
||||
#include "factionbindings.hpp"
|
||||
|
|
|
@ -3,13 +3,13 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
void addCoreTimeBindings(sol::table& api, const Context& context);
|
||||
|
||||
sol::table initCorePackage(const Context&);
|
||||
sol::table initCorePackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_COREBINDINGS_H
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef OPENMW_MWLUA_DEBUGBINDINGS_H
|
||||
#define OPENMW_MWLUA_DEBUGBINDINGS_H
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
|
|
|
@ -113,6 +113,15 @@ namespace MWLua
|
|||
scripts->onSkillLevelUp(event.mSkill, event.mSource);
|
||||
}
|
||||
|
||||
void operator()(const OnJailTimeServed& event) const
|
||||
{
|
||||
MWWorld::Ptr actor = getPtr(event.mActor);
|
||||
if (actor.isEmpty())
|
||||
return;
|
||||
if (auto* scripts = getLocalScripts(actor))
|
||||
scripts->onJailTimeServed(event.mDays);
|
||||
}
|
||||
|
||||
private:
|
||||
MWWorld::Ptr getPtr(ESM::RefNum id) const
|
||||
{
|
||||
|
|
|
@ -70,8 +70,13 @@ namespace MWLua
|
|||
std::string mSkill;
|
||||
std::string mSource;
|
||||
};
|
||||
struct OnJailTimeServed
|
||||
{
|
||||
ESM::RefNum mActor;
|
||||
int mDays;
|
||||
};
|
||||
using Event = std::variant<OnActive, OnInactive, OnConsume, OnActivate, OnUseItem, OnNewExterior, OnTeleported,
|
||||
OnAnimationTextKey, OnSkillUse, OnSkillLevelUp>;
|
||||
OnAnimationTextKey, OnSkillUse, OnSkillLevelUp, OnJailTimeServed>;
|
||||
|
||||
void clear() { mQueue.clear(); }
|
||||
void addToQueue(Event e) { mQueue.push_back(std::move(e)); }
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initCoreFactionBindings(const Context& context);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwinput/actions.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
|
||||
namespace sol
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initInputPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initInputPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_INPUTBINDINGS_H
|
||||
|
|
|
@ -1,14 +1,24 @@
|
|||
#include "landbindings.hpp"
|
||||
|
||||
#include <span>
|
||||
#include <string>
|
||||
|
||||
#include <sol/object.hpp>
|
||||
#include <sol/table.hpp>
|
||||
#include <sol/variadic_results.hpp>
|
||||
|
||||
#include <components/esm/refid.hpp>
|
||||
#include <components/esm/util.hpp>
|
||||
#include <components/esmterrain/storage.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/worldmodel.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
namespace
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
#ifndef MWLUA_LANDBINDINGS_H
|
||||
#define MWLUA_LANDBINDINGS_H
|
||||
|
||||
#include "context.hpp"
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initCoreLandBindings(const Context& context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
#include "localscripts.hpp"
|
||||
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
#include <components/esm3/loadweap.hpp>
|
||||
#include <components/misc/strings/lower.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
#include "../mwmechanics/aicombat.hpp"
|
||||
|
@ -232,7 +228,7 @@ namespace MWLua
|
|||
[&](LuaUtil::LuaView& view) { addPackage("openmw.self", sol::make_object(view.sol(), &mData)); });
|
||||
registerEngineHandlers({ &mOnActiveHandlers, &mOnInactiveHandlers, &mOnConsumeHandlers, &mOnActivatedHandlers,
|
||||
&mOnTeleportedHandlers, &mOnAnimationTextKeyHandlers, &mOnPlayAnimationHandlers, &mOnSkillUse,
|
||||
&mOnSkillLevelUp });
|
||||
&mOnSkillLevelUp, &mOnJailTimeServed });
|
||||
}
|
||||
|
||||
void LocalScripts::setActive(bool active, bool callHandlers)
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef MWLUA_LOCALSCRIPTS_H
|
||||
#define MWLUA_LOCALSCRIPTS_H
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
#include <components/lua/luastate.hpp>
|
||||
|
@ -89,6 +87,7 @@ namespace MWLua
|
|||
{
|
||||
callEngineHandlers(mOnSkillLevelUp, skillId, source);
|
||||
}
|
||||
void onJailTimeServed(int days) { callEngineHandlers(mOnJailTimeServed, days); }
|
||||
|
||||
void applyStatsCache();
|
||||
|
||||
|
@ -118,6 +117,7 @@ namespace MWLua
|
|||
EngineHandlerList mOnPlayAnimationHandlers{ "_onPlayAnimation" };
|
||||
EngineHandlerList mOnSkillUse{ "_onSkillUse" };
|
||||
EngineHandlerList mOnSkillLevelUp{ "_onSkillLevelUp" };
|
||||
EngineHandlerList mOnJailTimeServed{ "_onJailTimeServed" };
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -1,29 +1,30 @@
|
|||
#ifndef MWLUA_LUABINDINGS_H
|
||||
#define MWLUA_LUABINDINGS_H
|
||||
|
||||
#include <map>
|
||||
#include <sol/forward.hpp>
|
||||
#include <string>
|
||||
|
||||
#include "context.hpp"
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
// Initialize Lua packages that are available for all scripts.
|
||||
std::map<std::string, sol::object> initCommonPackages(const Context&);
|
||||
std::map<std::string, sol::object> initCommonPackages(const Context& context);
|
||||
|
||||
// Initialize Lua packages that are available for global scripts (additionally to common packages).
|
||||
std::map<std::string, sol::object> initGlobalPackages(const Context&);
|
||||
std::map<std::string, sol::object> initGlobalPackages(const Context& context);
|
||||
|
||||
// Initialize Lua packages that are available for local scripts (additionally to common packages).
|
||||
std::map<std::string, sol::object> initLocalPackages(const Context&);
|
||||
std::map<std::string, sol::object> initLocalPackages(const Context& context);
|
||||
|
||||
// Initialize Lua packages that are available only for local scripts on the player (additionally to common and local
|
||||
// packages).
|
||||
std::map<std::string, sol::object> initPlayerPackages(const Context&);
|
||||
std::map<std::string, sol::object> initPlayerPackages(const Context& context);
|
||||
|
||||
// Initialize Lua packages that are available only for menu scripts (additionally to common packages).
|
||||
std::map<std::string, sol::object> initMenuPackages(const Context&);
|
||||
std::map<std::string, sol::object> initMenuPackages(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_LUABINDINGS_H
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
#include <MyGUI_InputManager.h>
|
||||
#include <osg/Stats>
|
||||
|
||||
#include <sol/object.hpp>
|
||||
#include <sol/table.hpp>
|
||||
#include <sol/types.hpp>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include <components/esm/luascripts.hpp>
|
||||
|
@ -15,7 +19,6 @@
|
|||
|
||||
#include <components/l10n/manager.hpp>
|
||||
|
||||
#include <components/lua_ui/content.hpp>
|
||||
#include <components/lua_ui/registerscriptsettings.hpp>
|
||||
#include <components/lua_ui/util.hpp>
|
||||
|
||||
|
@ -212,13 +215,12 @@ namespace MWLua
|
|||
|
||||
// Run engine handlers
|
||||
mEngineEvents.callEngineHandlers();
|
||||
if (!timeManager.isPaused())
|
||||
{
|
||||
float frameDuration = MWBase::Environment::get().getFrameDuration();
|
||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->update(frameDuration);
|
||||
mGlobalScripts.update(frameDuration);
|
||||
}
|
||||
bool isPaused = timeManager.isPaused();
|
||||
|
||||
float frameDuration = MWBase::Environment::get().getFrameDuration();
|
||||
for (LocalScripts* scripts : mActiveLocalScripts)
|
||||
scripts->update(isPaused ? 0 : frameDuration);
|
||||
mGlobalScripts.update(isPaused ? 0 : frameDuration);
|
||||
|
||||
mLua.protectedCall([&](LuaUtil::LuaView& lua) { mScriptTracker.unloadInactiveScripts(lua); });
|
||||
}
|
||||
|
@ -491,6 +493,11 @@ namespace MWLua
|
|||
EngineEvents::OnSkillLevelUp{ getId(actor), skillId.serializeText(), std::string(source) });
|
||||
}
|
||||
|
||||
void LuaManager::jailTimeServed(const MWWorld::Ptr& actor, int days)
|
||||
{
|
||||
mEngineEvents.addToQueue(EngineEvents::OnJailTimeServed{ getId(actor), days });
|
||||
}
|
||||
|
||||
void LuaManager::onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon,
|
||||
const MWWorld::Ptr& ammo, int attackType, float attackStrength, float damage, bool isHealth,
|
||||
const osg::Vec3f& hitPos, bool successful, MWMechanics::DamageSourceType sourceType)
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <osg/Stats>
|
||||
#include <set>
|
||||
|
||||
#include <osg/Stats>
|
||||
|
||||
#include <components/lua/inputactions.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/scripttracker.hpp>
|
||||
|
@ -92,6 +93,7 @@ namespace MWLua
|
|||
bool loopfallback) override;
|
||||
void skillUse(const MWWorld::Ptr& actor, ESM::RefId skillId, int useType, float scale) override;
|
||||
void skillLevelUp(const MWWorld::Ptr& actor, ESM::RefId skillId, std::string_view source) override;
|
||||
void jailTimeServed(const MWWorld::Ptr& actor, int days) override;
|
||||
void onHit(const MWWorld::Ptr& attacker, const MWWorld::Ptr& victim, const MWWorld::Ptr& weapon,
|
||||
const MWWorld::Ptr& ammo, int attackType, float attackStrength, float damage, bool isHealth,
|
||||
const osg::Vec3f& hitPos, bool successful, MWMechanics::DamageSourceType sourceType) override;
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initCoreMagicBindings(const Context& context);
|
||||
void addActorMagicBindings(sol::table& actor, const Context& context);
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initMarkupPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initMarkupPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_MARKUPBINDINGS_H
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include "../mwbase/statemanager.hpp"
|
||||
#include "../mwstate/character.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
static const MWState::Character* findCharacter(std::string_view characterDir)
|
||||
|
|
|
@ -9,11 +9,11 @@
|
|||
|
||||
#include "../mwbase/luamanager.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "inputprocessor.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initMenuPackage(const Context& context);
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/worldimp.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "object.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
|
|
@ -3,13 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initMWScriptBindings(const Context&);
|
||||
|
||||
sol::table initMWScriptBindings(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_MWSCRIPTBINDINGS_H
|
||||
|
|
|
@ -13,9 +13,12 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/scene.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
#include "objectlists.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
template <class T = MWWorld::Ptr>
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initNearbyPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initNearbyPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_NEARBYBINDINGS_H
|
||||
|
|
|
@ -1,9 +1,7 @@
|
|||
#ifndef MWLUA_OBJECT_H
|
||||
#define MWLUA_OBJECT_H
|
||||
|
||||
#include <map>
|
||||
#include <stdexcept>
|
||||
#include <typeindex>
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
#ifndef MWLUA_OBJECTBINDINGS_H
|
||||
#define MWLUA_OBJECTBINDINGS_H
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
void initObjectBindingsForLocalScripts(const Context&);
|
||||
void initObjectBindingsForGlobalScripts(const Context&);
|
||||
struct Context;
|
||||
|
||||
void initObjectBindingsForLocalScripts(const Context& context);
|
||||
void initObjectBindingsForGlobalScripts(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_OBJECTBINDINGS_H
|
||||
|
|
|
@ -1,9 +1,5 @@
|
|||
#include "objectlists.hpp"
|
||||
|
||||
#include <components/esm3/esmreader.hpp>
|
||||
#include <components/esm3/esmwriter.hpp>
|
||||
#include <components/esm3/loadcell.hpp>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include "../mwbase/world.hpp"
|
||||
#include "../mwrender/postprocessor.hpp"
|
||||
|
||||
#include "context.hpp"
|
||||
#include "luamanagerimp.hpp"
|
||||
|
||||
namespace
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initPostprocessingPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initPostprocessingPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_POSTPROCESSINGBINDINGS_H
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "../mwworld/esmstore.hpp"
|
||||
|
||||
#include "idcollectionbindings.hpp"
|
||||
#include "types/types.hpp"
|
||||
#include "recordstore.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
struct Context;
|
||||
|
||||
sol::table initRaceRecordBindings(const Context& context);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,16 @@
|
|||
#ifndef MWLUA_RECORDSTORE_H
|
||||
#define MWLUA_RECORDSTORE_H
|
||||
|
||||
#include <sol/sol.hpp>
|
||||
#include <type_traits>
|
||||
|
||||
#include <sol/forward.hpp>
|
||||
#include <sol/overload.hpp>
|
||||
#include <sol/state_view.hpp>
|
||||
#include <sol/table.hpp>
|
||||
#include <sol/types.hpp>
|
||||
#include <sol/unsafe_function.hpp>
|
||||
#include <sol/usertype.hpp>
|
||||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/lua/util.hpp>
|
||||
|
||||
#include "apps/openmw/mwbase/environment.hpp"
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initCoreSoundBindings(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initCoreSoundBindings(const Context& context);
|
||||
|
||||
sol::table initAmbientPackage(const Context& context);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
#include "stats.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <variant>
|
||||
|
||||
#include <components/esm3/loadclas.hpp>
|
||||
|
|
|
@ -108,6 +108,10 @@ namespace MWLua
|
|||
}
|
||||
luaManager->addUIMessage(message, mode);
|
||||
};
|
||||
|
||||
api["_showInteractiveMessage"] = [windowManager](std::string_view message, sol::optional<sol::table>) {
|
||||
windowManager->interactiveMessageBox(message, { "#{Interface:OK}" });
|
||||
};
|
||||
api["CONSOLE_COLOR"] = LuaUtil::makeStrictReadOnly(LuaUtil::tableFromPairs<std::string, Misc::Color>(lua,
|
||||
{
|
||||
{ "Default", Misc::Color::fromHex(MWBase::WindowManager::sConsoleColor_Default.substr(1)) },
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initUserInterfacePackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initUserInterfacePackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_UIBINDINGS_H
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
#ifndef MWLUA_USERDATASERIALIZER_H
|
||||
#define MWLUA_USERDATASERIALIZER_H
|
||||
|
||||
#include "object.hpp"
|
||||
#include <map>
|
||||
#include <memory>
|
||||
|
||||
namespace LuaUtil
|
||||
{
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initVFSPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initVFSPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_VFSBINDINGS_H
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <components/esm3/loadclot.hpp>
|
||||
#include <components/esm3/loadligh.hpp>
|
||||
#include <components/esm3/loadmisc.hpp>
|
||||
#include <components/esm3/loadskil.hpp>
|
||||
#include <components/esm3/loadweap.hpp>
|
||||
#include <components/lua/luastate.hpp>
|
||||
#include <components/misc/finitenumbers.hpp>
|
||||
|
@ -27,6 +26,7 @@
|
|||
#include "luamanagerimp.hpp"
|
||||
|
||||
#include "animationbindings.hpp"
|
||||
#include "context.hpp"
|
||||
#include "corebindings.hpp"
|
||||
#include "mwscriptbindings.hpp"
|
||||
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
|
||||
#include <sol/forward.hpp>
|
||||
|
||||
#include "context.hpp"
|
||||
|
||||
namespace MWLua
|
||||
{
|
||||
sol::table initWorldPackage(const Context&);
|
||||
struct Context;
|
||||
|
||||
sol::table initWorldPackage(const Context& context);
|
||||
}
|
||||
|
||||
#endif // MWLUA_WORLDBINDINGS_H
|
||||
|
|
|
@ -93,9 +93,10 @@ namespace
|
|||
namespace MWPhysics
|
||||
{
|
||||
PhysicsSystem::PhysicsSystem(Resource::ResourceSystem* resourceSystem, osg::ref_ptr<osg::Group> parentNode)
|
||||
: mShapeManager(
|
||||
std::make_unique<Resource::BulletShapeManager>(resourceSystem->getVFS(), resourceSystem->getSceneManager(),
|
||||
resourceSystem->getNifFileManager(), Settings::cells().mCacheExpiryDelay))
|
||||
: mPhysicsDt(1.f / 60.f)
|
||||
, mShapeManager(std::make_unique<Resource::BulletShapeManager>(resourceSystem->getVFS(),
|
||||
resourceSystem->getSceneManager(), resourceSystem->getNifFileManager(),
|
||||
Settings::cells().mCacheExpiryDelay))
|
||||
, mResourceSystem(resourceSystem)
|
||||
, mDebugDrawEnabled(false)
|
||||
, mTimeAccum(0.0f)
|
||||
|
@ -103,7 +104,6 @@ namespace MWPhysics
|
|||
, mWaterHeight(0)
|
||||
, mWaterEnabled(false)
|
||||
, mParentNode(std::move(parentNode))
|
||||
, mPhysicsDt(1.f / 60.f)
|
||||
{
|
||||
mResourceSystem->addResourceManager(mShapeManager.get());
|
||||
|
||||
|
|
|
@ -287,6 +287,8 @@ namespace MWPhysics
|
|||
void reportStats(unsigned int frameNumber, osg::Stats& stats) const;
|
||||
void reportCollision(const btVector3& position, const btVector3& normal);
|
||||
|
||||
float mPhysicsDt;
|
||||
|
||||
private:
|
||||
void updateWater();
|
||||
|
||||
|
@ -330,8 +332,6 @@ namespace MWPhysics
|
|||
|
||||
osg::ref_ptr<osg::Group> mParentNode;
|
||||
|
||||
float mPhysicsDt;
|
||||
|
||||
std::size_t mSimulationsCounter = 0;
|
||||
std::array<std::vector<Simulation>, 2> mSimulations;
|
||||
std::vector<std::pair<MWWorld::Ptr, osg::Vec3f>> mActorsPositions;
|
||||
|
|
|
@ -1117,8 +1117,8 @@ namespace MWRender
|
|||
|
||||
return keyframeController->getAsCallback();
|
||||
}
|
||||
|
||||
return asCallback;
|
||||
else
|
||||
return asCallback;
|
||||
}
|
||||
|
||||
void Animation::resetActiveGroups()
|
||||
|
|
|
@ -401,14 +401,12 @@ namespace MWRender
|
|||
{
|
||||
if (mViewMode == VM_FirstPerson)
|
||||
{
|
||||
static bool prototypeAdded = false;
|
||||
if (!prototypeAdded)
|
||||
{
|
||||
[[maybe_unused]] static const bool prototypeAdded = [&] {
|
||||
osg::ref_ptr<osgUtil::RenderBin> depthClearBin(new osgUtil::RenderBin);
|
||||
depthClearBin->setDrawCallback(new DepthClearCallback());
|
||||
osgUtil::RenderBin::addRenderBinPrototype("DepthClear", depthClearBin);
|
||||
prototypeAdded = true;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
mObjectRoot->getOrCreateStateSet()->setRenderBinDetails(
|
||||
RenderBin_FirstPerson, "DepthClear", osg::StateSet::OVERRIDE_RENDERBIN_DETAILS);
|
||||
}
|
||||
|
|
|
@ -88,14 +88,13 @@ namespace MWRender
|
|||
|
||||
if (mProgramBlobber != nullptr)
|
||||
{
|
||||
static bool pipelineLogged = [&] {
|
||||
[[maybe_unused]] static const bool pipelineLogged = [&] {
|
||||
if (mUseCompute)
|
||||
Log(Debug::Info) << "Initialized compute shader pipeline for water ripples";
|
||||
else
|
||||
Log(Debug::Info) << "Initialized fallback fragment shader pipeline for water ripples";
|
||||
return true;
|
||||
}();
|
||||
(void)pipelineLogged;
|
||||
}
|
||||
|
||||
setCullCallback(new osg::NodeCallback);
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "terrainstorage.hpp"
|
||||
|
||||
#include <components/esm3/loadland.hpp>
|
||||
#include <components/esm4/loadltex.hpp>
|
||||
#include <components/esm4/loadtxst.hpp>
|
||||
#include <components/esm4/loadwrld.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -111,4 +113,15 @@ namespace MWRender
|
|||
return esmStore.get<ESM::LandTexture>().search(index, plugin);
|
||||
}
|
||||
|
||||
const ESM4::LandTexture* TerrainStorage::getEsm4LandTexture(ESM::RefId ltexId) const
|
||||
{
|
||||
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
||||
return esmStore.get<ESM4::LandTexture>().search(ltexId);
|
||||
}
|
||||
|
||||
const ESM4::TextureSet* TerrainStorage::getEsm4TextureSet(ESM::RefId txstId) const
|
||||
{
|
||||
const MWWorld::ESMStore& esmStore = *MWBase::Environment::get().getESMStore();
|
||||
return esmStore.get<ESM4::TextureSet>().search(txstId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ namespace MWRender
|
|||
osg::ref_ptr<const ESMTerrain::LandObject> getLand(ESM::ExteriorCellLocation cellLocation) override;
|
||||
const std::string* getLandTexture(std::uint16_t index, int plugin) override;
|
||||
|
||||
const ESM4::LandTexture* getEsm4LandTexture(ESM::RefId ltexId) const override;
|
||||
const ESM4::TextureSet* getEsm4TextureSet(ESM::RefId txstId) const override;
|
||||
|
||||
bool hasData(ESM::ExteriorCellLocation cellLocation) override;
|
||||
|
||||
/// Get bounds of the whole terrain in cell units
|
||||
|
|
|
@ -604,7 +604,7 @@ namespace MWScript
|
|||
{
|
||||
MWWorld::Ptr ptr = R()(runtime);
|
||||
|
||||
std::string_view effect = runtime.getStringLiteral(runtime[0].mInteger);
|
||||
const std::string_view effectName = runtime.getStringLiteral(runtime[0].mInteger);
|
||||
runtime.pop();
|
||||
|
||||
if (!ptr.getClass().isActor())
|
||||
|
@ -615,11 +615,11 @@ namespace MWScript
|
|||
|
||||
long key;
|
||||
|
||||
if (const auto k = ::Misc::StringUtils::toNumeric<long>(effect.data());
|
||||
if (const auto k = ::Misc::StringUtils::toNumeric<long>(effectName);
|
||||
k.has_value() && *k >= 0 && *k <= 32767)
|
||||
key = *k;
|
||||
else
|
||||
key = ESM::MagicEffect::effectGmstIdToIndex(effect);
|
||||
key = ESM::MagicEffect::effectGmstIdToIndex(effectName);
|
||||
|
||||
const MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||
for (const auto& spell : stats.getActiveSpells())
|
||||
|
|
|
@ -522,16 +522,14 @@ namespace MWSound
|
|||
|
||||
/* We need to make sure ffmpeg is initialized. Optionally silence warning
|
||||
* output from the lib */
|
||||
static bool done_init = false;
|
||||
if (!done_init)
|
||||
{
|
||||
[[maybe_unused]] static const bool doneInit = [] {
|
||||
// This is not needed anymore above FFMpeg version 4.0
|
||||
#if LIBAVCODEC_VERSION_INT < 3805796
|
||||
av_register_all();
|
||||
#endif
|
||||
av_log_set_level(AV_LOG_ERROR);
|
||||
done_init = true;
|
||||
}
|
||||
return true;
|
||||
}();
|
||||
}
|
||||
|
||||
FFmpegDecoder::~FFmpegDecoder()
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/misc/thread.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
#include <components/vfs/manager.hpp>
|
||||
|
||||
#include "efxpresets.h"
|
||||
|
@ -963,6 +964,7 @@ namespace MWSound
|
|||
// Speed of sound is in units per second. Take the sound speed in air (assumed
|
||||
// meters per second), multiply by the units per meter to get the speed in u/s.
|
||||
alSpeedOfSound(Constants::SoundSpeedInAir * Constants::UnitsPerMeter);
|
||||
alDopplerFactor(Settings::sound().mDopplerFactor);
|
||||
alGetError();
|
||||
|
||||
mInitialized = true;
|
||||
|
@ -1142,8 +1144,8 @@ namespace MWSound
|
|||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist,
|
||||
ALfloat gain, ALfloat pitch, bool loop, bool useenv)
|
||||
void OpenALOutput::initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist,
|
||||
ALfloat maxdist, ALfloat gain, ALfloat pitch, bool loop, bool useenv)
|
||||
{
|
||||
alSourcef(source, AL_REFERENCE_DISTANCE, mindist);
|
||||
alSourcef(source, AL_MAX_DISTANCE, maxdist);
|
||||
|
@ -1179,11 +1181,11 @@ namespace MWSound
|
|||
alSourcef(source, AL_PITCH, pitch);
|
||||
alSourcefv(source, AL_POSITION, pos.ptr());
|
||||
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSourcefv(source, AL_VELOCITY, vel.ptr());
|
||||
}
|
||||
|
||||
void OpenALOutput::updateCommon(
|
||||
ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv)
|
||||
void OpenALOutput::updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist,
|
||||
ALfloat gain, ALfloat pitch, bool useenv)
|
||||
{
|
||||
if (useenv && mListenerEnv == Env_Underwater && !mWaterFilter)
|
||||
{
|
||||
|
@ -1195,7 +1197,7 @@ namespace MWSound
|
|||
alSourcef(source, AL_PITCH, pitch);
|
||||
alSourcefv(source, AL_POSITION, pos.ptr());
|
||||
alSource3f(source, AL_DIRECTION, 0.0f, 0.0f, 0.0f);
|
||||
alSource3f(source, AL_VELOCITY, 0.0f, 0.0f, 0.0f);
|
||||
alSourcefv(source, AL_VELOCITY, vel.ptr());
|
||||
}
|
||||
|
||||
bool OpenALOutput::playSound(Sound* sound, Sound_Handle data, float offset)
|
||||
|
@ -1248,8 +1250,9 @@ namespace MWSound
|
|||
}
|
||||
source = mFreeSources.front();
|
||||
|
||||
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
|
||||
sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(), sound->getUseEnv());
|
||||
initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
|
||||
sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), sound->getIsLooping(),
|
||||
sound->getUseEnv());
|
||||
alSourcei(source, AL_BUFFER, GET_PTRID(data));
|
||||
alSourcef(source, AL_SEC_OFFSET, offset);
|
||||
if (getALError() != AL_NO_ERROR)
|
||||
|
@ -1312,8 +1315,8 @@ namespace MWSound
|
|||
return;
|
||||
ALuint source = GET_PTRID(sound->mHandle);
|
||||
|
||||
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
||||
getTimeScaledPitch(sound), sound->getUseEnv());
|
||||
updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
|
||||
sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
|
||||
getALError();
|
||||
}
|
||||
|
||||
|
@ -1360,8 +1363,8 @@ namespace MWSound
|
|||
if (sound->getIsLooping())
|
||||
Log(Debug::Warning) << "Warning: cannot loop stream \"" << decoder->getName() << "\"";
|
||||
|
||||
initCommon3D(source, sound->getPosition(), sound->getMinDistance(), sound->getMaxDistance(),
|
||||
sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv());
|
||||
initCommon3D(source, sound->getPosition(), sound->getVelocity(), sound->getMinDistance(),
|
||||
sound->getMaxDistance(), sound->getRealVolume(), getTimeScaledPitch(sound), false, sound->getUseEnv());
|
||||
if (getALError() != AL_NO_ERROR)
|
||||
return false;
|
||||
|
||||
|
@ -1443,8 +1446,8 @@ namespace MWSound
|
|||
OpenAL_SoundStream* stream = reinterpret_cast<OpenAL_SoundStream*>(sound->mHandle);
|
||||
ALuint source = stream->mSource;
|
||||
|
||||
updateCommon(source, sound->getPosition(), sound->getMaxDistance(), sound->getRealVolume(),
|
||||
getTimeScaledPitch(sound), sound->getUseEnv());
|
||||
updateCommon(source, sound->getPosition(), sound->getVelocity(), sound->getMaxDistance(),
|
||||
sound->getRealVolume(), getTimeScaledPitch(sound), sound->getUseEnv());
|
||||
getALError();
|
||||
}
|
||||
|
||||
|
@ -1459,12 +1462,13 @@ namespace MWSound
|
|||
}
|
||||
|
||||
void OpenALOutput::updateListener(
|
||||
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env)
|
||||
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, const osg::Vec3f& vel, Environment env)
|
||||
{
|
||||
if (mContext)
|
||||
{
|
||||
ALfloat orient[6] = { atdir.x(), atdir.y(), atdir.z(), updir.x(), updir.y(), updir.z() };
|
||||
alListenerfv(AL_POSITION, pos.ptr());
|
||||
alListenerfv(AL_VELOCITY, vel.ptr());
|
||||
alListenerfv(AL_ORIENTATION, orient);
|
||||
|
||||
if (env != mListenerEnv)
|
||||
|
@ -1497,6 +1501,7 @@ namespace MWSound
|
|||
}
|
||||
|
||||
mListenerPos = pos;
|
||||
mListenerVel = vel;
|
||||
mListenerEnv = env;
|
||||
}
|
||||
|
||||
|
@ -1582,7 +1587,6 @@ namespace MWSound
|
|||
: SoundOutput(mgr)
|
||||
, mDevice(nullptr)
|
||||
, mContext(nullptr)
|
||||
, mListenerPos(0.0f, 0.0f, 0.0f)
|
||||
, mListenerEnv(Env_Normal)
|
||||
, mWaterFilter(0)
|
||||
, mWaterEffect(0)
|
||||
|
|
|
@ -46,6 +46,7 @@ namespace MWSound
|
|||
StreamVec mActiveStreams;
|
||||
|
||||
osg::Vec3f mListenerPos;
|
||||
osg::Vec3f mListenerVel;
|
||||
Environment mListenerEnv;
|
||||
|
||||
ALuint mWaterFilter;
|
||||
|
@ -64,11 +65,11 @@ namespace MWSound
|
|||
std::unique_ptr<DefaultDeviceThread> mDefaultDeviceThread;
|
||||
|
||||
void initCommon2D(ALuint source, const osg::Vec3f& pos, ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
||||
void initCommon3D(ALuint source, const osg::Vec3f& pos, ALfloat mindist, ALfloat maxdist, ALfloat gain,
|
||||
ALfloat pitch, bool loop, bool useenv);
|
||||
void initCommon3D(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat mindist, ALfloat maxdist,
|
||||
ALfloat gain, ALfloat pitch, bool loop, bool useenv);
|
||||
|
||||
void updateCommon(
|
||||
ALuint source, const osg::Vec3f& pos, ALfloat maxdist, ALfloat gain, ALfloat pitch, bool useenv);
|
||||
void updateCommon(ALuint source, const osg::Vec3f& pos, const osg::Vec3f& vel, ALfloat maxdist, ALfloat gain,
|
||||
ALfloat pitch, bool useenv);
|
||||
|
||||
float getTimeScaledPitch(SoundBase* sound);
|
||||
|
||||
|
@ -108,8 +109,8 @@ namespace MWSound
|
|||
void startUpdate() override;
|
||||
void finishUpdate() override;
|
||||
|
||||
void updateListener(
|
||||
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env) override;
|
||||
void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
|
||||
const osg::Vec3f& vel, Environment env) override;
|
||||
|
||||
void pauseSounds(int types) override;
|
||||
void resumeSounds(int types) override;
|
||||
|
|
|
@ -31,6 +31,8 @@ namespace MWSound
|
|||
struct SoundParams
|
||||
{
|
||||
osg::Vec3f mPos;
|
||||
osg::Vec3f mLastPos;
|
||||
osg::Vec3f mVel;
|
||||
float mVolume = 1.0f;
|
||||
float mBaseVolume = 1.0f;
|
||||
float mPitch = 1.0f;
|
||||
|
@ -57,6 +59,8 @@ namespace MWSound
|
|||
|
||||
public:
|
||||
void setPosition(const osg::Vec3f& pos) { mParams.mPos = pos; }
|
||||
void setLastPosition(const osg::Vec3f& lastpos) { mParams.mLastPos = lastpos; }
|
||||
void setVelocity(const osg::Vec3f& vel) { mParams.mVel = vel; }
|
||||
void setVolume(float volume) { mParams.mVolume = volume; }
|
||||
void setBaseVolume(float volume) { mParams.mBaseVolume = volume; }
|
||||
void setFadeout(float duration) { setFade(duration, 0.0, Play_StopAtFadeEnd); }
|
||||
|
@ -150,6 +154,8 @@ namespace MWSound
|
|||
}
|
||||
|
||||
const osg::Vec3f& getPosition() const { return mParams.mPos; }
|
||||
const osg::Vec3f& getLastPosition() const { return mParams.mLastPos; }
|
||||
const osg::Vec3f& getVelocity() const { return mParams.mVel; }
|
||||
float getRealVolume() const { return mParams.mVolume * mParams.mBaseVolume * mParams.mFadeVolume; }
|
||||
float getPitch() const { return mParams.mPitch; }
|
||||
float getMinDistance() const { return mParams.mMinDistance; }
|
||||
|
|
|
@ -119,6 +119,7 @@ namespace MWSound
|
|||
, mListenerPos(0, 0, 0)
|
||||
, mListenerDir(1, 0, 0)
|
||||
, mListenerUp(0, 0, 1)
|
||||
, mListenerVel(0, 0, 0)
|
||||
, mUnderwaterSound(nullptr)
|
||||
, mNearWaterSound(nullptr)
|
||||
, mPlaybackPaused(false)
|
||||
|
@ -960,7 +961,7 @@ namespace MWSound
|
|||
}
|
||||
|
||||
mOutput->startUpdate();
|
||||
mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, env);
|
||||
mOutput->updateListener(mListenerPos, mListenerDir, mListenerUp, mListenerVel, env);
|
||||
|
||||
updateMusic(duration);
|
||||
|
||||
|
@ -977,7 +978,13 @@ namespace MWSound
|
|||
if (sound->getIs3D())
|
||||
{
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
sound->setLastPosition(sound->getPosition());
|
||||
sound->setPosition(ptr.getRefData().getPosition().asVec3());
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
sound->setVelocity(
|
||||
(sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
|
||||
}
|
||||
|
||||
cull3DSound(sound);
|
||||
}
|
||||
|
@ -1013,8 +1020,11 @@ namespace MWSound
|
|||
{
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
sound->setLastPosition(sound->getPosition());
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
sound->setPosition(world->getActorHeadTransform(ptr).getTrans());
|
||||
sound->setVelocity(
|
||||
(sound->getPosition() - sound->getLastPosition()) / world->getPhysicsFrameRateDt());
|
||||
}
|
||||
|
||||
cull3DSound(sound);
|
||||
|
@ -1153,6 +1163,11 @@ namespace MWSound
|
|||
mWaterSoundUpdater.setUnderwater(underwater);
|
||||
}
|
||||
|
||||
void SoundManager::setListenerVel(const osg::Vec3f& vel)
|
||||
{
|
||||
mListenerVel = vel;
|
||||
}
|
||||
|
||||
void SoundManager::updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated)
|
||||
{
|
||||
SoundMap::iterator snditer = mActiveSounds.find(old.mRef);
|
||||
|
|
|
@ -92,6 +92,7 @@ namespace MWSound
|
|||
osg::Vec3f mListenerPos;
|
||||
osg::Vec3f mListenerDir;
|
||||
osg::Vec3f mListenerUp;
|
||||
osg::Vec3f mListenerVel;
|
||||
|
||||
int mPausedSoundTypes[BlockerType::MaxCount] = {};
|
||||
|
||||
|
@ -283,6 +284,8 @@ namespace MWSound
|
|||
void setListenerPosDir(
|
||||
const osg::Vec3f& pos, const osg::Vec3f& dir, const osg::Vec3f& up, bool underwater) override;
|
||||
|
||||
void setListenerVel(const osg::Vec3f& vel) override;
|
||||
|
||||
void updatePtr(const MWWorld::ConstPtr& old, const MWWorld::ConstPtr& updated) override;
|
||||
|
||||
void clear() override;
|
||||
|
|
|
@ -61,8 +61,8 @@ namespace MWSound
|
|||
virtual void startUpdate() = 0;
|
||||
virtual void finishUpdate() = 0;
|
||||
|
||||
virtual void updateListener(
|
||||
const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir, Environment env)
|
||||
virtual void updateListener(const osg::Vec3f& pos, const osg::Vec3f& atdir, const osg::Vec3f& updir,
|
||||
const osg::Vec3f& vel, Environment env)
|
||||
= 0;
|
||||
|
||||
virtual void pauseSounds(int types) = 0;
|
||||
|
|
|
@ -110,6 +110,7 @@ namespace ESM4
|
|||
struct Static;
|
||||
struct StaticCollection;
|
||||
struct Terminal;
|
||||
struct TextureSet;
|
||||
struct Tree;
|
||||
struct Weapon;
|
||||
struct World;
|
||||
|
@ -149,7 +150,7 @@ namespace MWWorld
|
|||
Store<ESM4::LevelledNpc>, Store<ESM4::Light>, Store<ESM4::MiscItem>, Store<ESM4::MovableStatic>,
|
||||
Store<ESM4::Npc>, Store<ESM4::Outfit>, Store<ESM4::Potion>, Store<ESM4::Race>, Store<ESM4::Reference>,
|
||||
Store<ESM4::Sound>, Store<ESM4::SoundReference>, Store<ESM4::Static>, Store<ESM4::StaticCollection>,
|
||||
Store<ESM4::Terminal>, Store<ESM4::Tree>, Store<ESM4::Weapon>, Store<ESM4::World>>;
|
||||
Store<ESM4::Terminal>, Store<ESM4::TextureSet>, Store<ESM4::Tree>, Store<ESM4::Weapon>, Store<ESM4::World>>;
|
||||
|
||||
private:
|
||||
template <typename T>
|
||||
|
|
|
@ -461,6 +461,11 @@ namespace MWWorld
|
|||
|
||||
update(magicBoltState, duration);
|
||||
|
||||
for (const auto& sound : magicBoltState.mSounds)
|
||||
{
|
||||
sound->setVelocity(direction * speed);
|
||||
}
|
||||
|
||||
// For AI actors, get combat targets to use in the ray cast. Only those targets will return a positive hit
|
||||
// result.
|
||||
std::vector<MWWorld::Ptr> targetActors;
|
||||
|
|
|
@ -1273,13 +1273,12 @@ namespace MWWorld
|
|||
const std::size_t leftCapacity = mPreloader->getMaxCacheSize() - mPreloader->getCacheSize();
|
||||
if (cells.size() > leftCapacity)
|
||||
{
|
||||
static bool logged = [&] {
|
||||
[[maybe_unused]] static const bool logged = [&] {
|
||||
Log(Debug::Warning) << "Not enough cell preloader cache capacity to preload exterior cells, consider "
|
||||
"increasing \"preload cell cache max\" up to "
|
||||
<< (mPreloader->getCacheSize() + cells.size());
|
||||
return true;
|
||||
}();
|
||||
(void)logged;
|
||||
cells.resize(leftCapacity);
|
||||
}
|
||||
|
||||
|
|
|
@ -1354,6 +1354,7 @@ template class MWWorld::TypedDynamicStore<ESM4::SoundReference>;
|
|||
template class MWWorld::TypedDynamicStore<ESM4::Static>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::StaticCollection>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::Terminal>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::TextureSet>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::Tree>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::Weapon>;
|
||||
template class MWWorld::TypedDynamicStore<ESM4::World>;
|
||||
|
|
|
@ -1460,6 +1460,8 @@ namespace MWWorld
|
|||
void World::queueMovement(const Ptr& ptr, const osg::Vec3f& velocity)
|
||||
{
|
||||
mPhysics->queueObjectMovement(ptr, velocity);
|
||||
if (ptr == MWMechanics::getPlayer())
|
||||
MWBase::Environment::get().getSoundManager()->setListenerVel(velocity);
|
||||
}
|
||||
|
||||
void World::updateAnimatedCollisionShape(const Ptr& ptr)
|
||||
|
@ -3182,6 +3184,11 @@ namespace MWWorld
|
|||
return mWeatherManager->getSunPercentage(getTimeStamp().getHour());
|
||||
}
|
||||
|
||||
float World::getPhysicsFrameRateDt() const
|
||||
{
|
||||
return mPhysics->mPhysicsDt;
|
||||
}
|
||||
|
||||
bool World::findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result)
|
||||
{
|
||||
if (cell->isExterior())
|
||||
|
|
|
@ -584,6 +584,8 @@ namespace MWWorld
|
|||
float getSunVisibility() const override;
|
||||
float getSunPercentage() const override;
|
||||
|
||||
float getPhysicsFrameRateDt() const override;
|
||||
|
||||
bool findInteriorPositionInWorldSpace(const MWWorld::CellStore* cell, osg::Vec3f& result) override;
|
||||
|
||||
/// Teleports \a ptr to the closest reference of \a id (e.g. DivineMarker, PrisonMarker, TempleMarker)
|
||||
|
|
|
@ -407,6 +407,7 @@ add_component_dir(detournavigator
|
|||
areatype
|
||||
asyncnavmeshupdater
|
||||
bounds
|
||||
cellgridbounds
|
||||
changetype
|
||||
collisionshapetype
|
||||
commulativeaabb
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <tuple>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
|
|
@ -10,10 +10,8 @@
|
|||
|
||||
#include <osg/io_utils>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <vector>
|
||||
|
||||
namespace DetourNavigator
|
||||
|
@ -79,7 +77,7 @@ namespace DetourNavigator
|
|||
return;
|
||||
}
|
||||
|
||||
const auto data
|
||||
const std::unique_ptr<PreparedNavMeshData> data
|
||||
= prepareNavMeshTileData(*recastMesh, mWorldspace, mTilePosition, mAgentBounds, mSettings.mRecast);
|
||||
|
||||
if (data == nullptr)
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include "exceptions.hpp"
|
||||
#include "flags.hpp"
|
||||
#include "navmeshdata.hpp"
|
||||
#include "navmeshdb.hpp"
|
||||
#include "navmeshtilescache.hpp"
|
||||
#include "offmeshconnection.hpp"
|
||||
#include "preparednavmeshdata.hpp"
|
||||
#include "recastcontext.hpp"
|
||||
|
@ -22,8 +20,6 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <iomanip>
|
||||
#include <limits>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#include <DetourCommon.h>
|
||||
#include <DetourNavMesh.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <stdexcept>
|
||||
#include <tuple>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <osg/Vec3f>
|
||||
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
namespace DetourNavigator
|
||||
{
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <Recast.h>
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace
|
||||
{
|
||||
void initPolyMeshDetail(rcPolyMeshDetail& value) noexcept
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
|
||||
#include "flags.hpp"
|
||||
|
||||
#include <optional>
|
||||
#include <osg/Vec3f>
|
||||
|
||||
#include <optional>
|
||||
|
||||
class dtNavMeshQuery;
|
||||
|
||||
namespace DetourNavigator
|
||||
|
|
|
@ -11,9 +11,7 @@
|
|||
#include <osg/Vec3f>
|
||||
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <numeric>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ namespace ESM
|
|||
VER_134 = 0x3fab851f, // FONV, GunRunnersArsenal, LonesomeRoad, OldWorldBlues
|
||||
VER_094 = 0x3f70a3d7, // TES5/FO3
|
||||
VER_170 = 0x3fd9999a, // TES5
|
||||
VER_171 = 0x3fdae148, // TES5
|
||||
VER_095 = 0x3f733333, // FO4
|
||||
};
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ ESM::LandData::LandData(const ESM::Land& land, int loadFlags)
|
|||
, mNormals(mData->mNormals)
|
||||
, mColors(mData->mColours)
|
||||
, mTextures(mData->mTextures)
|
||||
, mIsEsm4(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -43,9 +44,11 @@ ESM::LandData::LandData(const ESM4::Land& land, int /*loadFlags*/)
|
|||
, mMaxHeight(std::numeric_limits<float>::lowest())
|
||||
, mSize(Constants::ESM4CellSizeInUnits)
|
||||
, mLandSize(ESM4::Land::sVertsPerSide)
|
||||
, mPlugin(land.mId.mContentFile)
|
||||
, mNormals(land.mVertNorm)
|
||||
, mColors(land.mVertColr)
|
||||
, mTextures(textures)
|
||||
, mIsEsm4(true)
|
||||
{
|
||||
float rowOffset = land.mHeightMap.heightOffset;
|
||||
for (int y = 0; y < mLandSize; y++)
|
||||
|
@ -69,6 +72,9 @@ ESM::LandData::LandData(const ESM4::Land& land, int /*loadFlags*/)
|
|||
}
|
||||
|
||||
mHeights = mHeightsData;
|
||||
|
||||
for (int i = 0; i < 4; ++i)
|
||||
mEsm4Textures[i] = land.mTextures[i];
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
#ifndef COMPONENTS_ESM_ESMTERRAIN
|
||||
#define COMPONENTS_ESM_ESMTERRAIN
|
||||
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
struct Land;
|
||||
}
|
||||
#include <components/esm4/loadland.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -28,7 +26,6 @@ namespace ESM
|
|||
std::span<const float> getHeights() const { return mHeights; }
|
||||
std::span<const std::int8_t> getNormals() const { return mNormals; }
|
||||
std::span<const std::uint8_t> getColors() const { return mColors; }
|
||||
std::span<const std::uint16_t> getTextures() const { return mTextures; }
|
||||
float getSize() const { return mSize; }
|
||||
float getMinHeight() const { return mMinHeight; }
|
||||
float getMaxHeight() const { return mMaxHeight; }
|
||||
|
@ -36,6 +33,22 @@ namespace ESM
|
|||
int getLoadFlags() const { return mLoadFlags; }
|
||||
int getPlugin() const { return mPlugin; }
|
||||
|
||||
bool isEsm4() const { return mIsEsm4; }
|
||||
|
||||
std::span<const std::uint16_t> getTextures() const
|
||||
{
|
||||
if (mIsEsm4)
|
||||
throw std::logic_error("ESM3 textures requested from ESM4 LandData");
|
||||
return mTextures;
|
||||
}
|
||||
|
||||
const ESM4::Land::Texture& getEsm4Texture(std::size_t quad) const
|
||||
{
|
||||
if (!mIsEsm4)
|
||||
throw std::logic_error("ESM4 texture requested from ESM3 LandData");
|
||||
return mEsm4Textures[quad];
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<const ESM::LandRecordData> mData;
|
||||
int mLoadFlags = 0;
|
||||
|
@ -49,6 +62,8 @@ namespace ESM
|
|||
std::span<const std::int8_t> mNormals;
|
||||
std::span<const std::uint8_t> mColors;
|
||||
std::span<const std::uint16_t> mTextures;
|
||||
std::array<ESM4::Land::Texture, 4> mEsm4Textures;
|
||||
bool mIsEsm4;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -51,10 +51,10 @@ namespace std
|
|||
{
|
||||
size_t operator()(const ESM::FormId& formId) const
|
||||
{
|
||||
static_assert(sizeof(ESM::FormId) == sizeof(size_t));
|
||||
size_t s;
|
||||
memcpy(&s, &formId, sizeof(size_t));
|
||||
return hash<size_t>()(s);
|
||||
static_assert(sizeof(ESM::FormId) == sizeof(uint64_t));
|
||||
uint64_t s;
|
||||
memcpy(&s, &formId, sizeof(ESM::FormId));
|
||||
return hash<uint64_t>()(s);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -79,6 +79,7 @@
|
|||
#include <components/esm4/loadstat.hpp>
|
||||
#include <components/esm4/loadterm.hpp>
|
||||
#include <components/esm4/loadtree.hpp>
|
||||
#include <components/esm4/loadtxst.hpp>
|
||||
#include <components/esm4/loadweap.hpp>
|
||||
#include <components/esm4/loadwrld.hpp>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
Copyright (C) 2015-2016, 2018, 2020-2021 cc9cii
|
||||
Copyright (C) 2015 - 2024 cc9cii
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
|
@ -17,7 +17,7 @@
|
|||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
cc9cii cc9c@iinet.net.au
|
||||
cc9cii cc9cii@hotmail.com
|
||||
|
||||
Much of the information on the data structures are based on the information
|
||||
from Tes4Mod:Mod_File_Format and Tes5Mod:File_Formats but also refined by
|
||||
|
@ -26,13 +26,51 @@
|
|||
*/
|
||||
#include "loadland.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <cstdint>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/debug/debuglog.hpp>
|
||||
|
||||
#include "reader.hpp"
|
||||
// #include "writer.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
void assignDefaultTextures(ESM4::Land& land, ESM4::Reader& reader)
|
||||
{
|
||||
std::uint32_t esmVer = reader.esmVersion();
|
||||
|
||||
// Note: in games after TES4 it can be configured in ini file (sDefaultLandDiffuseTexture)
|
||||
if (!reader.hasFormVersion() && (esmVer == ESM::VER_080 || esmVer == ESM::VER_100)) // TES4
|
||||
{
|
||||
land.mDefaultDiffuseMap = VFS::Path::NormalizedView("textures/landscape/terrainhddirt01.dds");
|
||||
land.mDefaultNormalMap = VFS::Path::NormalizedView("textures/landscape/terrainhddirt01_n.dds");
|
||||
}
|
||||
else if (reader.hasFormVersion() && reader.formVersion() >= 16
|
||||
&& (esmVer == ESM::VER_094 || esmVer == ESM::VER_170 || esmVer == ESM::VER_171)) // TES5
|
||||
{
|
||||
land.mDefaultDiffuseMap = VFS::Path::NormalizedView("textures/landscape/dirt02.dds");
|
||||
land.mDefaultNormalMap = VFS::Path::NormalizedView("textures/landscape/dirt02_n.dds");
|
||||
}
|
||||
else if (esmVer == ESM::VER_095 || esmVer == ESM::VER_100) // FO4
|
||||
{
|
||||
land.mDefaultDiffuseMap
|
||||
= VFS::Path::NormalizedView("textures/landscape/ground/commonwealthdefault01_d.dds");
|
||||
land.mDefaultNormalMap = VFS::Path::NormalizedView("textures/landscape/ground/commonwealthdefault01_n.dds");
|
||||
}
|
||||
else if (esmVer == ESM::VER_094 || esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134)
|
||||
{ // FO3, FONV
|
||||
land.mDefaultDiffuseMap = VFS::Path::NormalizedView("textures/landscape/dirtwasteland01.dds");
|
||||
land.mDefaultNormalMap = VFS::Path::NormalizedView("textures/landscape/dirtwasteland01_n.dds");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Nothing especially bad happens if default texture is not set (except of the missing texture of course),
|
||||
// but we throw an error because this case is unexpected and detection logic needs to be updated.
|
||||
throw std::runtime_error("ESM4::Land unknown ESM version");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// overlap north
|
||||
//
|
||||
|
@ -53,12 +91,16 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
{
|
||||
mId = reader.getFormIdFromHeader();
|
||||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
mDataTypes = 0;
|
||||
mCell = reader.currCell();
|
||||
TxtLayer layer;
|
||||
std::int8_t currentAddQuad = -1; // for VTXT following ATXT
|
||||
assignDefaultTextures(*this, reader);
|
||||
|
||||
// std::map<FormId, int> uniqueTextures; // FIXME: for temp testing only
|
||||
layer.texture.formId = 0;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
mTextures[i].base.formId = 0;
|
||||
|
||||
while (reader.getSubRecordHeader())
|
||||
{
|
||||
|
@ -78,12 +120,6 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
}
|
||||
case ESM::fourCC("VHGT"): // vertex height gradient, 4+33x33+3 = 4+1089+3 = 1096
|
||||
{
|
||||
#if 0
|
||||
reader.get(mHeightMap.heightOffset);
|
||||
reader.get(mHeightMap.gradientData);
|
||||
reader.get(mHeightMap.unknown1);
|
||||
reader.get(mHeightMap.unknown2);
|
||||
#endif
|
||||
reader.get(mHeightMap);
|
||||
mDataTypes |= LAND_VHGT;
|
||||
break;
|
||||
|
@ -102,13 +138,9 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
if (base.quadrant >= 4)
|
||||
throw std::runtime_error("base texture quadrant index error");
|
||||
|
||||
reader.adjustFormId(base.formId);
|
||||
mTextures[base.quadrant].base = std::move(base);
|
||||
#if 0
|
||||
std::cout << "Base Texture formid: 0x"
|
||||
<< std::hex << mTextures[base.quadrant].base.formId
|
||||
<< ", quad " << std::dec << (int)base.quadrant << std::endl;
|
||||
#endif
|
||||
if (base.formId != 0)
|
||||
reader.adjustFormId(base.formId);
|
||||
mTextures[base.quadrant].base = base;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -116,31 +148,23 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
{
|
||||
if (currentAddQuad != -1)
|
||||
{
|
||||
// FIXME: sometimes there are no VTXT following an ATXT? Just add a dummy one for now
|
||||
Log(Debug::Verbose) << "ESM4::Land VTXT empty layer " << layer.texture.layerIndex;
|
||||
// NOTE: sometimes there are no VTXT following an ATXT
|
||||
layer.data.resize(1); // just one spot
|
||||
layer.data.back().position = 0; // this corner
|
||||
layer.data.back().opacity = 0.f; // transparent
|
||||
|
||||
if (layer.texture.layerIndex != mTextures[currentAddQuad].layers.size())
|
||||
throw std::runtime_error("ESM4::LAND additional texture skipping layer");
|
||||
|
||||
mTextures[currentAddQuad].layers.push_back(layer);
|
||||
}
|
||||
|
||||
reader.get(layer.texture);
|
||||
reader.adjustFormId(layer.texture.formId);
|
||||
if (layer.texture.formId != 0)
|
||||
reader.adjustFormId(layer.texture.formId);
|
||||
if (layer.texture.quadrant >= 4)
|
||||
throw std::runtime_error("additional texture quadrant index error");
|
||||
#if 0
|
||||
FormId txt = layer.texture.formId;
|
||||
std::map<FormId, int>::iterator lb = uniqueTextures.lower_bound(txt);
|
||||
if (lb != uniqueTextures.end() && !(uniqueTextures.key_comp()(txt, lb->first)))
|
||||
{
|
||||
lb->second += 1;
|
||||
}
|
||||
else
|
||||
uniqueTextures.insert(lb, std::make_pair(txt, 1));
|
||||
#endif
|
||||
#if 0
|
||||
std::cout << "Additional Texture formId: 0x"
|
||||
<< std::hex << layer.texture.formId
|
||||
<< ", quad " << std::dec << (int)layer.texture.quadrant << std::endl;
|
||||
std::cout << "Additional Texture layer: "
|
||||
<< std::dec << (int)layer.texture.layerIndex << std::endl;
|
||||
#endif
|
||||
throw std::runtime_error("ESM4::LAND additional texture quadrant index error");
|
||||
|
||||
currentAddQuad = layer.texture.quadrant;
|
||||
break;
|
||||
}
|
||||
|
@ -156,25 +180,17 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
if (count)
|
||||
{
|
||||
layer.data.resize(count);
|
||||
std::vector<ESM4::Land::VTXT>::iterator it = layer.data.begin();
|
||||
for (; it != layer.data.end(); ++it)
|
||||
{
|
||||
reader.get(*it);
|
||||
// FIXME: debug only
|
||||
// std::cout << "pos: " << std::dec << (int)(*it).position << std::endl;
|
||||
}
|
||||
for (ESM4::Land::VTXT& vtxt : layer.data)
|
||||
reader.get(vtxt);
|
||||
}
|
||||
mTextures[currentAddQuad].layers.push_back(layer);
|
||||
|
||||
// Assumed that the layers are added in the correct sequence
|
||||
// FIXME: Knights.esp doesn't seem to observe this - investigate more
|
||||
// assert(layer.texture.layerIndex == mTextures[currentAddQuad].layers.size()-1
|
||||
//&& "additional texture layer index error");
|
||||
if (layer.texture.layerIndex != mTextures[currentAddQuad].layers.size())
|
||||
throw std::runtime_error("ESM4::LAND additional texture skipping layer");
|
||||
|
||||
mTextures[currentAddQuad].layers.push_back(layer);
|
||||
|
||||
currentAddQuad = -1;
|
||||
layer.data.clear();
|
||||
// FIXME: debug only
|
||||
// std::cout << "VTXT: count " << std::dec << count << std::endl;
|
||||
break;
|
||||
}
|
||||
case ESM::fourCC("VTEX"): // only in Oblivion?
|
||||
|
@ -195,44 +211,14 @@ void ESM4::Land::load(ESM4::Reader& reader)
|
|||
reader.skipSubRecordData();
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("ESM4::LAND::load - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
throw std::runtime_error("ESM4::LAND - Unknown subrecord " + ESM::printName(subHdr.typeId));
|
||||
}
|
||||
}
|
||||
|
||||
if (currentAddQuad != -1)
|
||||
{
|
||||
// FIXME: not sure if it happens here as well
|
||||
// not sure if it happens here as well, if so just ignore
|
||||
Log(Debug::Verbose) << "ESM4::Land VTXT empty layer " << layer.texture.layerIndex << " quad "
|
||||
<< static_cast<unsigned>(layer.texture.quadrant);
|
||||
mTextures[currentAddQuad].layers.push_back(layer);
|
||||
}
|
||||
|
||||
bool missing = false;
|
||||
for (int i = 0; i < 4; ++i)
|
||||
{
|
||||
if (mTextures[i].base.formId == 0)
|
||||
{
|
||||
// std::cout << "ESM4::LAND " << ESM4::formIdToString(mFormId) << " missing base, quad " << i << std::endl;
|
||||
// std::cout << "layers " << mTextures[i].layers.size() << std::endl;
|
||||
// NOTE: can't set the default here since FO3/FONV may have different defaults
|
||||
// mTextures[i].base.formId = 0x000008C0; // TerrainHDDirt01.dds
|
||||
missing = true;
|
||||
}
|
||||
// else
|
||||
//{
|
||||
// std::cout << "ESM4::LAND " << ESM4::formIdToString(mFormId) << " base, quad " << i << std::endl;
|
||||
// std::cout << "layers " << mTextures[i].layers.size() << std::endl;
|
||||
// }
|
||||
}
|
||||
// at least one of the quadrants do not have a base texture, return without setting the flag
|
||||
if (!missing)
|
||||
mDataTypes |= LAND_VTEX;
|
||||
}
|
||||
|
||||
// void ESM4::Land::save(ESM4::Writer& writer) const
|
||||
//{
|
||||
// }
|
||||
|
||||
// void ESM4::Land::blank()
|
||||
//{
|
||||
// }
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
#include <components/esm/defs.hpp>
|
||||
#include <components/esm/formid.hpp>
|
||||
#include <components/vfs/pathutil.hpp>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
|
@ -124,6 +125,8 @@ namespace ESM4
|
|||
Texture mTextures[4]; // 0 = bottom left, 1 = bottom right, 2 = top left, 3 = top right
|
||||
std::vector<ESM::FormId> mIds; // land texture (LTEX) formids
|
||||
ESM::FormId mCell;
|
||||
VFS::Path::NormalizedView mDefaultDiffuseMap;
|
||||
VFS::Path::NormalizedView mDefaultNormalMap;
|
||||
|
||||
void load(Reader& reader);
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue