mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-27 16:09: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 #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 #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 #2229: Improve pathfinding AI
|
||||
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::Weapon) properties += "Weapon ";
|
||||
if (flags & ESM::Creature::Essential) properties += "Essential ";
|
||||
int unused = (0xFF ^
|
||||
int unused = (0xFFFFFFFF ^
|
||||
(ESM::Creature::Base|
|
||||
ESM::Creature::Walks|
|
||||
ESM::Creature::Swims|
|
||||
|
|
|
@ -135,7 +135,7 @@ bool Launcher::GraphicsPage::loadSettings()
|
|||
if (mEngineSettings.getBool("player shadows", "Shadows"))
|
||||
playerShadowsCheckBox->setCheckState(Qt::Checked);
|
||||
if (mEngineSettings.getBool("terrain shadows", "Shadows"))
|
||||
objectShadowsCheckBox->setCheckState(Qt::Checked);
|
||||
terrainShadowsCheckBox->setCheckState(Qt::Checked);
|
||||
if (mEngineSettings.getBool("object shadows", "Shadows"))
|
||||
objectShadowsCheckBox->setCheckState(Qt::Checked);
|
||||
if (mEngineSettings.getBool("enable indoor shadows", "Shadows"))
|
||||
|
|
|
@ -1038,6 +1038,28 @@ bool CSVRender::TerrainShapeMode::isInCellSelection(int globalSelectionX, int gl
|
|||
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)
|
||||
{
|
||||
int r = mBrushSize / 2;
|
||||
|
@ -1045,7 +1067,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
|||
|
||||
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)
|
||||
|
@ -1054,7 +1076,7 @@ void CSVRender::TerrainShapeMode::selectTerrainShapes(const std::pair<int, int>&
|
|||
{
|
||||
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 distanceY = abs(j - vertexCoords.second);
|
||||
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)
|
||||
{
|
||||
std::pair<int, int> localVertexCoords (vertexCoords.first + value.first, vertexCoords.second + value.second);
|
||||
std::string cellId (CSMWorld::CellCoordinates::vertexGlobalToCellId(localVertexCoords));
|
||||
if (isInCellSelection(localVertexCoords.first, localVertexCoords.second)) selections.emplace_back(localVertexCoords);
|
||||
handleSelection(localVertexCoords.first, localVertexCoords.second, &selections);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1227,7 +1248,7 @@ void CSVRender::TerrainShapeMode::createNewLandData(const CSMWorld::CellCoordina
|
|||
|
||||
++averageDivider;
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -1418,8 +1439,12 @@ void CSVRender::TerrainShapeMode::setBrushShape(CSVWidget::BrushShape brushShape
|
|||
selectionCenterY = selectionCenterY + value.second;
|
||||
++selectionAmount;
|
||||
}
|
||||
selectionCenterX = selectionCenterX / selectionAmount;
|
||||
selectionCenterY = selectionCenterY / selectionAmount;
|
||||
|
||||
if (selectionAmount != 0)
|
||||
{
|
||||
selectionCenterX /= selectionAmount;
|
||||
selectionCenterY /= selectionAmount;
|
||||
}
|
||||
|
||||
mCustomBrushShape.clear();
|
||||
std::pair<int, int> differentialPos {};
|
||||
|
|
|
@ -134,6 +134,9 @@ namespace CSVRender
|
|||
/// Check if global selection coordinate belongs to cell in view
|
||||
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
|
||||
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;
|
||||
++selectionAmount;
|
||||
}
|
||||
selectionCenterX /= selectionAmount;
|
||||
selectionCenterY /= selectionAmount;
|
||||
|
||||
if (selectionAmount != 0)
|
||||
{
|
||||
selectionCenterX /= selectionAmount;
|
||||
selectionCenterY /= selectionAmount;
|
||||
}
|
||||
|
||||
mCustomBrushShape.clear();
|
||||
for (auto const& value: terrainSelection)
|
||||
|
|
|
@ -807,6 +807,8 @@ namespace MWBase
|
|||
|
||||
/// Return physical half extents of the given actor to be used in pathfinding
|
||||
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);
|
||||
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);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <MyGUI_Button.h>
|
||||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_ImageBox.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
#include <components/esm/quickkeys.hpp>
|
||||
|
@ -309,7 +310,12 @@ namespace MWGui
|
|||
mSelected->id = item.getCellRef().getRefId();
|
||||
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->setUserString("ToolTipType", "ItemPtr");
|
||||
|
@ -355,7 +361,12 @@ namespace MWGui
|
|||
path.insert(slashPos+1, "b_");
|
||||
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);
|
||||
|
||||
if (mMagicSelectionDialog)
|
||||
|
|
|
@ -149,7 +149,7 @@ float BookWindowBase::adjustButton (char const * name)
|
|||
Gui::ImageButton* button;
|
||||
WindowBase::getWidget (button, name);
|
||||
MyGUI::IntSize requested = button->getRequestedSize();
|
||||
float scale = requested.height / button->getSize().height;
|
||||
float scale = float(requested.height) / button->getSize().height;
|
||||
MyGUI::IntSize newSize = requested;
|
||||
newSize.width /= scale;
|
||||
newSize.height /= scale;
|
||||
|
|
|
@ -1079,7 +1079,7 @@ namespace MWMechanics
|
|||
|
||||
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();
|
||||
|
||||
MWBase::Environment::get().getMechanicsManager()->actorKilled(ptr, player);
|
||||
|
@ -2138,6 +2138,13 @@ namespace MWMechanics
|
|||
if (fx)
|
||||
MWBase::Environment::get().getWorld()->spawnEffect("meshes\\" + fx->mModel,
|
||||
"", 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)
|
||||
{
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
#include "../mwphysics/collisiontype.hpp"
|
||||
|
||||
#include "pathgrid.hpp"
|
||||
#include "creaturestats.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)
|
||||
{
|
||||
// note: AiWander currently does not open doors
|
||||
if (getTypeId() == TypeIdWander)
|
||||
return;
|
||||
|
||||
if (mPathFinder.getPathSize() == 0)
|
||||
return;
|
||||
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
static float distance = world->getMaxActivationDistance();
|
||||
|
||||
|
@ -231,9 +253,11 @@ void MWMechanics::AiPackage::openDoors(const MWWorld::Ptr& actor)
|
|||
if (door == MWWorld::Ptr())
|
||||
return;
|
||||
|
||||
// note: AiWander currently does not open doors
|
||||
if (getTypeId() != TypeIdWander && !door.getCellRef().getTeleport() && door.getClass().getDoorState(door) == MWWorld::DoorState::Idle)
|
||||
if (!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 ))
|
||||
{
|
||||
world->activate(door, actor);
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <components/esm/aisequence.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
|
@ -104,8 +105,7 @@ bool AiPursue::execute (const MWWorld::Ptr& actor, CharacterController& characte
|
|||
/*
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -1995,6 +1995,17 @@ void CharacterController::update(float duration, bool animationOnly)
|
|||
bool isPlayer = mPtr == MWMechanics::getPlayer();
|
||||
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())
|
||||
updateAnimQueue();
|
||||
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;
|
||||
|
||||
vec.x() *= scale;
|
||||
vec.y() *= scale;
|
||||
vec.z() = 0.0f;
|
||||
|
||||
inJump = false;
|
||||
|
@ -2445,20 +2458,9 @@ void CharacterController::update(float duration, bool animationOnly)
|
|||
else
|
||||
moved = osg::Vec3f(0.f, 0.f, 0.f);
|
||||
|
||||
float scale = mPtr.getCellRef().getScale();
|
||||
moved.x() *= 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...
|
||||
if(speed > 0.f)
|
||||
{
|
||||
|
|
|
@ -34,6 +34,7 @@ namespace MWMechanics
|
|||
Enchanting::Enchanting()
|
||||
: mCastStyle(ESM::Enchantment::CastOnce)
|
||||
, mSelfEnchanting(false)
|
||||
, mWeaponType(-1)
|
||||
{}
|
||||
|
||||
void Enchanting::setOldItem(const MWWorld::Ptr& oldItem)
|
||||
|
|
|
@ -133,10 +133,9 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
// Update summon effects
|
||||
bool casterDead = creatureStats.isDead();
|
||||
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)
|
||||
{
|
||||
// Effect has ended
|
||||
|
@ -147,39 +146,11 @@ namespace MWMechanics
|
|||
++it;
|
||||
}
|
||||
|
||||
std::vector<int>& graveyard = creatureStats.getSummonedCreatureGraveyard();
|
||||
for (std::vector<int>::iterator it = graveyard.begin(); it != graveyard.end(); )
|
||||
{
|
||||
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->searchPtrViaActorId(*it);
|
||||
if (!ptr.isEmpty())
|
||||
{
|
||||
it = graveyard.erase(it);
|
||||
std::vector<int> graveyard = creatureStats.getSummonedCreatureGraveyard();
|
||||
creatureStats.getSummonedCreatureGraveyard().clear();
|
||||
|
||||
const ESM::Static* fx = MWBase::Environment::get().getWorld()->getStore().get<ESM::Static>()
|
||||
.search("VFX_Summon_End");
|
||||
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;
|
||||
}
|
||||
for (const int creature : graveyard)
|
||||
MWBase::Environment::get().getMechanicsManager()->cleanupSummonedCreature(mActor, creature);
|
||||
|
||||
if (!cleanup)
|
||||
return;
|
||||
|
|
|
@ -113,7 +113,7 @@ bool ActorAnimation::updateCarriedLeftVisible(const int weaptype) const
|
|||
{
|
||||
SceneUtil::FindByNameVisitor findVisitor ("Bip01 AttachShield");
|
||||
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::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;
|
||||
bodypart = partStore.search(bodypartName);
|
||||
if (bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
||||
if (bodypart == nullptr || bodypart->mData.mType != ESM::BodyPart::MT_Armor)
|
||||
return "";
|
||||
else if (!bodypart->mModel.empty())
|
||||
mesh = "meshes\\" + bodypart->mModel;
|
||||
|
|
|
@ -527,7 +527,7 @@ void Water::createSimpleWaterStateSet(osg::Node* node, float alpha)
|
|||
|
||||
// Add animated 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");
|
||||
for (int i=0; i<frameCount; ++i)
|
||||
{
|
||||
|
@ -643,7 +643,7 @@ Water::~Water()
|
|||
|
||||
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");
|
||||
for (int i=0; i<frameCount; ++i)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace MWWorld
|
|||
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||
return;
|
||||
|
||||
if (actor != MWMechanics::getPlayer())
|
||||
return;
|
||||
|
||||
if (!MWBase::Environment::get().getMechanicsManager()->onOpen(getTarget()))
|
||||
return;
|
||||
|
||||
|
|
|
@ -3,12 +3,15 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include "../mwmechanics/actorutil.hpp"
|
||||
|
||||
namespace MWWorld
|
||||
{
|
||||
ActionTalk::ActionTalk (const Ptr& actor) : Action (false, 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;
|
||||
int index = ~0;
|
||||
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();
|
||||
if (Misc::StringUtils::ciEqual(fname, fnamecandidate)) {
|
||||
index = i;
|
||||
|
|
|
@ -262,7 +262,7 @@ namespace MWWorld
|
|||
{
|
||||
// Spawn at 0.75 * ActorHeight
|
||||
// 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
|
||||
|
|
|
@ -751,11 +751,9 @@ namespace MWWorld
|
|||
void Scene::changeToInteriorCell (const std::string& cellName, const ESM::Position& position, bool adjustPlayerPos, bool changeEvent)
|
||||
{
|
||||
CellStore *cell = MWBase::Environment::get().getWorld()->getInterior(cellName);
|
||||
bool loadcell = (mCurrentCell == nullptr);
|
||||
if(!loadcell)
|
||||
loadcell = *mCurrentCell != *cell;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
||||
bool useFading = (mCurrentCell != nullptr);
|
||||
if (useFading)
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenOut(0.5);
|
||||
|
||||
Loading::Listener* loadingListener = MWBase::Environment::get().getWindowManager()->getLoadingScreen();
|
||||
int messagesCount = MWBase::Environment::get().getWindowManager()->getMessagesCount();
|
||||
|
@ -763,7 +761,7 @@ namespace MWWorld
|
|||
loadingListener->setLabel(loadingInteriorText, false, messagesCount > 0);
|
||||
Loading::ScopedLoad load(loadingListener);
|
||||
|
||||
if(!loadcell)
|
||||
if(mCurrentCell != nullptr && *mCurrentCell == *cell)
|
||||
{
|
||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||
world->moveObject(world->getPlayerPtr(), position.pos[0], position.pos[1], position.pos[2]);
|
||||
|
@ -817,7 +815,8 @@ namespace MWWorld
|
|||
if (changeEvent)
|
||||
mCellChanged = true;
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||
if (useFading)
|
||||
MWBase::Environment::get().getWindowManager()->fadeScreenIn(0.5);
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->changeCell(mCurrentCell);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
#include <components/misc/constants.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/misc/rng.hpp>
|
||||
#include <components/misc/convert.hpp>
|
||||
|
||||
#include <components/files/collections.hpp>
|
||||
|
||||
|
@ -4351,4 +4352,23 @@ namespace MWWorld
|
|||
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
|
||||
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);
|
||||
return false;
|
||||
}
|
||||
|
||||
return Parser::parseName (name, loc, scanner);
|
||||
}
|
||||
|
||||
bool ExprParser::parseKeyword (int keyword, const TokenLoc& loc, Scanner& scanner)
|
||||
|
|
|
@ -301,7 +301,7 @@ namespace NifOsg
|
|||
|
||||
private:
|
||||
Vec3Interpolator mData;
|
||||
TargetColor mTargetColor;
|
||||
TargetColor mTargetColor = Ambient;
|
||||
};
|
||||
|
||||
class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller
|
||||
|
|
|
@ -341,6 +341,7 @@ namespace NifOsg
|
|||
osg::ref_ptr<osg::Switch> switchNode (new osg::Switch);
|
||||
switchNode->setName(niSwitchNode->name);
|
||||
switchNode->setNewChildDefaultValue(false);
|
||||
switchNode->setSingleChildOn(niSwitchNode->initialIndex);
|
||||
return switchNode;
|
||||
}
|
||||
|
||||
|
@ -433,7 +434,7 @@ namespace NifOsg
|
|||
osg::ref_ptr<osg::Group> node;
|
||||
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)
|
||||
{
|
||||
case Nif::RC_NiLODNode:
|
||||
|
@ -444,12 +445,6 @@ namespace NifOsg
|
|||
break;
|
||||
}
|
||||
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_NiTriStrips:
|
||||
case Nif::RC_NiAutoNormalParticles:
|
||||
|
@ -625,6 +620,19 @@ namespace NifOsg
|
|||
&& !nifNode->controller.empty() && node->getDataVariance() == osg::Object::DYNAMIC)
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,8 @@ namespace SceneUtil
|
|||
mShadowSettings->setReceivesShadowTraversalMask(~0u);
|
||||
|
||||
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
||||
numberOfShadowMapsPerLight = std::max(1, std::min(numberOfShadowMapsPerLight, 8));
|
||||
|
||||
mShadowSettings->setNumShadowMapsPerLight(numberOfShadowMapsPerLight);
|
||||
mShadowSettings->setBaseShadowTextureUnit(8 - numberOfShadowMapsPerLight);
|
||||
|
||||
|
@ -66,6 +68,8 @@ namespace SceneUtil
|
|||
void ShadowManager::disableShadowsForStateSet(osg::ref_ptr<osg::StateSet> stateset)
|
||||
{
|
||||
int numberOfShadowMapsPerLight = Settings::Manager::getInt("number of shadow maps", "Shadows");
|
||||
numberOfShadowMapsPerLight = std::max(1, std::min(numberOfShadowMapsPerLight, 8));
|
||||
|
||||
int baseShadowTextureUnit = 8 - numberOfShadowMapsPerLight;
|
||||
|
||||
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);
|
||||
|
||||
void setCullingActive(bool active) { mCullingActive = active; }
|
||||
void setCompositeMapSize(unsigned int size) { mCompositeMapSize = size; }
|
||||
void setCompositeMapLevel(float level) { mCompositeMapLevel = level; }
|
||||
void setMaxCompositeGeometrySize(float maxCompGeometrySize) { mMaxCompGeometrySize = maxCompGeometrySize; }
|
||||
|
@ -65,8 +64,6 @@ namespace Terrain
|
|||
unsigned int mCompositeMapSize;
|
||||
float mCompositeMapLevel;
|
||||
float mMaxCompGeometrySize;
|
||||
|
||||
bool mCullingActive;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,8 @@ namespace Gui
|
|||
, mMouseFocus(false)
|
||||
, mMousePress(false)
|
||||
, mKeyFocus(false)
|
||||
, mUseWholeTexture(true)
|
||||
, mTextureRect(MyGUI::IntCoord(0, 0, 0, 0))
|
||||
{
|
||||
setNeedKeyFocus(sDefaultNeedKeyFocus);
|
||||
}
|
||||
|
@ -23,6 +25,13 @@ namespace Gui
|
|||
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)
|
||||
{
|
||||
if (_key == "ImageHighlighted")
|
||||
|
@ -37,6 +46,11 @@ namespace Gui
|
|||
}
|
||||
mImageNormal = _value;
|
||||
}
|
||||
else if (_key == "TextureRect")
|
||||
{
|
||||
mTextureRect = MyGUI::IntCoord::parse(_value);
|
||||
mUseWholeTexture = (mTextureRect == MyGUI::IntCoord(0, 0, 0, 0));
|
||||
}
|
||||
else
|
||||
ImageBox::setPropertyOverride(_key, _value);
|
||||
}
|
||||
|
@ -66,12 +80,25 @@ namespace Gui
|
|||
|
||||
void ImageButton::updateImage()
|
||||
{
|
||||
std::string textureName = mImageNormal;
|
||||
if (mMousePress)
|
||||
setImageTexture(mImagePushed);
|
||||
textureName = mImagePushed;
|
||||
else if (mMouseFocus || mKeyFocus)
|
||||
setImageTexture(mImageHighlighted);
|
||||
else
|
||||
setImageTexture(mImageNormal);
|
||||
textureName = mImageHighlighted;
|
||||
|
||||
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()
|
||||
|
@ -82,7 +109,11 @@ namespace Gui
|
|||
Log(Debug::Error) << "ImageButton: can't find image " << mImageNormal;
|
||||
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)
|
||||
|
@ -96,7 +127,7 @@ namespace Gui
|
|||
mImageHighlighted = imageNoExt + "_over" + ext;
|
||||
mImagePushed = imageNoExt + "_pressed" + ext;
|
||||
|
||||
setImageTexture(mImageNormal);
|
||||
updateImage();
|
||||
}
|
||||
|
||||
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)
|
||||
void setImage(const std::string& image);
|
||||
|
||||
void setTextureRect(MyGUI::IntCoord coord);
|
||||
|
||||
private:
|
||||
void updateImage();
|
||||
|
||||
|
@ -44,6 +46,9 @@ namespace Gui
|
|||
bool mMouseFocus;
|
||||
bool mMousePress;
|
||||
bool mKeyFocus;
|
||||
bool mUseWholeTexture;
|
||||
|
||||
MyGUI::IntCoord mTextureRect;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -85,11 +85,11 @@ compute tight scene bounds
|
|||
|
||||
:Type: boolean
|
||||
: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.
|
||||
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
|
||||
---------------------
|
||||
|
@ -200,10 +200,10 @@ use front face culling
|
|||
|
||||
:Type: boolean
|
||||
:Range: True/False
|
||||
:Default: True
|
||||
:Default: False
|
||||
|
||||
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
|
||||
-------------------------------------
|
||||
|
|
|
@ -68,7 +68,7 @@ composite map level
|
|||
|
||||
:Type: integer
|
||||
: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.
|
||||
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.
|
||||
Note that resolution of composite maps is currently always fixed at 'composite map resolution',
|
||||
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
|
||||
------------------------
|
||||
|
|
33
extern/oics/ICSInputControlSystem.cpp
vendored
33
extern/oics/ICSInputControlSystem.cpp
vendored
|
@ -97,6 +97,13 @@ namespace ICS
|
|||
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)
|
||||
{
|
||||
size_t dif = controlChannelCount - channelCount;
|
||||
|
@ -116,7 +123,13 @@ namespace ICS
|
|||
TiXmlElement* xmlChannelFilter = xmlRoot->FirstChildElement("ChannelFilter");
|
||||
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");
|
||||
while(xmlInterval)
|
||||
|
@ -150,7 +163,6 @@ namespace ICS
|
|||
xmlInterval = xmlInterval->NextSiblingElement("Interval");
|
||||
}
|
||||
|
||||
|
||||
xmlChannelFilter = xmlChannelFilter->NextSiblingElement("ChannelFilter");
|
||||
}
|
||||
|
||||
|
@ -264,14 +276,21 @@ namespace ICS
|
|||
}
|
||||
}
|
||||
|
||||
int chNumber = FromString<int>(xmlChannel->Attribute("number"));
|
||||
if(std::string(xmlChannel->Attribute("direction")) == "DIRECT")
|
||||
size_t chNumber = FromString<size_t>(xmlChannel->Attribute("number"));
|
||||
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");
|
||||
|
|
|
@ -65,12 +65,14 @@
|
|||
<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="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 -->
|
||||
<Property key="TextureRect" value="0 0 96 32"/>
|
||||
</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 -->
|
||||
<Property key="TextureRect" value="0 0 72 32"/>
|
||||
</Widget>
|
||||
|
||||
<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="ItemWidget" skin="MW_ItemIconBox" position="0 0 60 59" name="QuickKey1"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 0 60 59" name="QuickKey2"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 0 60 59" name="QuickKey3"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 0 60 59" name="QuickKey4"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 0 60 59" name="QuickKey5"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 67 60 59" name="QuickKey6"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 67 60 59" name="QuickKey7"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 67 60 59" name="QuickKey8"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 67 60 59" name="QuickKey9"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 67 60 59" name="QuickKey10"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 0 60 60" name="QuickKey1"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 0 60 60" name="QuickKey2"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 0 60 60" name="QuickKey3"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 0 60 60" name="QuickKey4"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 0 60 60" name="QuickKey5"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="0 67 60 60" name="QuickKey6"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="68 67 60 60" name="QuickKey7"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="136 67 60 60" name="QuickKey8"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="204 67 60 60" name="QuickKey9"/>
|
||||
<Widget type="ItemWidget" skin="MW_ItemIconBox" position="272 67 60 60" name="QuickKey10"/>
|
||||
|
||||
</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.
|
||||
# Higher value is more detailed textures.
|
||||
composite map level = -2
|
||||
composite map level = 0
|
||||
|
||||
# Controls the resolution of composite maps.
|
||||
composite map resolution = 512
|
||||
|
@ -767,8 +767,8 @@ enable debug hud = false
|
|||
# Enable the debug overlay to see where each shadow map affects.
|
||||
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.
|
||||
compute tight scene bounds = false
|
||||
# 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 = 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.
|
||||
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.
|
||||
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.
|
||||
use front face culling = true
|
||||
# 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 = false
|
||||
|
||||
# Allow actors to cast shadows. Potentially decreases performance.
|
||||
actor shadows = false
|
||||
|
|
Loading…
Reference in a new issue