mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-27 19:39:41 +00:00
Add OpenMW commits up to 19 Nov 2019
# Conflicts: # apps/openmw/mwmechanics/aipursue.cpp # apps/openmw/mwmechanics/summoning.cpp
This commit is contained in:
commit
0c98c5d09e
39 changed files with 279 additions and 138 deletions
|
@ -172,6 +172,10 @@
|
||||||
Bug #5186: Equipped item enchantments don't affect creatures
|
Bug #5186: Equipped item enchantments don't affect creatures
|
||||||
Bug #5190: On-strike enchantments can be applied to and used with non-projectile ranged weapons
|
Bug #5190: On-strike enchantments can be applied to and used with non-projectile ranged weapons
|
||||||
Bug #5196: Dwarven ghosts do not use idle animations
|
Bug #5196: Dwarven ghosts do not use idle animations
|
||||||
|
Bug #5206: A "class does not have NPC stats" error when player's follower kills an enemy with damage spell
|
||||||
|
Bug #5209: Spellcasting ignores race height
|
||||||
|
Bug #5210: AiActivate allows actors to open dialogue and inventory windows
|
||||||
|
Bug #5211: Screen fades in if the first loaded save is in interior cell
|
||||||
Feature #1774: Handle AvoidNode
|
Feature #1774: Handle AvoidNode
|
||||||
Feature #2229: Improve pathfinding AI
|
Feature #2229: Improve pathfinding AI
|
||||||
Feature #3025: Analogue gamepad movement controls
|
Feature #3025: Analogue gamepad movement controls
|
||||||
|
|
|
@ -712,7 +712,7 @@ std::string creatureFlags(int flags)
|
||||||
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
|
if (flags & ESM::Creature::Respawn) properties += "Respawn ";
|
||||||
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
|
if (flags & ESM::Creature::Weapon) properties += "Weapon ";
|
||||||
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
||||||
int unused = (0xFF ^
|
int unused = (0xFFFFFFFF ^
|
||||||
(ESM::Creature::Base|
|
(ESM::Creature::Base|
|
||||||
ESM::Creature::Walks|
|
ESM::Creature::Walks|
|
||||||
ESM::Creature::Swims|
|
ESM::Creature::Swims|
|
||||||
|
|
|
@ -135,7 +135,7 @@ bool Launcher::GraphicsPage::loadSettings()
|
||||||
if (mEngineSettings.getBool("player shadows", "Shadows"))
|
if (mEngineSettings.getBool("player shadows", "Shadows"))
|
||||||
playerShadowsCheckBox->setCheckState(Qt::Checked);
|
playerShadowsCheckBox->setCheckState(Qt::Checked);
|
||||||
if (mEngineSettings.getBool("terrain shadows", "Shadows"))
|
if (mEngineSettings.getBool("terrain shadows", "Shadows"))
|
||||||
objectShadowsCheckBox->setCheckState(Qt::Checked);
|
terrainShadowsCheckBox->setCheckState(Qt::Checked);
|
||||||
if (mEngineSettings.getBool("object shadows", "Shadows"))
|
if (mEngineSettings.getBool("object shadows", "Shadows"))
|
||||||
objectShadowsCheckBox->setCheckState(Qt::Checked);
|
objectShadowsCheckBox->setCheckState(Qt::Checked);
|
||||||
if (mEngineSettings.getBool("enable indoor shadows", "Shadows"))
|
if (mEngineSettings.getBool("enable indoor shadows", "Shadows"))
|
||||||
|
|
|
@ -1038,6 +1038,28 @@ bool CSVRender::TerrainShapeMode::isInCellSelection(int globalSelectionX, int gl
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CSVRender::TerrainShapeMode::handleSelection(int globalSelectionX, int globalSelectionY, std::vector<std::pair<int, int>>* selections)
|
||||||
|
{
|
||||||
|
if (isInCellSelection(globalSelectionX, globalSelectionY)) selections->emplace_back(globalSelectionX, globalSelectionY);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int moduloX = globalSelectionX % (ESM::Land::LAND_SIZE - 1);
|
||||||
|
int moduloY = globalSelectionY % (ESM::Land::LAND_SIZE - 1);
|
||||||
|
bool xIsAtCellBorder = moduloX == 0;
|
||||||
|
bool yIsAtCellBorder = moduloY == 0;
|
||||||
|
if (!xIsAtCellBorder && !yIsAtCellBorder)
|
||||||
|
return;
|
||||||
|
int selectionX = globalSelectionX;
|
||||||
|
int selectionY = globalSelectionY;
|
||||||
|
if (xIsAtCellBorder)
|
||||||
|
selectionX--;
|
||||||
|
if (yIsAtCellBorder)
|
||||||
|
selectionY--;
|
||||||
|
if (isInCellSelection(selectionX, selectionY))
|
||||||
|
selections->emplace_back(globalSelectionX, globalSelectionY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation)
|
void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation)
|
||||||
{
|
{
|
||||||
int r = mBrushSize / 2;
|
int r = mBrushSize / 2;
|
||||||
|
@ -1045,7 +1067,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
|
|
||||||
if (mBrushShape == CSVWidget::BrushShape_Point)
|
if (mBrushShape == CSVWidget::BrushShape_Point)
|
||||||
{
|
{
|
||||||
if (isInCellSelection(vertexCoords.first, vertexCoords.second)) selections.emplace_back(vertexCoords.first, vertexCoords.second);
|
handleSelection(vertexCoords.first, vertexCoords.second, &selections);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBrushShape == CSVWidget::BrushShape_Square)
|
if (mBrushShape == CSVWidget::BrushShape_Square)
|
||||||
|
@ -1054,7 +1076,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
{
|
{
|
||||||
for(int j = vertexCoords.second - r; j <= vertexCoords.second + r; ++j)
|
for(int j = vertexCoords.second - r; j <= vertexCoords.second + r; ++j)
|
||||||
{
|
{
|
||||||
if (isInCellSelection(i, j)) selections.emplace_back(i, j);
|
handleSelection(i, j, &selections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1068,7 +1090,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
int distanceX = abs(i - vertexCoords.first);
|
int distanceX = abs(i - vertexCoords.first);
|
||||||
int distanceY = abs(j - vertexCoords.second);
|
int distanceY = abs(j - vertexCoords.second);
|
||||||
int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2)));
|
int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2)));
|
||||||
if (isInCellSelection(i, j) && distance <= r) selections.emplace_back(i, j);
|
if (distance <= r) handleSelection(i, j, &selections);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1080,8 +1102,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
||||||
for(auto const& value: mCustomBrushShape)
|
for(auto const& value: mCustomBrushShape)
|
||||||
{
|
{
|
||||||
std::pair<int, int> localVertexCoords (vertexCoords.first + value.first, vertexCoords.second + value.second);
|
std::pair<int, int> localVertexCoords (vertexCoords.first + value.first, vertexCoords.second + value.second);
|
||||||
std::string cellId (CSMWorld::CellCoordinates::vertexGlobalToCellId(localVertexCoords));
|
handleSelection(localVertexCoords.first, localVertexCoords.second, &selections);
|
||||||
if (isInCellSelection(localVertexCoords.first, localVertexCoords.second)) selections.emplace_back(localVertexCoords);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1227,7 +1248,7 @@ void CSVRender::TerrainShapeMode::createNewLandData(const CSMWorld::CellCoordina
|
||||||
|
|
||||||
++averageDivider;
|
++averageDivider;
|
||||||
downCellSampleHeight = landDownShapePointer[ESM::Land::LAND_SIZE / 2];
|
downCellSampleHeight = landDownShapePointer[ESM::Land::LAND_SIZE / 2];
|
||||||
if(paged->getCellAlteredHeight(cellLeftCoords, ESM::Land::LAND_SIZE / 2, 0))
|
if(paged->getCellAlteredHeight(cellDownCoords, ESM::Land::LAND_SIZE / 2, 0))
|
||||||
downCellSampleHeight += *paged->getCellAlteredHeight(cellDownCoords, ESM::Land::LAND_SIZE / 2, 0);
|
downCellSampleHeight += *paged->getCellAlteredHeight(cellDownCoords, ESM::Land::LAND_SIZE / 2, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1418,8 +1439,12 @@ void CSVRender::TerrainShapeMode::setBrushShape(CSVWidget::BrushShape brushShape
|
||||||
selectionCenterY = selectionCenterY + value.second;
|
selectionCenterY = selectionCenterY + value.second;
|
||||||
++selectionAmount;
|
++selectionAmount;
|
||||||
}
|
}
|
||||||
selectionCenterX = selectionCenterX / selectionAmount;
|
|
||||||
selectionCenterY = selectionCenterY / selectionAmount;
|
if (selectionAmount != 0)
|
||||||
|
{
|
||||||
|
selectionCenterX /= selectionAmount;
|
||||||
|
selectionCenterY /= selectionAmount;
|
||||||
|
}
|
||||||
|
|
||||||
mCustomBrushShape.clear();
|
mCustomBrushShape.clear();
|
||||||
std::pair<int, int> differentialPos {};
|
std::pair<int, int> differentialPos {};
|
||||||
|
|
|
@ -134,6 +134,9 @@ namespace CSVRender
|
||||||
/// Check if global selection coordinate belongs to cell in view
|
/// Check if global selection coordinate belongs to cell in view
|
||||||
bool isInCellSelection(int globalSelectionX, int globalSelectionY);
|
bool isInCellSelection(int globalSelectionX, int globalSelectionY);
|
||||||
|
|
||||||
|
/// Select vertex at global selection coordinate
|
||||||
|
void handleSelection(int globalSelectionX, int globalSelectionY, std::vector<std::pair<int, int>>* selections);
|
||||||
|
|
||||||
/// Handle brush mechanics for terrain shape selection
|
/// Handle brush mechanics for terrain shape selection
|
||||||
void selectTerrainShapes (const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation);
|
void selectTerrainShapes (const std::pair<int, int>& vertexCoords, unsigned char selectMode, bool dragOperation);
|
||||||
|
|
||||||
|
|
|
@ -730,8 +730,12 @@ void CSVRender::TerrainTextureMode::setBrushShape(int brushShape)
|
||||||
selectionCenterY += value.second;
|
selectionCenterY += value.second;
|
||||||
++selectionAmount;
|
++selectionAmount;
|
||||||
}
|
}
|
||||||
selectionCenterX /= selectionAmount;
|
|
||||||
selectionCenterY /= selectionAmount;
|
if (selectionAmount != 0)
|
||||||
|
{
|
||||||
|
selectionCenterX /= selectionAmount;
|
||||||
|
selectionCenterY /= selectionAmount;
|
||||||
|
}
|
||||||
|
|
||||||
mCustomBrushShape.clear();
|
mCustomBrushShape.clear();
|
||||||
for (auto const& value: terrainSelection)
|
for (auto const& value: terrainSelection)
|
||||||
|
|
|
@ -807,6 +807,8 @@ namespace MWBase
|
||||||
|
|
||||||
/// Return physical half extents of the given actor to be used in pathfinding
|
/// Return physical half extents of the given actor to be used in pathfinding
|
||||||
virtual osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const = 0;
|
virtual osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const = 0;
|
||||||
|
|
||||||
|
virtual bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -423,6 +423,12 @@ namespace MWGui
|
||||||
MWScript::InterpreterContext interpreterContext (&mPtr.getRefData().getLocals(), mPtr);
|
MWScript::InterpreterContext interpreterContext (&mPtr.getRefData().getLocals(), mPtr);
|
||||||
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
MWBase::Environment::get().getScriptManager()->run (script, interpreterContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Clean up summoned creatures as well
|
||||||
|
std::map<MWMechanics::CreatureStats::SummonKey, int>& creatureMap = creatureStats.getSummonedCreatureMap();
|
||||||
|
for (const auto& creature : creatureMap)
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mPtr, creature.second);
|
||||||
|
creatureMap.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->deleteObject(mPtr);
|
MWBase::Environment::get().getWorld()->deleteObject(mPtr);
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
#include <MyGUI_Button.h>
|
#include <MyGUI_Button.h>
|
||||||
#include <MyGUI_Gui.h>
|
#include <MyGUI_Gui.h>
|
||||||
#include <MyGUI_ImageBox.h>
|
#include <MyGUI_ImageBox.h>
|
||||||
|
#include <MyGUI_RenderManager.h>
|
||||||
|
|
||||||
#include <components/esm/esmwriter.hpp>
|
#include <components/esm/esmwriter.hpp>
|
||||||
#include <components/esm/quickkeys.hpp>
|
#include <components/esm/quickkeys.hpp>
|
||||||
|
@ -309,7 +310,12 @@ namespace MWGui
|
||||||
mSelected->id = item.getCellRef().getRefId();
|
mSelected->id = item.getCellRef().getRefId();
|
||||||
mSelected->name = item.getClass().getName(item);
|
mSelected->name = item.getClass().getName(item);
|
||||||
|
|
||||||
mSelected->button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
float scale = 1.f;
|
||||||
|
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture("textures\\menu_icon_select_magic_magic.dds");
|
||||||
|
if (texture)
|
||||||
|
scale = texture->getHeight() / 64.f;
|
||||||
|
|
||||||
|
mSelected->button->setFrame("textures\\menu_icon_select_magic_magic.dds", MyGUI::IntCoord(0, 0, 44*scale, 44*scale));
|
||||||
mSelected->button->setIcon(item);
|
mSelected->button->setIcon(item);
|
||||||
|
|
||||||
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
mSelected->button->setUserString("ToolTipType", "ItemPtr");
|
||||||
|
@ -355,7 +361,12 @@ namespace MWGui
|
||||||
path.insert(slashPos+1, "b_");
|
path.insert(slashPos+1, "b_");
|
||||||
path = MWBase::Environment::get().getWindowManager()->correctIconPath(path);
|
path = MWBase::Environment::get().getWindowManager()->correctIconPath(path);
|
||||||
|
|
||||||
mSelected->button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(2, 2, 40, 40));
|
float scale = 1.f;
|
||||||
|
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture("textures\\menu_icon_select_magic.dds");
|
||||||
|
if (texture)
|
||||||
|
scale = texture->getHeight() / 64.f;
|
||||||
|
|
||||||
|
mSelected->button->setFrame("textures\\menu_icon_select_magic.dds", MyGUI::IntCoord(0, 0, 44*scale, 44*scale));
|
||||||
mSelected->button->setIcon(path);
|
mSelected->button->setIcon(path);
|
||||||
|
|
||||||
if (mMagicSelectionDialog)
|
if (mMagicSelectionDialog)
|
||||||
|
|
|
@ -149,7 +149,7 @@ float BookWindowBase::adjustButton (char const * name)
|
||||||
Gui::ImageButton* button;
|
Gui::ImageButton* button;
|
||||||
WindowBase::getWidget (button, name);
|
WindowBase::getWidget (button, name);
|
||||||
MyGUI::IntSize requested = button->getRequestedSize();
|
MyGUI::IntSize requested = button->getRequestedSize();
|
||||||
float scale = requested.height / button->getSize().height;
|
float scale = float(requested.height) / button->getSize().height;
|
||||||
MyGUI::IntSize newSize = requested;
|
MyGUI::IntSize newSize = requested;
|
||||||
newSize.width /= scale;
|
newSize.width /= scale;
|
||||||
newSize.height /= scale;
|
newSize.height /= scale;
|
||||||
|
|
|
@ -1079,7 +1079,7 @@ namespace MWMechanics
|
||||||
|
|
||||||
if (caster == player || playerFollowers.find(caster) != playerFollowers.end())
|
if (caster == player || playerFollowers.find(caster) != playerFollowers.end())
|
||||||
{
|
{
|
||||||
if (caster.getClass().getNpcStats(caster).isWerewolf())
|
if (caster.getClass().isNpc() && caster.getClass().getNpcStats(caster).isWerewolf())
|
||||||
caster.getClass().getNpcStats(caster).addWerewolfKill();
|
caster.getClass().getNpcStats(caster).addWerewolfKill();
|
||||||
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->actorKilled(ptr, player);
|
MWBase::Environment::get().getMechanicsManager()->actorKilled(ptr, player);
|
||||||
|
@ -2138,6 +2138,13 @@ namespace MWMechanics
|
||||||
if (fx)
|
if (fx)
|
||||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
||||||
"", ptr.getRefData().getPosition().asVec3());
|
"", ptr.getRefData().getPosition().asVec3());
|
||||||
|
|
||||||
|
// Remove the summoned creature's summoned creatures as well
|
||||||
|
MWMechanics::CreatureStats& stats = ptr.getClass().getCreatureStats(ptr);
|
||||||
|
std::map<CreatureStats::SummonKey, int>& creatureMap = stats.getSummonedCreatureMap();
|
||||||
|
for (const auto& creature : creatureMap)
|
||||||
|
cleanupSummonedCreature(stats, creature.second);
|
||||||
|
creatureMap.clear();
|
||||||
}
|
}
|
||||||
else if (creatureActorId != -1)
|
else if (creatureActorId != -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/inventorystore.hpp"
|
#include "../mwworld/inventorystore.hpp"
|
||||||
|
|
||||||
|
#include "../mwphysics/collisiontype.hpp"
|
||||||
|
|
||||||
#include "pathgrid.hpp"
|
#include "pathgrid.hpp"
|
||||||
#include "creaturestats.hpp"
|
#include "creaturestats.hpp"
|
||||||
#include "movement.hpp"
|
#include "movement.hpp"
|
||||||
|
@ -222,8 +224,28 @@ void MWMechanics::AiPackage::evadeObstacles(const MWWorld::Ptr& actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
bool isDoorOnTheWay(const MWWorld::Ptr& actor, const MWWorld::Ptr& door, const osg::Vec3f& nextPathPoint)
|
||||||
|
{
|
||||||
|
const auto world = MWBase::Environment::get().getWorld();
|
||||||
|
const auto halfExtents = world->getHalfExtents(actor);
|
||||||
|
const auto position = actor.getRefData().getPosition().asVec3() + osg::Vec3f(0, 0, halfExtents.z());
|
||||||
|
const auto destination = nextPathPoint + osg::Vec3f(0, 0, halfExtents.z());
|
||||||
|
|
||||||
|
return world->hasCollisionWithDoor(door, position, destination);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
|
void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
|
||||||
{
|
{
|
||||||
|
// note: AiWander currently does not open doors
|
||||||
|
if (getTypeId() == TypeIdWander)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mPathFinder.getPathSize() == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||||
static float distance = world->getMaxActivationDistance();
|
static float distance = world->getMaxActivationDistance();
|
||||||
|
|
||||||
|
@ -231,9 +253,11 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
|
||||||
if (door == MWWorld::Ptr())
|
if (door == MWWorld::Ptr())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// note: AiWander currently does not open doors
|
if (!door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle)
|
||||||
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle)
|
|
||||||
{
|
{
|
||||||
|
if (!isDoorOnTheWay(actor, door, mPathFinder.getPath().front()))
|
||||||
|
return;
|
||||||
|
|
||||||
if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 ))
|
if ((door.getCellRef().getTrap().empty() && door.getCellRef().getLockLevel() <= 0 ))
|
||||||
{
|
{
|
||||||
world->activate(door, actor);
|
world->activate(door, actor);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
#include <components/esm/aisequence.hpp>
|
#include <components/esm/aisequence.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
#include "../mwworld/class.hpp"
|
#include "../mwworld/class.hpp"
|
||||||
|
@ -104,8 +105,7 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
target.getClass().activate(target,actor).get()->execute(actor); //Arrest player when reached
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, actor); //Arrest player when reached
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1995,6 +1995,17 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
bool isPlayer = mPtr == MWMechanics::getPlayer();
|
bool isPlayer = mPtr == MWMechanics::getPlayer();
|
||||||
bool godmode = isPlayer && MWBase::Environment::get().getWorld()->getGodModeState();
|
bool godmode = isPlayer && MWBase::Environment::get().getWorld()->getGodModeState();
|
||||||
|
|
||||||
|
float scale = mPtr.getCellRef().getScale();
|
||||||
|
|
||||||
|
static const bool normalizeSpeed = Settings::Manager::getBool("normalise race speed", "Game");
|
||||||
|
if (!normalizeSpeed && mPtr.getClass().isNpc())
|
||||||
|
{
|
||||||
|
const ESM::NPC* npc = mPtr.get<ESM::NPC>()->mBase;
|
||||||
|
const ESM::Race* race = world->getStore().get<ESM::Race>().find(npc->mRace);
|
||||||
|
float weight = npc->isMale() ? race->mData.mWeight.mMale : race->mData.mWeight.mFemale;
|
||||||
|
scale *= weight;
|
||||||
|
}
|
||||||
|
|
||||||
if(!cls.isActor())
|
if(!cls.isActor())
|
||||||
updateAnimQueue();
|
updateAnimQueue();
|
||||||
else if(!cls.getCreatureStats(mPtr).isDead())
|
else if(!cls.getCreatureStats(mPtr).isDead())
|
||||||
|
@ -2254,6 +2265,8 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
|
|
||||||
jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None;
|
jumpstate = mAnimation->isPlaying(mCurrentJump) ? JumpState_Landing : JumpState_None;
|
||||||
|
|
||||||
|
vec.x() *= scale;
|
||||||
|
vec.y() *= scale;
|
||||||
vec.z() = 0.0f;
|
vec.z() = 0.0f;
|
||||||
|
|
||||||
inJump = false;
|
inJump = false;
|
||||||
|
@ -2445,20 +2458,9 @@ void CharacterController::update(float duration, bool animationOnly)
|
||||||
else
|
else
|
||||||
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
||||||
|
|
||||||
float scale = mPtr.getCellRef().getScale();
|
|
||||||
moved.x() *= scale;
|
moved.x() *= scale;
|
||||||
moved.y() *= scale;
|
moved.y() *= scale;
|
||||||
|
|
||||||
static const bool normalizeSpeed = Settings::Manager::getBool("normalise race speed", "Game");
|
|
||||||
if (mPtr.getClass().isNpc() && !normalizeSpeed)
|
|
||||||
{
|
|
||||||
const ESM::NPC* npc = mPtr.get<ESM::NPC>()->mBase;
|
|
||||||
const ESM::Race* race = world->getStore().get<ESM::Race>().find(npc->mRace);
|
|
||||||
float weight = npc->isMale() ? race->mData.mWeight.mMale : race->mData.mWeight.mFemale;
|
|
||||||
moved.x() *= weight;
|
|
||||||
moved.y() *= weight;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Ensure we're moving in generally the right direction...
|
// Ensure we're moving in generally the right direction...
|
||||||
if(speed > 0.f)
|
if(speed > 0.f)
|
||||||
{
|
{
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace MWMechanics
|
||||||
Enchanting::Enchanting()
|
Enchanting::Enchanting()
|
||||||
: mCastStyle(ESM::Enchantment::CastOnce)
|
: mCastStyle(ESM::Enchantment::CastOnce)
|
||||||
, mSelfEnchanting(false)
|
, mSelfEnchanting(false)
|
||||||
|
, mWeaponType(-1)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void Enchanting::setOldItem(const MWWorld::Ptr& oldItem)
|
void Enchanting::setOldItem(const MWWorld::Ptr& oldItem)
|
||||||
|
|
|
@ -133,10 +133,9 @@ namespace MWMechanics
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update summon effects
|
// Update summon effects
|
||||||
bool casterDead = creatureStats.isDead();
|
|
||||||
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
for (std::map<CreatureStats::SummonKey, int>::iterator it = creatureMap.begin(); it != creatureMap.end(); )
|
||||||
{
|
{
|
||||||
bool found = !casterDead && mActiveEffects.find(it->first) != mActiveEffects.end();
|
bool found = mActiveEffects.find(it->first) != mActiveEffects.end();
|
||||||
if (!found)
|
if (!found)
|
||||||
{
|
{
|
||||||
// Effect has ended
|
// Effect has ended
|
||||||
|
@ -147,39 +146,11 @@ namespace MWMechanics
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<int>& graveyard = creatureStats.getSummonedCreatureGraveyard();
|
std::vector<int> graveyard = creatureStats.getSummonedCreatureGraveyard();
|
||||||
for (std::vector<int>::iterator it = graveyard.begin(); it != graveyard.end(); )
|
creatureStats.getSummonedCreatureGraveyard().clear();
|
||||||
{
|
|
||||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it);
|
|
||||||
if (!ptr.isEmpty())
|
|
||||||
{
|
|
||||||
it = graveyard.erase(it);
|
|
||||||
|
|
||||||
const ESM::Static* fx = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>()
|
for (const int creature : graveyard)
|
||||||
.search("VFX_Summon_End");
|
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, creature);
|
||||||
if (fx)
|
|
||||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
|
||||||
"", ptr.getRefData().getPosition().asVec3());
|
|
||||||
|
|
||||||
MWBase::Environment::get().getWorld()->deleteObject(ptr);
|
|
||||||
|
|
||||||
/*
|
|
||||||
Start of tes3mp addition
|
|
||||||
|
|
||||||
Send an ID_OBJECT_DELETE packet every time a summoned creature despawns
|
|
||||||
*/
|
|
||||||
mwmp::ObjectList *objectList = mwmp::Main::get().getNetworking()->getObjectList();
|
|
||||||
objectList->reset();
|
|
||||||
objectList->packetOrigin = mwmp::CLIENT_GAMEPLAY;
|
|
||||||
objectList->addObjectDelete(ptr);
|
|
||||||
objectList->sendObjectDelete();
|
|
||||||
/*
|
|
||||||
End of tes3mp addition
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
else
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!cleanup)
|
if (!cleanup)
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -113,7 +113,7 @@ bool ActorAnimation::updateCarriedLeftVisible(const int weaptype) const
|
||||||
{
|
{
|
||||||
SceneUtil::FindByNameVisitor findVisitor ("Bip01 AttachShield");
|
SceneUtil::FindByNameVisitor findVisitor ("Bip01 AttachShield");
|
||||||
mObjectRoot->accept(findVisitor);
|
mObjectRoot->accept(findVisitor);
|
||||||
if (findVisitor.mFoundNode)
|
if (findVisitor.mFoundNode || (mPtr == MWMechanics::getPlayer() && mPtr.isInCell() && MWBase::Environment::get().getWorld()->isFirstPerson()))
|
||||||
{
|
{
|
||||||
const MWWorld::InventoryStore& inv = cls.getInventoryStore(mPtr);
|
const MWWorld::InventoryStore& inv = cls.getInventoryStore(mPtr);
|
||||||
const MWWorld::ConstContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
const MWWorld::ConstContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight);
|
||||||
|
|
|
@ -539,7 +539,7 @@ std::string NpcAnimation::getShieldMesh(MWWorld::ConstPtr shield) const
|
||||||
{
|
{
|
||||||
const ESM::BodyPart *bodypart = 0;
|
const ESM::BodyPart *bodypart = 0;
|
||||||
bodypart = partStore.search(bodypartName);
|
bodypart = partStore.search(bodypartName);
|
||||||
if (bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
||||||
return "";
|
return "";
|
||||||
else if (!bodypart->mModel.empty())
|
else if (!bodypart->mModel.empty())
|
||||||
mesh = "meshes\\" + bodypart->mModel;
|
mesh = "meshes\\" + bodypart->mModel;
|
||||||
|
|
|
@ -527,7 +527,7 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
|
||||||
|
|
||||||
// Add animated textures
|
// Add animated textures
|
||||||
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
std::vector<osg::ref_ptr<osg::Texture2D> > textures;
|
||||||
int frameCount = Fallback::Map::getInt("Water_SurfaceFrameCount");
|
int frameCount = std::max(0, std::min(Fallback::Map::getInt("Water_SurfaceFrameCount"), 320));
|
||||||
const std::string& texture = Fallback::Map::getString("Water_SurfaceTexture");
|
const std::string& texture = Fallback::Map::getString("Water_SurfaceTexture");
|
||||||
for (int i=0; i<frameCount; ++i)
|
for (int i=0; i<frameCount; ++i)
|
||||||
{
|
{
|
||||||
|
@ -643,7 +643,7 @@ Water::~Water()
|
||||||
|
|
||||||
void Water::listAssetsToPreload(std::vector<std::string> &textures)
|
void Water::listAssetsToPreload(std::vector<std::string> &textures)
|
||||||
{
|
{
|
||||||
int frameCount = Fallback::Map::getInt("Water_SurfaceFrameCount");
|
int frameCount = std::max(0, std::min(Fallback::Map::getInt("Water_SurfaceFrameCount"), 320));
|
||||||
const std::string& texture = Fallback::Map::getString("Water_SurfaceTexture");
|
const std::string& texture = Fallback::Map::getString("Water_SurfaceTexture");
|
||||||
for (int i=0; i<frameCount; ++i)
|
for (int i=0; i<frameCount; ++i)
|
||||||
{
|
{
|
||||||
|
|
|
@ -18,6 +18,9 @@ namespace MWWorld
|
||||||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (actor != MWMechanics::getPlayer())
|
||||||
|
return;
|
||||||
|
|
||||||
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
|
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
|
@ -3,12 +3,15 @@
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
|
||||||
|
#include "../mwmechanics/actorutil.hpp"
|
||||||
|
|
||||||
namespace MWWorld
|
namespace MWWorld
|
||||||
{
|
{
|
||||||
ActionTalk::ActionTalk (const Ptr& actor) : Action (false, actor) {}
|
ActionTalk::ActionTalk (const Ptr& actor) : Action (false, actor) {}
|
||||||
|
|
||||||
void ActionTalk::executeImp (const Ptr& actor)
|
void ActionTalk::executeImp (const Ptr& actor)
|
||||||
{
|
{
|
||||||
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, getTarget());
|
if (actor == MWMechanics::getPlayer())
|
||||||
|
MWBase::Environment::get().getWindowManager()->pushGuiMode(MWGui::GM_Dialogue, getTarget());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ void ESMStore::load(ESM::ESMReader &esm, Loading::Listener* listener)
|
||||||
std::string fname = mast.name;
|
std::string fname = mast.name;
|
||||||
int index = ~0;
|
int index = ~0;
|
||||||
for (int i = 0; i < esm.getIndex(); i++) {
|
for (int i = 0; i < esm.getIndex(); i++) {
|
||||||
const std::string &candidate = allPlugins->at(i).getContext().filename;
|
const std::string candidate = allPlugins->at(i).getContext().filename;
|
||||||
std::string fnamecandidate = boost::filesystem::path(candidate).filename().string();
|
std::string fnamecandidate = boost::filesystem::path(candidate).filename().string();
|
||||||
if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) {
|
if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) {
|
||||||
index = i;
|
index = i;
|
||||||
|
|
|
@ -262,7 +262,7 @@ namespace MWWorld
|
||||||
{
|
{
|
||||||
// Spawn at 0.75 * ActorHeight
|
// Spawn at 0.75 * ActorHeight
|
||||||
// Note: we ignore the collision box offset, this is required to make some flying creatures work as intended.
|
// Note: we ignore the collision box offset, this is required to make some flying creatures work as intended.
|
||||||
pos.z() += mPhysics->getHalfExtents(caster).z() * 2 * 0.75;
|
pos.z() += mPhysics->getRenderingHalfExtents(caster).z() * 2 * 0.75;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible
|
if (MWBase::Environment::get().getWorld()->isUnderwater(caster.getCell(), pos)) // Underwater casting not possible
|
||||||
|
|
|
@ -751,11 +751,9 @@ namespace MWWorld
|
||||||
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
||||||
{
|
{
|
||||||
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
|
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
|
||||||
bool loadcell = (mCurrentCell == nullptr);
|
bool useFading = (mCurrentCell != nullptr);
|
||||||
if(!loadcell)
|
if (useFading)
|
||||||
loadcell = *mCurrentCell != *cell;
|
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
|
||||||
|
|
||||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||||
int messagesCount = MWBase::Environment::get().getWindowManager()->getMessagesCount();
|
int messagesCount = MWBase::Environment::get().getWindowManager()->getMessagesCount();
|
||||||
|
@ -763,7 +761,7 @@ namespace MWWorld
|
||||||
loadingListener->setLabel(loadingInteriorText, false, messagesCount > 0);
|
loadingListener->setLabel(loadingInteriorText, false, messagesCount > 0);
|
||||||
Loading::ScopedLoad load(loadingListener);
|
Loading::ScopedLoad load(loadingListener);
|
||||||
|
|
||||||
if(!loadcell)
|
if(mCurrentCell != nullptr && *mCurrentCell == *cell)
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
world->moveObject(world->getPlayerPtr(), position.pos[0], position.pos[1], position.pos[2]);
|
world->moveObject(world->getPlayerPtr(), position.pos[0], position.pos[1], position.pos[2]);
|
||||||
|
@ -817,7 +815,8 @@ namespace MWWorld
|
||||||
if (changeEvent)
|
if (changeEvent)
|
||||||
mCellChanged = true;
|
mCellChanged = true;
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
if (useFading)
|
||||||
|
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <components/misc/constants.hpp>
|
#include <components/misc/constants.hpp>
|
||||||
#include <components/misc/resourcehelpers.hpp>
|
#include <components/misc/resourcehelpers.hpp>
|
||||||
#include <components/misc/rng.hpp>
|
#include <components/misc/rng.hpp>
|
||||||
|
#include <components/misc/convert.hpp>
|
||||||
|
|
||||||
#include <components/files/collections.hpp>
|
#include <components/files/collections.hpp>
|
||||||
|
|
||||||
|
@ -4351,4 +4352,23 @@ namespace MWWorld
|
||||||
return getHalfExtents(actor);
|
return getHalfExtents(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool World::hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const
|
||||||
|
{
|
||||||
|
const auto object = mPhysics->getObject(door);
|
||||||
|
|
||||||
|
if (!object)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
btVector3 aabbMin;
|
||||||
|
btVector3 aabbMax;
|
||||||
|
object->getShapeInstance()->getCollisionShape()->getAabb(btTransform::getIdentity(), aabbMin, aabbMax);
|
||||||
|
|
||||||
|
const auto toLocal = object->getCollisionObject()->getWorldTransform().inverse();
|
||||||
|
const auto localFrom = toLocal(Misc::Convert::toBullet(position));
|
||||||
|
const auto localTo = toLocal(Misc::Convert::toBullet(destination));
|
||||||
|
|
||||||
|
btScalar hitDistance = 1;
|
||||||
|
btVector3 hitNormal;
|
||||||
|
return btRayAabb(localFrom, localTo, aabbMin, aabbMax, hitDistance, hitNormal);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -898,6 +898,8 @@ namespace MWWorld
|
||||||
|
|
||||||
/// Return physical half extents of the given actor to be used in pathfinding
|
/// Return physical half extents of the given actor to be used in pathfinding
|
||||||
osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const override;
|
osg::Vec3f getPathfindingHalfExtents(const MWWorld::ConstPtr& actor) const override;
|
||||||
|
|
||||||
|
bool hasCollisionWithDoor(const MWWorld::ConstPtr& door, const osg::Vec3f& position, const osg::Vec3f& destination) const override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -347,8 +347,6 @@ namespace Compiler
|
||||||
scanner.putbackName (name, loc);
|
scanner.putbackName (name, loc);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Parser::parseName (name, loc, scanner);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||||
|
|
|
@ -301,7 +301,7 @@ namespace NifOsg
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vec3Interpolator mData;
|
Vec3Interpolator mData;
|
||||||
TargetColor mTargetColor;
|
TargetColor mTargetColor = Ambient;
|
||||||
};
|
};
|
||||||
|
|
||||||
class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
||||||
|
|
|
@ -341,6 +341,7 @@ namespace NifOsg
|
||||||
osg::ref_ptr<osg::Switch> switchNode (new osg::Switch);
|
osg::ref_ptr<osg::Switch> switchNode (new osg::Switch);
|
||||||
switchNode->setName(niSwitchNode->name);
|
switchNode->setName(niSwitchNode->name);
|
||||||
switchNode->setNewChildDefaultValue(false);
|
switchNode->setNewChildDefaultValue(false);
|
||||||
|
switchNode->setSingleChildOn(niSwitchNode->initialIndex);
|
||||||
return switchNode;
|
return switchNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -433,7 +434,7 @@ namespace NifOsg
|
||||||
osg::ref_ptr<osg::Group> node;
|
osg::ref_ptr<osg::Group> node;
|
||||||
osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED;
|
osg::Object::DataVariance dataVariance = osg::Object::UNSPECIFIED;
|
||||||
|
|
||||||
// TODO: it is unclear how to handle transformations of LOD and Switch nodes and controllers for them.
|
// TODO: it is unclear how to handle transformations of LOD nodes and controllers for them.
|
||||||
switch (nifNode->recType)
|
switch (nifNode->recType)
|
||||||
{
|
{
|
||||||
case Nif::RC_NiLODNode:
|
case Nif::RC_NiLODNode:
|
||||||
|
@ -444,12 +445,6 @@ namespace NifOsg
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Nif::RC_NiSwitchNode:
|
case Nif::RC_NiSwitchNode:
|
||||||
{
|
|
||||||
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
|
||||||
node = handleSwitchNode(niSwitchNode);
|
|
||||||
dataVariance = osg::Object::STATIC;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Nif::RC_NiTriShape:
|
case Nif::RC_NiTriShape:
|
||||||
case Nif::RC_NiTriStrips:
|
case Nif::RC_NiTriStrips:
|
||||||
case Nif::RC_NiAutoNormalParticles:
|
case Nif::RC_NiAutoNormalParticles:
|
||||||
|
@ -625,6 +620,19 @@ namespace NifOsg
|
||||||
&& !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
|
&& !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
|
||||||
handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
|
handleNodeControllers(nifNode, static_cast<osg::MatrixTransform*>(node.get()), animflags);
|
||||||
|
|
||||||
|
if (nifNode->recType == Nif::RC_NiSwitchNode)
|
||||||
|
{
|
||||||
|
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
||||||
|
osg::ref_ptr<osg::Switch> switchNode = handleSwitchNode(niSwitchNode);
|
||||||
|
node->addChild(switchNode);
|
||||||
|
if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel))
|
||||||
|
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel);
|
||||||
|
else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel))
|
||||||
|
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel);
|
||||||
|
|
||||||
|
node = switchNode;
|
||||||
|
}
|
||||||
|
|
||||||
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
const Nif::NiNode *ninode = dynamic_cast<const Nif::NiNode*>(nifNode);
|
||||||
if(ninode)
|
if(ninode)
|
||||||
{
|
{
|
||||||
|
@ -643,16 +651,6 @@ namespace NifOsg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nifNode->recType == Nif::RC_NiSwitchNode)
|
|
||||||
{
|
|
||||||
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
|
||||||
node->asSwitch()->setSingleChildOn(niSwitchNode->initialIndex);
|
|
||||||
if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel))
|
|
||||||
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel);
|
|
||||||
else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel))
|
|
||||||
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel);
|
|
||||||
}
|
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,8 @@ namespace SceneUtil
|
||||||
mShadowSettings->setReceivesShadowTraversalMask(~0u);
|
mShadowSettings->setReceivesShadowTraversalMask(~0u);
|
||||||
|
|
||||||
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
||||||
|
numberOfShadowMapsPerLight = std::max(1, std::min(numberOfShadowMapsPerLight, 8));
|
||||||
|
|
||||||
mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight);
|
mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight);
|
||||||
mShadowSettings->setBaseShadowTextureUnit(8 - numberOfShadowMapsPerLight);
|
mShadowSettings->setBaseShadowTextureUnit(8 - numberOfShadowMapsPerLight);
|
||||||
|
|
||||||
|
@ -66,6 +68,8 @@ namespace SceneUtil
|
||||||
void ShadowManager::disableShadowsForStateSet(osg::ref_ptr<osg::StateSet> stateset)
|
void ShadowManager::disableShadowsForStateSet(osg::ref_ptr<osg::StateSet> stateset)
|
||||||
{
|
{
|
||||||
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
||||||
|
numberOfShadowMapsPerLight = std::max(1, std::min(numberOfShadowMapsPerLight, 8));
|
||||||
|
|
||||||
int baseShadowTextureUnit = 8 - numberOfShadowMapsPerLight;
|
int baseShadowTextureUnit = 8 - numberOfShadowMapsPerLight;
|
||||||
|
|
||||||
osg::ref_ptr<osg::Image> fakeShadowMapImage = new osg::Image();
|
osg::ref_ptr<osg::Image> fakeShadowMapImage = new osg::Image();
|
||||||
|
|
|
@ -36,7 +36,6 @@ namespace Terrain
|
||||||
|
|
||||||
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags);
|
osg::ref_ptr<osg::Node> getChunk(float size, const osg::Vec2f& center, unsigned char lod, unsigned int lodFlags);
|
||||||
|
|
||||||
void setCullingActive(bool active) { mCullingActive = active; }
|
|
||||||
void setCompositeMapSize(unsigned int size) { mCompositeMapSize = size; }
|
void setCompositeMapSize(unsigned int size) { mCompositeMapSize = size; }
|
||||||
void setCompositeMapLevel(float level) { mCompositeMapLevel = level; }
|
void setCompositeMapLevel(float level) { mCompositeMapLevel = level; }
|
||||||
void setMaxCompositeGeometrySize(float maxCompGeometrySize) { mMaxCompGeometrySize = maxCompGeometrySize; }
|
void setMaxCompositeGeometrySize(float maxCompGeometrySize) { mMaxCompGeometrySize = maxCompGeometrySize; }
|
||||||
|
@ -65,8 +64,6 @@ namespace Terrain
|
||||||
unsigned int mCompositeMapSize;
|
unsigned int mCompositeMapSize;
|
||||||
float mCompositeMapLevel;
|
float mCompositeMapLevel;
|
||||||
float mMaxCompGeometrySize;
|
float mMaxCompGeometrySize;
|
||||||
|
|
||||||
bool mCullingActive;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,8 @@ namespace Gui
|
||||||
, mMouseFocus(false)
|
, mMouseFocus(false)
|
||||||
, mMousePress(false)
|
, mMousePress(false)
|
||||||
, mKeyFocus(false)
|
, mKeyFocus(false)
|
||||||
|
, mUseWholeTexture(true)
|
||||||
|
, mTextureRect(MyGUI::IntCoord(0, 0, 0, 0))
|
||||||
{
|
{
|
||||||
setNeedKeyFocus(sDefaultNeedKeyFocus);
|
setNeedKeyFocus(sDefaultNeedKeyFocus);
|
||||||
}
|
}
|
||||||
|
@ -23,6 +25,13 @@ namespace Gui
|
||||||
sDefaultNeedKeyFocus = enabled;
|
sDefaultNeedKeyFocus = enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImageButton::setTextureRect(MyGUI::IntCoord coord)
|
||||||
|
{
|
||||||
|
mTextureRect = coord;
|
||||||
|
mUseWholeTexture = (coord == MyGUI::IntCoord(0, 0, 0, 0));
|
||||||
|
updateImage();
|
||||||
|
}
|
||||||
|
|
||||||
void ImageButton::setPropertyOverride(const std::string &_key, const std::string &_value)
|
void ImageButton::setPropertyOverride(const std::string &_key, const std::string &_value)
|
||||||
{
|
{
|
||||||
if (_key == "ImageHighlighted")
|
if (_key == "ImageHighlighted")
|
||||||
|
@ -37,6 +46,11 @@ namespace Gui
|
||||||
}
|
}
|
||||||
mImageNormal = _value;
|
mImageNormal = _value;
|
||||||
}
|
}
|
||||||
|
else if (_key == "TextureRect")
|
||||||
|
{
|
||||||
|
mTextureRect = MyGUI::IntCoord::parse(_value);
|
||||||
|
mUseWholeTexture = (mTextureRect == MyGUI::IntCoord(0, 0, 0, 0));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
ImageBox::setPropertyOverride(_key, _value);
|
ImageBox::setPropertyOverride(_key, _value);
|
||||||
}
|
}
|
||||||
|
@ -66,12 +80,25 @@ namespace Gui
|
||||||
|
|
||||||
void ImageButton::updateImage()
|
void ImageButton::updateImage()
|
||||||
{
|
{
|
||||||
|
std::string textureName = mImageNormal;
|
||||||
if (mMousePress)
|
if (mMousePress)
|
||||||
setImageTexture(mImagePushed);
|
textureName = mImagePushed;
|
||||||
else if (mMouseFocus || mKeyFocus)
|
else if (mMouseFocus || mKeyFocus)
|
||||||
setImageTexture(mImageHighlighted);
|
textureName = mImageHighlighted;
|
||||||
else
|
|
||||||
setImageTexture(mImageNormal);
|
if (!mUseWholeTexture)
|
||||||
|
{
|
||||||
|
int scale = 1.f;
|
||||||
|
MyGUI::ITexture* texture = MyGUI::RenderManager::getInstance().getTexture(textureName);
|
||||||
|
if (texture && getHeight() != 0)
|
||||||
|
scale = texture->getHeight() / getHeight();
|
||||||
|
|
||||||
|
setImageTile(MyGUI::IntSize(mTextureRect.width * scale, mTextureRect.height * scale));
|
||||||
|
MyGUI::IntCoord scaledSize(mTextureRect.left * scale, mTextureRect.top * scale, mTextureRect.width * scale, mTextureRect.height * scale);
|
||||||
|
setImageCoord(scaledSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
setImageTexture(textureName);
|
||||||
}
|
}
|
||||||
|
|
||||||
MyGUI::IntSize ImageButton::getRequestedSize()
|
MyGUI::IntSize ImageButton::getRequestedSize()
|
||||||
|
@ -82,7 +109,11 @@ namespace Gui
|
||||||
Log(Debug::Error) << "ImageButton: can't find image " << mImageNormal;
|
Log(Debug::Error) << "ImageButton: can't find image " << mImageNormal;
|
||||||
return MyGUI::IntSize(0,0);
|
return MyGUI::IntSize(0,0);
|
||||||
}
|
}
|
||||||
return MyGUI::IntSize (texture->getWidth(), texture->getHeight());
|
|
||||||
|
if (mUseWholeTexture)
|
||||||
|
return MyGUI::IntSize(texture->getWidth(), texture->getHeight());
|
||||||
|
|
||||||
|
return MyGUI::IntSize(mTextureRect.width, mTextureRect.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageButton::setImage(const std::string &image)
|
void ImageButton::setImage(const std::string &image)
|
||||||
|
@ -96,7 +127,7 @@ namespace Gui
|
||||||
mImageHighlighted = imageNoExt + "_over" + ext;
|
mImageHighlighted = imageNoExt + "_over" + ext;
|
||||||
mImagePushed = imageNoExt + "_pressed" + ext;
|
mImagePushed = imageNoExt + "_pressed" + ext;
|
||||||
|
|
||||||
setImageTexture(mImageNormal);
|
updateImage();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageButton::onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id)
|
void ImageButton::onMouseButtonReleased(int _left, int _top, MyGUI::MouseButton _id)
|
||||||
|
|
|
@ -23,6 +23,8 @@ namespace Gui
|
||||||
/// Set mImageNormal, mImageHighlighted and mImagePushed based on file convention (image_idle.ext, image_over.ext and image_pressed.ext)
|
/// Set mImageNormal, mImageHighlighted and mImagePushed based on file convention (image_idle.ext, image_over.ext and image_pressed.ext)
|
||||||
void setImage(const std::string& image);
|
void setImage(const std::string& image);
|
||||||
|
|
||||||
|
void setTextureRect(MyGUI::IntCoord coord);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void updateImage();
|
void updateImage();
|
||||||
|
|
||||||
|
@ -44,6 +46,9 @@ namespace Gui
|
||||||
bool mMouseFocus;
|
bool mMouseFocus;
|
||||||
bool mMousePress;
|
bool mMousePress;
|
||||||
bool mKeyFocus;
|
bool mKeyFocus;
|
||||||
|
bool mUseWholeTexture;
|
||||||
|
|
||||||
|
MyGUI::IntCoord mTextureRect;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,11 +85,11 @@ compute tight scene bounds
|
||||||
|
|
||||||
:Type: boolean
|
:Type: boolean
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: False
|
:Default: True
|
||||||
|
|
||||||
With this setting enabled, attempt to better use the shadow map(s) by making them cover a smaller area.
|
With this setting enabled, attempt to better use the shadow map(s) by making them cover a smaller area.
|
||||||
This can be especially helpful when looking downwards with a high viewing distance but will be less useful with the default value.
|
This can be especially helpful when looking downwards with a high viewing distance but will be less useful with the default value.
|
||||||
The performance impact of this may be very large.
|
May have a minor to major performance impact.
|
||||||
|
|
||||||
shadow map resolution
|
shadow map resolution
|
||||||
---------------------
|
---------------------
|
||||||
|
@ -200,10 +200,10 @@ use front face culling
|
||||||
|
|
||||||
:Type: boolean
|
:Type: boolean
|
||||||
:Range: True/False
|
:Range: True/False
|
||||||
:Default: True
|
:Default: False
|
||||||
|
|
||||||
Excludes theoretically unnecessary faces from shadow maps, slightly increasing performance.
|
Excludes theoretically unnecessary faces from shadow maps, slightly increasing performance.
|
||||||
In practice, Peter Panning can be much less visible with these faces included, so if you have high polygon offset values, disabling this may help minimise the side effects.
|
In practice, Peter Panning can be much less visible with these faces included, so if you have high polygon offset values, leaving this off may help minimise the side effects.
|
||||||
|
|
||||||
split point uniform logarithmic ratio
|
split point uniform logarithmic ratio
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
|
@ -68,7 +68,7 @@ composite map level
|
||||||
|
|
||||||
:Type: integer
|
:Type: integer
|
||||||
:Range: >= -3
|
:Range: >= -3
|
||||||
:Default: -2
|
:Default: 0
|
||||||
|
|
||||||
Controls at which minimum size (in 2^value cell units) terrain chunks will start to use a composite map instead of the high-detail textures.
|
Controls at which minimum size (in 2^value cell units) terrain chunks will start to use a composite map instead of the high-detail textures.
|
||||||
With value -3 composite maps are used everywhere.
|
With value -3 composite maps are used everywhere.
|
||||||
|
@ -76,7 +76,7 @@ With value -3 composite maps are used everywhere.
|
||||||
A composite map is a pre-rendered texture that contains all the texture layers combined.
|
A composite map is a pre-rendered texture that contains all the texture layers combined.
|
||||||
Note that resolution of composite maps is currently always fixed at 'composite map resolution',
|
Note that resolution of composite maps is currently always fixed at 'composite map resolution',
|
||||||
regardless of the resolution of the underlying terrain textures.
|
regardless of the resolution of the underlying terrain textures.
|
||||||
If high-detail texture replacers are used, probably it is worth to increase 'composite map resolution' setting value.
|
If high resolution texture replacers are used, it is recommended to increase 'composite map resolution' setting value.
|
||||||
|
|
||||||
composite map resolution
|
composite map resolution
|
||||||
------------------------
|
------------------------
|
||||||
|
|
33
extern/oics/ICSInputControlSystem.cpp
vendored
33
extern/oics/ICSInputControlSystem.cpp
vendored
|
@ -97,6 +97,13 @@ namespace ICS
|
||||||
xmlControl = xmlControl->NextSiblingElement("Control");
|
xmlControl = xmlControl->NextSiblingElement("Control");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const size_t channelsCountLimit = 65536;
|
||||||
|
if (controlChannelCount > channelsCountLimit)
|
||||||
|
{
|
||||||
|
ICS_LOG("Warning: requested channels count (" + ToString<size_t>(controlChannelCount) + ") exceeds allowed maximum (" + ToString<size_t>(channelsCountLimit) + "), clamping it");
|
||||||
|
controlChannelCount = channelsCountLimit;
|
||||||
|
}
|
||||||
|
|
||||||
if(controlChannelCount > channelCount)
|
if(controlChannelCount > channelCount)
|
||||||
{
|
{
|
||||||
size_t dif = controlChannelCount - channelCount;
|
size_t dif = controlChannelCount - channelCount;
|
||||||
|
@ -116,7 +123,13 @@ namespace ICS
|
||||||
TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter");
|
TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter");
|
||||||
while(xmlChannelFilter)
|
while(xmlChannelFilter)
|
||||||
{
|
{
|
||||||
int ch = FromString<int>(xmlChannelFilter->Attribute("number"));
|
size_t ch = FromString<size_t>(xmlChannelFilter->Attribute("number"));
|
||||||
|
if(ch >= controlChannelCount)
|
||||||
|
{
|
||||||
|
ICS_LOG("ERROR: channel number (ch) is out of range");
|
||||||
|
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
TiXmlElement* xmlInterval = xmlChannelFilter->FirstChildElement("Interval");
|
TiXmlElement* xmlInterval = xmlChannelFilter->FirstChildElement("Interval");
|
||||||
while(xmlInterval)
|
while(xmlInterval)
|
||||||
|
@ -150,7 +163,6 @@ namespace ICS
|
||||||
xmlInterval = xmlInterval->NextSiblingElement("Interval");
|
xmlInterval = xmlInterval->NextSiblingElement("Interval");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
|
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -264,14 +276,21 @@ namespace ICS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int chNumber = FromString<int>(xmlChannel->Attribute("number"));
|
size_t chNumber = FromString<size_t>(xmlChannel->Attribute("number"));
|
||||||
if(std::string(xmlChannel->Attribute("direction")) == "DIRECT")
|
if(chNumber >= controlChannelCount)
|
||||||
{
|
{
|
||||||
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::DIRECT, percentage);
|
ICS_LOG("ERROR: channel number (chNumber) is out of range");
|
||||||
}
|
}
|
||||||
else if(std::string(xmlChannel->Attribute("direction")) == "INVERSE")
|
else
|
||||||
{
|
{
|
||||||
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::INVERSE, percentage);
|
if(std::string(xmlChannel->Attribute("direction")) == "DIRECT")
|
||||||
|
{
|
||||||
|
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::DIRECT, percentage);
|
||||||
|
}
|
||||||
|
else if(std::string(xmlChannel->Attribute("direction")) == "INVERSE")
|
||||||
|
{
|
||||||
|
mControls.back()->attachChannel(mChannels[ chNumber ],Channel::INVERSE, percentage);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
xmlChannel = xmlChannel->NextSiblingElement("Channel");
|
xmlChannel = xmlChannel->NextSiblingElement("Channel");
|
||||||
|
|
|
@ -65,12 +65,14 @@
|
||||||
<Widget type="BookPage" skin="MW_BookPage" position="75 10 92 260" name="CenterTopicIndex"/>
|
<Widget type="BookPage" skin="MW_BookPage" position="75 10 92 260" name="CenterTopicIndex"/>
|
||||||
<Widget type="BookPage" skin="MW_BookPage" position="130 10 92 260" name="RightTopicIndex"/>
|
<Widget type="BookPage" skin="MW_BookPage" position="130 10 92 260" name="RightTopicIndex"/>
|
||||||
|
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="71 15 100 20" Align="Top|Left" name="ShowActiveBTN">
|
<Widget type="ImageButton" skin="ImageBox" position="76 15 96 32" Align="Top|Left" name="ShowActiveBTN">
|
||||||
<!-- Image set at runtime since it may not be available in all versions of the game -->
|
<!-- Image set at runtime since it may not be available in all versions of the game -->
|
||||||
|
<Property key="TextureRect" value="0 0 96 32"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="ImageButton" skin="ImageBox" position="85 15 72 20" Align="Top|Left" name="ShowAllBTN">
|
<Widget type="ImageButton" skin="ImageBox" position="83 15 72 32" Align="Top|Left" name="ShowAllBTN">
|
||||||
<!-- Image set at runtime since it may not be available in all versions of the game -->
|
<!-- Image set at runtime since it may not be available in all versions of the game -->
|
||||||
|
<Property key="TextureRect" value="0 0 72 32"/>
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
<Widget type="MWList" skin="MW_QuestList" position="8 40 226 212" name="TopicsList" align="Right VStretch">
|
<Widget type="MWList" skin="MW_QuestList" position="8 40 226 212" name="TopicsList" align="Right VStretch">
|
||||||
|
|
|
@ -17,16 +17,16 @@
|
||||||
|
|
||||||
<Widget type="Widget" skin="" position="15 55 332 128" align="Left Bottom HCenter">
|
<Widget type="Widget" skin="" position="15 55 332 128" align="Left Bottom HCenter">
|
||||||
|
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 60 59" name="QuickKey1"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 60 60" name="QuickKey1"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 0 60 59" name="QuickKey2"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 0 60 60" name="QuickKey2"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 0 60 59" name="QuickKey3"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 0 60 60" name="QuickKey3"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 0 60 59" name="QuickKey4"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 0 60 60" name="QuickKey4"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 0 60 59" name="QuickKey5"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 0 60 60" name="QuickKey5"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 67 60 59" name="QuickKey6"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 67 60 60" name="QuickKey6"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 67 60 59" name="QuickKey7"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 67 60 60" name="QuickKey7"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 67 60 59" name="QuickKey8"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 67 60 60" name="QuickKey8"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 67 60 59" name="QuickKey9"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 67 60 60" name="QuickKey9"/>
|
||||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 67 60 59" name="QuickKey10"/>
|
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 67 60 60" name="QuickKey10"/>
|
||||||
|
|
||||||
</Widget>
|
</Widget>
|
||||||
|
|
||||||
|
|
|
@ -98,7 +98,7 @@ vertex lod mod = 0
|
||||||
|
|
||||||
# Controls when the distant terrain will flip to composited textures instead of high-detail textures, should be >= -3.
|
# Controls when the distant terrain will flip to composited textures instead of high-detail textures, should be >= -3.
|
||||||
# Higher value is more detailed textures.
|
# Higher value is more detailed textures.
|
||||||
composite map level = -2
|
composite map level = 0
|
||||||
|
|
||||||
# Controls the resolution of composite maps.
|
# Controls the resolution of composite maps.
|
||||||
composite map resolution = 512
|
composite map resolution = 512
|
||||||
|
@ -767,8 +767,8 @@ enable debug hud = false
|
||||||
# Enable the debug overlay to see where each shadow map affects.
|
# Enable the debug overlay to see where each shadow map affects.
|
||||||
enable debug overlay = false
|
enable debug overlay = false
|
||||||
|
|
||||||
# Attempt to better use the shadow map by making them cover a smaller area. Especially helpful when looking downwards with a high viewing distance. The performance impact of this may be very large.
|
# Attempt to better use the shadow map by making them cover a smaller area. Especially helpful when looking downwards. May have a minor to major performance impact.
|
||||||
compute tight scene bounds = false
|
compute tight scene bounds = true
|
||||||
|
|
||||||
# How large to make the shadow map(s). Higher values increase GPU load, but can produce better-looking results. Power-of-two values may turn out to be faster on some GPU/driver combinations.
|
# How large to make the shadow map(s). Higher values increase GPU load, but can produce better-looking results. Power-of-two values may turn out to be faster on some GPU/driver combinations.
|
||||||
shadow map resolution = 1024
|
shadow map resolution = 1024
|
||||||
|
@ -785,8 +785,8 @@ polygon offset units = 4.0
|
||||||
# How far along the surface normal to project shadow coordinates. Higher values significantly reduce shadow flicker, usually with a lower increase of Peter Panning than the Polygon Offset settings. This value is in in-game units, so 1.0 is roughly 1.4 cm.
|
# How far along the surface normal to project shadow coordinates. Higher values significantly reduce shadow flicker, usually with a lower increase of Peter Panning than the Polygon Offset settings. This value is in in-game units, so 1.0 is roughly 1.4 cm.
|
||||||
normal offset distance = 1.0
|
normal offset distance = 1.0
|
||||||
|
|
||||||
# Excludes theoretically unnecessary faces from shadow maps, slightly increasing performance. In practice, Peter Panning can be much less visible with these faces included, so if you have high polygon offset values, disabling this may help minimise the side effects.
|
# Excludes theoretically unnecessary faces from shadow maps, slightly increasing performance. In practice, Peter Panning can be much less visible with these faces included, so if you have high polygon offset values, leave this off to minimise the side effects.
|
||||||
use front face culling = true
|
use front face culling = false
|
||||||
|
|
||||||
# Allow actors to cast shadows. Potentially decreases performance.
|
# Allow actors to cast shadows. Potentially decreases performance.
|
||||||
actor shadows = false
|
actor shadows = false
|
||||||
|
|
Loading…
Reference in a new issue