1
0
mirror of https://gitlab.com/OpenMW/openmw.git synced 2025-02-28 12:40:06 +00:00

Merge branch 'master' of gitlab.com:openmw/openmw into doc_has_more_probls

This commit is contained in:
Zackhasacat 2024-05-07 15:57:30 -05:00
commit 921ee8ffe6
51 changed files with 2615 additions and 170 deletions

View File

@ -81,7 +81,7 @@ message(STATUS "Configuring OpenMW...")
set(OPENMW_VERSION_MAJOR 0)
set(OPENMW_VERSION_MINOR 49)
set(OPENMW_VERSION_RELEASE 0)
set(OPENMW_LUA_API_REVISION 60)
set(OPENMW_LUA_API_REVISION 61)
set(OPENMW_POSTPROCESSING_API_REVISION 1)
set(OPENMW_VERSION_COMMITHASH "")

View File

@ -2,7 +2,8 @@
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
#include <components/esm/esmcommon.hpp>
#include <components/esm/util.hpp>
#include <components/esm/vector3.hpp>
#include <cstdint>
#include <vector>

View File

@ -6,13 +6,13 @@
<rect>
<x>0</x>
<y>0</y>
<width>750</width>
<width>775</width>
<height>635</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>750</width>
<width>775</width>
<height>635</height>
</size>
</property>

View File

@ -2,6 +2,7 @@
#include <vector>
#include <QApplication>
#include <QDragEnterEvent>
#include <QMenu>
#include <QPainter>
@ -424,6 +425,7 @@ void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent* event)
painter.setBackgroundMode(Qt::OpaqueMode);
QFont font = painter.font();
QBrush background = painter.background();
QColor textColor = QApplication::palette().text().color();
while (block.isValid() && top <= event->rect().bottom())
{
@ -440,7 +442,7 @@ void CSVWorld::ScriptEdit::lineNumberAreaPaintEvent(QPaintEvent* event)
else
{
painter.setBackground(background);
painter.setPen(Qt::black);
painter.setPen(textColor);
}
painter.setFont(newFont);
painter.drawText(0, top, mLineNumberArea->width(), fontMetrics().height(), Qt::AlignRight, number);

View File

@ -343,7 +343,12 @@ namespace MWGui
MWBase::Environment::get().getInputManager()->update(0, true, true);
mResourceSystem->reportStats(mViewer->getFrameStamp()->getFrameNumber(), mViewer->getViewerStats());
osg::Stats* const stats = mViewer->getViewerStats();
const unsigned frameNumber = mViewer->getFrameStamp()->getFrameNumber();
stats->setAttribute(frameNumber, "Loading", 1);
mResourceSystem->reportStats(frameNumber, stats);
if (osgUtil::IncrementalCompileOperation* ico = mViewer->getIncrementalCompileOperation())
{
ico->setMinimumTimeAvailableForGLCompileAndDeletePerFrame(1.f / getTargetFrameRate());

View File

@ -104,7 +104,27 @@ namespace MWLua
});
aiPackage["sideWithTarget"] = sol::readonly_property([](const AiPackage& p) { return p.sideWithTarget(); });
aiPackage["destPosition"] = sol::readonly_property([](const AiPackage& p) { return p.getDestination(); });
aiPackage["distance"] = sol::readonly_property([](const AiPackage& p) { return p.getDistance(); });
aiPackage["duration"] = sol::readonly_property([](const AiPackage& p) { return p.getDuration(); });
aiPackage["idle"] = sol::readonly_property([context](const AiPackage& p) -> sol::optional<sol::table> {
if (p.getTypeId() == MWMechanics::AiPackageTypeId::Wander)
{
sol::table idles(context.mLua->sol(), sol::create);
const std::vector<unsigned char>& idle = static_cast<const MWMechanics::AiWander&>(p).getIdle();
if (!idle.empty())
{
for (size_t i = 0; i < idle.size(); ++i)
{
std::string_view groupName = MWMechanics::AiWander::getIdleGroupName(i);
idles[groupName] = idle[i];
}
return idles;
}
}
return sol::nullopt;
});
aiPackage["isRepeat"] = sol::readonly_property([](const AiPackage& p) { return p.getRepeat(); });
selfAPI["_getActiveAiPackage"] = [](SelfObject& self) -> sol::optional<std::shared_ptr<AiPackage>> {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
@ -132,13 +152,25 @@ namespace MWLua
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
ai.stack(MWMechanics::AiPursue(target.ptr()), ptr, cancelOther);
};
selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target, bool cancelOther) {
selfAPI["_startAiFollow"] = [](SelfObject& self, const LObject& target, sol::optional<LCell> cell,
float duration, const osg::Vec3f& dest, bool repeat, bool cancelOther) {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
ai.stack(MWMechanics::AiFollow(target.ptr()), ptr, cancelOther);
if (cell)
{
ai.stack(MWMechanics::AiFollow(target.ptr().getCellRef().getRefId(),
cell->mStore->getCell()->getNameId(), duration, dest.x(), dest.y(), dest.z(), repeat),
ptr, cancelOther);
}
else
{
ai.stack(MWMechanics::AiFollow(
target.ptr().getCellRef().getRefId(), duration, dest.x(), dest.y(), dest.z(), repeat),
ptr, cancelOther);
}
};
selfAPI["_startAiEscort"] = [](SelfObject& self, const LObject& target, LCell cell, float duration,
const osg::Vec3f& dest, bool cancelOther) {
const osg::Vec3f& dest, bool repeat, bool cancelOther) {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
// TODO: change AiEscort implementation to accept ptr instead of a non-unique refId.
@ -146,23 +178,27 @@ namespace MWLua
int gameHoursDuration = static_cast<int>(std::ceil(duration / 3600.0));
auto* esmCell = cell.mStore->getCell();
if (esmCell->isExterior())
ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), false), ptr,
ai.stack(MWMechanics::AiEscort(refId, gameHoursDuration, dest.x(), dest.y(), dest.z(), repeat), ptr,
cancelOther);
else
ai.stack(MWMechanics::AiEscort(
refId, esmCell->getNameId(), gameHoursDuration, dest.x(), dest.y(), dest.z(), false),
refId, esmCell->getNameId(), gameHoursDuration, dest.x(), dest.y(), dest.z(), repeat),
ptr, cancelOther);
};
selfAPI["_startAiWander"] = [](SelfObject& self, int distance, float duration, bool cancelOther) {
selfAPI["_startAiWander"]
= [](SelfObject& self, int distance, int duration, sol::table luaIdle, bool repeat, bool cancelOther) {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
std::vector<unsigned char> idle;
// Lua index starts at 1
for (size_t i = 1; i <= luaIdle.size(); i++)
idle.emplace_back(luaIdle.get<unsigned char>(i));
ai.stack(MWMechanics::AiWander(distance, duration, 0, idle, repeat), ptr, cancelOther);
};
selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target, bool repeat, bool cancelOther) {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
int gameHoursDuration = static_cast<int>(std::ceil(duration / 3600.0));
ai.stack(MWMechanics::AiWander(distance, gameHoursDuration, 0, {}, false), ptr, cancelOther);
};
selfAPI["_startAiTravel"] = [](SelfObject& self, const osg::Vec3f& target, bool cancelOther) {
const MWWorld::Ptr& ptr = self.ptr();
MWMechanics::AiSequence& ai = ptr.getClass().getCreatureStats(ptr).getAiSequence();
ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), false), ptr, cancelOther);
ai.stack(MWMechanics::AiTravel(target.x(), target.y(), target.z(), repeat), ptr, cancelOther);
};
selfAPI["_enableLuaAnimations"] = [](SelfObject& self, bool enable) {
const MWWorld::Ptr& ptr = self.ptr();

View File

@ -1,5 +1,6 @@
#include "aiescort.hpp"
#include <components/esm/util.hpp>
#include <components/esm3/aisequence.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/misc/algorithm.hpp>

View File

@ -51,6 +51,8 @@ namespace MWMechanics
osg::Vec3f getDestination() const override { return osg::Vec3f(mX, mY, mZ); }
std::optional<float> getDuration() const override { return mDuration; }
private:
const std::string mCellId;
const float mX;

View File

@ -110,6 +110,10 @@ namespace MWMechanics
virtual osg::Vec3f getDestination() const { return osg::Vec3f(0, 0, 0); }
virtual std::optional<int> getDistance() const { return std::nullopt; }
virtual std::optional<float> getDuration() const { return std::nullopt; }
/// Return true if any loaded actor with this AI package must be active.
bool alwaysActive() const { return mOptions.mAlwaysActive; }

View File

@ -113,6 +113,14 @@ namespace MWMechanics
bool isStationary() const { return mDistance == 0; }
std::optional<int> getDistance() const override { return mDistance; }
std::optional<float> getDuration() const override { return static_cast<float>(mDuration); }
const std::vector<unsigned char>& getIdle() const { return mIdle; }
static std::string_view getIdleGroupName(size_t index) { return sIdleSelectToGroupName[index]; }
private:
void stopWalking(const MWWorld::Ptr& actor);

View File

@ -3,7 +3,9 @@
#include <atomic>
#include <condition_variable>
#include <memory>
#include <optional>
#include <set>
#include <shared_mutex>
#include <thread>
#include <unordered_set>

View File

@ -6,7 +6,6 @@
#include <map>
#include <memory>
#include <optional>
#include <set>
#include <span>
#include <unordered_map>
#include <variant>
@ -16,8 +15,6 @@
#include <osg/Timer>
#include <osg/ref_ptr>
#include <components/esm/util.hpp>
#include "../mwworld/ptr.hpp"
#include "collisiontype.hpp"

View File

@ -3,7 +3,7 @@
#include <osg/Object>
#include <components/esm/util.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esmterrain/storage.hpp>
#include <components/resource/resourcemanager.hpp>

View File

@ -555,11 +555,19 @@ namespace MWRender
// TODO
}
if (activeGrid)
if (activeGrid && !refs.empty())
{
std::lock_guard<std::mutex> lock(mRefTrackerMutex);
for (auto ref : getRefTracker().mBlacklist)
refs.erase(ref);
const std::set<ESM::RefNum>& blacklist = getRefTracker().mBlacklist;
if (blacklist.size() < refs.size())
{
for (ESM::RefNum ref : blacklist)
refs.erase(ref);
}
else
{
std::erase_if(refs, [&](const auto& ref) { return blacklist.contains(ref.first); });
}
}
osg::Vec2f minBound = (center - osg::Vec2f(size / 2.f, size / 2.f));

View File

@ -11,6 +11,8 @@
#include <components/misc/strings/algorithm.hpp>
#include <components/esm/util.hpp>
#include "../mwbase/environment.hpp"
#include "../mwbase/statemanager.hpp"
#include "../mwbase/windowmanager.hpp"
@ -123,7 +125,7 @@ namespace MWScript
MWBase::World* world = MWBase::Environment::get().getWorld();
MWWorld::Ptr playerPtr = world->getPlayerPtr();
osg::Vec2 posFromIndex
const osg::Vec2f posFromIndex
= ESM::indexToPosition(ESM::ExteriorCellLocation(x, y, ESM::Cell::sDefaultWorldspaceId), true);
pos.pos[0] = posFromIndex.x();
pos.pos[1] = posFromIndex.y();

View File

@ -4,6 +4,8 @@
#include <components/esm3/loadcell.hpp>
#include <components/esm/util.hpp>
#include <components/compiler/opcodes.hpp>
#include <components/interpreter/interpreter.hpp>

View File

@ -624,7 +624,7 @@ void MWState::StateManager::loadGame(const Character* character, const std::file
Log(Debug::Warning) << "Player character's cell no longer exists, changing to the default cell";
ESM::ExteriorCellLocation cellIndex(0, 0, ESM::Cell::sDefaultWorldspaceId);
MWWorld::CellStore& cell = MWBase::Environment::get().getWorldModel()->getExterior(cellIndex);
osg::Vec2 posFromIndex = ESM::indexToPosition(cellIndex, false);
const osg::Vec2f posFromIndex = ESM::indexToPosition(cellIndex, false);
ESM::Position pos;
pos.pos[0] = posFromIndex.x();
pos.pos[1] = posFromIndex.y();

View File

@ -4,8 +4,8 @@
#include <osg/Vec2i>
#include <components/esm/esmbridge.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esm/refid.hpp>
#include <components/esm/util.hpp>
namespace ESM
{

View File

@ -15,6 +15,9 @@
#include <components/esm3/loadrace.hpp>
#include <components/esm3/projectilestate.hpp>
#include <components/esm/quaternion.hpp>
#include <components/esm/vector3.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/convert.hpp>
#include <components/misc/resourcehelpers.hpp>

View File

@ -542,7 +542,7 @@ namespace MWWorld
= mCurrentCell ? mCurrentCell->getCell()->getWorldSpace() : ESM::Cell::sDefaultWorldspaceId;
if (currentGridCenter)
{
osg::Vec2 center = ESM::indexToPosition(
const osg::Vec2f center = ESM::indexToPosition(
ESM::ExteriorCellLocation(currentGridCenter->x(), currentGridCenter->y(), worldspace), true);
float distance = std::max(std::abs(center.x() - pos.x()), std::abs(center.y() - pos.y()));
float cellSize = ESM::getCellSize(worldspace);
@ -1171,7 +1171,7 @@ namespace MWWorld
&& dx != -halfGridSizePlusOne)
continue; // only care about the outer (not yet loaded) part of the grid
ESM::ExteriorCellLocation cellIndex(cellX + dx, cellY + dy, extWorldspace);
osg::Vec2 thisCellCenter = ESM::indexToPosition(cellIndex, true);
const osg::Vec2f thisCellCenter = ESM::indexToPosition(cellIndex, true);
float dist = std::max(
std::abs(thisCellCenter.x() - playerPos.x()), std::abs(thisCellCenter.y() - playerPos.y()));

View File

@ -10,10 +10,9 @@
#include <memory>
#include <optional>
#include <set>
#include <unordered_map>
#include <vector>
#include <components/esm/util.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/misc/constants.hpp>
namespace osg

View File

@ -2784,7 +2784,7 @@ namespace MWWorld
int x = ext->getGridX();
int y = ext->getGridY();
osg::Vec2 posFromIndex = indexToPosition(ESM::ExteriorCellLocation(x, y, ext->getWorldSpace()), true);
const osg::Vec2f posFromIndex = indexToPosition(ESM::ExteriorCellLocation(x, y, ext->getWorldSpace()), true);
pos.pos[0] = posFromIndex.x();
pos.pos[1] = posFromIndex.y();

View File

@ -7,7 +7,7 @@
#include <string_view>
#include <unordered_map>
#include <components/esm/util.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/misc/algorithm.hpp>
#include "cellstore.hpp"

View File

@ -169,6 +169,9 @@ add_component_dir(esm attr common defs esmcommon records util luascripts format
indexrefid
serializerefid
esm3exteriorcellrefid
quaternion
vector3
exteriorcelllocation
)
add_component_dir(fx pass technique lexer lexer_types parse_constants widgets stateupdater)
@ -186,6 +189,7 @@ add_component_dir (esm3
weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
aisequence magiceffects custommarkerstate stolenitems transport animationstate controlsstate mappings readerscache
infoorder timestamp formatversion landrecorddata selectiongroup dialoguecondition
refnum
)
add_component_dir (esmterrain

View File

@ -602,7 +602,8 @@ void ContentSelectorModel::ContentModel::sortFiles()
emit layoutAboutToBeChanged();
int firstModifiable = 0;
while (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile())
while (firstModifiable < mFiles.size()
&& (mFiles.at(firstModifiable)->builtIn() || mFiles.at(firstModifiable)->fromAnotherConfigFile()))
++firstModifiable;
// Dependency sort

View File

@ -0,0 +1,53 @@
#ifndef OPENMW_COMPONENTS_ESM_EXTERIORCELLLOCATION_H
#define OPENMW_COMPONENTS_ESM_EXTERIORCELLLOCATION_H
#include "refid.hpp"
#include <components/esm3/loadcell.hpp>
#include <tuple>
namespace ESM
{
struct ExteriorCellLocation
{
int mX = 0;
int mY = 0;
ESM::RefId mWorldspace = ESM::Cell::sDefaultWorldspaceId;
ExteriorCellLocation() = default;
ExteriorCellLocation(int x, int y, ESM::RefId worldspace)
: mX(x)
, mY(y)
, mWorldspace(worldspace)
{
}
friend bool operator==(const ExteriorCellLocation& lhs, const ExteriorCellLocation& rhs) = default;
friend inline bool operator<(const ExteriorCellLocation& lhs, const ExteriorCellLocation& rhs)
{
return std::make_tuple(lhs.mX, lhs.mY, lhs.mWorldspace) < std::make_tuple(rhs.mX, rhs.mY, rhs.mWorldspace);
}
};
}
namespace std
{
template <>
struct hash<ESM::ExteriorCellLocation>
{
std::size_t operator()(const ESM::ExteriorCellLocation& toHash) const
{
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<int>()(toHash.mX) ^ (hash<int>()(toHash.mY) << 1)) >> 1)
^ (hash<ESM::RefId>()(toHash.mWorldspace) << 1);
}
};
}
#endif

View File

@ -0,0 +1,29 @@
#ifndef OPENMW_COMPONENTS_ESM_QUATERNION_H
#define OPENMW_COMPONENTS_ESM_QUATERNION_H
#include <osg/Quat>
namespace ESM
{
// format 0, savegames only
struct Quaternion
{
float mValues[4];
Quaternion() = default;
Quaternion(const osg::Quat& q)
: mValues{
static_cast<float>(q.w()),
static_cast<float>(q.x()),
static_cast<float>(q.y()),
static_cast<float>(q.z()),
}
{
}
operator osg::Quat() const { return osg::Quat(mValues[1], mValues[2], mValues[3], mValues[0]); }
};
}
#endif

View File

@ -1,8 +1,9 @@
#include "util.hpp"
#include <components/esm3/loadland.hpp>
#include <components/esm4/loadland.hpp>
osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre)
osg::Vec2f ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre)
{
const int cellSize = ESM::getCellSize(cellIndex.mWorldspace);
@ -14,7 +15,8 @@ osg::Vec2 ESM::indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool
x += cellSize / 2;
y += cellSize / 2;
}
return osg::Vec2(x, y);
return osg::Vec2f(x, y);
}
int ESM::getLandSize(ESM::RefId worldspaceId)

View File

@ -1,79 +1,18 @@
#ifndef OPENMW_ESM_UTIL_H
#define OPENMW_ESM_UTIL_H
#ifndef OPENMW_COMPONENTS_ESM_UTIL_H
#define OPENMW_COMPONENTS_ESM_UTIL_H
#include <cmath>
#include <osg/Quat>
#include <osg/Vec2>
#include <osg/Vec2i>
#include <osg/Vec3f>
#include <osg/Vec2f>
#include <components/esm/refid.hpp>
#include <components/esm3/loadcell.hpp>
#include <components/misc/constants.hpp>
#include "components/esm3/loadcell.hpp"
#include "components/misc/constants.hpp"
#include "exteriorcelllocation.hpp"
#include "refid.hpp"
namespace ESM
{
// format 0, savegames only
struct Quaternion
{
float mValues[4];
Quaternion() = default;
Quaternion(const osg::Quat& q)
{
mValues[0] = q.w();
mValues[1] = q.x();
mValues[2] = q.y();
mValues[3] = q.z();
}
operator osg::Quat() const { return osg::Quat(mValues[1], mValues[2], mValues[3], mValues[0]); }
};
struct Vector3
{
float mValues[3];
Vector3() = default;
Vector3(const osg::Vec3f& v)
{
mValues[0] = v.x();
mValues[1] = v.y();
mValues[2] = v.z();
}
operator osg::Vec3f() const { return osg::Vec3f(mValues[0], mValues[1], mValues[2]); }
};
struct ExteriorCellLocation
{
int mX = 0;
int mY = 0;
ESM::RefId mWorldspace = ESM::Cell::sDefaultWorldspaceId;
ExteriorCellLocation() = default;
ExteriorCellLocation(int x, int y, ESM::RefId worldspace)
: mX(x)
, mY(y)
, mWorldspace(worldspace)
{
}
bool operator==(const ExteriorCellLocation& other) const
{
return mX == other.mX && mY == other.mY && mWorldspace == other.mWorldspace;
}
bool operator<(const ExteriorCellLocation& other) const
{
return std::make_tuple(mX, mY, mWorldspace) < std::make_tuple(other.mX, other.mY, other.mWorldspace);
}
};
inline bool isEsm4Ext(ESM::RefId worldspaceId)
{
return worldspaceId != ESM::Cell::sDefaultWorldspaceId;
@ -81,7 +20,6 @@ namespace ESM
inline int getCellSize(ESM::RefId worldspaceId)
{
return isEsm4Ext(worldspaceId) ? Constants::ESM4CellSizeInUnits : Constants::CellSizeInUnits;
}
@ -95,25 +33,8 @@ namespace ESM
return { static_cast<int>(std::floor(x / cellSize)), static_cast<int>(std::floor(y / cellSize)), worldspaceId };
}
osg::Vec2 indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre = false);
///< Convert cell numbers to position.
}
namespace std
{
template <>
struct hash<ESM::ExteriorCellLocation>
{
std::size_t operator()(const ESM::ExteriorCellLocation& toHash) const
{
// Compute individual hash values for first,
// second and third and combine them using XOR
// and bit shifting:
return ((hash<int>()(toHash.mX) ^ (hash<int>()(toHash.mY) << 1)) >> 1)
^ (hash<ESM::RefId>()(toHash.mWorldspace) << 1);
}
};
// Convert exterior cell location to position.
osg::Vec2f indexToPosition(const ESM::ExteriorCellLocation& cellIndex, bool centre = false);
}
#endif

View File

@ -0,0 +1,24 @@
#ifndef OPENMW_COMPONENTS_ESM_VECTOR3_H
#define OPENMW_COMPONENTS_ESM_VECTOR3_H
#include <osg/Vec3f>
namespace ESM
{
// format 0, savegames only
struct Vector3
{
float mValues[3];
Vector3() = default;
Vector3(const osg::Vec3f& v)
: mValues{ v.x(), v.y(), v.z() }
{
}
operator osg::Vec3f() const { return osg::Vec3f(mValues[0], mValues[1], mValues[2]); }
};
}
#endif

View File

@ -6,8 +6,8 @@
#include <string>
#include <vector>
#include "components/esm/refid.hpp"
#include "components/esm/util.hpp"
#include <components/esm/refid.hpp>
#include <components/esm/vector3.hpp>
namespace ESM
{

View File

@ -8,13 +8,13 @@
#include <components/esm/position.hpp>
#include <components/esm/refid.hpp>
#include "refnum.hpp"
namespace ESM
{
class ESMWriter;
class ESMReader;
using RefNum = ESM::FormId;
/* Cell reference. This represents ONE object (of many) inside the
cell. The cell references are not loaded as part of the normal
loading process, but are rather loaded later on demand when we are

View File

@ -1,18 +1,19 @@
#ifndef OPENMW_ESM_PROJECTILESTATE_H
#define OPENMW_ESM_PROJECTILESTATE_H
#include <string>
#include <osg/Quat>
#include <osg/Vec3f>
#include "effectlist.hpp"
#include "components/esm/quaternion.hpp"
#include "components/esm/refid.hpp"
#include "components/esm/util.hpp"
#include "components/esm/vector3.hpp"
#include "refnum.hpp"
namespace ESM
{
class ESMReader;
class ESMWriter;
// format 0, savegames only

View File

@ -0,0 +1,11 @@
#ifndef OPENMW_COMPONENTS_ESM3_REFNUM_H
#define OPENMW_COMPONENTS_ESM3_REFNUM_H
#include <components/esm/formid.hpp>
namespace ESM
{
using RefNum = ESM::FormId;
}
#endif

View File

@ -32,8 +32,8 @@
#include <vector>
#include <components/esm/defs.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esm/refid.hpp>
#include <components/esm/util.hpp>
#include <components/esm4/reader.hpp>
#include <components/misc/constants.hpp>

View File

@ -9,6 +9,7 @@
#include <components/debug/debuglog.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/util.hpp>
#include <components/esm3/loadland.hpp>
#include <components/esm4/loadland.hpp>
#include <components/misc/resourcehelpers.hpp>

View File

@ -7,7 +7,7 @@
#include <components/terrain/storage.hpp>
#include <components/esm/esmterrain.hpp>
#include <components/esm/util.hpp>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esm3/loadltex.hpp>
namespace ESM4

View File

@ -54,6 +54,7 @@ namespace Resource
constexpr std::string_view firstPage[] = {
"FrameNumber",
"",
"Loading",
"Compiling",
"WorkQueue",
"WorkThread",
@ -75,7 +76,6 @@ namespace Resource
"",
"",
"",
"",
};
static_assert(std::size(firstPage) == itemsPerPage);

View File

@ -7,6 +7,7 @@
#include <limits>
#include <components/esm/util.hpp>
#include <components/loadinglistener/reporter.hpp>
#include <components/misc/constants.hpp>
#include <components/misc/mathutil.hpp>

View File

@ -8,8 +8,8 @@
#include <osg/Vec3f>
#include <osg/ref_ptr>
#include <components/esm/exteriorcelllocation.hpp>
#include <components/esm/refid.hpp>
#include <components/esm/util.hpp>
#include "defs.hpp"

View File

@ -99,6 +99,18 @@ Follow another actor.
* - target
- `GameObject <openmw_core.html##(GameObject)>`_ [required]
- the actor to follow
* - destCell
- Cell [optional]
- the destination cell
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - destPosition
- `3d vector <openmw_util.html##(Vector3)>`_ [optional]
- the destination point
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
Escort
------
@ -126,6 +138,9 @@ Escort another actor to the given location.
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
@ -136,6 +151,7 @@ Escort another actor to the given location.
target = object.self,
destPosition = util.vector3(x, y, z),
duration = 3 * time.hour,
isRepeat = true
})
Wander
@ -158,6 +174,34 @@ Wander nearby current position.
* - duration
- number [optional]
- duration in game time (will be rounded up to the next hour)
* - idle
- table [optional]
- Idle chance values, up to 8
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)
**Example**
.. code-block:: Lua
local idleTable = {
idle2 = 60,
idle3 = 50,
idle4 = 40,
idle5 = 30,
idle6 = 20,
idle7 = 10,
idle8 = 0,
idle9 = 25
}
actor:sendEvent('StartAIPackage', {
type = 'Wander',
distance = 5000,
duration = 5 * time.hour,
idle = idleTable,
isRepeat = true
})
Travel
------
@ -176,4 +220,6 @@ Go to given location.
* - destPosition
- `3d vector <openmw_util.html##(Vector3)>`_ [required]
- the point to travel to
* - isRepeat
- boolean [optional]
- Will the package repeat (true or false)

View File

@ -1,5 +1,6 @@
local self = require('openmw.self')
local interfaces = require('openmw.interfaces')
local util = require('openmw.util')
local function startPackage(args)
local cancelOther = args.cancelOther
@ -12,16 +13,36 @@ local function startPackage(args)
self:_startAiPursue(args.target, cancelOther)
elseif args.type == 'Follow' then
if not args.target then error("target required") end
self:_startAiFollow(args.target, cancelOther)
self:_startAiFollow(args.target, args.cellId, args.duration or 0, args.destPosition or util.vector3(0, 0, 0), args.isRepeat or false, cancelOther)
elseif args.type == 'Escort' then
if not args.target then error("target required") end
if not args.destPosition then error("destPosition required") end
self:_startAiEscort(args.target, args.destCell or self.cell, args.duration or 0, args.destPosition, cancelOther)
elseif args.type == 'Wander' then
self:_startAiWander(args.distance or 0, args.duration or 0, cancelOther)
local key = "idle"
local idle = {}
local duration = 0
if args.idle then
for i = 2, 9 do
local val = args.idle[key .. i]
if val == nil then
idle[i-1] = 0
else
local v = tonumber(val) or 0
if v < 0 or v > 100 then
error("idle values cannot exceed 100")
end
idle[i-1] = v
end
end
end
if args.duration then
duration = args.duration / 3600
end
self:_startAiWander(args.distance or 0, duration, idle, args.isRepeat or false, cancelOther)
elseif args.type == 'Travel' then
if not args.destPosition then error("destPosition required") end
self:_startAiTravel(args.destPosition, cancelOther)
self:_startAiTravel(args.destPosition, args.isRepeat or false, cancelOther)
else
error('Unsupported AI Package: ' .. args.type)
end
@ -47,6 +68,10 @@ return {
-- @field openmw.core#GameObject target Target (usually an actor) of the AI package (can be nil).
-- @field #boolean sideWithTarget Whether to help the target in combat (true or false).
-- @field openmw.util#Vector3 destPosition Destination point of the AI package.
-- @field #number distance Distance value (can be nil).
-- @field #number duration Duration value (can be nil).
-- @field #table idle Idle value (can be nil).
-- @field #boolean isRepeat Should this package be repeated (true or false).
--- Return the currently active AI package (or `nil` if there are no AI packages).
-- @function [parent=#AI] getActivePackage

View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en">
<context>
<name>ContentSelector</name>
<message>
<source>Select language used by ESM/ESP content files to allow OpenMW to detect their encoding. </source>
<translation></translation>
</message>
</context>
<context>
<name>ContentSelectorModel::ContentModel</name>
<message>
<source>Unable to find dependent file: %1</source>
<translation></translation>
</message>
<message>
<source>Dependent file needs to be active: %1</source>
<translation></translation>
</message>
<message>
<source>This file needs to load after %1</source>
<translation></translation>
</message>
</context>
<context>
<name>ContentSelectorModel::EsmFile</name>
<message>
<source>&lt;br/&gt;&lt;b&gt;This content file cannot be disabled because it is part of OpenMW.&lt;/b&gt;&lt;br/&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;br/&gt;&lt;b&gt;This content file cannot be disabled because it is enabled in a config file other than the user one.&lt;/b&gt;&lt;br/&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;b&gt;Author:&lt;/b&gt; %1&lt;br/&gt;&lt;b&gt;Format version:&lt;/b&gt; %2&lt;br/&gt;&lt;b&gt;Modified:&lt;/b&gt; %3&lt;br/&gt;&lt;b&gt;Path:&lt;/b&gt;&lt;br/&gt;%4&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Description:&lt;/b&gt;&lt;br/&gt;%5&lt;br/&gt;&lt;br/&gt;&lt;b&gt;Dependencies: &lt;/b&gt;%6&lt;br/&gt;</source>
<translation></translation>
</message>
</context>
<context>
<name>ContentSelectorView::ContentSelector</name>
<message>
<source>&lt;No game file&gt;</source>
<translation></translation>
</message>
<message>
<source>&amp;Check Selected</source>
<translation></translation>
</message>
<message>
<source>&amp;Uncheck Selected</source>
<translation></translation>
</message>
<message>
<source>&amp;Copy Path(s) to Clipboard</source>
<translation></translation>
</message>
</context>
<context>
<name>Process::ProcessInvoker</name>
<message>
<source>Error starting executable</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not find %1&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The application is not found.&lt;/p&gt;&lt;p&gt;Please make sure OpenMW is installed correctly and try again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not start %1&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The application is not executable.&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not start %1&lt;/b&gt;&lt;/p&gt;&lt;p&gt;An error occurred while starting %1.&lt;/p&gt;&lt;p&gt;Press &quot;Show Details...&quot; for more information.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Error running executable</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Executable %1 returned an error&lt;/b&gt;&lt;/p&gt;&lt;p&gt;An error occurred while running %1.&lt;/p&gt;&lt;p&gt;Press &quot;Show Details...&quot; for more information.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>
Arguments:
</source>
<translation></translation>
</message>
</context>
</TS>

1475
files/lang/launcher_en.ts Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1226,11 +1226,11 @@ to default Morrowind fonts. Check this box if you still prefer original fonts ov
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;If enabled, a magical ammunition is required to bypass normal weapon resistance or weakness. If disabled, a magical ranged weapon or a magical ammunition is required.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Если настройка включена, требуются магические метательные снаряды, чтобы обойти сопротивление обычному оружию или уязвимость к нему. Если отключена, то требуются магические снаряды или магическое оружие дальнего боя.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
<translation>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Если настройка включена, для обхода сопротивления или уязвимости к обычному оружию необходимо, чтобы снаряд был магическим. Если выключена, то магическим для этого может быть как снаряд, так и оружие дальнего боя.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</translation>
</message>
<message>
<source>Only Magical Ammo Bypass Resistance</source>
<translation>Только снаряды обходят сопротивление</translation>
<translation>Обычные снаряды не обходят сопротивление</translation>
</message>
<message>
<source>Graphic Herbalism</source>

656
files/lang/wizard_en.ts Normal file
View File

@ -0,0 +1,656 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="en_EN">
<context>
<name>ComponentSelectionPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Select Components</source>
<translation></translation>
</message>
<message>
<source>Which components should be installed?</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select which official Morrowind expansions should be installed. For best results, it is recommended to have both expansions installed.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:bold;&quot;&gt;Note:&lt;/span&gt; It is possible to install expansions later by re-running this Wizard.&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Selected components:</source>
<translation></translation>
</message>
</context>
<context>
<name>ConclusionPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Completing the OpenMW Wizard</source>
<translation></translation>
</message>
<message>
<source>Placeholder</source>
<translation></translation>
</message>
</context>
<context>
<name>ExistingInstallationPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Select Existing Installation</source>
<translation></translation>
</message>
<message>
<source>Select an existing installation for OpenMW to use or modify.</source>
<translation></translation>
</message>
<message>
<source>Detected installations:</source>
<translation></translation>
</message>
<message>
<source>Browse...</source>
<translation></translation>
</message>
</context>
<context>
<name>ImportPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Import Settings</source>
<translation></translation>
</message>
<message>
<source>Import settings from the Morrowind installation.</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;OpenMW needs to import settings from the Morrowind configuration file in order to function properly.&lt;/p&gt;&lt;p&gt;&lt;span style=&quot; font-weight:bold;&quot;&gt;Note:&lt;/span&gt; It is possible to import settings later by re-running this Wizard.&lt;/p&gt;&lt;p/&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Import Settings From Morrowind.ini</source>
<translation></translation>
</message>
<message>
<source>Import Add-on and Plugin Selection</source>
<translation></translation>
</message>
<message>
<source>Import Bitmap Fonts Setup From Morrowind.ini</source>
<translation></translation>
</message>
<message>
<source>Fonts shipped with the original engine are blurry with UI scaling and support only a small amount of characters,
so OpenMW provides another set of fonts to avoid these issues. These fonts use TrueType technology and are quite similar
to default Morrowind fonts. Check this box if you still prefer original fonts over OpenMW ones or if you use custom bitmap fonts.</source>
<translation></translation>
</message>
</context>
<context>
<name>InstallationPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Installing</source>
<translation></translation>
</message>
<message>
<source>Please wait while Morrowind is installed on your computer.</source>
<translation></translation>
</message>
</context>
<context>
<name>InstallationTargetPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Select Installation Destination</source>
<translation></translation>
</message>
<message>
<source>Where should Morrowind be installed?</source>
<translation></translation>
</message>
<message>
<source>Morrowind will be installed to the following location. </source>
<translation></translation>
</message>
<message>
<source>Browse...</source>
<translation></translation>
</message>
</context>
<context>
<name>IntroPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Welcome to the OpenMW Wizard</source>
<translation></translation>
</message>
<message>
<source>This Wizard will help you install Morrowind and its add-ons for OpenMW to use.</source>
<translation></translation>
</message>
</context>
<context>
<name>LanguageSelectionPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Select Morrowind Language</source>
<translation></translation>
</message>
<message>
<source>What is the language of the Morrowind installation?</source>
<translation></translation>
</message>
<message>
<source>Select the language of the Morrowind installation.</source>
<translation></translation>
</message>
</context>
<context>
<name>MethodSelectionPage</name>
<message>
<source>WizardPage</source>
<translation></translation>
</message>
<message>
<source>Select Installation Method</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Select how you would like to install &lt;i&gt;The Elder Scrolls III: Morrowind&lt;/i&gt;.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Retail CD/DVD</source>
<translation></translation>
</message>
<message>
<source>Install from a retail disc to a new location.</source>
<translation></translation>
</message>
<message>
<source>Existing Installation</source>
<translation></translation>
</message>
<message>
<source>Select an existing installation.</source>
<translation></translation>
</message>
<message>
<source>Don&apos;t have a copy?</source>
<translation></translation>
</message>
<message>
<source>Buy the game</source>
<translation></translation>
</message>
</context>
<context>
<name>QObject</name>
<message>
<source>&lt;br&gt;&lt;b&gt;Could not find Morrowind.ini&lt;/b&gt;&lt;br&gt;&lt;br&gt;The Wizard needs to update settings in this file.&lt;br&gt;&lt;br&gt;Press &quot;Browse...&quot; to specify the location manually.&lt;br&gt;</source>
<translation></translation>
</message>
<message>
<source>B&amp;rowse...</source>
<translation></translation>
</message>
<message>
<source>Select configuration file</source>
<translation></translation>
</message>
<message>
<source>&lt;b&gt;Morrowind.bsa&lt;/b&gt; is missing!&lt;br&gt;Make sure your Morrowind installation is complete.</source>
<translation></translation>
</message>
<message>
<source>Most recent Morrowind not detected</source>
<translation></translation>
</message>
<message>
<source>&lt;br&gt;&lt;b&gt;There may be a more recent version of Morrowind available.&lt;/b&gt;&lt;br&gt;&lt;br&gt;Do you wish to continue anyway?&lt;br&gt;</source>
<translation></translation>
</message>
<message>
<source>Select a valid %1 installation media.&lt;br&gt;&lt;b&gt;Hint&lt;/b&gt;: make sure that it contains at least one &lt;b&gt;.cab&lt;/b&gt; file.</source>
<translation></translation>
</message>
<message>
<source>There may be a more recent version of Morrowind available.&lt;br&gt;&lt;br&gt;Do you wish to continue anyway?</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::ComponentSelectionPage</name>
<message>
<source>&amp;Install</source>
<translation></translation>
</message>
<message>
<source>&amp;Skip</source>
<translation></translation>
</message>
<message>
<source>Morrowind (installed)</source>
<translation></translation>
</message>
<message>
<source>Morrowind</source>
<translation></translation>
</message>
<message>
<source>Tribunal (installed)</source>
<translation></translation>
</message>
<message>
<source>Tribunal</source>
<translation></translation>
</message>
<message>
<source>Bloodmoon (installed)</source>
<translation></translation>
</message>
<message>
<source>Bloodmoon</source>
<translation></translation>
</message>
<message>
<source>About to install Tribunal after Bloodmoon</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;You are about to install Tribunal&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Bloodmoon is already installed on your computer.&lt;/p&gt;&lt;p&gt;However, it is recommended that you install Tribunal before Bloodmoon.&lt;/p&gt;&lt;p&gt;Would you like to re-install Bloodmoon?&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Re-install &amp;Bloodmoon</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::ConclusionPage</name>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The OpenMW Wizard successfully installed Morrowind on your computer.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The OpenMW Wizard successfully modified your existing Morrowind installation.&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;The OpenMW Wizard failed to install Morrowind on your computer.&lt;/p&gt;&lt;p&gt;Please report any bugs you might have encountered to our &lt;a href=&quot;https://gitlab.com/OpenMW/openmw/issues&quot;&gt;bug tracker&lt;/a&gt;.&lt;br/&gt;Make sure to include the installation log.&lt;/p&gt;&lt;br/&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::ExistingInstallationPage</name>
<message>
<source>No existing installations detected</source>
<translation></translation>
</message>
<message>
<source>Error detecting Morrowind configuration</source>
<translation></translation>
</message>
<message>
<source>Morrowind configuration file (*.ini)</source>
<translation></translation>
</message>
<message>
<source>Select Morrowind.esm (located in Data Files)</source>
<translation></translation>
</message>
<message>
<source>Morrowind master file (Morrowind.esm)</source>
<translation></translation>
</message>
<message>
<source>Error detecting Morrowind files</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::InstallationPage</name>
<message>
<source>&lt;p&gt;Attempting to install component %1.&lt;/p&gt;</source>
<translation></translation>
</message>
<message>
<source>Attempting to install component %1.</source>
<translation></translation>
</message>
<message>
<source>%1 Installation</source>
<translation></translation>
</message>
<message>
<source>Select %1 installation media</source>
<translation></translation>
</message>
<message>
<source>&lt;p&gt;&lt;br/&gt;&lt;span style=&quot;color:red;&quot;&gt;&lt;b&gt;Error: The installation was aborted by the user&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;p&gt;Detected old version of component Morrowind.&lt;/p&gt;</source>
<translation></translation>
</message>
<message>
<source>Detected old version of component Morrowind.</source>
<translation></translation>
</message>
<message>
<source>Morrowind Installation</source>
<translation></translation>
</message>
<message>
<source>Installation finished</source>
<translation></translation>
</message>
<message>
<source>Installation completed successfully!</source>
<translation></translation>
</message>
<message>
<source>Installation failed!</source>
<translation></translation>
</message>
<message>
<source>&lt;p&gt;&lt;br/&gt;&lt;span style=&quot;color:red;&quot;&gt;&lt;b&gt;Error: %1&lt;/b&gt;&lt;/p&gt;</source>
<translation></translation>
</message>
<message>
<source>&lt;p&gt;&lt;span style=&quot;color:red;&quot;&gt;&lt;b&gt;%1&lt;/b&gt;&lt;/p&gt;</source>
<translation></translation>
</message>
<message>
<source>An error occurred</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;The Wizard has encountered an error&lt;/b&gt;&lt;/p&gt;&lt;p&gt;The error reported was:&lt;/p&gt;&lt;p&gt;%1&lt;/p&gt;&lt;p&gt;Press &amp;quot;Show Details...&amp;quot; for more information.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::InstallationTargetPage</name>
<message>
<source>Error creating destination</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not create the destination directory&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again, or specify a different location.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Insufficient permissions</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not write to the destination directory&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again, or specify a different location.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Destination not empty</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;The destination directory is not empty&lt;/b&gt;&lt;/p&gt;&lt;p&gt;An existing Morrowind installation is present in the specified location.&lt;/p&gt;&lt;p&gt;Please specify a different location, or go back and select the location as an existing installation.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Select where to install Morrowind</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::LanguageSelectionPage</name>
<message>
<source>English</source>
<translation></translation>
</message>
<message>
<source>French</source>
<translation></translation>
</message>
<message>
<source>German</source>
<translation></translation>
</message>
<message>
<source>Italian</source>
<translation></translation>
</message>
<message>
<source>Polish</source>
<translation></translation>
</message>
<message>
<source>Russian</source>
<translation></translation>
</message>
<message>
<source>Spanish</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::MainWizard</name>
<message>
<source>OpenMW Wizard</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not open %1 for writing&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Error opening Wizard log file</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not open %1 for reading&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Error opening OpenMW configuration file</source>
<translation></translation>
</message>
<message>
<source>Quit Wizard</source>
<translation></translation>
</message>
<message>
<source>Are you sure you want to exit the Wizard?</source>
<translation></translation>
</message>
<message>
<source>Error creating OpenMW configuration directory</source>
<translation></translation>
</message>
<message>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;b&gt;Could not create %1&lt;/b&gt;&lt;/p&gt;&lt;p&gt;Please make sure you have the right permissions and try again.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation></translation>
</message>
<message>
<source>Error writing OpenMW configuration file</source>
<translation></translation>
</message>
</context>
<context>
<name>Wizard::UnshieldWorker</name>
<message>
<source>Failed to open Morrowind configuration file!</source>
<translation></translation>
</message>
<message>
<source>Opening %1 failed: %2.</source>
<translation></translation>
</message>
<message>
<source>Failed to write Morrowind configuration file!</source>
<translation></translation>
</message>
<message>
<source>Writing to %1 failed: %2.</source>
<translation></translation>
</message>
<message>
<source>Installing: %1</source>
<translation></translation>
</message>
<message>
<source>Installing: %1 directory</source>
<translation></translation>
</message>
<message>
<source>Installation finished!</source>
<translation></translation>
</message>
<message>
<source>Component parameter is invalid!</source>
<translation></translation>
</message>
<message>
<source>An invalid component parameter was supplied.</source>
<translation></translation>
</message>
<message>
<source>Failed to find a valid archive containing %1.bsa! Retrying.</source>
<translation></translation>
</message>
<message>
<source>Installing %1</source>
<translation></translation>
</message>
<message>
<source>Installation media path not set!</source>
<translation></translation>
</message>
<message>
<source>The source path for %1 was not set.</source>
<translation></translation>
</message>
<message>
<source>Cannot create temporary directory!</source>
<translation></translation>
</message>
<message>
<source>Failed to create %1.</source>
<translation></translation>
</message>
<message>
<source>Cannot move into temporary directory!</source>
<translation></translation>
</message>
<message>
<source>Failed to move into %1.</source>
<translation></translation>
</message>
<message>
<source>Moving installation files</source>
<translation></translation>
</message>
<message>
<source>Could not install directory!</source>
<translation></translation>
</message>
<message>
<source>Installing %1 to %2 failed.</source>
<translation></translation>
</message>
<message>
<source>Could not install translation file!</source>
<translation></translation>
</message>
<message>
<source>Failed to install *%1 files.</source>
<translation></translation>
</message>
<message>
<source>Could not install Morrowind data file!</source>
<translation></translation>
</message>
<message>
<source>Failed to install %1.</source>
<translation></translation>
</message>
<message>
<source>Could not install Morrowind configuration file!</source>
<translation></translation>
</message>
<message>
<source>Installing: Sound directory</source>
<translation></translation>
</message>
<message>
<source>Could not find Tribunal data file!</source>
<translation></translation>
</message>
<message>
<source>Failed to find %1.</source>
<translation></translation>
</message>
<message>
<source>Could not find Tribunal patch file!</source>
<translation></translation>
</message>
<message>
<source>Could not find Bloodmoon data file!</source>
<translation></translation>
</message>
<message>
<source>Updating Morrowind configuration file</source>
<translation></translation>
</message>
<message>
<source>%1 installation finished!</source>
<translation></translation>
</message>
<message>
<source>Extracting: %1</source>
<translation></translation>
</message>
<message>
<source>Failed to open InstallShield Cabinet File.</source>
<translation></translation>
</message>
<message>
<source>Opening %1 failed.</source>
<translation></translation>
</message>
<message>
<source>Failed to extract %1.</source>
<translation></translation>
</message>
<message>
<source>Complete path: %1</source>
<translation></translation>
</message>
</context>
</TS>

View File

@ -117,7 +117,7 @@
xlink:href="#Main-3"
id="linearGradient6786"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.7795276,0,0,3.7795276,-5.9999999,-6.9999999)"
gradientTransform="matrix(0.95388135,0,0,1.0509393,2.6074109,-0.47696551)"
x1="2.116667"
y1="-3.7041662"
x2="6.3499999"
@ -137,8 +137,7 @@
rx="2.8318619e-14" />
<path
id="path6782"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6786);fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="M 186.2207,24.220703 C 186.09149,24.184168 186,24.274642 186,24.46875 v 8.931641 c 0,0.331351 0.20639,0.426988 0.46094,0.214843 l 5.17968,-4.314453 c 0.19881,-0.165685 0.19881,-0.435875 0,-0.601562 l -5.28124,-4.398438 c -0.0497,-0.04142 -0.0956,-0.0679 -0.13868,-0.08008 z m 0.78321,1.916016 3.43164,2.865234 -3.43164,2.855469 z"
transform="matrix(0.26458333,0,0,0.26458333,1.8520833,1.8520833)" />
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6786);fill-opacity:1;stroke:none;stroke-width:0.26491px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.120283,8.2042949 c -0.03261,-0.010163 -0.0557,0.014998 -0.0557,0.068972 v 2.4835411 c 0,0.09214 0.05209,0.118729 0.116333,0.05973 l 1.433536,-1.1996808 c 0.05017,-0.04607 0.05017,-0.1211999 0,-0.1672709 L 51.155284,8.2265564 c -0.01254,-0.011517 -0.02412,-0.01888 -0.035,-0.022267 z m 0.197668,0.5327694 0.992382,0.7967099 -0.992382,0.7939938 z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -117,7 +117,7 @@
xlink:href="#Main-3"
id="linearGradient6770"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.39687235)"
gradientTransform="matrix(0.95393695,0,0,1.0509392,2.7307818,-0.47696343)"
x1="2.116667"
y1="-3.7041662"
x2="6.3499999"
@ -137,7 +137,7 @@
rx="2.8318619e-14" />
<path
id="path6766"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6770);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.255265,8.2604776 c -0.03419,-0.00967 -0.05839,0.014271 -0.05839,0.065629 V 10.68927 c 0,0.08767 0.05461,0.112974 0.121957,0.05684 l 1.370457,-1.1415325 c 0.0526,-0.043838 0.0526,-0.1153253 0,-0.1591633 L 51.291958,8.2816649 c -0.01315,-0.010959 -0.02529,-0.017965 -0.03669,-0.021188 z m 0.207225,0.5069458 0.907954,0.7580932 -0.907954,0.7555094 z" />
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6770);fill-opacity:1;stroke:none;stroke-width:0.264917px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.120363,8.204296 c -0.03261,-0.010162 -0.05578,0.014998 -0.05578,0.068972 v 2.483541 c 0,0.09214 0.05211,0.118729 0.116355,0.05973 L 52.61445,9.6168633 c 0.05018,-0.046071 0.05018,-0.1211999 0,-0.167271 L 51.15519,8.2265626 c -0.01254,-0.011517 -0.02395,-0.01888 -0.03483,-0.022267 z m 0.197626,0.5327692 0.992304,0.7967099 -0.983218,0.7939939 z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -117,7 +117,7 @@
xlink:href="#Main-3"
id="linearGradient6778"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(0.39694445)"
gradientTransform="matrix(0.95389396,0,0,1.0509392,2.7330252,-0.47696299)"
x1="2.116667"
y1="-3.7041662"
x2="6.3499999"
@ -137,7 +137,7 @@
rx="2.8318619e-14" />
<path
id="path6774"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6778);fill-opacity:1;stroke:none;stroke-width:0.264583px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.255337,8.2604776 c -0.03419,-0.00967 -0.05839,0.014271 -0.05839,0.065629 V 10.68927 c 0,0.08767 0.05461,0.112974 0.121957,0.05684 l 1.370457,-1.1415325 c 0.0526,-0.043838 0.0526,-0.1153253 0,-0.1591633 L 51.29203,8.2816649 c -0.01315,-0.010959 -0.02529,-0.017965 -0.03669,-0.021188 z m 0.207225,0.5069458 0.907954,0.7580932 -0.907954,0.7555094 z" />
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6778);fill-opacity:1;stroke:none;stroke-width:0.264912px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.120353,8.2042965 c -0.03261,-0.010163 -0.05577,0.014998 -0.05577,0.068972 V 10.75681 c 0,0.09214 0.05211,0.118729 0.116349,0.05973 l 1.43352,-1.1996813 c 0.05017,-0.046071 0.05017,-0.1211999 0,-0.167271 L 51.155435,8.2265631 c -0.01254,-0.011517 -0.02421,-0.01888 -0.03509,-0.022267 z M 51.31696,8.7370657 52.310301,9.5337756 51.31696,10.32777 Z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -117,7 +117,7 @@
xlink:href="#Main-3"
id="linearGradient6788"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(3.7795276,0,0,3.7795276,-5.9999999,-6.9999999)"
gradientTransform="matrix(0.95388135,0,0,1.0509393,2.6074049,-0.4769654)"
x1="2.116667"
y1="-3.7041662"
x2="6.3499999"
@ -137,8 +137,7 @@
rx="2.8318619e-14" />
<path
id="path6695"
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6788);fill-opacity:1;stroke:none;stroke-width:0.999999px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="M 186.2207,24.220703 C 186.09149,24.184168 186,24.274642 186,24.46875 v 8.931641 c 0,0.331351 0.20639,0.426988 0.46094,0.214843 l 5.17968,-4.314453 c 0.19881,-0.165685 0.19881,-0.435875 0,-0.601562 l -5.28124,-4.398438 c -0.0497,-0.04142 -0.0956,-0.0679 -0.13868,-0.08008 z m 0.78321,1.916016 3.43164,2.865234 -3.43164,2.855469 z"
transform="matrix(0.26458333,0,0,0.26458333,1.8520833,1.8520833)" />
style="font-variation-settings:normal;opacity:1;vector-effect:none;fill:url(#linearGradient6788);fill-opacity:1;stroke:none;stroke-width:0.26491px;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke;stop-color:#000000;stop-opacity:1"
d="m 51.120277,8.2042951 c -0.03261,-0.010162 -0.0557,0.014998 -0.0557,0.068972 v 2.4835409 c 0,0.09214 0.05209,0.118729 0.116333,0.05974 l 1.433536,-1.1996855 c 0.05018,-0.04607 0.05018,-0.1211998 0,-0.167271 L 51.155278,8.2265617 c -0.01254,-0.011517 -0.02412,-0.01888 -0.035,-0.022267 z m 0.197668,0.5327694 0.992382,0.7967099 -0.992382,0.7939946 z" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 7.4 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@ -59,6 +59,39 @@ uniform int PointLightCount;
#endif
float lcalcConstantAttenuation(int lightIndex)
{
#if @lightingMethodPerObjectUniform
return @getLight[lightIndex][0].w;
#elif @lightingMethodUBO
return @getLight[lightIndex].attenuation.x;
#else
return @getLight[lightIndex].constantAttenuation;
#endif
}
float lcalcLinearAttenuation(int lightIndex)
{
#if @lightingMethodPerObjectUniform
return @getLight[lightIndex][1].w;
#elif @lightingMethodUBO
return @getLight[lightIndex].attenuation.y;
#else
return @getLight[lightIndex].linearAttenuation;
#endif
}
float lcalcQuadraticAttenuation(int lightIndex)
{
#if @lightingMethodPerObjectUniform
return @getLight[lightIndex][2].w;
#elif @lightingMethodUBO
return @getLight[lightIndex].attenuation.z;
#else
return @getLight[lightIndex].quadraticAttenuation;
#endif
}
#if !@lightingMethodFFP
float lcalcRadius(int lightIndex)
{
@ -70,17 +103,16 @@ float lcalcRadius(int lightIndex)
}
#endif
float lcalcIllumination(int lightIndex, float lightDistance)
float lcalcIllumination(int lightIndex, float dist)
{
#if @lightingMethodPerObjectUniform
float illumination = clamp(1.0 / (@getLight[lightIndex][0].w + @getLight[lightIndex][1].w * lightDistance + @getLight[lightIndex][2].w * lightDistance * lightDistance), 0.0, 1.0);
return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0)));
#elif @lightingMethodUBO
float illumination = clamp(1.0 / (@getLight[lightIndex].attenuation.x + @getLight[lightIndex].attenuation.y * lightDistance + @getLight[lightIndex].attenuation.z * lightDistance * lightDistance), 0.0, 1.0);
return (illumination * (1.0 - quickstep((lightDistance / lcalcRadius(lightIndex)) - 1.0)));
#else
return clamp(1.0 / (@getLight[lightIndex].constantAttenuation + @getLight[lightIndex].linearAttenuation * lightDistance + @getLight[lightIndex].quadraticAttenuation * lightDistance * lightDistance), 0.0, 1.0);
float illumination = 1.0 / (lcalcConstantAttenuation(lightIndex) + lcalcLinearAttenuation(lightIndex) * dist + lcalcQuadraticAttenuation(lightIndex) * dist * dist);
// FIXME: FFP doesn't do this
illumination = clamp(illumination, 0.0, 1.0);
#if @lightingMethodPerObjectUniform || @lightingMethodUBO
// Fade illumination between the radius and the radius doubled to diminish pop-in
illumination *= 1.0 - quickstep((dist / lcalcRadius(lightIndex)) - 1.0);
#endif
return illumination;
}
vec3 lcalcPosition(int lightIndex)