From cf0c71c6511b2a66dfe3335e2c21929ade49e500 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 30 Aug 2019 22:01:03 +0300 Subject: [PATCH 01/48] Water shader cleanup --- files/shaders/water_fragment.glsl | 101 +++++++++--------------------- files/shaders/water_vertex.glsl | 2 +- 2 files changed, 31 insertions(+), 72 deletions(-) diff --git a/files/shaders/water_fragment.glsl b/files/shaders/water_fragment.glsl index cc211a3d64..2ad4ddeb6b 100644 --- a/files/shaders/water_fragment.glsl +++ b/files/shaders/water_fragment.glsl @@ -48,11 +48,6 @@ const vec3 WATER_COLOR = vec3(0.090195, 0.115685, 0.12745); const float RAIN_RIPPLE_GAPS = 5.0; const float RAIN_RIPPLE_RADIUS = 0.1; -int modulo(int v1, int v2) -{ - return v1 - v2 * int(floor(float(v1) / float(v2))); -} - vec2 randOffset(vec2 c) { return fract(vec2( @@ -170,8 +165,6 @@ void main(void) vec2 screenCoords = screenCoordsPassthrough.xy / screenCoordsPassthrough.z; screenCoords.y = (1.0-screenCoords.y); - vec2 nCoord = vec2(0.0); - #define waterTimer osg_SimulationTime vec3 normal0 = 2.0 * texture2D(normalMap,normalCoords(UV, 0.05, 0.04, waterTimer, -0.015, -0.005, vec3(0.0,0.0,0.0))).rgb - 1.0; @@ -195,100 +188,66 @@ void main(void) vec2 smallWaves = mix(vec2(SMALL_WAVES_X,SMALL_WAVES_Y),vec2(SMALL_WAVES_RAIN_X,SMALL_WAVES_RAIN_Y),rainIntensity); float bump = mix(BUMP,BUMP_RAIN,rainIntensity); - vec3 normal = (normal0 * bigWaves.x + normal1 * bigWaves.y + - normal2 * midWaves.x + normal3 * midWaves.y + - normal4 * smallWaves.x + normal5 * smallWaves.y + - rippleAdd); - - normal = normalize(vec3(normal.x * bump, normal.y * bump, normal.z)); - - normal = vec3(-normal.x, -normal.y, normal.z); - - // normal for sunlight scattering - vec3 lNormal = (normal0 * bigWaves.x * 0.5 + normal1 * bigWaves.y * 0.5 + - normal2 * midWaves.x * 0.2 + normal3 * midWaves.y * 0.2 + - normal4 * smallWaves.x * 0.1 + normal5 * smallWaves.y * 0.1 + - rippleAdd).xyz; - - lNormal = normalize(vec3(lNormal.x * bump, lNormal.y * bump, lNormal.z)); - lNormal = vec3(-lNormal.x, -lNormal.y, lNormal.z); + vec3 normal = (normal0 * bigWaves.x + normal1 * bigWaves.y + normal2 * midWaves.x + + normal3 * midWaves.y + normal4 * smallWaves.x + normal5 * smallWaves.y + rippleAdd); + normal = normalize(vec3(-normal.x * bump, -normal.y * bump, normal.z)); vec3 lVec = normalize((gl_ModelViewMatrixInverse * vec4(gl_LightSource[0].position.xyz, 0.0)).xyz); vec3 cameraPos = (gl_ModelViewMatrixInverse * vec4(0,0,0,1)).xyz; vec3 vVec = normalize(position.xyz - cameraPos.xyz); - float isUnderwater = (cameraPos.z > 0.0) ? 0.0 : 1.0; - - // sunlight scattering - vec3 pNormal = vec3(0,0,1); - vec3 lR = reflect(lVec, lNormal); - vec3 llR = reflect(lVec, pNormal); - - float sunHeight = lVec.z; float sunFade = length(gl_LightModel.ambient.xyz); - float s = clamp(dot(lR, vVec)*2.0-1.2, 0.0, 1.0); - float lightScatter = shadow * clamp(dot(lVec,lNormal)*0.7+0.3, 0.0, 1.0) * s * SCATTER_AMOUNT * sunFade * clamp(1.0-exp(-sunHeight), 0.0, 1.0); - vec3 scatterColour = mix(vec3(SCATTER_COLOUR)*vec3(1.0,0.4,0.0), SCATTER_COLOUR, clamp(1.0-exp(-sunHeight*SUN_EXT), 0.0, 1.0)); - // fresnel float ior = (cameraPos.z>0.0)?(1.333/1.0):(1.0/1.333); // air to water; water to air - float fresnel = fresnel_dielectric(vVec, normal, ior); - - fresnel = clamp(fresnel, 0.0, 1.0); + float fresnel = clamp(fresnel_dielectric(vVec, normal, ior), 0.0, 1.0); + vec2 screenCoordsOffset = normal.xy * REFL_BUMP; #if REFRACTION float depthSample = linearizeDepth(texture2D(refractionDepthMap,screenCoords).x); - float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-(normal.xy*REFR_BUMP)).x); + float depthSampleDistorted = linearizeDepth(texture2D(refractionDepthMap,screenCoords-screenCoordsOffset).x); float surfaceDepth = linearizeDepth(gl_FragCoord.z); float realWaterDepth = depthSample - surfaceDepth; // undistorted water depth in view direction, independent of frustum - float shore = clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1); -#else - float shore = 1.0; + screenCoordsOffset *= clamp(realWaterDepth / BUMP_SUPPRESS_DEPTH,0,1); #endif - vec2 screenCoordsOffset = normal.xy * REFL_BUMP * shore; - // reflection vec3 reflection = texture2D(reflectionMap, screenCoords + screenCoordsOffset).rgb; - // refraction + // specular + float specular = pow(max(dot(reflect(vVec, normal), lVec), 0.0),SPEC_HARDNESS) * shadow; + + vec3 waterColor = WATER_COLOR * sunFade; + #if REFRACTION + // refraction vec3 refraction = texture2D(refractionMap, screenCoords - screenCoordsOffset).rgb; // brighten up the refraction underwater - refraction = (cameraPos.z < 0.0) ? clamp(refraction * 1.5, 0.0, 1.0) : refraction; -#endif - // specular - vec3 R = reflect(vVec, normal); - float specular = pow(max(dot(R, lVec), 0.0),SPEC_HARDNESS) * shadow; - - vec3 waterColor = WATER_COLOR; - waterColor = waterColor * length(gl_LightModel.ambient.xyz); - -#if REFRACTION - if (cameraPos.z > 0.0) + if (cameraPos.z < 0.0) + refraction = clamp(refraction * 1.5, 0.0, 1.0); + else refraction = mix(refraction, waterColor, clamp(depthSampleDistorted/VISIBILITY, 0.0, 1.0)); - gl_FragData[0].xyz = mix( mix(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * gl_LightSource[0].specular.xyz; + // sunlight scattering + // normal for sunlight scattering + vec3 lNormal = (normal0 * bigWaves.x * 0.5 + normal1 * bigWaves.y * 0.5 + normal2 * midWaves.x * 0.2 + + normal3 * midWaves.y * 0.2 + normal4 * smallWaves.x * 0.1 + normal5 * smallWaves.y * 0.1 + rippleAdd); + lNormal = normalize(vec3(-lNormal.x * bump, -lNormal.y * bump, lNormal.z)); + float sunHeight = lVec.z; + vec3 scatterColour = mix(SCATTER_COLOUR*vec3(1.0,0.4,0.0), SCATTER_COLOUR, clamp(1.0-exp(-sunHeight*SUN_EXT), 0.0, 1.0)); + vec3 lR = reflect(lVec, lNormal); + float lightScatter = shadow * clamp(dot(lVec,lNormal)*0.7+0.3, 0.0, 1.0) * clamp(dot(lR, vVec)*2.0-1.2, 0.0, 1.0) * SCATTER_AMOUNT * sunFade * clamp(1.0-exp(-sunHeight), 0.0, 1.0); + gl_FragData[0].xyz = mix( mix(refraction, scatterColour, lightScatter), reflection, fresnel) + specular * gl_LightSource[0].specular.xyz + vec3(rainRipple.w) * 0.2; + gl_FragData[0].w = 1.0; #else - gl_FragData[0].xyz = mix(reflection, waterColor, (1.0-fresnel)*0.5) + specular * gl_LightSource[0].specular.xyz; + gl_FragData[0].xyz = mix(reflection, waterColor, (1.0-fresnel)*0.5) + specular * gl_LightSource[0].specular.xyz + vec3(rainRipple.w) * 0.7; + gl_FragData[0].w = clamp(fresnel*6.0 + specular * gl_LightSource[0].specular.w, 0.0, 1.0); //clamp(fresnel*2.0 + specular * gl_LightSource[0].specular.w, 0.0, 1.0); #endif + // fog float fogValue = clamp((depthPassthrough - gl_Fog.start) * gl_Fog.scale, 0.0, 1.0); gl_FragData[0].xyz = mix(gl_FragData[0].xyz, gl_Fog.color.xyz, fogValue); -#if REFRACTION - gl_FragData[0].xyz += vec3(rainRipple.w) * 0.2; -#else - gl_FragData[0].xyz += vec3(rainRipple.w) * 0.7; -#endif - -#if REFRACTION - gl_FragData[0].w = 1.0; -#else - gl_FragData[0].w = clamp(fresnel*6.0 + specular * gl_LightSource[0].specular.w, 0.0, 1.0); //clamp(fresnel*2.0 + specular * gl_LightSource[0].specular.w, 0.0, 1.0); -#endif - applyShadowDebugOverlay(); } diff --git a/files/shaders/water_vertex.glsl b/files/shaders/water_vertex.glsl index 575f8f3c2f..2377f0af4b 100644 --- a/files/shaders/water_vertex.glsl +++ b/files/shaders/water_vertex.glsl @@ -16,7 +16,7 @@ void main(void) 0.5, 0.5, 0.5, 1.0); vec4 texcoordProj = ((scalemat) * ( gl_Position)); - screenCoordsPassthrough = vec3(texcoordProj.x, texcoordProj.y, texcoordProj.w); + screenCoordsPassthrough = texcoordProj.xyw; position = gl_Vertex; From 8f2ed884a54b58d885bd2f9db55aaa159a497918 Mon Sep 17 00:00:00 2001 From: capostrophic Date: Sun, 18 Aug 2019 19:43:26 +0300 Subject: [PATCH 02/48] Allow usage of more keywords as string arguments (bug #5087) --- CHANGELOG.md | 1 + components/compiler/stringparser.cpp | 17 +++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74ad52cd72..5fe3e190e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -118,6 +118,7 @@ Bug #5075: Enchanting cast style can be changed if there's no object Bug #5078: DisablePlayerLooking is broken Bug #5082: Scrolling with controller in GUI mode is broken + Bug #5087: Some valid script names can't be used as string arguments Bug #5089: Swimming/Underwater creatures only swim around ground level Bug #5092: NPCs with enchanted weapons play sound when out of charges Bug #5093: Hand to hand sound plays on knocked out enemies diff --git a/components/compiler/stringparser.cpp b/components/compiler/stringparser.cpp index 8041b0f024..ad88bb857b 100644 --- a/components/compiler/stringparser.cpp +++ b/components/compiler/stringparser.cpp @@ -56,6 +56,23 @@ namespace Compiler } } + if (keyword==Scanner::K_end || keyword==Scanner::K_begin || + keyword==Scanner::K_short || keyword==Scanner::K_long || + keyword==Scanner::K_float || keyword==Scanner::K_if || + keyword==Scanner::K_endif || keyword==Scanner::K_else || + keyword==Scanner::K_elseif || keyword==Scanner::K_while || + keyword==Scanner::K_endwhile || keyword==Scanner::K_return || + keyword==Scanner::K_messagebox || keyword==Scanner::K_set || + keyword==Scanner::K_to || keyword==Scanner::K_startscript || + keyword==Scanner::K_stopscript || keyword==Scanner::K_enable || + keyword==Scanner::K_disable || keyword==Scanner::K_getdisabled || + keyword==Scanner::K_getdistance || keyword==Scanner::K_scriptrunning || + keyword==Scanner::K_getsquareroot || keyword==Scanner::K_menumode || + keyword==Scanner::K_random || keyword==Scanner::K_getsecondspassed) + { + return parseName (loc.mLiteral, loc, scanner); + } + return Parser::parseKeyword (keyword, loc, scanner); } From 56b6a7ada490662c4b5af5e98aace2d1180920f1 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Mon, 9 Sep 2019 22:29:59 +0200 Subject: [PATCH 03/48] Fix #5155 --- CHANGELOG.md | 1 + apps/openmw/mwclass/container.cpp | 3 ++- apps/openmw/mwmechanics/security.cpp | 3 +-- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa84ec10ae..32254d65b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,7 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime + Bug #5155: Shouldn't be able to magically lock organic containers Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 2b36f23390..b7da1960e3 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -321,7 +321,8 @@ namespace MWClass bool Container::canLock(const MWWorld::ConstPtr &ptr) const { - return true; + const MWWorld::LiveCellRef *ref = ptr.get(); + return !(ref->mBase->mFlags & ESM::Container::Organic); } MWWorld::Ptr Container::copyToCellImpl(const MWWorld::ConstPtr &ptr, MWWorld::CellStore &cell) const diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index d09355ccab..65fab88197 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -29,8 +29,7 @@ namespace MWMechanics std::string& resultMessage, std::string& resultSound) { if (lock.getCellRef().getLockLevel() <= 0 || - lock.getCellRef().getLockLevel() == ESM::UnbreakableLock || - !lock.getClass().canLock(lock)) //If it's unlocked or can not be unlocked back out immediately + lock.getCellRef().getLockLevel() == ESM::UnbreakableLock) //If it's unlocked or can not be unlocked back out immediately return; int lockStrength = lock.getCellRef().getLockLevel(); From d6722c74928d960fb45b14a25b8f6c54bd87133e Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 7 Apr 2019 11:10:02 +0300 Subject: [PATCH 04/48] Terrain texture selection, support for vertex selection --- CHANGELOG.md | 1 + apps/opencs/CMakeLists.txt | 2 +- .../view/render/pagedworldspacewidget.cpp | 2 +- apps/opencs/view/render/terrainselection.cpp | 271 ++++++++++++++++ apps/opencs/view/render/terrainselection.hpp | 75 +++++ .../opencs/view/render/terraintexturemode.cpp | 288 ++++++++++++++---- .../opencs/view/render/terraintexturemode.hpp | 25 +- 7 files changed, 610 insertions(+), 54 deletions(-) create mode 100644 apps/opencs/view/render/terrainselection.cpp create mode 100644 apps/opencs/view/render/terrainselection.hpp diff --git a/CHANGELOG.md b/CHANGELOG.md index fa84ec10ae..f8beb82cbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -143,6 +143,7 @@ Feature #3025: Analogue gamepad movement controls Feature #3442: Default values for fallbacks from ini file Feature #3610: Option to invert X axis + Feature #3871: Editor: Terrain Selection Feature #3893: Implicit target for "set" function in console Feature #3980: In-game option to disable controller Feature #3999: Shift + Double Click should maximize/restore menu size diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index b0bd95eb95..00855dad0c 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -89,7 +89,7 @@ opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget previewwidget editmode instancemode instanceselectionmode instancemovemode orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller - cellwater terraintexturemode actor + cellwater terraintexturemode actor terrainselection ) opencs_units_noqt (view/render diff --git a/apps/opencs/view/render/pagedworldspacewidget.cpp b/apps/opencs/view/render/pagedworldspacewidget.cpp index 7f31373ee8..540a15dd10 100644 --- a/apps/opencs/view/render/pagedworldspacewidget.cpp +++ b/apps/opencs/view/render/pagedworldspacewidget.cpp @@ -140,7 +140,7 @@ void CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons ( new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain shape editing"), "terrain-shape"); tool->addButton ( - new TerrainTextureMode (this, tool), + new TerrainTextureMode (this, mRootNode, tool), "terrain-texture"); tool->addButton ( new EditMode (this, QIcon (":placeholder"), Mask_Reference, "Terrain vertex paint editing"), diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp new file mode 100644 index 0000000000..5725a35c08 --- /dev/null +++ b/apps/opencs/view/render/terrainselection.cpp @@ -0,0 +1,271 @@ +#include "terrainselection.hpp" + +#include + +#include +#include +#include + +#include + +#include "../../model/world/cellcoordinates.hpp" +#include "../../model/world/columnimp.hpp" +#include "../../model/world/idtable.hpp" + +#include "cell.hpp" +#include "worldspacewidget.hpp" + +namespace +{ + const int cellSize {ESM::Land::REAL_SIZE}; + const int landSize {ESM::Land::LAND_SIZE}; + const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; +} + +CSVRender::TerrainSelection::TerrainSelection(osg::Group* parentNode, WorldspaceWidget *worldspaceWidget, TerrainSelectionType type): +mParentNode(parentNode), mWorldspaceWidget (worldspaceWidget), mDraggedOperationFlag(false), mSelectionType(type) +{ + mGeometry = new osg::Geometry(); + + mSelectionNode = new osg::Group(); + mSelectionNode->addChild(mGeometry); + + activate(); +} + +CSVRender::TerrainSelection::~TerrainSelection() +{ + deactivate(); +} + +std::vector> CSVRender::TerrainSelection::getTerrainSelection() const +{ + return mSelection; +} + +void CSVRender::TerrainSelection::onlySelect(const std::vector> localPositions) +{ + mSelection.clear(); + for(auto const& value: localPositions) + { + mSelection.emplace_back(value); + } + update(); +} + +void CSVRender::TerrainSelection::addSelect(const std::pair localPos) +{ + if (std::find(mSelection.begin(), mSelection.end(), localPos) == mSelection.end()) + mSelection.emplace_back(localPos); + update(); +} + +void CSVRender::TerrainSelection::toggleSelect(const std::vector> localPositions, bool toggleInProgress) +{ + if (toggleInProgress == true) + { + for(auto const& localPos: localPositions) + { + auto iter = std::find(mSelection.begin(), mSelection.end(), localPos); + auto itertemp = std::find(mTemporarySelection.begin(), mTemporarySelection.end(), localPos); + mDraggedOperationFlag = true; + + if (itertemp == mTemporarySelection.end()) + { + if (iter != mSelection.end()) + { + mSelection.erase(iter); + } + else + { + mSelection.emplace_back(localPos); + } + } + + mTemporarySelection.push_back(localPos); + } + } + else if (mDraggedOperationFlag == false) + { + for(auto const& localPos: localPositions) + { + const auto iter = std::find(mSelection.begin(), mSelection.end(), localPos); + if (iter != mSelection.end()) + { + mSelection.erase(iter); + } + else + { + mSelection.emplace_back(localPos); + } + } + } + else + { + mDraggedOperationFlag = false; + mTemporarySelection.clear(); + } + update(); +} + +void CSVRender::TerrainSelection::activate() +{ + mParentNode->addChild(mSelectionNode); +} + +void CSVRender::TerrainSelection::deactivate() +{ + mParentNode->removeChild(mSelectionNode); +} + +void CSVRender::TerrainSelection::update() +{ + mSelectionNode->removeChild(mGeometry); + mGeometry = new osg::Geometry(); + + const osg::ref_ptr vertices (new osg::Vec3Array); + + switch (mSelectionType) + { + case TerrainSelectionType::Texture : drawTextureSelection(vertices); + break; + case TerrainSelectionType::Shape : drawShapeSelection(vertices); + break; + } + + mGeometry->setVertexArray(vertices); + osg::ref_ptr drawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES); + drawArrays->setCount(vertices->size()); + mGeometry->addPrimitiveSet(drawArrays); + mSelectionNode->addChild(mGeometry); +} + +void CSVRender::TerrainSelection::drawShapeSelection(const osg::ref_ptr vertices) +{ + if (!mSelection.empty()) + { + for (std::pair localPos : mSelection) + { + int x (localPos.first); + int y (localPos.second); + + float xWorldCoord(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(x)); + float yWorldCoord(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(y)); + + osg::Vec3f pointXY(xWorldCoord, yWorldCoord, calculateLandHeight(x, y) + 2); + + vertices->push_back(pointXY); + vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(y - 1), calculateLandHeight(x, y - 1) + 2)); + vertices->push_back(pointXY); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(x - 1), yWorldCoord, calculateLandHeight(x - 1, y) + 2)); + + const auto north = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x, y + 1)); + if (north == mSelection.end()) + { + vertices->push_back(pointXY); + vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(y + 1), calculateLandHeight(x, y + 1) + 2)); + } + + const auto east = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x + 1, y)); + if (east == mSelection.end()) + { + vertices->push_back(pointXY); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(x + 1), yWorldCoord, calculateLandHeight(x + 1, y) + 2)); + } + } + } +} + +void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr vertices) +{ + if (!mSelection.empty()) + { + + // Nudge selection by 1/4th of a texture size, similar how blendmaps are nudged + const float nudgePercentage = 0.25f; + const int nudgeOffset = (cellSize / landTextureSize) * nudgePercentage; + const int landHeightsNudge = (cellSize / landSize) / (landSize - 1); // Does this work with all land size configurations? + + const int textureSizeToLandSizeModifier = (landSize - 1) / landTextureSize; + + for (std::pair localPos : mSelection) + { + int x (localPos.first); + int y (localPos.second); + + // convert texture selection to global vertex coordinates at selection box corners + int x1 = x * textureSizeToLandSizeModifier + landHeightsNudge; + int x2 = x * textureSizeToLandSizeModifier + textureSizeToLandSizeModifier + landHeightsNudge; + int y1 = y * textureSizeToLandSizeModifier - landHeightsNudge; + int y2 = y * textureSizeToLandSizeModifier + textureSizeToLandSizeModifier - landHeightsNudge; + + // Draw edges (check all sides, draw lines between vertices, +1 height to keep lines above ground) + // Check adjancent selections, draw lines only to edges of the selection + const auto north = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x, y + 1)); + if (north == mSelection.end()) + { + for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) + { + float drawPreviousX = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x)+(i-1)*(cellSize / (landSize - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x)+i*(cellSize / (landSize - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); + } + } + + const auto south = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x, y - 1)); + if (south == mSelection.end()) + { + for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) + { + float drawPreviousX = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x)+(i-1)*(cellSize / (landSize - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x)+i*(cellSize / (landSize - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); + } + } + + const auto east = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x + 1, y)); + if (east == mSelection.end()) + { + for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) + { + float drawPreviousY = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y)+(i-1)*(cellSize / (landSize - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y)+i*(cellSize / (landSize - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); + } + } + + const auto west = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x - 1, y)); + if (west == mSelection.end()) + { + for(int i = 1; i < (textureSizeToLandSizeModifier + 1); i++) + { + float drawPreviousY = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y)+(i-1)*(cellSize / (landSize - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y)+i*(cellSize / (landSize - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); + } + } + } + } +} + +int CSVRender::TerrainSelection::calculateLandHeight(int x, int y) // global vertex coordinates +{ + int cellX = std::floor((1.0f*x / (landSize - 1))); + int cellY = std::floor((1.0f*y / (landSize - 1))); + int localX = x - cellX * (landSize - 1); + int localY = y - cellY * (landSize - 1); + + std::string cellId = CSMWorld::CellCoordinates::generateId(cellX, cellY); + + CSMDoc::Document& document = mWorldspaceWidget->getDocument(); + CSMWorld::IdTable& landTable = dynamic_cast ( + *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); + int landshapeColumn = landTable.findColumnIndex(CSMWorld::Columns::ColumnId_LandHeightsIndex); + const CSMWorld::LandHeightsColumn::DataType mPointer = landTable.data(landTable.getModelIndex(cellId, landshapeColumn)).value(); + + return mPointer[localY*landSize + localX]; +} diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp new file mode 100644 index 0000000000..02916fa937 --- /dev/null +++ b/apps/opencs/view/render/terrainselection.hpp @@ -0,0 +1,75 @@ +#ifndef CSV_RENDER_TERRAINSELECTION_H +#define CSV_RENDER_TERRAINSELECTION_H + +#include +#include + +#include +#include +#include + +#include +#include "../../model/world/cellcoordinates.hpp" + +namespace osg +{ + class Group; +} + +namespace CSVRender +{ + struct WorldspaceHitResult; + class WorldspaceWidget; + + enum class TerrainSelectionType + { + Texture, + Shape + }; + + /// \brief Class handling the terrain selection data and rendering + class TerrainSelection + { + + public: + + TerrainSelection(osg::Group* parentNode, WorldspaceWidget *worldspaceWidget, TerrainSelectionType type); + ~TerrainSelection(); + + void onlySelect(const std::vector> localPositions); + void addSelect(const std::pair localPos); + void toggleSelect(const std::vector> localPositions, bool); + + void activate(); + void deactivate(); + + std::vector> getTerrainSelection() const; + + protected: + + void addToSelection(osg::Vec3d worldPos); + void toggleSelection(osg::Vec3d worldPos); + void deselect(); + + void update(); + + void drawShapeSelection(const osg::ref_ptr vertices); + void drawTextureSelection(const osg::ref_ptr vertices); + + int calculateLandHeight(int x, int y); + + private: + + osg::Group* mParentNode; + WorldspaceWidget *mWorldspaceWidget; + osg::ref_ptr mBaseNode; + osg::ref_ptr mGeometry; + osg::ref_ptr mSelectionNode; + std::vector> mSelection; // Global terrain selection coordinate in either vertex or texture units + std::vector> mTemporarySelection; // Used during toggle to compare the most recent drag operation + bool mDraggedOperationFlag; //true during drag operation, false when click-operation + TerrainSelectionType mSelectionType; + }; +} + +#endif diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 4205188e40..82737e9283 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -10,6 +10,8 @@ #include #include +#include + #include #include "../widget/modebutton.hpp" @@ -34,14 +36,18 @@ #include "pagedworldspacewidget.hpp" #include "mask.hpp" #include "object.hpp" // Something small needed regarding pointers from here () +#include "terrainselection.hpp" #include "worldspacewidget.hpp" -CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, QWidget *parent) +CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent) : EditMode (worldspaceWidget, QIcon {":scenetoolbar/editing-terrain-texture"}, Mask_Terrain | Mask_Reference, "Terrain texture editing", parent), mBrushTexture("L0#0"), mBrushSize(0), mBrushShape(0), - mTextureBrushScenetool(0) + mTextureBrushScenetool(0), + mDragMode(InteractionType_None), + mParentNode(parentNode), + mIsEditing(false) { } @@ -62,6 +68,11 @@ void CSVRender::TerrainTextureMode::activate(CSVWidget::SceneToolbar* toolbar) connect(this, SIGNAL(passBrushTexture(std::string)), mTextureBrushScenetool, SLOT(updateBrushHistory(std::string))); } + if (!mTerrainTextureSelection) + { + mTerrainTextureSelection.reset(new TerrainSelection(mParentNode, &getWorldspaceWidget(), TerrainSelectionType::Texture)); + } + EditMode::activate(toolbar); toolbar->addTool (mTextureBrushScenetool); } @@ -74,6 +85,12 @@ void CSVRender::TerrainTextureMode::deactivate(CSVWidget::SceneToolbar* toolbar) delete mTextureBrushScenetool; mTextureBrushScenetool = 0; } + + if (mTerrainTextureSelection) + { + mTerrainTextureSelection.reset(); + } + EditMode::deactivate(toolbar); } @@ -95,7 +112,7 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); int index = landtexturesCollection.searchId(mBrushTexture); - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true) + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) { undoStack.beginMacro ("Edit texture records"); if(allowLandTextureEditing(mCellId)==true) @@ -109,10 +126,18 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult void CSVRender::TerrainTextureMode::primarySelectPressed(const WorldspaceHitResult& hit) { + if(hit.hit && hit.tag == 0) + { + selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 0, false); + } } void CSVRender::TerrainTextureMode::secondarySelectPressed(const WorldspaceHitResult& hit) { + if(hit.hit && hit.tag == 0) + { + selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 1, false); + } } bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) @@ -129,13 +154,16 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) QUndoStack& undoStack = document.getUndoStack(); + mDragMode = InteractionType_PrimaryEdit; + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); int index = landtexturesCollection.searchId(mBrushTexture); - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) { undoStack.beginMacro ("Edit texture records"); - if(allowLandTextureEditing(mCellId)==true && hit.hit == true) + mIsEditing = true; + if(allowLandTextureEditing(mCellId)==true) { undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); @@ -152,47 +180,91 @@ bool CSVRender::TerrainTextureMode::secondaryEditStartDrag (const QPoint& pos) bool CSVRender::TerrainTextureMode::primarySelectStartDrag (const QPoint& pos) { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + mDragMode = InteractionType_PrimarySelect; + if (!hit.hit || hit.tag != 0) + { + mDragMode = InteractionType_None; + return false; + } + selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 0, true); return false; } bool CSVRender::TerrainTextureMode::secondarySelectStartDrag (const QPoint& pos) { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + mDragMode = InteractionType_SecondarySelect; + if (!hit.hit || hit.tag != 0) + { + mDragMode = InteractionType_None; + return false; + } + selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 1, true); return false; } void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diffY, double speedFactor) { - WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); - CSMDoc::Document& document = getWorldspaceWidget().getDocument(); - - CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); - int index = landtexturesCollection.searchId(mBrushTexture); - - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit == true) + if (mDragMode == InteractionType_PrimaryEdit) { - editTerrainTextureGrid(hit); + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + std::string cellId = getWorldspaceWidget().getCellId (hit.worldPos); + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) + { + editTerrainTextureGrid(hit); + } + } + + if (mDragMode == InteractionType_PrimarySelect) + { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + if (hit.hit && hit.tag == 0) selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 0, true); + } + + if (mDragMode == InteractionType_SecondarySelect) + { + WorldspaceHitResult hit = getWorldspaceWidget().mousePick (pos, getWorldspaceWidget().getInteractionMask()); + if (hit.hit && hit.tag == 0) selectTerrainTextures(CSMWorld::CellCoordinates::toTextureCoords(hit.worldPos), 1, true); } } -void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) { - CSMDoc::Document& document = getWorldspaceWidget().getDocument(); - QUndoStack& undoStack = document.getUndoStack(); - - CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); - int index = landtexturesCollection.searchId(mBrushTexture); - - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) +void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) +{ + if (mDragMode == InteractionType_PrimaryEdit) { - undoStack.endMacro(); + CSMDoc::Document& document = getWorldspaceWidget().getDocument(); + QUndoStack& undoStack = document.getUndoStack(); + + CSMWorld::IdCollection& landtexturesCollection = document.getData().getLandTextures(); + int index = landtexturesCollection.searchId(mBrushTexture); + + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) + { + if (mIsEditing == true) + { + undoStack.endMacro(); + mIsEditing = false; + } + } } } -void CSVRender::TerrainTextureMode::dragAborted() { +void CSVRender::TerrainTextureMode::dragAborted() +{ } -void CSVRender::TerrainTextureMode::dragWheel (int diff, double speedFactor) {} +void CSVRender::TerrainTextureMode::dragWheel (int diff, double speedFactor) +{ +} -void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) { +void CSVRender::TerrainTextureMode::handleDropEvent (QDropEvent *event) +{ const CSMWorld::TableMimeData* mime = dynamic_cast (event->mimeData()); if (!mime) // May happen when non-records (e.g. plain text) are dragged and dropped @@ -236,8 +308,8 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe int cellY = cellCoordinates_pair.first.getY(); // The coordinates of hit in mCellId - int xHitInCell (float(((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize) - 0.5)); - int yHitInCell (float(((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize) + 0.5)); + int xHitInCell (float(((hit.worldPos.x() - (cellX* cellSize)) * landTextureSize / cellSize) - 0.25)); + int yHitInCell (float(((hit.worldPos.y() - (cellY* cellSize)) * landTextureSize / cellSize) + 0.25)); if (xHitInCell < 0) { xHitInCell = xHitInCell + landTextureSize; @@ -249,7 +321,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe cellY = cellY + 1; } - mCellId = "#" + std::to_string(cellX) + " " + std::to_string(cellY); + mCellId = CSMWorld::CellCoordinates::generateId(cellX, cellY); if(allowLandTextureEditing(mCellId)==true) {} std::string iteratedCellId; @@ -266,13 +338,13 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe if (mBrushShape == 0) { - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); if(allowLandTextureEditing(mCellId)==true) { - mNew[yHitInCell*landTextureSize+xHitInCell] = brushInt; - pushEditToCommand(mNew, document, landTable, mCellId); + newTerrain[yHitInCell*landTextureSize+xHitInCell] = brushInt; + pushEditToCommand(newTerrain, document, landTable, mCellId); } } @@ -292,19 +364,19 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { - iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); + iteratedCellId = CSMWorld::CellCoordinates::generateId(i_cell, j_cell); if(allowLandTextureEditing(iteratedCellId)==true) { - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); for(int i = 0; i < landTextureSize; i++) { for(int j = 0; j < landTextureSize; j++) { - if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) + if (i_cell == cellX && j_cell == cellY && abs(i-xHitInCell) < r && abs(j-yHitInCell) < r) { - mNew[j*landTextureSize+i] = brushInt; + newTerrain[j*landTextureSize+i] = brushInt; } else { @@ -316,11 +388,11 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe if (j_cell > cellY) distanceY = -yHitInCell + landTextureSize * abs(j_cell-cellY) + j; if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); - if (distanceX < r && distanceY < r) mNew[j*landTextureSize+i] = brushInt; + if (distanceX < r && distanceY < r) newTerrain[j*landTextureSize+i] = brushInt; } } } - pushEditToCommand(mNew, document, landTable, iteratedCellId); + pushEditToCommand(newTerrain, document, landTable, iteratedCellId); } } } @@ -342,11 +414,11 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe { for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { - iteratedCellId = "#" + std::to_string(i_cell) + " " + std::to_string(j_cell); + iteratedCellId = CSMWorld::CellCoordinates::generateId(i_cell, j_cell); if(allowLandTextureEditing(iteratedCellId)==true) { - CSMWorld::LandTexturesColumn::DataType mPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); - CSMWorld::LandTexturesColumn::DataType mNew(mPointer); + CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); for(int i = 0; i < landTextureSize; i++) { for(int j = 0; j < landTextureSize; j++) @@ -363,7 +435,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt; } else { @@ -376,11 +448,11 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe if (i_cell == cellX) distanceX = abs(i-xHitInCell); if (j_cell == cellY) distanceY = abs(j-yHitInCell); distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < rf) mNew[j*landTextureSize+i] = brushInt; + if (distance < rf) newTerrain[j*landTextureSize+i] = brushInt; } } } - pushEditToCommand(mNew, document, landTable, iteratedCellId); + pushEditToCommand(newTerrain, document, landTable, iteratedCellId); } } } @@ -388,9 +460,87 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe if (mBrushShape == 3) { - // Not implemented + CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); + + if(allowLandTextureEditing(mCellId)==true && !mCustomBrushShape.empty()) + { + for(auto const& value: mCustomBrushShape) + { + if(yHitInCell + value.second >= 0 && yHitInCell + value.second <= 15 && xHitInCell + value.first >= 0 && xHitInCell + value.first <= 15) + { + newTerrain[(yHitInCell+value.second)*landTextureSize+xHitInCell+value.first] = brushInt; + } + else + { + int cellXDifference = std::floor(1.0f*(xHitInCell + value.first)/landTextureSize); + int cellYDifference = std::floor(1.0f*(yHitInCell + value.second)/landTextureSize); + int xInOtherCell = xHitInCell + value.first - cellXDifference * landTextureSize; + int yInOtherCell = yHitInCell + value.second - cellYDifference * landTextureSize; + + std::string cellId = CSMWorld::CellCoordinates::generateId(cellX+cellXDifference, cellY+cellYDifference); + if (allowLandTextureEditing(cellId)==true) + { + CSMWorld::LandTexturesColumn::DataType newTerrainPointerOtherCell = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); + CSMWorld::LandTexturesColumn::DataType newTerrainOtherCell(newTerrainPointerOtherCell); + newTerrainOtherCell[yInOtherCell*landTextureSize+xInOtherCell] = brushInt; + pushEditToCommand(newTerrainOtherCell, document, landTable, cellId); + } + } + } + pushEditToCommand(newTerrain, document, landTable, mCellId); + } + } +} + +void CSVRender::TerrainTextureMode::selectTerrainTextures(std::pair texCoords, unsigned char selectMode, bool dragOperation) +{ + int r = mBrushSize / 2; + std::vector> selections; + + if (mBrushShape == 0) + { + selections.emplace_back(texCoords); } + if (mBrushShape == 1) + { + for(int i = texCoords.first - r; i <= texCoords.first + r; ++i) + { + for(int j = texCoords.second - r; j <= texCoords.second + r; ++j) + { + selections.emplace_back(std::make_pair(i, j)); + } + } + } + + if (mBrushShape == 2) + { + for(int i = texCoords.first - r; i <= texCoords.first + r; ++i) + { + for(int j = texCoords.second - r; j <= texCoords.second + r; ++j) + { + int distanceX = abs(i - texCoords.first); + int distanceY = abs(j - texCoords.second); + int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); + if (distance < r) selections.emplace_back(std::make_pair(i, j)); + } + } + } + + if (mBrushShape == 3) + { + if(!mCustomBrushShape.empty()) + { + for(auto const& value: mCustomBrushShape) + { + selections.emplace_back(std::make_pair(texCoords.first + value.first, texCoords.second + value.second)); + } + } + } + + if(selectMode == 0) mTerrainTextureSelection->onlySelect(selections); + if(selectMode == 1) mTerrainTextureSelection->toggleSelect(selections, dragOperation); } void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, @@ -405,8 +555,8 @@ void CSVRender::TerrainTextureMode::pushEditToCommand(CSMWorld::LandTexturesColu QModelIndex index(landTable.getModelIndex (cellId, landTable.findColumnIndex (CSMWorld::Columns::ColumnId_LandTexturesIndex))); QUndoStack& undoStack = document.getUndoStack(); - undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); undoStack.push (new CSMWorld::ModifyCommand(landTable, index, changedLand)); + undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, cellId)); } void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) @@ -422,18 +572,21 @@ void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) int counter=0; bool freeIndexFound = false; - do { + do + { const size_t maxCounter = std::numeric_limits::max() - 1; try { newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); if (ltexTable.getRecord(newId).isDeleted() == 0) counter = (counter + 1) % maxCounter; - } catch (const std::exception& e) + } + catch (const std::exception& e) { newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); freeIndexFound = true; } - } while (freeIndexFound == false); + } + while (freeIndexFound == false); std::size_t idlocation = textureFileName.find("Texture: "); textureFileName = textureFileName.substr (idlocation + 9); @@ -527,7 +680,8 @@ bool CSVRender::TerrainTextureMode::allowLandTextureEditing(std::string cellId) return true; } -void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) { +void CSVRender::TerrainTextureMode::dragMoveEvent (QDragMoveEvent *event) +{ } void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) @@ -538,9 +692,41 @@ void CSVRender::TerrainTextureMode::setBrushSize(int brushSize) void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) { mBrushShape = brushShape; + + //Set custom brush shape + if (mBrushShape == 3 && !mTerrainTextureSelection->getTerrainSelection().empty()) + { + auto terrainSelection = mTerrainTextureSelection->getTerrainSelection(); + int selectionCenterX = 0; + int selectionCenterY = 0; + int selectionAmount = 0; + + for(auto const& value: terrainSelection) + { + selectionCenterX = selectionCenterX + value.first; + selectionCenterY = selectionCenterY + value.second; + ++selectionAmount; + } + selectionCenterX = selectionCenterX / selectionAmount; + selectionCenterY = selectionCenterY / selectionAmount; + + mCustomBrushShape.clear(); + std::pair differentialPos {}; + for(auto const& value: terrainSelection) + { + differentialPos.first = value.first - selectionCenterX; + differentialPos.second = value.second - selectionCenterY; + mCustomBrushShape.push_back(differentialPos); + } + } } void CSVRender::TerrainTextureMode::setBrushTexture(std::string brushTexture) { mBrushTexture = brushTexture; } + +CSVRender::PagedWorldspaceWidget& CSVRender::TerrainTextureMode::getPagedWorldspaceWidget() +{ + return dynamic_cast(getWorldspaceWidget()); +} diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 10ea842c98..81669ed74f 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -4,6 +4,7 @@ #include "editmode.hpp" #include +#include #include #include @@ -18,6 +19,8 @@ #include "../../model/world/landtexture.hpp" #endif +#include "terrainselection.hpp" + namespace CSVWidget { class SceneToolTextureBrush; @@ -25,6 +28,7 @@ namespace CSVWidget namespace CSVRender { + class PagedWorldspaceWidget; class TerrainTextureMode : public EditMode { @@ -32,8 +36,17 @@ namespace CSVRender public: + enum InteractionType + { + InteractionType_PrimaryEdit, + InteractionType_PrimarySelect, + InteractionType_SecondaryEdit, + InteractionType_SecondarySelect, + InteractionType_None + }; + /// \brief Editmode for terrain texture grid - TerrainTextureMode(WorldspaceWidget*, QWidget* parent = nullptr); + TerrainTextureMode(WorldspaceWidget*, osg::Group* parentNode, QWidget* parent = nullptr); void primaryOpenPressed (const WorldspaceHitResult& hit); @@ -68,6 +81,9 @@ namespace CSVRender /// \brief Handle brush mechanics, maths regarding worldspace hit etc. void editTerrainTextureGrid (const WorldspaceHitResult& hit); + /// \brief Handle brush mechanics for texture selection + void selectTerrainTextures (std::pair, unsigned char, bool); + /// \brief Push texture edits to command macro void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, CSMWorld::IdTable& landTable, std::string cellId); @@ -83,12 +99,19 @@ namespace CSVRender std::string mBrushTexture; int mBrushSize; int mBrushShape; + std::vector> mCustomBrushShape; CSVWidget::SceneToolTextureBrush *mTextureBrushScenetool; + int mDragMode; + osg::Group* mParentNode; + bool mIsEditing; + std::unique_ptr mTerrainTextureSelection; const int cellSize {ESM::Land::REAL_SIZE}; const int landSize {ESM::Land::LAND_SIZE}; const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; + PagedWorldspaceWidget& getPagedWorldspaceWidget(); + signals: void passBrushTexture(std::string brushTexture); From 1a08944a8b04eecbf61c47ee7f3d3565782d8065 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 7 Apr 2019 20:58:03 +0300 Subject: [PATCH 05/48] Remove unused code, clarifications, optimizations --- apps/opencs/view/render/terrainselection.cpp | 6 +-- .../opencs/view/render/terraintexturemode.cpp | 38 +++++++------------ .../opencs/view/render/terraintexturemode.hpp | 2 - 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 5725a35c08..8fd0d8aed7 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -66,12 +66,12 @@ void CSVRender::TerrainSelection::toggleSelect(const std::vector& landtexturesCollection = document.getData().getLandTextures(); int index = landtexturesCollection.searchId(mBrushTexture); - if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) + if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) { undoStack.beginMacro ("Edit texture records"); if(allowLandTextureEditing(mCellId)==true) @@ -505,25 +505,24 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(std::pair te if (mBrushShape == 1) { - for(int i = texCoords.first - r; i <= texCoords.first + r; ++i) + for (int i = -r; i <= r; i++) { - for(int j = texCoords.second - r; j <= texCoords.second + r; ++j) + for (int j = -r; j <= r; j++) { - selections.emplace_back(std::make_pair(i, j)); + selections.emplace_back(i + texCoords.first, j + texCoords.second); } } } if (mBrushShape == 2) { - for(int i = texCoords.first - r; i <= texCoords.first + r; ++i) + for (int i = -r; i <= r; i++) { - for(int j = texCoords.second - r; j <= texCoords.second + r; ++j) + for (int j = -r; j <= r; j++) { - int distanceX = abs(i - texCoords.first); - int distanceY = abs(j - texCoords.second); - int distance = std::round(sqrt(pow(distanceX, 2)+pow(distanceY, 2))); - if (distance < r) selections.emplace_back(std::make_pair(i, j)); + osg::Vec2f coords(i,j); + if (std::round(coords.length()) < r) + selections.emplace_back(i + texCoords.first, j + texCoords.second); } } } @@ -534,7 +533,7 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(std::pair te { for(auto const& value: mCustomBrushShape) { - selections.emplace_back(std::make_pair(texCoords.first + value.first, texCoords.second + value.second)); + selections.emplace_back(texCoords.first + value.first, texCoords.second + value.second); } } } @@ -585,8 +584,7 @@ void CSVRender::TerrainTextureMode::createTexture(std::string textureFileName) newId = CSMWorld::LandTexture::createUniqueRecordId(0, counter); freeIndexFound = true; } - } - while (freeIndexFound == false); + } while (freeIndexFound == false); std::size_t idlocation = textureFileName.find("Texture: "); textureFileName = textureFileName.substr (idlocation + 9); @@ -711,13 +709,8 @@ void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) selectionCenterY = selectionCenterY / selectionAmount; mCustomBrushShape.clear(); - std::pair differentialPos {}; - for(auto const& value: terrainSelection) - { - differentialPos.first = value.first - selectionCenterX; - differentialPos.second = value.second - selectionCenterY; - mCustomBrushShape.push_back(differentialPos); - } + for (auto const& value: terrainSelection) + mCustomBrushShape.emplace_back(value.first - selectionCenterX, value.second - selectionCenterY); } } @@ -725,8 +718,3 @@ void CSVRender::TerrainTextureMode::setBrushTexture(std::string brushTexture) { mBrushTexture = brushTexture; } - -CSVRender::PagedWorldspaceWidget& CSVRender::TerrainTextureMode::getPagedWorldspaceWidget() -{ - return dynamic_cast(getWorldspaceWidget()); -} diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 81669ed74f..1f18409b03 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -110,8 +110,6 @@ namespace CSVRender const int landSize {ESM::Land::LAND_SIZE}; const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; - PagedWorldspaceWidget& getPagedWorldspaceWidget(); - signals: void passBrushTexture(std::string brushTexture); From 20ab7df19fe6a2a7aa3b2f9c2c52b6cc187e95bd Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 7 Apr 2019 21:48:55 +0300 Subject: [PATCH 06/48] Fixes, cleanup. --- apps/opencs/view/render/terrainselection.cpp | 4 ++-- apps/opencs/view/render/terraintexturemode.hpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 8fd0d8aed7..ab94da3544 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -110,12 +110,12 @@ void CSVRender::TerrainSelection::toggleSelect(const std::vectoraddChild(mSelectionNode); + if (!mParentNode->containsNode(mSelectionNode)) mParentNode->addChild(mSelectionNode); } void CSVRender::TerrainSelection::deactivate() { - mParentNode->removeChild(mSelectionNode); + if (mParentNode->containsNode(mSelectionNode)) mParentNode->removeChild(mSelectionNode); } void CSVRender::TerrainSelection::update() diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 1f18409b03..72e7df9dee 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -6,6 +6,8 @@ #include #include +#include + #include #include @@ -28,8 +30,6 @@ namespace CSVWidget namespace CSVRender { - class PagedWorldspaceWidget; - class TerrainTextureMode : public EditMode { Q_OBJECT From 46ee6398925621f761ee110f9ddaae14decc5344 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sun, 7 Apr 2019 23:11:13 +0300 Subject: [PATCH 07/48] pass by const ref and other fixes --- apps/opencs/view/render/terrainselection.cpp | 8 +++++--- apps/opencs/view/render/terraintexturemode.cpp | 2 +- apps/opencs/view/render/terraintexturemode.hpp | 9 ++++++--- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index ab94da3544..359338c674 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -56,8 +56,10 @@ void CSVRender::TerrainSelection::onlySelect(const std::vector localPos) { if (std::find(mSelection.begin(), mSelection.end(), localPos) == mSelection.end()) - mSelection.emplace_back(localPos); - update(); + { + mSelection.emplace_back(localPos); + update(); + } } void CSVRender::TerrainSelection::toggleSelect(const std::vector> localPositions, bool toggleInProgress) @@ -115,7 +117,7 @@ void CSVRender::TerrainSelection::activate() void CSVRender::TerrainSelection::deactivate() { - if (mParentNode->containsNode(mSelectionNode)) mParentNode->removeChild(mSelectionNode); + mParentNode->removeChild(mSelectionNode); } void CSVRender::TerrainSelection::update() diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 8218d65965..ad13e80bee 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -493,7 +493,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } -void CSVRender::TerrainTextureMode::selectTerrainTextures(std::pair texCoords, unsigned char selectMode, bool dragOperation) +void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair& texCoords, unsigned char selectMode, bool dragOperation) { int r = mBrushSize / 2; std::vector> selections; diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 72e7df9dee..d2ad99aaf0 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -6,8 +6,6 @@ #include #include -#include - #include #include @@ -23,6 +21,11 @@ #include "terrainselection.hpp" +namespace osg +{ + class Group; +} + namespace CSVWidget { class SceneToolTextureBrush; @@ -82,7 +85,7 @@ namespace CSVRender void editTerrainTextureGrid (const WorldspaceHitResult& hit); /// \brief Handle brush mechanics for texture selection - void selectTerrainTextures (std::pair, unsigned char, bool); + void selectTerrainTextures (const std::pair& texCoords, unsigned char selectMode, bool dragOperation); /// \brief Push texture edits to command macro void pushEditToCommand (CSMWorld::LandTexturesColumn::DataType& newLandGrid, CSMDoc::Document& document, From 001ca68cc719436bedbe6a11109ba55d967ea1b2 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 8 Apr 2019 11:33:11 +0300 Subject: [PATCH 08/48] Remove empty lines --- apps/opencs/view/render/terrainselection.cpp | 1 - apps/opencs/view/render/terrainselection.hpp | 1 - 2 files changed, 2 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 359338c674..f7db31e1e6 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -182,7 +182,6 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr Date: Mon, 6 May 2019 12:22:16 +0300 Subject: [PATCH 09/48] Make less copies --- apps/opencs/view/render/terrainselection.cpp | 16 ++++++---------- apps/opencs/view/render/terrainselection.hpp | 6 +++--- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index f7db31e1e6..45b06e8f6e 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -43,17 +43,13 @@ std::vector> CSVRender::TerrainSelection::getTerrainSelectio return mSelection; } -void CSVRender::TerrainSelection::onlySelect(const std::vector> localPositions) +void CSVRender::TerrainSelection::onlySelect(const std::vector> &localPositions) { - mSelection.clear(); - for(auto const& value: localPositions) - { - mSelection.emplace_back(value); - } + mSelection = localPositions; update(); } -void CSVRender::TerrainSelection::addSelect(const std::pair localPos) +void CSVRender::TerrainSelection::addSelect(const std::pair &localPos) { if (std::find(mSelection.begin(), mSelection.end(), localPos) == mSelection.end()) { @@ -62,7 +58,7 @@ void CSVRender::TerrainSelection::addSelect(const std::pair localPos) } } -void CSVRender::TerrainSelection::toggleSelect(const std::vector> localPositions, bool toggleInProgress) +void CSVRender::TerrainSelection::toggleSelect(const std::vector> &localPositions, bool toggleInProgress) { if (toggleInProgress == true) { @@ -146,7 +142,7 @@ void CSVRender::TerrainSelection::drawShapeSelection(const osg::ref_ptr localPos : mSelection) + for (std::pair &localPos : mSelection) { int x (localPos.first); int y (localPos.second); @@ -189,7 +185,7 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr localPos : mSelection) + for (std::pair &localPos : mSelection) { int x (localPos.first); int y (localPos.second); diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp index 7a20bd87f2..ed4548fa7d 100644 --- a/apps/opencs/view/render/terrainselection.hpp +++ b/apps/opencs/view/render/terrainselection.hpp @@ -35,9 +35,9 @@ namespace CSVRender TerrainSelection(osg::Group* parentNode, WorldspaceWidget *worldspaceWidget, TerrainSelectionType type); ~TerrainSelection(); - void onlySelect(const std::vector> localPositions); - void addSelect(const std::pair localPos); - void toggleSelect(const std::vector> localPositions, bool); + void onlySelect(const std::vector> &localPositions); + void addSelect(const std::pair &localPos); + void toggleSelect(const std::vector> &localPositions, bool); void activate(); void deactivate(); From 39ab449431b77662d2ccc4aba1fbeb233c7ac47b Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 6 May 2019 12:56:04 +0300 Subject: [PATCH 10/48] Only allow selection of cells in view --- apps/opencs/model/world/cellcoordinates.cpp | 7 ++++ apps/opencs/model/world/cellcoordinates.hpp | 2 + .../opencs/view/render/terraintexturemode.cpp | 40 +++++++++++++++++-- .../opencs/view/render/terraintexturemode.hpp | 3 ++ 4 files changed, 48 insertions(+), 4 deletions(-) diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp index 1e545e38de..55adc3eff1 100644 --- a/apps/opencs/model/world/cellcoordinates.cpp +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -113,6 +113,13 @@ int CSMWorld::CellCoordinates::vertexSelectionToInCellCoords(int pos) return static_cast(pos - std::floor(static_cast(pos) / (landSize - 1)) * (landSize - 1)); } +std::string CSMWorld::CellCoordinates::textureGlobalToCellId(std::pair textureGlobal) +{ + int x = std::floor(static_cast(textureGlobal.first) / landTextureSize); + int y = std::floor(static_cast(textureGlobal.second) / landTextureSize); + return generateId(x, y); +} + std::string CSMWorld::CellCoordinates::vertexGlobalToCellId(std::pair vertexGlobal) { int x = std::floor(static_cast(vertexGlobal.first) / (landSize - 1)); diff --git a/apps/opencs/model/world/cellcoordinates.hpp b/apps/opencs/model/world/cellcoordinates.hpp index 3b21195174..c6c2c7ccd6 100644 --- a/apps/opencs/model/world/cellcoordinates.hpp +++ b/apps/opencs/model/world/cellcoordinates.hpp @@ -63,6 +63,8 @@ namespace CSMWorld ///Converts local cell's heightmap coordinates from the global vertex coordinate static int vertexSelectionToInCellCoords(int); + static std::string textureGlobalToCellId(std::pair); + ///Converts global vertex coordinates to cell id static std::string vertexGlobalToCellId(std::pair); }; diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index ad13e80bee..fae18f8c21 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -493,6 +493,21 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } +bool CSVRender::TerrainTextureMode::isInCellSelection(const int& globalSelectionX, const int& globalSelectionY) +{ + if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) + { + CSMWorld::CellSelection selection = paged->getCellSelection(); + if (selection.has (CSMWorld::CellCoordinates::fromId( + CSMWorld::CellCoordinates::textureGlobalToCellId(std::make_pair(globalSelectionX, globalSelectionY))).first)) + { + return true; + } + } + return false; +} + + void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair& texCoords, unsigned char selectMode, bool dragOperation) { int r = mBrushSize / 2; @@ -500,7 +515,7 @@ void CSVRender::TerrainTextureMode::selectTerrainTextures(const std::pair& texCoords, unsigned char selectMode, bool dragOperation); From 5a143fe99d01e455e7e2d24d6789b72de4928318 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 6 May 2019 12:59:28 +0300 Subject: [PATCH 11/48] Remove extra include --- apps/opencs/view/render/terraintexturemode.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index fae18f8c21..42c3a5d392 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -36,7 +36,6 @@ #include "pagedworldspacewidget.hpp" #include "mask.hpp" #include "object.hpp" // Something small needed regarding pointers from here () -#include "terrainselection.hpp" #include "worldspacewidget.hpp" CSVRender::TerrainTextureMode::TerrainTextureMode (WorldspaceWidget *worldspaceWidget, osg::Group* parentNode, QWidget *parent) From 1dcee833a12d8cf632b5d4d9a447b9e105a42a17 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Mon, 6 May 2019 13:02:49 +0300 Subject: [PATCH 12/48] Less verbose syntax --- apps/opencs/view/render/terrainselection.cpp | 2 +- .../opencs/view/render/terraintexturemode.cpp | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 45b06e8f6e..4a5deb4b00 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -60,7 +60,7 @@ void CSVRender::TerrainSelection::addSelect(const std::pair &localPos) void CSVRender::TerrainSelection::toggleSelect(const std::vector> &localPositions, bool toggleInProgress) { - if (toggleInProgress == true) + if (toggleInProgress) { for(auto const& localPos: localPositions) { diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 42c3a5d392..dee60f2b32 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -114,7 +114,7 @@ void CSVRender::TerrainTextureMode::primaryEditPressed(const WorldspaceHitResult if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted() && hit.hit && hit.tag == 0) { undoStack.beginMacro ("Edit texture records"); - if(allowLandTextureEditing(mCellId)==true) + if(allowLandTextureEditing(mCellId)) { undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); @@ -162,7 +162,7 @@ bool CSVRender::TerrainTextureMode::primaryEditStartDrag (const QPoint& pos) { undoStack.beginMacro ("Edit texture records"); mIsEditing = true; - if(allowLandTextureEditing(mCellId)==true) + if(allowLandTextureEditing(mCellId)) { undoStack.push (new CSMWorld::TouchLandCommand(landTable, ltexTable, mCellId)); editTerrainTextureGrid(hit); @@ -245,7 +245,7 @@ void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - if (mIsEditing == true) + if (mIsEditing) { undoStack.endMacro(); mIsEditing = false; @@ -299,7 +299,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe *document.getData().getTableModel (CSMWorld::UniversalId::Type_Land)); mCellId = getWorldspaceWidget().getCellId (hit.worldPos); - if(allowLandTextureEditing(mCellId)==true) {} + if(allowLandTextureEditing(mCellId)) {} std::pair cellCoordinates_pair = CSMWorld::CellCoordinates::fromId (mCellId); @@ -321,7 +321,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } mCellId = CSMWorld::CellCoordinates::generateId(cellX, cellY); - if(allowLandTextureEditing(mCellId)==true) {} + if(allowLandTextureEditing(mCellId)) {} std::string iteratedCellId; @@ -340,7 +340,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); - if(allowLandTextureEditing(mCellId)==true) + if(allowLandTextureEditing(mCellId)) { newTerrain[yHitInCell*landTextureSize+xHitInCell] = brushInt; pushEditToCommand(newTerrain, document, landTable, mCellId); @@ -364,7 +364,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = CSMWorld::CellCoordinates::generateId(i_cell, j_cell); - if(allowLandTextureEditing(iteratedCellId)==true) + if(allowLandTextureEditing(iteratedCellId)) { CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); @@ -414,7 +414,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe for(int j_cell = upperLeftCellY; j_cell <= lowerrightCellY; j_cell++) { iteratedCellId = CSMWorld::CellCoordinates::generateId(i_cell, j_cell); - if(allowLandTextureEditing(iteratedCellId)==true) + if(allowLandTextureEditing(iteratedCellId)) { CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(iteratedCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); @@ -462,7 +462,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe CSMWorld::LandTexturesColumn::DataType newTerrainPointer = landTable.data(landTable.getModelIndex(mCellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrain(newTerrainPointer); - if(allowLandTextureEditing(mCellId)==true && !mCustomBrushShape.empty()) + if(allowLandTextureEditing(mCellId) && !mCustomBrushShape.empty()) { for(auto const& value: mCustomBrushShape) { @@ -478,7 +478,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe int yInOtherCell = yHitInCell + value.second - cellYDifference * landTextureSize; std::string cellId = CSMWorld::CellCoordinates::generateId(cellX+cellXDifference, cellY+cellYDifference); - if (allowLandTextureEditing(cellId)==true) + if (allowLandTextureEditing(cellId)) { CSMWorld::LandTexturesColumn::DataType newTerrainPointerOtherCell = landTable.data(landTable.getModelIndex(cellId, textureColumn)).value(); CSMWorld::LandTexturesColumn::DataType newTerrainOtherCell(newTerrainPointerOtherCell); From 3becacf6d1c385e7a6136ea3b18da0f09a3381ee Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 9 May 2019 20:31:36 +0300 Subject: [PATCH 13/48] Remove globals, const int& -> int, values to const ref. --- apps/opencs/model/world/cellcoordinates.cpp | 37 +++++++----------- apps/opencs/model/world/cellcoordinates.hpp | 8 ++-- apps/opencs/view/render/terrainselection.cpp | 39 ++++++++----------- apps/opencs/view/render/terrainselection.hpp | 4 -- .../opencs/view/render/terraintexturemode.cpp | 10 ++--- .../opencs/view/render/terraintexturemode.hpp | 2 +- 6 files changed, 41 insertions(+), 59 deletions(-) diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp index 55adc3eff1..ce48b5a128 100644 --- a/apps/opencs/model/world/cellcoordinates.cpp +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -8,13 +8,6 @@ #include #include -namespace -{ - const int cellSize {ESM::Land::REAL_SIZE}; - const int landSize {ESM::Land::LAND_SIZE}; - const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; -} - CSMWorld::CellCoordinates::CellCoordinates() : mX (0), mY (0) {} CSMWorld::CellCoordinates::CellCoordinates (int x, int y) : mX (x), mY (y) {} @@ -76,10 +69,10 @@ std::pair CSMWorld::CellCoordinates::coordinatesToCellIndex (float x, return std::make_pair (std::floor (x / Constants::CellSizeInUnits), std::floor (y / Constants::CellSizeInUnits)); } -std::pair CSMWorld::CellCoordinates::toTextureCoords(osg::Vec3d worldPos) +std::pair CSMWorld::CellCoordinates::toTextureCoords(const osg::Vec3d& worldPos) { - const auto xd = static_cast(worldPos.x() * landTextureSize / cellSize - 0.25f); - const auto yd = static_cast(worldPos.y() * landTextureSize / cellSize + 0.25f); + const auto xd = static_cast(worldPos.x() * ESM::Land::LAND_TEXTURE_SIZE / ESM::Land::REAL_SIZE - 0.25f); + const auto yd = static_cast(worldPos.y() * ESM::Land::LAND_TEXTURE_SIZE / ESM::Land::REAL_SIZE + 0.25f); const auto x = static_cast(std::floor(xd)); const auto y = static_cast(std::floor(yd)); @@ -87,10 +80,10 @@ std::pair CSMWorld::CellCoordinates::toTextureCoords(osg::Vec3d worldP return std::make_pair(x, y); } -std::pair CSMWorld::CellCoordinates::toVertexCoords(osg::Vec3d worldPos) +std::pair CSMWorld::CellCoordinates::toVertexCoords(const osg::Vec3d& worldPos) { - const auto xd = static_cast(worldPos.x() * (landSize - 1) / cellSize + 0.5f); - const auto yd = static_cast(worldPos.y() * (landSize - 1) / cellSize + 0.5f); + const auto xd = static_cast(worldPos.x() * (ESM::Land::LAND_SIZE - 1) / ESM::Land::REAL_SIZE + 0.5f); + const auto yd = static_cast(worldPos.y() * (ESM::Land::LAND_SIZE - 1) / ESM::Land::REAL_SIZE + 0.5f); const auto x = static_cast(std::floor(xd)); const auto y = static_cast(std::floor(yd)); @@ -100,30 +93,30 @@ std::pair CSMWorld::CellCoordinates::toVertexCoords(osg::Vec3d worldPo float CSMWorld::CellCoordinates::textureSelectionToWorldCoords(int pos) { - return cellSize * static_cast(pos) / landTextureSize; + return ESM::Land::REAL_SIZE * static_cast(pos) / ESM::Land::LAND_TEXTURE_SIZE; } float CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(int pos) { - return cellSize * static_cast(pos) / (landSize - 1); + return ESM::Land::REAL_SIZE * static_cast(pos) / (ESM::Land::LAND_SIZE - 1); } int CSMWorld::CellCoordinates::vertexSelectionToInCellCoords(int pos) { - return static_cast(pos - std::floor(static_cast(pos) / (landSize - 1)) * (landSize - 1)); + return static_cast(pos - std::floor(static_cast(pos) / (ESM::Land::LAND_SIZE - 1)) * (ESM::Land::LAND_SIZE - 1)); } -std::string CSMWorld::CellCoordinates::textureGlobalToCellId(std::pair textureGlobal) +std::string CSMWorld::CellCoordinates::textureGlobalToCellId(const std::pair& textureGlobal) { - int x = std::floor(static_cast(textureGlobal.first) / landTextureSize); - int y = std::floor(static_cast(textureGlobal.second) / landTextureSize); + int x = std::floor(static_cast(textureGlobal.first) / ESM::Land::LAND_TEXTURE_SIZE); + int y = std::floor(static_cast(textureGlobal.second) / ESM::Land::LAND_TEXTURE_SIZE); return generateId(x, y); } -std::string CSMWorld::CellCoordinates::vertexGlobalToCellId(std::pair vertexGlobal) +std::string CSMWorld::CellCoordinates::vertexGlobalToCellId(const std::pair& vertexGlobal) { - int x = std::floor(static_cast(vertexGlobal.first) / (landSize - 1)); - int y = std::floor(static_cast(vertexGlobal.second) / (landSize - 1)); + int x = std::floor(static_cast(vertexGlobal.first) / (ESM::Land::LAND_SIZE - 1)); + int y = std::floor(static_cast(vertexGlobal.second) / (ESM::Land::LAND_SIZE - 1)); return generateId(x, y); } diff --git a/apps/opencs/model/world/cellcoordinates.hpp b/apps/opencs/model/world/cellcoordinates.hpp index c6c2c7ccd6..554aff32be 100644 --- a/apps/opencs/model/world/cellcoordinates.hpp +++ b/apps/opencs/model/world/cellcoordinates.hpp @@ -49,10 +49,10 @@ namespace CSMWorld static std::pair coordinatesToCellIndex (float x, float y); ///Converts worldspace coordinates to global texture selection, taking in account the texture offset. - static std::pair toTextureCoords(osg::Vec3d worldPos); + static std::pair toTextureCoords(const osg::Vec3d& worldPos); ///Converts worldspace coordinates to global vertex selection. - static std::pair toVertexCoords(osg::Vec3d worldPos); + static std::pair toVertexCoords(const osg::Vec3d& worldPos); ///Converts global texture coordinate to worldspace coordinate that is at the upper left corner of the selected texture. static float textureSelectionToWorldCoords(int); @@ -63,10 +63,10 @@ namespace CSMWorld ///Converts local cell's heightmap coordinates from the global vertex coordinate static int vertexSelectionToInCellCoords(int); - static std::string textureGlobalToCellId(std::pair); + static std::string textureGlobalToCellId(const std::pair&); ///Converts global vertex coordinates to cell id - static std::string vertexGlobalToCellId(std::pair); + static std::string vertexGlobalToCellId(const std::pair&); }; bool operator== (const CellCoordinates& left, const CellCoordinates& right); diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 4a5deb4b00..93a9046899 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -15,13 +15,6 @@ #include "cell.hpp" #include "worldspacewidget.hpp" -namespace -{ - const int cellSize {ESM::Land::REAL_SIZE}; - const int landSize {ESM::Land::LAND_SIZE}; - const int landTextureSize {ESM::Land::LAND_TEXTURE_SIZE}; -} - CSVRender::TerrainSelection::TerrainSelection(osg::Group* parentNode, WorldspaceWidget *worldspaceWidget, TerrainSelectionType type): mParentNode(parentNode), mWorldspaceWidget (worldspaceWidget), mDraggedOperationFlag(false), mSelectionType(type) { @@ -180,10 +173,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr &localPos : mSelection) { @@ -203,8 +196,8 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); } @@ -215,8 +208,8 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); } @@ -227,8 +220,8 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); } @@ -239,8 +232,8 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); } @@ -251,10 +244,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptr(); - return mPointer[localY*landSize + localX]; + return mPointer[localY*ESM::Land::LAND_SIZE + localX]; } diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp index ed4548fa7d..cf2da2b8ea 100644 --- a/apps/opencs/view/render/terrainselection.hpp +++ b/apps/opencs/view/render/terrainselection.hpp @@ -46,10 +46,6 @@ namespace CSVRender protected: - void addToSelection(osg::Vec3d worldPos); - void toggleSelection(osg::Vec3d worldPos); - void deselect(); - void update(); void drawShapeSelection(const osg::ref_ptr vertices); diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index dee60f2b32..08a437b372 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -492,7 +492,7 @@ void CSVRender::TerrainTextureMode::editTerrainTextureGrid(const WorldspaceHitRe } } -bool CSVRender::TerrainTextureMode::isInCellSelection(const int& globalSelectionX, const int& globalSelectionY) +bool CSVRender::TerrainTextureMode::isInCellSelection(int globalSelectionX, int globalSelectionY) { if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) { @@ -732,12 +732,12 @@ void CSVRender::TerrainTextureMode::setBrushShape(int brushShape) for(auto const& value: terrainSelection) { - selectionCenterX = selectionCenterX + value.first; - selectionCenterY = selectionCenterY + value.second; + selectionCenterX += value.first; + selectionCenterY += value.second; ++selectionAmount; } - selectionCenterX = selectionCenterX / selectionAmount; - selectionCenterY = selectionCenterY / selectionAmount; + selectionCenterX /= selectionAmount; + selectionCenterY /= selectionAmount; mCustomBrushShape.clear(); for (auto const& value: terrainSelection) diff --git a/apps/opencs/view/render/terraintexturemode.hpp b/apps/opencs/view/render/terraintexturemode.hpp index 392f1ce297..0d670d725f 100644 --- a/apps/opencs/view/render/terraintexturemode.hpp +++ b/apps/opencs/view/render/terraintexturemode.hpp @@ -85,7 +85,7 @@ namespace CSVRender void editTerrainTextureGrid (const WorldspaceHitResult& hit); /// \brief Check if global selection coordinate belongs to cell in view - bool isInCellSelection(const int& globalSelectionX, const int& globalSelectionY); + bool isInCellSelection(int globalSelectionX, int globalSelectionY); /// \brief Handle brush mechanics for texture selection void selectTerrainTextures (const std::pair& texCoords, unsigned char selectMode, bool dragOperation); From 780055899d2f8287f7a6bc7849c576607c031f36 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 9 May 2019 21:26:34 +0300 Subject: [PATCH 14/48] Don't add empty primitive sets to geometry. --- apps/opencs/view/render/terrainselection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index 93a9046899..cefcfa1175 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -127,7 +127,7 @@ void CSVRender::TerrainSelection::update() mGeometry->setVertexArray(vertices); osg::ref_ptr drawArrays = new osg::DrawArrays(osg::PrimitiveSet::LINES); drawArrays->setCount(vertices->size()); - mGeometry->addPrimitiveSet(drawArrays); + if (vertices->size() != 0) mGeometry->addPrimitiveSet(drawArrays); mSelectionNode->addChild(mGeometry); } From 6dc3d8b44b3c363a75f0d95764a2a9880df921e0 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Thu, 9 May 2019 21:34:14 +0300 Subject: [PATCH 15/48] More readable code --- apps/opencs/view/render/terraintexturemode.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 08a437b372..468574c032 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -496,12 +496,9 @@ bool CSVRender::TerrainTextureMode::isInCellSelection(int globalSelectionX, int { if (CSVRender::PagedWorldspaceWidget *paged = dynamic_cast (&getWorldspaceWidget())) { - CSMWorld::CellSelection selection = paged->getCellSelection(); - if (selection.has (CSMWorld::CellCoordinates::fromId( - CSMWorld::CellCoordinates::textureGlobalToCellId(std::make_pair(globalSelectionX, globalSelectionY))).first)) - { - return true; - } + std::pair textureCoords = std::make_pair(globalSelectionX, globalSelectionY); + std::string cellId = CSMWorld::CellCoordinates::textureGlobalToCellId(textureCoords); + return paged->getCellSelection().has(CSMWorld::CellCoordinates::fromId(cellId).first); } return false; } From 08809231894e554544d58d7fcb18942d3cdf7207 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Sat, 11 May 2019 21:07:22 +0300 Subject: [PATCH 16/48] Consistency for variable and header argument names. --- apps/opencs/model/world/cellcoordinates.cpp | 12 +++--- apps/opencs/model/world/cellcoordinates.hpp | 13 +++--- apps/opencs/view/render/terrainselection.cpp | 44 ++++++++++---------- apps/opencs/view/render/terrainselection.hpp | 2 +- 4 files changed, 36 insertions(+), 35 deletions(-) diff --git a/apps/opencs/model/world/cellcoordinates.cpp b/apps/opencs/model/world/cellcoordinates.cpp index ce48b5a128..9f98c7b4c6 100644 --- a/apps/opencs/model/world/cellcoordinates.cpp +++ b/apps/opencs/model/world/cellcoordinates.cpp @@ -91,19 +91,19 @@ std::pair CSMWorld::CellCoordinates::toVertexCoords(const osg::Vec3d& return std::make_pair(x, y); } -float CSMWorld::CellCoordinates::textureSelectionToWorldCoords(int pos) +float CSMWorld::CellCoordinates::textureGlobalToWorldCoords(int textureGlobal) { - return ESM::Land::REAL_SIZE * static_cast(pos) / ESM::Land::LAND_TEXTURE_SIZE; + return ESM::Land::REAL_SIZE * static_cast(textureGlobal) / ESM::Land::LAND_TEXTURE_SIZE; } -float CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(int pos) +float CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(int vertexGlobal) { - return ESM::Land::REAL_SIZE * static_cast(pos) / (ESM::Land::LAND_SIZE - 1); + return ESM::Land::REAL_SIZE * static_cast(vertexGlobal) / (ESM::Land::LAND_SIZE - 1); } -int CSMWorld::CellCoordinates::vertexSelectionToInCellCoords(int pos) +int CSMWorld::CellCoordinates::vertexGlobalToInCellCoords(int vertexGlobal) { - return static_cast(pos - std::floor(static_cast(pos) / (ESM::Land::LAND_SIZE - 1)) * (ESM::Land::LAND_SIZE - 1)); + return static_cast(vertexGlobal - std::floor(static_cast(vertexGlobal) / (ESM::Land::LAND_SIZE - 1)) * (ESM::Land::LAND_SIZE - 1)); } std::string CSMWorld::CellCoordinates::textureGlobalToCellId(const std::pair& textureGlobal) diff --git a/apps/opencs/model/world/cellcoordinates.hpp b/apps/opencs/model/world/cellcoordinates.hpp index 554aff32be..77d76f6efb 100644 --- a/apps/opencs/model/world/cellcoordinates.hpp +++ b/apps/opencs/model/world/cellcoordinates.hpp @@ -55,18 +55,19 @@ namespace CSMWorld static std::pair toVertexCoords(const osg::Vec3d& worldPos); ///Converts global texture coordinate to worldspace coordinate that is at the upper left corner of the selected texture. - static float textureSelectionToWorldCoords(int); + static float textureGlobalToWorldCoords(int textureGlobal); ///Converts global vertex coordinate to worldspace coordinate - static float vertexSelectionToWorldCoords(int); + static float vertexGlobalToWorldCoords(int vertexGlobal); - ///Converts local cell's heightmap coordinates from the global vertex coordinate - static int vertexSelectionToInCellCoords(int); + ///Converts global vertex coordinate to local cell's heightmap coordinates + static int vertexGlobalToInCellCoords(int vertexGlobal); - static std::string textureGlobalToCellId(const std::pair&); + ///Converts global texture coordinates to cell id + static std::string textureGlobalToCellId(const std::pair& textureGlobal); ///Converts global vertex coordinates to cell id - static std::string vertexGlobalToCellId(const std::pair&); + static std::string vertexGlobalToCellId(const std::pair& vertexGlobal); }; bool operator== (const CellCoordinates& left, const CellCoordinates& right); diff --git a/apps/opencs/view/render/terrainselection.cpp b/apps/opencs/view/render/terrainselection.cpp index cefcfa1175..225cfc20b6 100644 --- a/apps/opencs/view/render/terrainselection.cpp +++ b/apps/opencs/view/render/terrainselection.cpp @@ -140,28 +140,28 @@ void CSVRender::TerrainSelection::drawShapeSelection(const osg::ref_ptrpush_back(pointXY); - vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(y - 1), calculateLandHeight(x, y - 1) + 2)); + vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(y - 1), calculateLandHeight(x, y - 1) + 2)); vertices->push_back(pointXY); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(x - 1), yWorldCoord, calculateLandHeight(x - 1, y) + 2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(x - 1), yWorldCoord, calculateLandHeight(x - 1, y) + 2)); const auto north = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x, y + 1)); if (north == mSelection.end()) { vertices->push_back(pointXY); - vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(y + 1), calculateLandHeight(x, y + 1) + 2)); + vertices->push_back(osg::Vec3f(xWorldCoord, CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(y + 1), calculateLandHeight(x, y + 1) + 2)); } const auto east = std::find(mSelection.begin(), mSelection.end(), std::make_pair(x + 1, y)); if (east == mSelection.end()) { vertices->push_back(pointXY); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexSelectionToWorldCoords(x + 1), yWorldCoord, calculateLandHeight(x + 1, y) + 2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::vertexGlobalToWorldCoords(x + 1), yWorldCoord, calculateLandHeight(x + 1, y) + 2)); } } } @@ -196,10 +196,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); - vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); + float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+(i-1), y2)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y + 1) - nudgeOffset, calculateLandHeight(x1+i, y2)+2)); } } @@ -208,10 +208,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); - vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureSelectionToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); + float drawPreviousX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + (i - 1) *(ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentX = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(drawPreviousX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+(i-1), y1)+2)); + vertices->push_back(osg::Vec3f(drawCurrentX + nudgeOffset, CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) - nudgeOffset, calculateLandHeight(x1+i, y1)+2)); } } @@ -220,10 +220,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); + float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x2, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x + 1) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x2, y1+i)+2)); } } @@ -232,10 +232,10 @@ void CSVRender::TerrainSelection::drawTextureSelection(const osg::ref_ptrpush_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); - vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureSelectionToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); + float drawPreviousY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + (i - 1) * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + float drawCurrentY = CSMWorld::CellCoordinates::textureGlobalToWorldCoords(y) + i * (ESM::Land::REAL_SIZE / (ESM::Land::LAND_SIZE - 1)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawPreviousY - nudgeOffset, calculateLandHeight(x1, y1+(i-1))+2)); + vertices->push_back(osg::Vec3f(CSMWorld::CellCoordinates::textureGlobalToWorldCoords(x) + nudgeOffset, drawCurrentY - nudgeOffset, calculateLandHeight(x1, y1+i)+2)); } } } diff --git a/apps/opencs/view/render/terrainselection.hpp b/apps/opencs/view/render/terrainselection.hpp index cf2da2b8ea..ba80aeb073 100644 --- a/apps/opencs/view/render/terrainselection.hpp +++ b/apps/opencs/view/render/terrainselection.hpp @@ -37,7 +37,7 @@ namespace CSVRender void onlySelect(const std::vector> &localPositions); void addSelect(const std::pair &localPos); - void toggleSelect(const std::vector> &localPositions, bool); + void toggleSelect(const std::vector> &localPositions, bool toggleInProgress); void activate(); void deactivate(); From 4ccb951126a21e6e597fe2770112350b929e9192 Mon Sep 17 00:00:00 2001 From: Nelsson Huotari Date: Fri, 31 May 2019 11:28:48 +0300 Subject: [PATCH 17/48] move check to outermost scope --- apps/opencs/view/render/terraintexturemode.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/apps/opencs/view/render/terraintexturemode.cpp b/apps/opencs/view/render/terraintexturemode.cpp index 468574c032..b8181eed59 100644 --- a/apps/opencs/view/render/terraintexturemode.cpp +++ b/apps/opencs/view/render/terraintexturemode.cpp @@ -235,7 +235,7 @@ void CSVRender::TerrainTextureMode::drag (const QPoint& pos, int diffX, int diff void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) { - if (mDragMode == InteractionType_PrimaryEdit) + if (mDragMode == InteractionType_PrimaryEdit && mIsEditing) { CSMDoc::Document& document = getWorldspaceWidget().getDocument(); QUndoStack& undoStack = document.getUndoStack(); @@ -245,11 +245,8 @@ void CSVRender::TerrainTextureMode::dragCompleted(const QPoint& pos) if (index != -1 && !landtexturesCollection.getRecord(index).isDeleted()) { - if (mIsEditing) - { - undoStack.endMacro(); - mIsEditing = false; - } + undoStack.endMacro(); + mIsEditing = false; } } } From a86a8ecc0eeef23efff358134e593cf4337b9a55 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 10 Sep 2019 21:53:26 +0200 Subject: [PATCH 18/48] Allow locking/picking just about everything --- CHANGELOG.md | 2 +- apps/openmw/mwclass/container.cpp | 14 -------------- apps/openmw/mwclass/container.hpp | 6 ------ apps/openmw/mwclass/door.cpp | 14 -------------- apps/openmw/mwclass/door.hpp | 6 ------ apps/openmw/mwmechanics/security.cpp | 3 ++- apps/openmw/mwworld/class.cpp | 10 +++++++--- 7 files changed, 10 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32254d65b8..a12d695f4d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,7 +138,7 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime - Bug #5155: Shouldn't be able to magically lock organic containers + Bug #5155: Lock/unlock behavior differs from vanilla Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index b7da1960e3..f77a9307cd 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -305,20 +305,6 @@ namespace MWClass return getContainerStore (ptr).getWeight(); } - void Container::lock (const MWWorld::Ptr& ptr, int lockLevel) const - { - if(lockLevel != 0) - ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive - else - ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level - } - - void Container::unlock (const MWWorld::Ptr& ptr) const - { - int lockLevel = ptr.getCellRef().getLockLevel(); - ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative - } - bool Container::canLock(const MWWorld::ConstPtr &ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index b137411870..8eae463538 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -47,12 +47,6 @@ namespace MWClass ///< Returns total weight of objects inside this object (including modifications from magic /// effects). Throws an exception, if the object can't hold other objects. - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = 0) const; - ///< Lock object - - virtual void unlock (const MWWorld::Ptr& ptr) const; - ///< Unlock object - virtual bool canLock(const MWWorld::ConstPtr &ptr) const; virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 4f144e1f7a..b98a8cc994 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -240,20 +240,6 @@ namespace MWClass } } - void Door::lock (const MWWorld::Ptr& ptr, int lockLevel) const - { - if(lockLevel != 0) - ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive - else - ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level - } - - void Door::unlock (const MWWorld::Ptr& ptr) const - { - int lockLevel = ptr.getCellRef().getLockLevel(); - ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative - } - bool Door::canLock(const MWWorld::ConstPtr &ptr) const { return true; diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index b3e4e383c3..46acdec72a 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -41,12 +41,6 @@ namespace MWClass static std::string getDestination (const MWWorld::LiveCellRef& door); ///< @return destination cell name or token - virtual void lock (const MWWorld::Ptr& ptr, int lockLevel = 0) const; - ///< Lock object - - virtual void unlock (const MWWorld::Ptr& ptr) const; - ///< Unlock object - virtual bool canLock(const MWWorld::ConstPtr &ptr) const; virtual bool allowTelekinesis(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 65fab88197..62169c84a8 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -29,7 +29,8 @@ namespace MWMechanics std::string& resultMessage, std::string& resultSound) { if (lock.getCellRef().getLockLevel() <= 0 || - lock.getCellRef().getLockLevel() == ESM::UnbreakableLock) //If it's unlocked or can not be unlocked back out immediately + lock.getCellRef().getLockLevel() == ESM::UnbreakableLock || + !lock.getClass().hasToolTip(lock)) //If it's unlocked or can not be unlocked back out immediately return; int lockStrength = lock.getCellRef().getLockLevel(); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 191552bc5a..d7e4220068 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -146,17 +146,21 @@ namespace MWWorld void Class::lock (const Ptr& ptr, int lockLevel) const { - throw std::runtime_error ("class does not support locking"); + if(lockLevel != 0) + ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive + else + ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level } void Class::unlock (const Ptr& ptr) const { - throw std::runtime_error ("class does not support unlocking"); + int lockLevel = ptr.getCellRef().getLockLevel(); + ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative } bool Class::canLock(const ConstPtr &ptr) const { - return false; + return hasToolTip(ptr); } void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const From 9788a776b9395857506b567cd89fdbf0f6c27b5f Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 10 Sep 2019 22:54:43 +0300 Subject: [PATCH 19/48] Avoid Qt "opening user openmw.cfg twice" warning --- apps/launcher/maindialog.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/launcher/maindialog.cpp b/apps/launcher/maindialog.cpp index 2982a30f7a..637017ce81 100644 --- a/apps/launcher/maindialog.cpp +++ b/apps/launcher/maindialog.cpp @@ -329,6 +329,7 @@ bool Launcher::MainDialog::setupGameSettings() stream.setCodec(QTextCodec::codecForName("UTF-8")); mGameSettings.readUserFile(stream); + file.close(); } // Now the rest - priority: user > local > global @@ -353,8 +354,8 @@ bool Launcher::MainDialog::setupGameSettings() stream.setCodec(QTextCodec::codecForName("UTF-8")); mGameSettings.readFile(stream); + file.close(); } - file.close(); } return true; From 6b74630f6e112f18f8d7d38c0b584f8a1682cf4e Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 10 Sep 2019 21:56:10 +0300 Subject: [PATCH 20/48] Preparation work Phase out canBeActivated() to unify activation checks Use getName() for the name caption in tooltips Always use tooltips for non-activator objects Invert hasTooltip default value --- apps/openmw/mwclass/activator.cpp | 6 ++---- apps/openmw/mwclass/activator.hpp | 2 +- apps/openmw/mwclass/actor.cpp | 10 ---------- apps/openmw/mwclass/actor.hpp | 2 -- apps/openmw/mwclass/apparatus.cpp | 9 +-------- apps/openmw/mwclass/apparatus.hpp | 3 --- apps/openmw/mwclass/armor.cpp | 9 +-------- apps/openmw/mwclass/armor.hpp | 3 --- apps/openmw/mwclass/bodypart.cpp | 5 +++++ apps/openmw/mwclass/bodypart.hpp | 3 +++ apps/openmw/mwclass/book.cpp | 9 +-------- apps/openmw/mwclass/book.hpp | 3 --- apps/openmw/mwclass/clothing.cpp | 9 +-------- apps/openmw/mwclass/clothing.hpp | 3 --- apps/openmw/mwclass/container.cpp | 10 +--------- apps/openmw/mwclass/container.hpp | 4 +--- apps/openmw/mwclass/creature.cpp | 2 +- apps/openmw/mwclass/creature.hpp | 2 +- apps/openmw/mwclass/creaturelevlist.cpp | 5 +++++ apps/openmw/mwclass/creaturelevlist.hpp | 3 +++ apps/openmw/mwclass/door.cpp | 9 +-------- apps/openmw/mwclass/door.hpp | 3 --- apps/openmw/mwclass/ingredient.cpp | 9 +-------- apps/openmw/mwclass/ingredient.hpp | 3 --- apps/openmw/mwclass/itemlevlist.cpp | 5 +++++ apps/openmw/mwclass/itemlevlist.hpp | 3 +++ apps/openmw/mwclass/light.cpp | 6 ++---- apps/openmw/mwclass/light.hpp | 2 +- apps/openmw/mwclass/lockpick.cpp | 9 +-------- apps/openmw/mwclass/lockpick.hpp | 3 --- apps/openmw/mwclass/misc.cpp | 13 ++++--------- apps/openmw/mwclass/misc.hpp | 3 --- apps/openmw/mwclass/npc.cpp | 2 +- apps/openmw/mwclass/npc.hpp | 2 +- apps/openmw/mwclass/potion.cpp | 9 +-------- apps/openmw/mwclass/potion.hpp | 3 --- apps/openmw/mwclass/probe.cpp | 9 +-------- apps/openmw/mwclass/probe.hpp | 3 --- apps/openmw/mwclass/repair.cpp | 9 +-------- apps/openmw/mwclass/repair.hpp | 3 --- apps/openmw/mwclass/static.cpp | 5 +++++ apps/openmw/mwclass/static.hpp | 3 +++ apps/openmw/mwclass/weapon.cpp | 9 +-------- apps/openmw/mwclass/weapon.hpp | 3 --- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwworld/class.cpp | 7 +------ apps/openmw/mwworld/class.hpp | 6 +----- apps/openmw/mwworld/player.cpp | 2 +- apps/openmw/mwworld/worldimp.cpp | 6 +++--- 49 files changed, 66 insertions(+), 187 deletions(-) diff --git a/apps/openmw/mwclass/activator.cpp b/apps/openmw/mwclass/activator.cpp index 411b720fe4..c54b1c3691 100644 --- a/apps/openmw/mwclass/activator.cpp +++ b/apps/openmw/mwclass/activator.cpp @@ -89,9 +89,7 @@ namespace MWClass bool Activator::hasToolTip (const MWWorld::ConstPtr& ptr) const { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); + return !getName(ptr).empty(); } bool Activator::allowTelekinesis(const MWWorld::ConstPtr &ptr) const { @@ -103,7 +101,7 @@ namespace MWClass const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index b92dc75cbd..1821317d8b 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -24,7 +24,7 @@ namespace MWClass /// can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual bool allowTelekinesis(const MWWorld::ConstPtr& ptr) const; ///< Return whether this class of object can be activated with telekinesis diff --git a/apps/openmw/mwclass/actor.cpp b/apps/openmw/mwclass/actor.cpp index aa356f62d1..4eb9728a1a 100644 --- a/apps/openmw/mwclass/actor.cpp +++ b/apps/openmw/mwclass/actor.cpp @@ -91,14 +91,4 @@ namespace MWClass { return true; } - - bool Actor::canBeActivated(const MWWorld::Ptr& ptr) const - { - MWMechanics::CreatureStats &stats = getCreatureStats(ptr); - - if (stats.getAiSequence().isInCombat() && !stats.isDead()) - return false; - - return true; - } } diff --git a/apps/openmw/mwclass/actor.hpp b/apps/openmw/mwclass/actor.hpp index c3720050cc..7cdee8061f 100644 --- a/apps/openmw/mwclass/actor.hpp +++ b/apps/openmw/mwclass/actor.hpp @@ -42,8 +42,6 @@ namespace MWClass virtual bool isActor() const; - virtual bool canBeActivated(const MWWorld::Ptr& ptr) const; - // not implemented Actor(const Actor&); Actor& operator= (const Actor&); diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index ca610efc29..b8c855d562 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -93,19 +93,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Apparatus::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Apparatus::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index e9b6457635..98459cbd61 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -33,9 +33,6 @@ namespace MWClass virtual int getValue (const MWWorld::ConstPtr& ptr) const; ///< Return trade value of the object. Throws an exception, if the object can't be traded. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 44e708d5b0..265b386cdb 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -199,19 +199,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Armor::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Armor::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 6b098fa9ab..7e069701bc 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -43,9 +43,6 @@ namespace MWClass /// Return the index of the skill this item corresponds to when equipped or -1, if there is /// no such skill. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/bodypart.cpp b/apps/openmw/mwclass/bodypart.cpp index 41a9d998e0..0315d3ddb0 100644 --- a/apps/openmw/mwclass/bodypart.cpp +++ b/apps/openmw/mwclass/bodypart.cpp @@ -31,6 +31,11 @@ namespace MWClass return std::string(); } + bool BodyPart::hasToolTip(const MWWorld::ConstPtr& ptr) const + { + return false; + } + void BodyPart::registerSelf() { std::shared_ptr instance (new BodyPart); diff --git a/apps/openmw/mwclass/bodypart.hpp b/apps/openmw/mwclass/bodypart.hpp index 79c7c860de..cad39a2e46 100644 --- a/apps/openmw/mwclass/bodypart.hpp +++ b/apps/openmw/mwclass/bodypart.hpp @@ -21,6 +21,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: true) + static void registerSelf(); virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index ce08ce4224..36d623c094 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -109,19 +109,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Book::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Book::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 4cb51ff583..9cb6fcafcc 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -27,9 +27,6 @@ namespace MWClass virtual std::string getScript (const MWWorld::ConstPtr& ptr) const; ///< Return name of the script attached to ptr - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index c252085952..a1a6d63680 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -157,19 +157,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Clothing::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Clothing::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index 81b5c2ef41..fd5a197b34 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -35,9 +35,6 @@ namespace MWClass /// Return the index of the skill this item corresponds to when equipped or -1, if there is /// no such skill. - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 2b36f23390..917e7c9c15 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -252,26 +252,18 @@ namespace MWClass bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const { - if (getName(ptr).empty()) - return false; - if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData()) return !canBeHarvested(ptr) || data->asContainerCustomData().mContainerStore.hasVisibleItems(); return true; } - bool Container::canBeActivated(const MWWorld::Ptr& ptr) const - { - return hasToolTip(ptr); - } - MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)); std::string text; int lockLevel = ptr.getCellRef().getLockLevel(); diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index b137411870..b49f864d7c 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -28,7 +28,7 @@ namespace MWClass ///< Generate action for activation virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. @@ -63,8 +63,6 @@ namespace MWClass const; ///< Write additional state from \a ptr into \a state. - virtual bool canBeActivated(const MWWorld::Ptr& ptr) const; - static void registerSelf(); virtual void respawn (const MWWorld::Ptr& ptr) const; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index ba0bbf97f9..09040df024 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -586,7 +586,7 @@ namespace MWClass const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)); std::string text; if (MWBase::Environment::get().getWindowManager()->getFullHelp()) diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index e3689204a7..ffdf8be16e 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -48,7 +48,7 @@ namespace MWClass /// can return an empty string. virtual bool hasToolTip(const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/creaturelevlist.cpp b/apps/openmw/mwclass/creaturelevlist.cpp index b8c4cbb620..1dab9e4839 100644 --- a/apps/openmw/mwclass/creaturelevlist.cpp +++ b/apps/openmw/mwclass/creaturelevlist.cpp @@ -39,6 +39,11 @@ namespace MWClass return ""; } + bool CreatureLevList::hasToolTip(const MWWorld::ConstPtr& ptr) const + { + return false; + } + void CreatureLevList::respawn(const MWWorld::Ptr &ptr) const { ensureCustomData(ptr); diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index 25b5cbddfb..7fe4b1b4db 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -15,6 +15,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: true) + static void registerSelf(); virtual void getModelsToPreload(const MWWorld::Ptr& ptr, std::vector& models) const; diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 4f144e1f7a..4d4ec05fbd 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -281,19 +281,12 @@ namespace MWClass registerClass (typeid (ESM::Door).name(), instance); } - bool Door::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Door::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)); std::string text; diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index b3e4e383c3..e1e9976804 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -32,9 +32,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index b632953919..74f38b2a20 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -105,19 +105,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Ingredient::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Ingredient::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 668fea29a9..8598b40d74 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/itemlevlist.cpp b/apps/openmw/mwclass/itemlevlist.cpp index d2c246a851..5608a8d233 100644 --- a/apps/openmw/mwclass/itemlevlist.cpp +++ b/apps/openmw/mwclass/itemlevlist.cpp @@ -10,6 +10,11 @@ namespace MWClass return ""; } + bool ItemLevList::hasToolTip(const MWWorld::ConstPtr& ptr) const + { + return false; + } + void ItemLevList::registerSelf() { std::shared_ptr instance (new ItemLevList); diff --git a/apps/openmw/mwclass/itemlevlist.hpp b/apps/openmw/mwclass/itemlevlist.hpp index a8b313185c..6e3832c279 100644 --- a/apps/openmw/mwclass/itemlevlist.hpp +++ b/apps/openmw/mwclass/itemlevlist.hpp @@ -13,6 +13,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: true) + static void registerSelf(); }; } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index f31df3aed2..3612e6d003 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -141,9 +141,7 @@ namespace MWClass bool Light::hasToolTip (const MWWorld::ConstPtr& ptr) const { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); + return showsInInventory(ptr); } MWGui::ToolTipInfo Light::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const @@ -151,7 +149,7 @@ namespace MWClass const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 013b9eee34..432e4a7077 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -23,7 +23,7 @@ namespace MWClass /// can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index 33d4632cae..b4cd51638a 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -104,19 +104,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Lockpick::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Lockpick::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index c8df860f67..29d1c06312 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index af68f4743c..1a03021aef 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -134,13 +134,6 @@ namespace MWClass return ref->mBase->mIcon; } - bool Miscellaneous::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Miscellaneous::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); @@ -159,14 +152,16 @@ namespace MWClass else // gold displays its count also if it's 1. countString = " (" + std::to_string(count) + ")"; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + countString; + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + countString; info.icon = ref->mBase->mIcon; if (ref->mRef.getSoul() != "") { const ESM::Creature *creature = store.get().search(ref->mRef.getSoul()); - if (creature) + if (creature && !creature->mName.empty()) info.caption += " (" + creature->mName + ")"; + else if (creature) + info.caption += " (" + creature->mId + ")"; } std::string text; diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index 77e7d105bf..ff6c80f5af 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 868ab9d85d..6458ba589e 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -1071,7 +1071,7 @@ namespace MWClass MWGui::ToolTipInfo info; info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)); - if(fullHelp && ptr.getRefData().getCustomData() && ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats.isWerewolf()) + if(fullHelp && !ref->mBase->mName.empty() && ptr.getRefData().getCustomData() && ptr.getRefData().getCustomData()->asNpcCustomData().mNpcStats.isWerewolf()) { info.caption += " ("; info.caption += MyGUI::TextIterator::toTagsString(ref->mBase->mName); diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index e91dc7113b..6b8c336172 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -61,7 +61,7 @@ namespace MWClass ///< Return container store virtual bool hasToolTip(const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 5c40f17d3e..59c2fc006c 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -98,19 +98,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Potion::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Potion::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index 90dbe5281e..cb66c66828 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 0a0c1548fa..72d9c1d9c8 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -104,19 +104,12 @@ namespace MWClass return ref->mBase->mIcon; } - bool Probe::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Probe::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index 86f6f677a8..a64c0166f3 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index 9050d9f94e..f334c21a10 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -93,13 +93,6 @@ namespace MWClass return ref->mBase->mIcon; } - bool Repair::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - bool Repair::hasItemHealth (const MWWorld::ConstPtr& ptr) const { return true; @@ -117,7 +110,7 @@ namespace MWClass const MWWorld::LiveCellRef *ref = ptr.get(); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; std::string text; diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index f60dbad909..20fe50b962 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -24,9 +24,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwclass/static.cpp b/apps/openmw/mwclass/static.cpp index a6e4fe5e79..5551b3d731 100644 --- a/apps/openmw/mwclass/static.cpp +++ b/apps/openmw/mwclass/static.cpp @@ -45,6 +45,11 @@ namespace MWClass return ""; } + bool Static::hasToolTip(const MWWorld::ConstPtr& ptr) const + { + return false; + } + void Static::registerSelf() { std::shared_ptr instance (new Static); diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 076c39cf10..98e2fcf653 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -20,6 +20,9 @@ namespace MWClass ///< \return name (the one that is to be presented to the user; not the internal one); /// can return an empty string. + virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; + ///< @return true if this object has a tooltip when focused (default implementation: true) + static void registerSelf(); virtual std::string getModel(const MWWorld::ConstPtr &ptr) const; diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index 82740a2e19..ab010af063 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -155,20 +155,13 @@ namespace MWClass return ref->mBase->mIcon; } - bool Weapon::hasToolTip (const MWWorld::ConstPtr& ptr) const - { - const MWWorld::LiveCellRef *ref = ptr.get(); - - return (ref->mBase->mName != ""); - } - MWGui::ToolTipInfo Weapon::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const { const MWWorld::LiveCellRef *ref = ptr.get(); const ESM::WeaponType* weaponType = MWMechanics::getWeaponType(ref->mBase->mData.mType); MWGui::ToolTipInfo info; - info.caption = MyGUI::TextIterator::toTagsString(ref->mBase->mName) + MWGui::ToolTips::getCountString(count); + info.caption = MyGUI::TextIterator::toTagsString(getName(ptr)) + MWGui::ToolTips::getCountString(count); info.icon = ref->mBase->mIcon; const MWWorld::ESMStore& store = MWBase::Environment::get().getWorld()->getStore(); diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 423ba0dd27..4a35901e89 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -25,9 +25,6 @@ namespace MWClass const MWWorld::Ptr& actor) const; ///< Generate action for activation - virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) - virtual MWGui::ToolTipInfo getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7547f086b2..d450c014c4 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -959,7 +959,7 @@ namespace MWMechanics return true; } - if (!target.getClass().canBeActivated(target)) + if (!target.getClass().hasToolTip(target)) return true; // TODO: implement a better check to check if target is owned bed diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 191552bc5a..637a8d3da2 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -109,11 +109,6 @@ namespace MWWorld throw std::runtime_error("class cannot block"); } - bool Class::canBeActivated(const Ptr& ptr) const - { - return !getName(ptr).empty(); - } - void Class::onHit(const Ptr& ptr, float damage, bool ishealth, const Ptr& object, const Ptr& attacker, const osg::Vec3f& hitPosition, bool successful) const { throw std::runtime_error("class cannot be hit"); @@ -298,7 +293,7 @@ namespace MWWorld bool Class::hasToolTip (const ConstPtr& ptr) const { - return false; + return true; } std::string Class::getEnchantment (const ConstPtr& ptr) const diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 964ef19a5f..add70c4b6b 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -95,7 +95,7 @@ namespace MWWorld /// (default implementation: throw an exception) virtual bool hasToolTip (const ConstPtr& ptr) const; - ///< @return true if this object has a tooltip when focused (default implementation: false) + ///< @return true if this object has a tooltip when focused (default implementation: true) virtual MWGui::ToolTipInfo getToolTipInfo (const ConstPtr& ptr, int count) const; ///< @return the content of the tool tip to be displayed. raises exception if the object has no tooltip. @@ -140,10 +140,6 @@ namespace MWWorld ///< Play the appropriate sound for a blocked attack, depending on the currently equipped shield /// (default implementation: throw an exception) - virtual bool canBeActivated(const Ptr& ptr) const; - ///< \return Can the player activate this object? - /// (default implementation: true if object's user-readable name is not empty, false otherwise) - virtual std::shared_ptr activate (const Ptr& ptr, const Ptr& actor) const; ///< Generate action for activation (default implementation: return a null action). diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 9e2d9d6ff4..8e047677bc 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -236,7 +236,7 @@ namespace MWWorld if (toActivate.isEmpty()) return; - if (!toActivate.getClass().canBeActivated(toActivate)) + if (!toActivate.getClass().hasToolTip(toActivate)) return; MWBase::Environment::get().getWorld()->activate(toActivate, player); diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 07680e76f3..7aa9d6023a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -3023,7 +3023,7 @@ namespace MWWorld target = getFacedObject(); // if the faced object can not be activated, do not use it - if (!target.isEmpty() && !target.getClass().canBeActivated(target)) + if (!target.isEmpty() && !target.getClass().hasToolTip(target)) target = nullptr; if (target.isEmpty()) @@ -3082,7 +3082,7 @@ namespace MWWorld { target = result2.mHitObject; hitPosition = result2.mHitPointWorld; - if (dist2 > getMaxActivationDistance() && !target.isEmpty() && !target.getClass().canBeActivated(target)) + if (dist2 > getMaxActivationDistance() && !target.isEmpty() && !target.getClass().hasToolTip(target)) target = nullptr; } } @@ -3650,7 +3650,7 @@ namespace MWWorld if (fromProjectile && effectInfo.mArea <= 0) continue; // Don't play explosion for projectiles with 0-area effects - if (!fromProjectile && effectInfo.mRange == ESM::RT_Touch && (!ignore.isEmpty()) && (!ignore.getClass().isActor() && !ignore.getClass().canBeActivated(ignore))) + if (!fromProjectile && effectInfo.mRange == ESM::RT_Touch && !ignore.isEmpty() && !ignore.getClass().isActor() && !ignore.getClass().hasToolTip(ignore)) continue; // Don't play explosion for touch spells on non-activatable objects except when spell is from the projectile enchantment // Spawn the explosion orb effect From 718dbd3f9a24503196d6935e931ab037b5cf3d24 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Wed, 11 Sep 2019 00:06:50 +0300 Subject: [PATCH 21/48] Use object ID as the substitution for their name (bug #5158) --- CHANGELOG.md | 1 + apps/openmw/mwclass/activator.hpp | 3 +-- apps/openmw/mwclass/apparatus.cpp | 3 ++- apps/openmw/mwclass/apparatus.hpp | 3 +-- apps/openmw/mwclass/armor.cpp | 3 ++- apps/openmw/mwclass/armor.hpp | 3 +-- apps/openmw/mwclass/bodypart.hpp | 3 +-- apps/openmw/mwclass/book.cpp | 3 ++- apps/openmw/mwclass/book.hpp | 3 +-- apps/openmw/mwclass/clothing.cpp | 3 ++- apps/openmw/mwclass/clothing.hpp | 3 +-- apps/openmw/mwclass/container.cpp | 3 ++- apps/openmw/mwclass/container.hpp | 3 +-- apps/openmw/mwclass/creature.cpp | 3 ++- apps/openmw/mwclass/creature.hpp | 3 +-- apps/openmw/mwclass/creaturelevlist.hpp | 3 +-- apps/openmw/mwclass/door.cpp | 3 ++- apps/openmw/mwclass/door.hpp | 3 +-- apps/openmw/mwclass/ingredient.cpp | 3 ++- apps/openmw/mwclass/ingredient.hpp | 3 +-- apps/openmw/mwclass/itemlevlist.hpp | 3 +-- apps/openmw/mwclass/light.cpp | 5 +++-- apps/openmw/mwclass/light.hpp | 3 +-- apps/openmw/mwclass/lockpick.cpp | 3 ++- apps/openmw/mwclass/lockpick.hpp | 3 +-- apps/openmw/mwclass/misc.cpp | 3 ++- apps/openmw/mwclass/misc.hpp | 3 +-- apps/openmw/mwclass/npc.cpp | 4 +++- apps/openmw/mwclass/npc.hpp | 3 +-- apps/openmw/mwclass/potion.cpp | 3 ++- apps/openmw/mwclass/potion.hpp | 3 +-- apps/openmw/mwclass/probe.cpp | 3 ++- apps/openmw/mwclass/probe.hpp | 3 +-- apps/openmw/mwclass/repair.cpp | 3 ++- apps/openmw/mwclass/repair.hpp | 3 +-- apps/openmw/mwclass/static.hpp | 3 +-- apps/openmw/mwclass/weapon.cpp | 3 ++- apps/openmw/mwclass/weapon.hpp | 3 +-- apps/openmw/mwworld/class.hpp | 3 +-- 39 files changed, 57 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa84ec10ae..372f9c7610 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,7 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime + Bug #5188: Objects without a name don't fallback to their ID Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwclass/activator.hpp b/apps/openmw/mwclass/activator.hpp index 1821317d8b..d5175b739c 100644 --- a/apps/openmw/mwclass/activator.hpp +++ b/apps/openmw/mwclass/activator.hpp @@ -20,8 +20,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/apparatus.cpp b/apps/openmw/mwclass/apparatus.cpp index b8c855d562..518695fabf 100644 --- a/apps/openmw/mwclass/apparatus.cpp +++ b/apps/openmw/mwclass/apparatus.cpp @@ -45,8 +45,9 @@ namespace MWClass std::string Apparatus::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Apparatus::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/apparatus.hpp b/apps/openmw/mwclass/apparatus.hpp index 98459cbd61..ea06f74bd5 100644 --- a/apps/openmw/mwclass/apparatus.hpp +++ b/apps/openmw/mwclass/apparatus.hpp @@ -20,8 +20,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/armor.cpp b/apps/openmw/mwclass/armor.cpp index 265b386cdb..e649bba12b 100644 --- a/apps/openmw/mwclass/armor.cpp +++ b/apps/openmw/mwclass/armor.cpp @@ -53,8 +53,9 @@ namespace MWClass std::string Armor::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Armor::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/armor.hpp b/apps/openmw/mwclass/armor.hpp index 7e069701bc..e25a4ae8aa 100644 --- a/apps/openmw/mwclass/armor.hpp +++ b/apps/openmw/mwclass/armor.hpp @@ -19,8 +19,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/bodypart.hpp b/apps/openmw/mwclass/bodypart.hpp index cad39a2e46..b75dee7544 100644 --- a/apps/openmw/mwclass/bodypart.hpp +++ b/apps/openmw/mwclass/bodypart.hpp @@ -18,8 +18,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/book.cpp b/apps/openmw/mwclass/book.cpp index 36d623c094..4ea71e3ac2 100644 --- a/apps/openmw/mwclass/book.cpp +++ b/apps/openmw/mwclass/book.cpp @@ -50,8 +50,9 @@ namespace MWClass std::string Book::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Book::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/book.hpp b/apps/openmw/mwclass/book.hpp index 9cb6fcafcc..6bdb4e79bd 100644 --- a/apps/openmw/mwclass/book.hpp +++ b/apps/openmw/mwclass/book.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/clothing.cpp b/apps/openmw/mwclass/clothing.cpp index a1a6d63680..6d7960aac2 100644 --- a/apps/openmw/mwclass/clothing.cpp +++ b/apps/openmw/mwclass/clothing.cpp @@ -48,8 +48,9 @@ namespace MWClass std::string Clothing::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Clothing::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/clothing.hpp b/apps/openmw/mwclass/clothing.hpp index fd5a197b34..e71e9b307b 100644 --- a/apps/openmw/mwclass/clothing.hpp +++ b/apps/openmw/mwclass/clothing.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 917e7c9c15..958f8351ec 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -224,8 +224,9 @@ namespace MWClass std::string Container::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } MWWorld::ContainerStore& Container::getContainerStore (const MWWorld::Ptr& ptr) diff --git a/apps/openmw/mwclass/container.hpp b/apps/openmw/mwclass/container.hpp index b49f864d7c..87826da880 100644 --- a/apps/openmw/mwclass/container.hpp +++ b/apps/openmw/mwclass/container.hpp @@ -20,8 +20,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index 09040df024..aed0882edb 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -214,8 +214,9 @@ namespace MWClass std::string Creature::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } MWMechanics::CreatureStats& Creature::getCreatureStats (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/creature.hpp b/apps/openmw/mwclass/creature.hpp index ffdf8be16e..35688ed1ac 100644 --- a/apps/openmw/mwclass/creature.hpp +++ b/apps/openmw/mwclass/creature.hpp @@ -44,8 +44,7 @@ namespace MWClass ///< Add reference into a cell for rendering virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip(const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/creaturelevlist.hpp b/apps/openmw/mwclass/creaturelevlist.hpp index 7fe4b1b4db..3a05f5272c 100644 --- a/apps/openmw/mwclass/creaturelevlist.hpp +++ b/apps/openmw/mwclass/creaturelevlist.hpp @@ -12,8 +12,7 @@ namespace MWClass public: virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index 4d4ec05fbd..3a0e13e625 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -102,8 +102,9 @@ namespace MWClass std::string Door::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Door::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/door.hpp b/apps/openmw/mwclass/door.hpp index e1e9976804..fa566b98e2 100644 --- a/apps/openmw/mwclass/door.hpp +++ b/apps/openmw/mwclass/door.hpp @@ -25,8 +25,7 @@ namespace MWClass virtual bool useAnim() const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/ingredient.cpp b/apps/openmw/mwclass/ingredient.cpp index 74f38b2a20..bd61131bfc 100644 --- a/apps/openmw/mwclass/ingredient.cpp +++ b/apps/openmw/mwclass/ingredient.cpp @@ -47,8 +47,9 @@ namespace MWClass std::string Ingredient::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Ingredient::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/ingredient.hpp b/apps/openmw/mwclass/ingredient.hpp index 8598b40d74..8b2ea4f86a 100644 --- a/apps/openmw/mwclass/ingredient.hpp +++ b/apps/openmw/mwclass/ingredient.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/itemlevlist.hpp b/apps/openmw/mwclass/itemlevlist.hpp index 6e3832c279..36019f491d 100644 --- a/apps/openmw/mwclass/itemlevlist.hpp +++ b/apps/openmw/mwclass/itemlevlist.hpp @@ -10,8 +10,7 @@ namespace MWClass public: virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index 3612e6d003..3bdf10f475 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -70,9 +70,10 @@ namespace MWClass const MWWorld::LiveCellRef *ref = ptr.get(); if (ref->mBase->mModel.empty()) - return ""; + return std::string(); - return ref->mBase->mName; + const std::string& name = ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Light::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 432e4a7077..ba3179971e 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -19,8 +19,7 @@ namespace MWClass virtual bool useAnim() const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/lockpick.cpp b/apps/openmw/mwclass/lockpick.cpp index b4cd51638a..9b8abc8f23 100644 --- a/apps/openmw/mwclass/lockpick.cpp +++ b/apps/openmw/mwclass/lockpick.cpp @@ -47,8 +47,9 @@ namespace MWClass std::string Lockpick::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Lockpick::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/lockpick.hpp b/apps/openmw/mwclass/lockpick.hpp index 29d1c06312..20ca2d1666 100644 --- a/apps/openmw/mwclass/lockpick.hpp +++ b/apps/openmw/mwclass/lockpick.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 1a03021aef..4eb3eabef3 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -56,8 +56,9 @@ namespace MWClass std::string Miscellaneous::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Miscellaneous::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/misc.hpp b/apps/openmw/mwclass/misc.hpp index ff6c80f5af..4812deb5f8 100644 --- a/apps/openmw/mwclass/misc.hpp +++ b/apps/openmw/mwclass/misc.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 6458ba589e..83c989bd49 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -531,7 +531,9 @@ namespace MWClass } const MWWorld::LiveCellRef *ref = ptr.get(); - return ref->mBase->mName; + const std::string& name = ref->mBase->mName; + + return !name.empty() ? name : ref->mBase->mId; } MWMechanics::CreatureStats& Npc::getCreatureStats (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 6b8c336172..9b92f63382 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -48,8 +48,7 @@ namespace MWClass ///< Add reference into a cell for rendering virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual MWMechanics::CreatureStats& getCreatureStats (const MWWorld::Ptr& ptr) const; ///< Return creature stats diff --git a/apps/openmw/mwclass/potion.cpp b/apps/openmw/mwclass/potion.cpp index 59c2fc006c..4af97e6345 100644 --- a/apps/openmw/mwclass/potion.cpp +++ b/apps/openmw/mwclass/potion.cpp @@ -49,8 +49,9 @@ namespace MWClass std::string Potion::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Potion::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/potion.hpp b/apps/openmw/mwclass/potion.hpp index cb66c66828..8ec4aef446 100644 --- a/apps/openmw/mwclass/potion.hpp +++ b/apps/openmw/mwclass/potion.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/probe.cpp b/apps/openmw/mwclass/probe.cpp index 72d9c1d9c8..dba4e8c063 100644 --- a/apps/openmw/mwclass/probe.cpp +++ b/apps/openmw/mwclass/probe.cpp @@ -47,8 +47,9 @@ namespace MWClass std::string Probe::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Probe::activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const diff --git a/apps/openmw/mwclass/probe.hpp b/apps/openmw/mwclass/probe.hpp index a64c0166f3..51a5f8231a 100644 --- a/apps/openmw/mwclass/probe.hpp +++ b/apps/openmw/mwclass/probe.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/repair.cpp b/apps/openmw/mwclass/repair.cpp index f334c21a10..8907c8212e 100644 --- a/apps/openmw/mwclass/repair.cpp +++ b/apps/openmw/mwclass/repair.cpp @@ -44,8 +44,9 @@ namespace MWClass std::string Repair::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Repair::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/repair.hpp b/apps/openmw/mwclass/repair.hpp index 20fe50b962..5d2cfb6828 100644 --- a/apps/openmw/mwclass/repair.hpp +++ b/apps/openmw/mwclass/repair.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwclass/static.hpp b/apps/openmw/mwclass/static.hpp index 98e2fcf653..6b3b8088c5 100644 --- a/apps/openmw/mwclass/static.hpp +++ b/apps/openmw/mwclass/static.hpp @@ -17,8 +17,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual bool hasToolTip (const MWWorld::ConstPtr& ptr) const; ///< @return true if this object has a tooltip when focused (default implementation: true) diff --git a/apps/openmw/mwclass/weapon.cpp b/apps/openmw/mwclass/weapon.cpp index ab010af063..0d6a27cf60 100644 --- a/apps/openmw/mwclass/weapon.cpp +++ b/apps/openmw/mwclass/weapon.cpp @@ -53,8 +53,9 @@ namespace MWClass std::string Weapon::getName (const MWWorld::ConstPtr& ptr) const { const MWWorld::LiveCellRef *ref = ptr.get(); + const std::string& name = ref->mBase->mName; - return ref->mBase->mName; + return !name.empty() ? name : ref->mBase->mId; } std::shared_ptr Weapon::activate (const MWWorld::Ptr& ptr, diff --git a/apps/openmw/mwclass/weapon.hpp b/apps/openmw/mwclass/weapon.hpp index 4a35901e89..2c1197b69e 100644 --- a/apps/openmw/mwclass/weapon.hpp +++ b/apps/openmw/mwclass/weapon.hpp @@ -18,8 +18,7 @@ namespace MWClass virtual void insertObject(const MWWorld::Ptr& ptr, const std::string& model, MWPhysics::PhysicsSystem& physics) const; virtual std::string getName (const MWWorld::ConstPtr& ptr) const; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual std::shared_ptr activate (const MWWorld::Ptr& ptr, const MWWorld::Ptr& actor) const; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index add70c4b6b..1e3eefe33d 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -83,8 +83,7 @@ namespace MWWorld ///< Add reference into a cell for rendering (default implementation: don't render anything). virtual std::string getName (const ConstPtr& ptr) const = 0; - ///< \return name (the one that is to be presented to the user; not the internal one); - /// can return an empty string. + ///< \return name or ID; can return an empty string. virtual void adjustPosition(const MWWorld::Ptr& ptr, bool force) const; ///< Adjust position to stand on ground. Must be called post model load From 85d52ec18327e635dd262a0442ef9438c44469cf Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Wed, 11 Sep 2019 22:05:24 +0200 Subject: [PATCH 22/48] oops --- apps/openmw/mwworld/class.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index d7e4220068..3efc00491b 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -160,7 +160,7 @@ namespace MWWorld bool Class::canLock(const ConstPtr &ptr) const { - return hasToolTip(ptr); + return false; } void Class::setRemainingUsageTime (const Ptr& ptr, float duration) const From 8baddefdbd808c73568bd376521f0e507da318e3 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 13 Sep 2019 19:54:19 +0300 Subject: [PATCH 23/48] Refactor extra data and particle modifier handling Objects no longer inherit from extra data class "Controlled" harmful abstraction no longer exists Introduced NiParticleModifier/NiParticleCollider abstractions Extra data size reading moved into the base read() method --- .../nifloader/testbulletnifloader.cpp | 11 ++--- components/nif/base.hpp | 42 ++++++++----------- components/nif/controlled.cpp | 35 ++++++++++++---- components/nif/controlled.hpp | 30 +++++++++---- components/nif/controller.hpp | 4 +- components/nif/extra.cpp | 11 +---- components/nif/recordptr.hpp | 6 ++- components/nifbullet/bulletnifloader.cpp | 9 +--- components/nifosg/nifloader.cpp | 12 +++--- 9 files changed, 82 insertions(+), 78 deletions(-) diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index c94907e684..7598b63b05 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -211,15 +211,10 @@ namespace value.extra = Nif::ExtraPtr(nullptr); } - void init(Nif::Controlled& value) - { - init(static_cast(value)); - value.controller = Nif::ControllerPtr(nullptr); - } - void init(Nif::Named& value) { - init(static_cast(value)); + value.extra = Nif::ExtraPtr(nullptr); + value.controller = Nif::ControllerPtr(nullptr); } void init(Nif::Node& value) @@ -254,7 +249,7 @@ namespace value.phase = 0; value.timeStart = 0; value.timeStop = 0; - value.target = Nif::ControlledPtr(nullptr); + value.target = Nif::NamedPtr(nullptr); } void copy(const btTransform& src, Nif::Transformation& dst) diff --git a/components/nif/base.hpp b/components/nif/base.hpp index 4b2e40dec0..f67de02216 100644 --- a/components/nif/base.hpp +++ b/components/nif/base.hpp @@ -10,17 +10,19 @@ namespace Nif { -/** A record that can have extra data. The extra data objects - themselves descend from the Extra class, and all the extra data - connected to an object form a linked list -*/ +// An extra data record. All the extra data connected to an object form a linked list. class Extra : public Record { public: - ExtraPtr extra; + ExtraPtr next; // Next extra data record in the list - void read(NIFStream *nif) { extra.read(nif); } - void post(NIFFile *nif) { extra.post(nif); } + void read(NIFStream *nif) + { + next.read(nif); + nif->getUInt(); // Size of the record + } + + void post(NIFFile *nif) { next.post(nif); } }; class Controller : public Record @@ -30,43 +32,33 @@ public: int flags; float frequency, phase; float timeStart, timeStop; - ControlledPtr target; + NamedPtr target; void read(NIFStream *nif); void post(NIFFile *nif); }; -/// Anything that has a controller -class Controlled : public Extra +/// Has name, extra-data and controller +class Named : public Record { public: + std::string name; + ExtraPtr extra; ControllerPtr controller; void read(NIFStream *nif) { - Extra::read(nif); + name = nif->getString(); + extra.read(nif); controller.read(nif); } void post(NIFFile *nif) { - Extra::post(nif); + extra.post(nif); controller.post(nif); } }; - -/// Has name, extra-data and controller -class Named : public Controlled -{ -public: - std::string name; - - void read(NIFStream *nif) - { - name = nif->getString(); - Controlled::read(nif); - } -}; typedef Named NiSequenceStreamHelper; } // Namespace diff --git a/components/nif/controlled.cpp b/components/nif/controlled.cpp index 52e7a7302f..51ccf85412 100644 --- a/components/nif/controlled.cpp +++ b/components/nif/controlled.cpp @@ -31,28 +31,40 @@ namespace Nif data.post(nif); } + void NiParticleModifier::read(NIFStream *nif) + { + next.read(nif); + controller.read(nif); + } + + void NiParticleModifier::post(NIFFile *nif) + { + next.post(nif); + controller.post(nif); + } + void NiParticleGrowFade::read(NIFStream *nif) { - Controlled::read(nif); + NiParticleModifier::read(nif); growTime = nif->getFloat(); fadeTime = nif->getFloat(); } void NiParticleColorModifier::read(NIFStream *nif) { - Controlled::read(nif); + NiParticleModifier::read(nif); data.read(nif); } void NiParticleColorModifier::post(NIFFile *nif) { - Controlled::post(nif); + NiParticleModifier::post(nif); data.post(nif); } void NiGravity::read(NIFStream *nif) { - Controlled::read(nif); + NiParticleModifier::read(nif); mDecay = nif->getFloat(); mForce = nif->getFloat(); @@ -61,11 +73,17 @@ namespace Nif mDirection = nif->getVector3(); } - void NiPlanarCollider::read(NIFStream *nif) + void NiParticleCollider::read(NIFStream *nif) { - Controlled::read(nif); + NiParticleModifier::read(nif); mBounceFactor = nif->getFloat(); + } + + void NiPlanarCollider::read(NIFStream *nif) + { + NiParticleCollider::read(nif); + /*unknown*/nif->getFloat(); for (int i=0;i<10;++i) @@ -77,7 +95,7 @@ namespace Nif void NiParticleRotation::read(NIFStream *nif) { - Controlled::read(nif); + NiParticleModifier::read(nif); /* byte (0 or 1) @@ -89,9 +107,8 @@ namespace Nif void NiSphericalCollider::read(NIFStream* nif) { - Controlled::read(nif); + NiParticleCollider::read(nif); - mBounceFactor = nif->getFloat(); mRadius = nif->getFloat(); mCenter = nif->getVector3(); } diff --git a/components/nif/controlled.hpp b/components/nif/controlled.hpp index be48e912ea..00ff45eda9 100644 --- a/components/nif/controlled.hpp +++ b/components/nif/controlled.hpp @@ -66,7 +66,16 @@ public: void post(NIFFile *nif); }; -class NiParticleGrowFade : public Controlled +struct NiParticleModifier : public Record +{ + NiParticleModifierPtr next; + ControllerPtr controller; + + void read(NIFStream *nif); + void post(NIFFile *nif); +}; + +class NiParticleGrowFade : public NiParticleModifier { public: float growTime; @@ -75,7 +84,7 @@ public: void read(NIFStream *nif); }; -class NiParticleColorModifier : public Controlled +class NiParticleColorModifier : public NiParticleModifier { public: NiColorDataPtr data; @@ -84,7 +93,7 @@ public: void post(NIFFile *nif); }; -class NiGravity : public Controlled +class NiGravity : public NiParticleModifier { public: float mForce; @@ -99,29 +108,32 @@ public: void read(NIFStream *nif); }; +struct NiParticleCollider : public NiParticleModifier +{ + float mBounceFactor; + void read(NIFStream *nif); +}; + // NiPinaColada -class NiPlanarCollider : public Controlled +class NiPlanarCollider : public NiParticleCollider { public: void read(NIFStream *nif); - float mBounceFactor; - osg::Vec3f mPlaneNormal; float mPlaneDistance; }; -class NiSphericalCollider : public Controlled +class NiSphericalCollider : public NiParticleCollider { public: - float mBounceFactor; float mRadius; osg::Vec3f mCenter; void read(NIFStream *nif); }; -class NiParticleRotation : public Controlled +class NiParticleRotation : public NiParticleModifier { public: void read(NIFStream *nif); diff --git a/components/nif/controller.hpp b/components/nif/controller.hpp index 113a7becdd..52ab6f1f61 100644 --- a/components/nif/controller.hpp +++ b/components/nif/controller.hpp @@ -72,8 +72,8 @@ public: int activeCount; std::vector particles; - ExtraPtr affectors; - ExtraPtr colliders; + NiParticleModifierPtr affectors; + NiParticleModifierPtr colliders; void read(NIFStream *nif); void post(NIFFile *nif); diff --git a/components/nif/extra.cpp b/components/nif/extra.cpp index b7e2216688..cb654d5a0d 100644 --- a/components/nif/extra.cpp +++ b/components/nif/extra.cpp @@ -6,8 +6,6 @@ namespace Nif void NiStringExtraData::read(NIFStream *nif) { Extra::read(nif); - - nif->getInt(); // size of string + 4. Really useful... string = nif->getString(); } @@ -15,8 +13,6 @@ void NiTextKeyExtraData::read(NIFStream *nif) { Extra::read(nif); - nif->getInt(); // 0 - int keynum = nif->getInt(); list.resize(keynum); for(int i=0; igetInt(); - int s = nif->getUShort(); - - nif->skip(s * sizeof(float)); // vertex weights I guess + nif->skip(nif->getUShort() * sizeof(float)); // vertex weights I guess } diff --git a/components/nif/recordptr.hpp b/components/nif/recordptr.hpp index e23beb7869..fbd148a046 100644 --- a/components/nif/recordptr.hpp +++ b/components/nif/recordptr.hpp @@ -127,7 +127,7 @@ class NiUVData; class NiPosData; class NiVisData; class Controller; -class Controlled; +class Named; class NiSkinData; class NiFloatData; struct NiMorphData; @@ -141,6 +141,7 @@ class NiSourceTexture; class NiRotatingParticlesData; class NiAutoNormalParticlesData; class NiPalette; +struct NiParticleModifier; typedef RecordPtrT NodePtr; typedef RecordPtrT ExtraPtr; @@ -148,7 +149,7 @@ typedef RecordPtrT NiUVDataPtr; typedef RecordPtrT NiPosDataPtr; typedef RecordPtrT NiVisDataPtr; typedef RecordPtrT ControllerPtr; -typedef RecordPtrT ControlledPtr; +typedef RecordPtrT NamedPtr; typedef RecordPtrT NiSkinDataPtr; typedef RecordPtrT NiMorphDataPtr; typedef RecordPtrT NiPixelDataPtr; @@ -162,6 +163,7 @@ typedef RecordPtrT NiSourceTexturePtr; typedef RecordPtrT NiRotatingParticlesDataPtr; typedef RecordPtrT NiAutoNormalParticlesDataPtr; typedef RecordPtrT NiPalettePtr; +typedef RecordPtrT NiParticleModifierPtr; typedef RecordListT NodeList; typedef RecordListT PropertyList; diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 2f24a40674..5993d04fdf 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -260,18 +260,13 @@ void BulletNifLoader::handleNode(const std::string& fileName, const Nif::Node *n Log(Debug::Info) << "RootCollisionNode is not attached to the root node in " << fileName << ". Treating it as a common NiTriShape."; // Check for extra data - Nif::Extra const *e = node; - while (!e->extra.empty()) + for (Nif::ExtraPtr e = node->extra; !e.empty(); e = e->next) { - // Get the next extra data in the list - e = e->extra.getPtr(); - assert(e != nullptr); - if (e->recType == Nif::RC_NiStringExtraData) { // String markers may contain important information // affecting the entire subtree of this node - Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e; + Nif::NiStringExtraData *sd = (Nif::NiStringExtraData*)e.getPtr(); if (Misc::StringUtils::ciCompareLen(sd->string, "NC", 2) == 0) { diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 568286a4d6..7699271d35 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -222,9 +222,9 @@ namespace NifOsg extractTextKeys(static_cast(extra.getPtr()), target.mTextKeys); - extra = extra->extra; + extra = extra->next; Nif::ControllerPtr ctrl = seq->controller; - for(;!extra.empty() && !ctrl.empty();(extra=extra->extra),(ctrl=ctrl->next)) + for(;!extra.empty() && !ctrl.empty();(extra=extra->next),(ctrl=ctrl->next)) { if(extra->recType != Nif::RC_NiStringExtraData || ctrl->recType != Nif::RC_NiKeyframeController) { @@ -524,7 +524,7 @@ namespace NifOsg node->getOrCreateUserDataContainer()->addUserObject( new NodeUserData(nifNode->recIndex, nifNode->trafo.scale, nifNode->trafo.rotation)); - for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->extra) + for (Nif::ExtraPtr e = nifNode->extra; !e.empty(); e = e->next) { if(e->recType == Nif::RC_NiTextKeyExtraData && textKeys) { @@ -802,13 +802,13 @@ namespace NifOsg } } - void handleParticlePrograms(Nif::ExtraPtr affectors, Nif::ExtraPtr colliders, osg::Group *attachTo, osgParticle::ParticleSystem* partsys, osgParticle::ParticleProcessor::ReferenceFrame rf) + void handleParticlePrograms(Nif::NiParticleModifierPtr affectors, Nif::NiParticleModifierPtr colliders, osg::Group *attachTo, osgParticle::ParticleSystem* partsys, osgParticle::ParticleProcessor::ReferenceFrame rf) { osgParticle::ModularProgram* program = new osgParticle::ModularProgram; attachTo->addChild(program); program->setParticleSystem(partsys); program->setReferenceFrame(rf); - for (; !affectors.empty(); affectors = affectors->extra) + for (; !affectors.empty(); affectors = affectors->next) { if (affectors->recType == Nif::RC_NiParticleGrowFade) { @@ -833,7 +833,7 @@ namespace NifOsg else Log(Debug::Info) << "Unhandled particle modifier " << affectors->recName << " in " << mFilename; } - for (; !colliders.empty(); colliders = colliders->extra) + for (; !colliders.empty(); colliders = colliders->next) { if (colliders->recType == Nif::RC_NiPlanarCollider) { From 790531671a6e44d02b10dca77fa95a35b99d0d0f Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Fri, 13 Sep 2019 21:29:49 +0300 Subject: [PATCH 24/48] Fix tests --- apps/openmw_test_suite/nifloader/testbulletnifloader.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp index 7598b63b05..b02b8b9ef7 100644 --- a/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp +++ b/apps/openmw_test_suite/nifloader/testbulletnifloader.cpp @@ -208,7 +208,7 @@ namespace void init(Nif::Extra& value) { - value.extra = Nif::ExtraPtr(nullptr); + value.next = Nif::ExtraPtr(nullptr); } void init(Nif::Named& value) @@ -879,7 +879,7 @@ namespace TEST_F(TestBulletNifLoader, for_tri_shape_child_node_with_not_first_extra_data_string_starting_with_nc_should_return_shape_with_null_collision_shape) { - mNiStringExtraData.extra = Nif::ExtraPtr(&mNiStringExtraData2); + mNiStringExtraData.next = Nif::ExtraPtr(&mNiStringExtraData2); mNiStringExtraData2.string = "NC___"; mNiStringExtraData2.recType = Nif::RC_NiStringExtraData; mNiTriShape.extra = Nif::ExtraPtr(&mNiStringExtraData); From 480000da07fe5e8138a73226df4aff752f2c1388 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sun, 15 Sep 2019 23:17:36 +0300 Subject: [PATCH 25/48] Use Open action as fallback for companion activation (bug #5161) --- CHANGELOG.md | 1 + apps/openmw/mwclass/creature.cpp | 15 ++++++--------- apps/openmw/mwclass/npc.cpp | 24 ++++++++++++------------ 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f8beb82cbf..b3f458f095 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,6 +138,7 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime + Bug #5161: Creature companions can't be activated when they are knocked down Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwclass/creature.cpp b/apps/openmw/mwclass/creature.cpp index ba0bbf97f9..855f083afd 100644 --- a/apps/openmw/mwclass/creature.cpp +++ b/apps/openmw/mwclass/creature.cpp @@ -454,18 +454,15 @@ namespace MWClass // otherwise wait until death animation if(stats.isDeathAnimationFinished()) return std::shared_ptr(new MWWorld::ActionOpen(ptr)); - - // death animation is not finished, do nothing - return std::shared_ptr (new MWWorld::FailedAction("")); } + else if (!stats.getAiSequence().isInCombat() && !stats.getKnockedDown()) + return std::shared_ptr(new MWWorld::ActionTalk(ptr)); - if(stats.getAiSequence().isInCombat()) - return std::shared_ptr(new MWWorld::FailedAction("")); + // Tribunal and some mod companions oddly enough must use open action as fallback + if (!getScript(ptr).empty() && ptr.getRefData().getLocals().getIntVar(getScript(ptr), "companion")) + return std::shared_ptr(new MWWorld::ActionOpen(ptr)); - if(stats.getKnockedDown()) - return std::shared_ptr(new MWWorld::FailedAction("")); - - return std::shared_ptr(new MWWorld::ActionTalk(ptr)); + return std::shared_ptr(new MWWorld::FailedAction("")); } MWWorld::ContainerStore& Creature::getContainerStore (const MWWorld::Ptr& ptr) const diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 868ab9d85d..0eabe8ff28 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -884,22 +884,22 @@ namespace MWClass // otherwise wait until death animation if(stats.isDeathAnimationFinished()) return std::shared_ptr(new MWWorld::ActionOpen(ptr)); + } + else if (!stats.getAiSequence().isInCombat()) + { + if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak) || stats.getKnockedDown()) + return std::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing - // death animation is not finished, do nothing - return std::shared_ptr (new MWWorld::FailedAction("")); + // Can't talk to werewolves + if (!getNpcStats(ptr).isWerewolf()) + return std::shared_ptr(new MWWorld::ActionTalk(ptr)); } - if(stats.getAiSequence().isInCombat()) - return std::shared_ptr(new MWWorld::FailedAction("")); + // Tribunal and some mod companions oddly enough must use open action as fallback + if (!getScript(ptr).empty() && ptr.getRefData().getLocals().getIntVar(getScript(ptr), "companion")) + return std::shared_ptr(new MWWorld::ActionOpen(ptr)); - if(getCreatureStats(actor).getStance(MWMechanics::CreatureStats::Stance_Sneak) || stats.getKnockedDown()) - return std::shared_ptr(new MWWorld::ActionOpen(ptr)); // stealing - - // Can't talk to werewolfs - if(getNpcStats(ptr).isWerewolf()) - return std::shared_ptr (new MWWorld::FailedAction("")); - - return std::shared_ptr(new MWWorld::ActionTalk(ptr)); + return std::shared_ptr (new MWWorld::FailedAction("")); } MWWorld::ContainerStore& Npc::getContainerStore (const MWWorld::Ptr& ptr) From 83f61d16366b2c93699c2dbbc0d14ec22b9c3d56 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 12 Sep 2019 22:15:41 +0300 Subject: [PATCH 26/48] Support target color in NiMaterialColorController (bug #5159) --- CHANGELOG.md | 3 ++- components/nifosg/controller.cpp | 38 ++++++++++++++++++++++++++++---- components/nifosg/controller.hpp | 16 ++++++++++---- components/nifosg/nifloader.cpp | 8 ++++++- 4 files changed, 55 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4adb325341..dbd44a9cfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -138,8 +138,9 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime - Bug #5188: Objects without a name don't fallback to their ID + Bug #5159: NiMaterialColorController can only control the diffuse color Bug #5161: Creature companions can't be activated when they are knocked down + Bug #5188: Objects without a name don't fallback to their ID Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/components/nifosg/controller.cpp b/components/nifosg/controller.cpp index 4029e9b158..1842e00170 100644 --- a/components/nifosg/controller.cpp +++ b/components/nifosg/controller.cpp @@ -385,8 +385,9 @@ void AlphaController::apply(osg::StateSet *stateset, osg::NodeVisitor *nv) } } -MaterialColorController::MaterialColorController(const Nif::NiPosData *data) +MaterialColorController::MaterialColorController(const Nif::NiPosData *data, TargetColor color) : mData(data->mKeyList, osg::Vec3f(1,1,1)) + , mTargetColor(color) { } @@ -397,6 +398,7 @@ MaterialColorController::MaterialColorController() MaterialColorController::MaterialColorController(const MaterialColorController ©, const osg::CopyOp ©op) : StateSetUpdater(copy, copyop), Controller(copy) , mData(copy.mData) + , mTargetColor(copy.mTargetColor) { } @@ -413,9 +415,37 @@ void MaterialColorController::apply(osg::StateSet *stateset, osg::NodeVisitor *n { osg::Vec3f value = mData.interpKey(getInputValue(nv)); osg::Material* mat = static_cast(stateset->getAttribute(osg::StateAttribute::MATERIAL)); - osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK); - diffuse.set(value.x(), value.y(), value.z(), diffuse.a()); - mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse); + switch (mTargetColor) + { + case Diffuse: + { + osg::Vec4f diffuse = mat->getDiffuse(osg::Material::FRONT_AND_BACK); + diffuse.set(value.x(), value.y(), value.z(), diffuse.a()); + mat->setDiffuse(osg::Material::FRONT_AND_BACK, diffuse); + break; + } + case Specular: + { + osg::Vec4f specular = mat->getSpecular(osg::Material::FRONT_AND_BACK); + specular.set(value.x(), value.y(), value.z(), specular.a()); + mat->setSpecular(osg::Material::FRONT_AND_BACK, specular); + break; + } + case Emissive: + { + osg::Vec4f emissive = mat->getEmission(osg::Material::FRONT_AND_BACK); + emissive.set(value.x(), value.y(), value.z(), emissive.a()); + mat->setEmission(osg::Material::FRONT_AND_BACK, emissive); + break; + } + case Ambient: + default: + { + osg::Vec4f ambient = mat->getAmbient(osg::Material::FRONT_AND_BACK); + ambient.set(value.x(), value.y(), value.z(), ambient.a()); + mat->setAmbient(osg::Material::FRONT_AND_BACK, ambient); + } + } } } diff --git a/components/nifosg/controller.hpp b/components/nifosg/controller.hpp index 36217f31a3..d5fb56f0ef 100644 --- a/components/nifosg/controller.hpp +++ b/components/nifosg/controller.hpp @@ -281,11 +281,15 @@ namespace NifOsg class MaterialColorController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller { - private: - Vec3Interpolator mData; - public: - MaterialColorController(const Nif::NiPosData *data); + enum TargetColor + { + Ambient = 0, + Diffuse = 1, + Specular = 2, + Emissive = 3 + }; + MaterialColorController(const Nif::NiPosData *data, TargetColor color); MaterialColorController(); MaterialColorController(const MaterialColorController& copy, const osg::CopyOp& copyop); @@ -294,6 +298,10 @@ namespace NifOsg virtual void setDefaults(osg::StateSet* stateset); virtual void apply(osg::StateSet* stateset, osg::NodeVisitor* nv); + + private: + Vec3Interpolator mData; + TargetColor mTargetColor; }; class FlipController : public SceneUtil::StateSetUpdater, public SceneUtil::Controller diff --git a/components/nifosg/nifloader.cpp b/components/nifosg/nifloader.cpp index 7699271d35..58e336b5d7 100644 --- a/components/nifosg/nifloader.cpp +++ b/components/nifosg/nifloader.cpp @@ -750,7 +750,13 @@ namespace NifOsg else if (ctrl->recType == Nif::RC_NiMaterialColorController) { const Nif::NiMaterialColorController* matctrl = static_cast(ctrl.getPtr()); - osg::ref_ptr osgctrl(new MaterialColorController(matctrl->data.getPtr())); + // Two bits that correspond to the controlled material color. + // 00: Ambient + // 01: Diffuse + // 10: Specular + // 11: Emissive + MaterialColorController::TargetColor targetColor = static_cast((matctrl->flags >> 4) & 3); + osg::ref_ptr osgctrl(new MaterialColorController(matctrl->data.getPtr(), targetColor)); setupController(matctrl, osgctrl, animflags); composite->addController(osgctrl); } From 4a6d2cbaff17a27a0eac0676804db1a56ecf80b9 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 16 Sep 2019 14:18:41 +0400 Subject: [PATCH 27/48] Do not allow player to take items from evidence chests (bug #3609) --- CHANGELOG.md | 1 + apps/openmw/mwclass/container.cpp | 6 ++++-- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 5 +++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dbd44a9cfc..1422eee754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Bug #3109: SetPos/Position handles actors differently Bug #3282: Unintended behaviour when assigning F3 and Windows keys Bug #3550: Companion from mod attacks the air after combat has ended + Bug #3609: Items from evidence chest are not considered to be stolen if player is allowed to use the chest Bug #3623: Display scaling breaks mouse recognition Bug #3725: Using script function in a non-conditional expression breaks script compilation Bug #3733: Normal maps are inverted on mirrored UVs diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index 958f8351ec..243b6ce117 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -275,9 +275,11 @@ namespace MWClass if (ptr.getCellRef().getTrap() != "") text += "\n#{sTrapped}"; - if (MWBase::Environment::get().getWindowManager()->getFullHelp()) { - text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); + if (MWBase::Environment::get().getWindowManager()->getFullHelp()) + { text += MWGui::ToolTips::getCellRefString(ptr.getCellRef()); text += MWGui::ToolTips::getMiscString(ref->mBase->mScript, "Script"); + if (Misc::StringUtils::ciEqual(ptr.getCellRef().getRefId(), "stolen_goods")) + text += "\nYou can not use evidence chests"; } info.text = text; diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index d450c014c4..6a35224bc7 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -950,6 +950,7 @@ namespace MWMechanics return true; const MWWorld::CellRef& cellref = target.getCellRef(); + // there is no harm to use unlocked doors int lockLevel = cellref.getLockLevel(); if (target.getClass().isDoor() && @@ -1005,6 +1006,10 @@ namespace MWMechanics if (!cellref.getOwner().empty()) victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true, false); + // A special case for evidence chest - we should not allow to take items even if it is technically permitted + if (Misc::StringUtils::ciEqual(cellref.getRefId(), "stolen_goods")) + return false; + return (!isOwned && !isFactionOwned); } From 85bb4a76f6d7020c4fabce652826d0c62527d89a Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Mon, 16 Sep 2019 14:20:43 +0400 Subject: [PATCH 28/48] Improve faction items handling (bug #5164) --- CHANGELOG.md | 1 + apps/openmw/mwbase/mechanicsmanager.hpp | 4 +-- apps/openmw/mwgui/tooltips.cpp | 19 +++++++++++--- .../mwmechanics/mechanicsmanagerimp.cpp | 25 ++++++++++++------- .../mwmechanics/mechanicsmanagerimp.hpp | 4 +-- 5 files changed, 37 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1422eee754..ebf884d860 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -141,6 +141,7 @@ Bug #5149: Failing lock pick attempts isn't always a crime Bug #5159: NiMaterialColorController can only control the diffuse color Bug #5161: Creature companions can't be activated when they are knocked down + Bug #5164: Faction owned items handling is incorrect Bug #5188: Objects without a name don't fallback to their ID Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index aecff2cc6d..d1bb5a83d9 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -130,8 +130,8 @@ namespace MWBase * If this parameter is false, it will be determined by a line-of-sight and awareness check. * @return was the crime seen? */ - virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, - OffenseType type, int arg=0, bool victimAware=false) = 0; + virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, OffenseType type, + const std::string& factionId="", int arg=0, bool victimAware=false) = 0; /// @return false if the attack was considered a "friendly hit" and forgiven virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0; diff --git a/apps/openmw/mwgui/tooltips.cpp b/apps/openmw/mwgui/tooltips.cpp index 3891cf8a26..d6d51d4463 100644 --- a/apps/openmw/mwgui/tooltips.cpp +++ b/apps/openmw/mwgui/tooltips.cpp @@ -651,9 +651,22 @@ namespace MWGui { std::string ret; ret += getMiscString(cellref.getOwner(), "Owner"); - ret += getMiscString(cellref.getFaction(), "Faction"); - if (cellref.getFactionRank() > 0) - ret += getValueString(cellref.getFactionRank(), "Rank"); + const std::string factionId = cellref.getFaction(); + ret += getMiscString(factionId, "Faction"); + if (!factionId.empty() && cellref.getFactionRank() >= 0) + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const ESM::Faction *fact = store.get().search(factionId); + if (fact != nullptr) + { + int rank = cellref.getFactionRank(); + const std::string rankName = fact->mRanks[rank]; + if (rankName.empty()) + ret += getValueString(cellref.getFactionRank(), "Rank"); + else + ret += getMiscString(rankName, "Rank"); + } + } std::vector > itemOwners = MWBase::Environment::get().getMechanicsManager()->getStolenItemOwners(cellref.getRefId()); diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 6a35224bc7..de1780ce7c 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -950,7 +950,6 @@ namespace MWMechanics return true; const MWWorld::CellRef& cellref = target.getCellRef(); - // there is no harm to use unlocked doors int lockLevel = cellref.getLockLevel(); if (target.getClass().isDoor() && @@ -1030,7 +1029,7 @@ namespace MWMechanics if (isAllowedToUse(ptr, bed, victim)) return false; - if(commitCrime(ptr, victim, OT_SleepingInOwnedBed)) + if(commitCrime(ptr, victim, OT_SleepingInOwnedBed, bed.getCellRef().getFaction())) { MWBase::Environment::get().getWindowManager()->messageBox("#{sNotifyMessage64}"); return true; @@ -1044,7 +1043,7 @@ namespace MWMechanics MWWorld::Ptr victim; if (isAllowedToUse(ptr, item, victim)) return; - commitCrime(ptr, victim, OT_Trespassing); + commitCrime(ptr, victim, OT_Trespassing, item.getCellRef().getFaction()); } std::vector > MechanicsManager::getStolenItemOwners(const std::string& itemid) @@ -1125,7 +1124,7 @@ namespace MWMechanics // move items from player to owner and report about theft victim.getClass().getContainerStore(victim).add(item, toRemove, victim); store.remove(item, toRemove, player); - commitCrime(player, victim, OT_Theft, item.getClass().getValue(item) * toRemove); + commitCrime(player, victim, OT_Theft, item.getCellRef().getFaction(), item.getClass().getValue(item) * toRemove); } void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer) @@ -1212,11 +1211,11 @@ namespace MWMechanics mStolenItems[Misc::StringUtils::lowerCase(item.getCellRef().getRefId())][owner] += count; } if (alarm) - commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count); + commitCrime(ptr, victim, OT_Theft, ownerCellRef->getFaction(), item.getClass().getValue(item) * count); } - bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg, bool victimAware) + bool MechanicsManager::commitCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, const std::string& factionId, int arg, bool victimAware) { // NOTE: victim may be empty @@ -1263,13 +1262,13 @@ namespace MWMechanics } if (crimeSeen) - reportCrime(player, victim, type, arg); + reportCrime(player, victim, type, factionId, arg); else if (type == OT_Assault && !victim.isEmpty()) { bool reported = false; if (victim.getClass().isClass(victim, "guard") && !victim.getClass().getCreatureStats(victim).getAiSequence().hasPackage(AiPackage::TypeIdPursue)) - reported = reportCrime(player, victim, type, arg); + reported = reportCrime(player, victim, type, std::string(), arg); if (!reported) startCombat(victim, player); // TODO: combat should be started with an "unaware" flag, which makes the victim flee? @@ -1300,7 +1299,7 @@ namespace MWMechanics return true; } - bool MechanicsManager::reportCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, int arg) + bool MechanicsManager::reportCrime(const MWWorld::Ptr &player, const MWWorld::Ptr &victim, OffenseType type, const std::string& factionId, int arg) { const MWWorld::Store& store = MWBase::Environment::get().getWorld()->getStore().get(); @@ -1471,6 +1470,14 @@ namespace MWMechanics player.getClass().getNpcStats(player).expell(factionID); } } + else if (!factionId.empty()) + { + const std::map& playerRanks = player.getClass().getNpcStats(player).getFactionRanks(); + if (playerRanks.find(Misc::StringUtils::lowerCase(factionId)) != playerRanks.end()) + { + player.getClass().getNpcStats(player).expell(factionId); + } + } if (type == OT_Assault && !victim.isEmpty() && !victim.getClass().getCreatureStats(victim).getAiSequence().isInCombat(player) diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 5a8826a6a5..9e8ce87d15 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -130,7 +130,7 @@ namespace MWMechanics * @return was the crime seen? */ virtual bool commitCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, - OffenseType type, int arg=0, bool victimAware=false) override; + OffenseType type, const std::string& factionId="", int arg=0, bool victimAware=false) override; /// @return false if the attack was considered a "friendly hit" and forgiven virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) override; @@ -247,7 +247,7 @@ namespace MWMechanics bool canReportCrime(const MWWorld::Ptr &actor, const MWWorld::Ptr &victim, std::set &playerFollowers); bool reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim, - OffenseType type, int arg=0); + OffenseType type, const std::string& factionId, int arg=0); }; } From 3a912485ca216fee31029c4575e6d1f592964438 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 17 Sep 2019 21:16:35 +0300 Subject: [PATCH 29/48] openmw.cfg-related fixes Make sure the defaults exist in local openmw.cfg too Make sure constant attenuation settings are defined now that they are implemented Fix config file loading order once and for all (bug #2976) --- CHANGELOG.md | 1 + components/files/configurationmanager.cpp | 7 +- files/openmw.cfg | 2 + files/openmw.cfg.local | 487 ++++++++++++++++++++++ 4 files changed, 494 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf884d860..03d84cedb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ Bug #1515: Opening console masks dialogue, inventory menu Bug #2395: Duplicated plugins in the launcher when multiple data directories provide the same plugin Bug #2969: Scripted items can stack + Bug #2976: Data lines in global openmw.cfg take priority over user openmw.cfg Bug #2987: Editor: some chance and AI data fields can overflow Bug #3006: 'else if' operator breaks script compilation Bug #3109: SetPos/Position handles actors differently diff --git a/components/files/configurationmanager.cpp b/components/files/configurationmanager.cpp index 3df6faf623..3bc6e17729 100644 --- a/components/files/configurationmanager.cpp +++ b/components/files/configurationmanager.cpp @@ -51,9 +51,6 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m bool silent = mSilent; mSilent = quiet; - loadConfig(mFixedPath.getUserConfigPath(), variables, description); - boost::program_options::notify(variables); - // read either local or global config depending on type of installation bool loaded = loadConfig(mFixedPath.getLocalPath(), variables, description); boost::program_options::notify(variables); @@ -63,6 +60,10 @@ void ConfigurationManager::readConfiguration(boost::program_options::variables_m boost::program_options::notify(variables); } + // User config has the highest priority. + loadConfig(mFixedPath.getUserConfigPath(), variables, description); + boost::program_options::notify(variables); + mSilent = silent; } diff --git a/files/openmw.cfg b/files/openmw.cfg index d71b6b53d5..afbf0810cc 100644 --- a/files/openmw.cfg +++ b/files/openmw.cfg @@ -13,6 +13,8 @@ script-blacklist=wereDreamScript2 script-blacklist=wereDreamScript3 # lighting +fallback=LightAttenuation_UseConstant,0 +fallback=LightAttenuation_ConstantValue,0.0 fallback=LightAttenuation_UseLinear,1 fallback=LightAttenuation_LinearMethod,1 fallback=LightAttenuation_LinearValue,3.0 diff --git a/files/openmw.cfg.local b/files/openmw.cfg.local index 804d168b30..76f829379b 100644 --- a/files/openmw.cfg.local +++ b/files/openmw.cfg.local @@ -12,3 +12,490 @@ script-blacklist=doortestwarp script-blacklist=WereChange2Script script-blacklist=wereDreamScript2 script-blacklist=wereDreamScript3 + +# lighting +fallback=LightAttenuation_UseConstant,0 +fallback=LightAttenuation_ConstantValue,0.0 +fallback=LightAttenuation_UseLinear,1 +fallback=LightAttenuation_LinearMethod,1 +fallback=LightAttenuation_LinearValue,3.0 +fallback=LightAttenuation_LinearRadiusMult,1.0 +fallback=LightAttenuation_UseQuadratic,0 +fallback=LightAttenuation_QuadraticMethod,2 +fallback=LightAttenuation_QuadraticValue,16.0 +fallback=LightAttenuation_QuadraticRadiusMult,1.0 +fallback=LightAttenuation_OutQuadInLin,0 + +# inventory +fallback=Inventory_DirectionalDiffuseR,1.0 +fallback=Inventory_DirectionalDiffuseG,1.0 +fallback=Inventory_DirectionalDiffuseB,1.0 +fallback=Inventory_DirectionalAmbientR,0.0 +fallback=Inventory_DirectionalAmbientG,0.0 +fallback=Inventory_DirectionalAmbientB,0.0 +fallback=Inventory_DirectionalRotationX,110 +fallback=Inventory_DirectionalRotationY,90 +fallback=Inventory_UniformScaling,0 + +# water effects +fallback=Water_Map_Alpha,0.4 +fallback=Water_World_Alpha,0.75 +fallback=Water_SurfaceTextureSize,128 +fallback=Water_SurfaceTileCount,10 +fallback=Water_SurfaceFPS,12 +fallback=Water_SurfaceTexture,water +fallback=Water_SurfaceFrameCount,32 +fallback=Water_TileTextureDivisor,4.75 +fallback=Water_RippleTexture,ripple +fallback=Water_RippleFrameCount,4 +fallback=Water_RippleLifetime,3.0 +fallback=Water_MaxNumberRipples,75 +fallback=Water_RippleScale,0.15, 6.5 +fallback=Water_RippleRotSpeed,0.5 +fallback=Water_RippleAlphas,0.7, 0.1, 0.01 +fallback=Water_NearWaterRadius,1000 +fallback=Water_NearWaterPoints,8 +fallback=Water_NearWaterUnderwaterFreq,0.3 +fallback=Water_NearWaterUnderwaterVolume,0.9 +fallback=Water_NearWaterIndoorTolerance,512.0 +fallback=Water_NearWaterOutdoorTolerance,1024.0 +fallback=Water_NearWaterIndoorID,Water Layer +fallback=Water_NearWaterOutdoorID,Water Layer +fallback=Water_UnderwaterSunriseFog,3 +fallback=Water_UnderwaterDayFog,2.5 +fallback=Water_UnderwaterSunsetFog,3 +fallback=Water_UnderwaterNightFog,4 +fallback=Water_UnderwaterIndoorFog,3 +fallback=Water_UnderwaterColor,012,030,037 +fallback=Water_UnderwaterColorWeight,0.85 + +# fonts +fallback=Fonts_Font_0,magic_cards_regular +fallback=Fonts_Font_1,century_gothic_font_regular +fallback=Fonts_Font_2,daedric_font +fallback=FontColor_color_normal,202,165,96 +fallback=FontColor_color_normal_over,223,201,159 +fallback=FontColor_color_normal_pressed,243,237,221 +fallback=FontColor_color_active,96,112,202 +fallback=FontColor_color_active_over,159,169,223 +fallback=FontColor_color_active_pressed,223,226,244 +fallback=FontColor_color_disabled,179,168,135 +fallback=FontColor_color_disabled_over,223,201,159 +fallback=FontColor_color_disabled_pressed,243,237,221 +fallback=FontColor_color_link,112,126,207 +fallback=FontColor_color_link_over,143,155,218 +fallback=FontColor_color_link_pressed,175,184,228 +fallback=FontColor_color_journal_link,37,49,112 +fallback=FontColor_color_journal_link_over,58,77,175 +fallback=FontColor_color_journal_link_pressed,112,126,207 +fallback=FontColor_color_journal_topic,0,0,0 +fallback=FontColor_color_journal_topic_over,58,77,175 +fallback=FontColor_color_journal_topic_pressed,112,126,207 +fallback=FontColor_color_answer,150,50,30 +fallback=FontColor_color_answer_over,223,201,159 +fallback=FontColor_color_answer_pressed,243,237,221 +fallback=FontColor_color_header,223,201,159 +fallback=FontColor_color_notify,223,201,159 +fallback=FontColor_color_big_normal,202,165,96 +fallback=FontColor_color_big_normal_over,223,201,159 +fallback=FontColor_color_big_normal_pressed,243,237,221 +fallback=FontColor_color_big_link,112,126,207 +fallback=FontColor_color_big_link_over,143,155,218 +fallback=FontColor_color_big_link_pressed,175,184,228 +fallback=FontColor_color_big_answer,150,50,30 +fallback=FontColor_color_big_answer_over,223,201,159 +fallback=FontColor_color_big_answer_pressed,243,237,22 +fallback=FontColor_color_big_header,223,201,159 +fallback=FontColor_color_big_notify,223,201,159 +fallback=FontColor_color_background,0,0,0 +fallback=FontColor_color_focus,80,80,80 +fallback=FontColor_color_health,200,60,30 +fallback=FontColor_color_magic,53,69,159 +fallback=FontColor_color_fatigue,0,150,60 +fallback=FontColor_color_misc,0,205,205 +fallback=FontColor_color_weapon_fill,200,60,30 +fallback=FontColor_color_magic_fill,200,60,30 +fallback=FontColor_color_positive,223,201,159 +fallback=FontColor_color_negative,200,60,30 +fallback=FontColor_color_count,223,201,159 + +# leveling +fallback=Level_Up_Level2,The last few days have opened your eyes: you realize now that there is more to the life than you thought. An uncertain future awaits you. +fallback=Level_Up_Level3,You finally come to understand that great doings start from hard work and determination. +fallback=Level_Up_Level4,After reminiscing upon all that time you lost in your youth, it's as clear as day to you now: this - this is the life, and all the experience you gain gives you the tools you need to succeed in it. +fallback=Level_Up_Level5,Things seem to be working out for you. As you become more capable, the world is opening up. +fallback=Level_Up_Level6,With every push you did to gain knowledge, and yet your thirst for it increased, you realize there is so much more to learn still. +fallback=Level_Up_Level7,You dig deep within yourself, trying to finally become the one who you thought you would be... but there's much to keep digging through. +fallback=Level_Up_Level8,Success doesn't come easily, but you make it appear that way to others. +fallback=Level_Up_Level9,Everything may slowly become a second nature to you, but it also can turn just a bit more dangerous. +fallback=Level_Up_Level10,Nothing in life is easy, or it wouldn't have been worth the blood, sweat and tears. +fallback=Level_Up_Level11,Working smarter, not harder is something even a barbarian could benefit from. +fallback=Level_Up_Level12,Perhaps some would call you delusional for keeping at it, but you know better. Your dilegence has already paid off, after all. +fallback=Level_Up_Level13,One night's sleep is all the difference between something being difficult and something being easy. +fallback=Level_Up_Level14,After waking up, you wonder: could today be the best day in your life? You never know. +fallback=Level_Up_Level15,Ouch! You lean back feeling your whole body for what seems the first time. You'll be more mindful in the future -- you can only live once. +fallback=Level_Up_Level16,Trusting your instincts has gotten you this far, but now it's clear to you that you need to be smarter to survive. +fallback=Level_Up_Level17,You're forging your spirit in the crucible that is experience. Be ever vigilant. +fallback=Level_Up_Level18,The frustrations of the day before vanish as you wake up. Today is a new day. +fallback=Level_Up_Level19,Today isn't yesterday, you feel that deep inside. You know that there is still more to this life. +fallback=Level_Up_Level20,Luck has never been a factor in your success -- that's obvious from the scars on your body and from the number of trails you've endured. +fallback=Level_Up_Default,Through sheer force of will, you push onwards and upwards. The toil of your persistence is paying off. + +# character creation +fallback=Question_1_Question,Before you lies a creature you have never seen before. Its hind leg is caught in a hunter's trap, and you can tell that the leg is broken. What will you do? +fallback=Question_1_AnswerOne,Pull out you knife for a short and merciful kill. +fallback=Question_1_AnswerTwo,Reach into your herbal pouch to find something to ease its suffering before putting it to sleep. +fallback=Question_1_AnswerThree,Leave the leg alone, but take the time to observe and learn from this odd creature. +fallback=Question_1_Sound,Voice\CharGen\QA1.mp3 +fallback=Question_2_Question,Your mother suggests you to help with work around your family household. Do you decide to... +fallback=Question_2_AnswerOne,Help your father with fence post replacement? +fallback=Question_2_AnswerTwo,Collect a few herbs in the forest for tonight's supper? +fallback=Question_2_AnswerThree,Help the fish to find their way into the kitchen? +fallback=Question_2_Sound,Voice\CharGen\QA2.mp3 +fallback=Question_3_Question,Your brother teases you mercilessly in front of everyone with embarrassing details you would rather have forgotten. +fallback=Question_3_AnswerOne,Give him a black-eye and dare him to keep it up. +fallback=Question_3_AnswerTwo,Beat him to the punch and play it up -- if you can control the negative, then he can't embarrass you. +fallback=Question_3_AnswerThree,Wait until he sleeps, put his hand in a bowl of water and call everyone around the next day to see the results. +fallback=Question_3_Sound,Voice\CharGen\QA3.mp3 +fallback=Question_4_Question,Rumor has it that the King's security console has a new tool at their disposal for sniffing out the truth, which could be used for reading minds. +fallback=Question_4_AnswerOne,You recoil at the thought of someone being able to read your thoughts. It's not that you think something that you'll ever act on it. +fallback=Question_4_AnswerTwo,For those who have done nothing, there is nothing to fear. This is just yet another utility for catching thieves, murderers and plots against the crown. +fallback=Question_4_AnswerThree,While you loath the idea of someone reading your mind, you accept that it does have its uses if tempered by law and common sense. You wouldn't believe the mind of a madman. +fallback=Question_4_Sound,Voice\CharGen\QA4.mp3 +fallback=Question_5_Question,You are returning home from the market after acquiring supplies, and notice that one of the merchants had given you too much back in change. +fallback=Question_5_AnswerOne,How dreadful, what if it was you? You head back to the merchant. +fallback=Question_5_AnswerTwo,Happy days indeed. Put that extra money towards the needs of your family? +fallback=Question_5_AnswerThree,You win some and you lose some. In this case you have won and they have lost, and the oversight is the merchant's problem, not yours, right? +fallback=Question_5_Sound,Voice\CharGen\QA5.mp3 +fallback=Question_6_Question,While at market, a noble yells out to the city watch about a theft. As you turn around a man bumps into you and drops a sack, startled he darts into the crowd. +fallback=Question_6_AnswerOne,You pick up the sack and head over to the noble to return his property? +fallback=Question_6_AnswerTwo,Just walk away, the last thing you need is someone thinking you had anything to do with it? +fallback=Question_6_AnswerThree,Finders, keepers... you whistle as you walk away with the bag hidden? +fallback=Question_6_Sound,Voice\CharGen\QA6.mp3 +fallback=Question_7_Question,If it's one thing you hate, it's cleaning out the stalls. It has to be done before sunset before the critters return. On your way there an old friend greets you and offers to help if you promise to help them in the future. +fallback=Question_7_AnswerOne,You thank him for the offer but would rather get it over with and not make promises you can't keep? +fallback=Question_7_AnswerTwo,You reason that two pairs of hands are better than one regardless of the task? +fallback=Question_7_AnswerThree,You say that it sounds great and anything is better than cleaning the stalls? +fallback=Question_7_Sound,Voice\CharGen\QA7.mp3 +fallback=Question_8_Question,You just climbed down the ladder after working on the roof. Your mother thanks you for the hard work but just at the moment you notice that a hammer is about to fall down on her head. +fallback=Question_8_AnswerOne,You lunge at your mother, pushing her out the way while the hammer falls on top of you? +fallback=Question_8_AnswerTwo,Try to use the ladder to intercept the hammer before it lands on her? +fallback=Question_8_AnswerThree,Warn her to take a step back? +fallback=Question_8_Sound,Voice\CharGen\QA8.mp3 +fallback=Question_9_Question,It's the end of the week, and you have just got your wages for your hard work. You decide to take the quick way back home, darting into a alley only to be confronted by ruffians who demand that you empty your pockets. +fallback=Question_9_AnswerOne,You tell them to go pack sand, planting your feet and raising your fists? +fallback=Question_9_AnswerTwo,Acting dejected, you turn your wages over. You know that you can count on your friends to help you track these brigands down and recover what's yours? +fallback=Question_9_AnswerThree,Tossing the sack into the air, you charge the leader who's attention is squarely focused on the coins in flight? +fallback=Question_9_Sound,Voice\CharGen\QA9.mp3 +fallback=Question_10_Question,Upon coming to town, you see a clown running at you with an angry mob following after him. +fallback=Question_10_AnswerOne,Stand your ground, you hate clowns? +fallback=Question_10_AnswerTwo,Move out of the way, letting fate decide the clown's fate? +fallback=Question_10_AnswerThree,Come to the clown's aid, clowns are people too? +fallback=Question_10_Sound,Voice\CharGen\QA10.mp3 + +# blood splatters +fallback=Blood_Model_0,BloodSplat.nif +fallback=Blood_Model_1,BloodSplat2.nif +fallback=Blood_Model_2,BloodSplat3.nif +fallback=Blood_Texture_0,Tx_Blood.dds +fallback=Blood_Texture_1,Tx_Blood_White.dds +fallback=Blood_Texture_2,Tx_Blood_Gold.dds +fallback=Blood_Texture_Name_0,Default (Red) +fallback=Blood_Texture_Name_1,Skeleton (White) +fallback=Blood_Texture_Name_2,Metal Sparks (Gold) + +# movies +fallback=Movies_Project_Logo,openmw_project_logo.webm +fallback=Movies_Game_Logo,openmw_example_suite_logo.webm +fallback=Movies_New_Game,new_game.webm +fallback=Movies_Loading,loading.webm +fallback=Movies_Options_Menu,options_menu.webm + +# weather +fallback=Weather_Thunderstorm_Thunder_Sound_ID_0,Thunder0 +fallback=Weather_Thunderstorm_Thunder_Sound_ID_1,Thunder1 +fallback=Weather_Thunderstorm_Thunder_Sound_ID_2,Thunder2 +fallback=Weather_Thunderstorm_Thunder_Sound_ID_3,Thunder3 +fallback=Weather_Sunrise_Time,6 +fallback=Weather_Sunset_Time,18 +fallback=Weather_Sunrise_Duration,2 +fallback=Weather_Sunset_Duration,2 +fallback=Weather_Hours_Between_Weather_Changes,20 +fallback=Weather_Thunderstorm_Thunder_Frequency,.4 +fallback=Weather_Thunderstorm_Thunder_Threshold,0.6 +fallback=Weather_EnvReduceColor,255,255,255,255 +fallback=Weather_LerpCloseColor,037,046,048,255 +fallback=Weather_BumpFadeColor,230,239,255,255 +fallback=Weather_AlphaReduce,0.35 +fallback=Weather_Minimum_Time_Between_Environmental_Sounds,1.0 +fallback=Weather_Maximum_Time_Between_Environmental_Sounds,5.0 +fallback=Weather_Sun_Glare_Fader_Max,0.5 +fallback=Weather_Sun_Glare_Fader_Angle_Max,30.0 +fallback=Weather_Sun_Glare_Fader_Color,222,095,039 +fallback=Weather_Timescale_Clouds,0 +fallback=Weather_Precip_Gravity,575 +fallback=Weather_Rain_Ripples,1 +fallback=Weather_Rain_Ripple_Radius,1024 +fallback=Weather_Rain_Ripples_Per_Drop,1 +fallback=Weather_Rain_Ripple_Scale,0.3 +fallback=Weather_Rain_Ripple_Speed,1.0 +fallback=Weather_Fog_Depth_Change_Speed,3 +fallback=Weather_Sky_Pre-Sunrise_Time,.5 +fallback=Weather_Sky_Post-Sunrise_Time,1 +fallback=Weather_Sky_Pre-Sunset_Time,1.5 +fallback=Weather_Sky_Post-Sunset_Time,.5 +fallback=Weather_Ambient_Pre-Sunrise_Time,.5 +fallback=Weather_Ambient_Post-Sunrise_Time,2 +fallback=Weather_Ambient_Pre-Sunset_Time,1 +fallback=Weather_Ambient_Post-Sunset_Time,1.25 +fallback=Weather_Fog_Pre-Sunrise_Time,.5 +fallback=Weather_Fog_Post-Sunrise_Time,1 +fallback=Weather_Fog_Pre-Sunset_Time,2 +fallback=Weather_Fog_Post-Sunset_Time,1 +fallback=Weather_Sun_Pre-Sunrise_Time,0 +fallback=Weather_Sun_Post-Sunrise_Time,0 +fallback=Weather_Sun_Pre-Sunset_Time,1 +fallback=Weather_Sun_Post-Sunset_Time,1.25 +fallback=Weather_Stars_Post-Sunset_Start,1 +fallback=Weather_Stars_Pre-Sunrise_Finish,2 +fallback=Weather_Stars_Fading_Duration,2 +fallback=Weather_Snow_Ripples,0 +fallback=Weather_Snow_Ripple_Radius,1024 +fallback=Weather_Snow_Ripples_Per_Flake,1 +fallback=Weather_Snow_Ripple_Scale,0.3 +fallback=Weather_Snow_Ripple_Speed,1.0 +fallback=Weather_Snow_Gravity_Scale,0.1 +fallback=Weather_Snow_High_Kill,700 +fallback=Weather_Snow_Low_Kill,150 +fallback=Weather_Clear_Cloud_Texture,Tx_Sky_Clear.dds +fallback=Weather_Clear_Clouds_Maximum_Percent,1.0 +fallback=Weather_Clear_Transition_Delta,.015 +fallback=Weather_Clear_Sky_Sunrise_Color,117,141,164 +fallback=Weather_Clear_Sky_Day_Color,095,135,203 +fallback=Weather_Clear_Sky_Sunset_Color,056,089,129 +fallback=Weather_Clear_Sky_Night_Color,009,010,011 +fallback=Weather_Clear_Fog_Sunrise_Color,255,189,157 +fallback=Weather_Clear_Fog_Day_Color,206,227,255 +fallback=Weather_Clear_Fog_Sunset_Color,255,189,157 +fallback=Weather_Clear_Fog_Night_Color,009,010,011 +fallback=Weather_Clear_Ambient_Sunrise_Color,047,066,096 +fallback=Weather_Clear_Ambient_Day_Color,137,140,160 +fallback=Weather_Clear_Ambient_Sunset_Color,068,075,096 +fallback=Weather_Clear_Ambient_Night_Color,032,035,042 +fallback=Weather_Clear_Sun_Sunrise_Color,242,159,119 +fallback=Weather_Clear_Sun_Day_Color,255,252,238 +fallback=Weather_Clear_Sun_Sunset_Color,255,114,079 +fallback=Weather_Clear_Sun_Night_Color,059,097,176 +fallback=Weather_Clear_Sun_Disc_Sunset_Color,255,189,157 +fallback=Weather_Clear_Land_Fog_Day_Depth,.69 +fallback=Weather_Clear_Land_Fog_Night_Depth,.69 +fallback=Weather_Clear_Wind_Speed,.1 +fallback=Weather_Clear_Cloud_Speed,1.25 +fallback=Weather_Clear_Glare_View,1 +fallback=Weather_Clear_Ambient_Loop_Sound_ID,None +fallback=Weather_Cloudy_Cloud_Texture,Tx_Sky_Cloudy.dds +fallback=Weather_Cloudy_Clouds_Maximum_Percent,1.0 +fallback=Weather_Cloudy_Transition_Delta,.015 +fallback=Weather_Cloudy_Sky_Sunrise_Color,126,158,173 +fallback=Weather_Cloudy_Sky_Day_Color,117,160,215 +fallback=Weather_Cloudy_Sky_Sunset_Color,111,114,159 +fallback=Weather_Cloudy_Sky_Night_Color,009,010,011 +fallback=Weather_Cloudy_Fog_Sunrise_Color,255,207,149 +fallback=Weather_Cloudy_Fog_Day_Color,245,235,224 +fallback=Weather_Cloudy_Fog_Sunset_Color,255,155,106 +fallback=Weather_Cloudy_Fog_Night_Color,009,010,011 +fallback=Weather_Cloudy_Ambient_Sunrise_Color,066,074,087 +fallback=Weather_Cloudy_Ambient_Day_Color,137,145,160 +fallback=Weather_Cloudy_Ambient_Sunset_Color,071,080,092 +fallback=Weather_Cloudy_Ambient_Night_Color,032,039,054 +fallback=Weather_Cloudy_Sun_Sunrise_Color,241,177,099 +fallback=Weather_Cloudy_Sun_Day_Color,255,236,221 +fallback=Weather_Cloudy_Sun_Sunset_Color,255,089,000 +fallback=Weather_Cloudy_Sun_Night_Color,077,091,124 +fallback=Weather_Cloudy_Sun_Disc_Sunset_Color,255,202,179 +fallback=Weather_Cloudy_Land_Fog_Day_Depth,.72 +fallback=Weather_Cloudy_Land_Fog_Night_Depth,.72 +fallback=Weather_Cloudy_Wind_Speed,.2 +fallback=Weather_Cloudy_Cloud_Speed,2 +fallback=Weather_Cloudy_Glare_View,1 +fallback=Weather_Cloudy_Ambient_Loop_Sound_ID,None +fallback=Weather_Foggy_Cloud_Texture,Tx_Sky_Foggy.dds +fallback=Weather_Foggy_Clouds_Maximum_Percent,1.0 +fallback=Weather_Foggy_Transition_Delta,.015 +fallback=Weather_Foggy_Sky_Sunrise_Color,197,190,180 +fallback=Weather_Foggy_Sky_Day_Color,184,211,228 +fallback=Weather_Foggy_Sky_Sunset_Color,142,159,176 +fallback=Weather_Foggy_Sky_Night_Color,018,023,028 +fallback=Weather_Foggy_Fog_Sunrise_Color,173,164,148 +fallback=Weather_Foggy_Fog_Day_Color,150,187,209 +fallback=Weather_Foggy_Fog_Sunset_Color,113,135,157 +fallback=Weather_Foggy_Fog_Night_Color,019,024,029 +fallback=Weather_Foggy_Ambient_Sunrise_Color,048,043,037 +fallback=Weather_Foggy_Ambient_Day_Color,092,109,120 +fallback=Weather_Foggy_Ambient_Sunset_Color,029,053,076 +fallback=Weather_Foggy_Ambient_Night_Color,028,033,039 +fallback=Weather_Foggy_Sun_Sunrise_Color,177,162,137 +fallback=Weather_Foggy_Sun_Day_Color,111,131,151 +fallback=Weather_Foggy_Sun_Sunset_Color,125,157,189 +fallback=Weather_Foggy_Sun_Night_Color,081,100,119 +fallback=Weather_Foggy_Sun_Disc_Sunset_Color,223,223,223 +fallback=Weather_Foggy_Land_Fog_Day_Depth,1.0 +fallback=Weather_Foggy_Land_Fog_Night_Depth,1.9 +fallback=Weather_Foggy_Wind_Speed,0 +fallback=Weather_Foggy_Cloud_Speed,1.25 +fallback=Weather_Foggy_Glare_View,0.25 +fallback=Weather_Foggy_Ambient_Loop_Sound_ID,None +fallback=Weather_Thunderstorm_Cloud_Texture,Tx_Sky_Thunder.dds +fallback=Weather_Thunderstorm_Clouds_Maximum_Percent,0.66 +fallback=Weather_Thunderstorm_Transition_Delta,.030 +fallback=Weather_Thunderstorm_Sky_Sunrise_Color,035,036,039 +fallback=Weather_Thunderstorm_Sky_Day_Color,097,104,115 +fallback=Weather_Thunderstorm_Sky_Sunset_Color,035,036,039 +fallback=Weather_Thunderstorm_Sky_Night_Color,019,020,022 +fallback=Weather_Thunderstorm_Fog_Sunrise_Color,070,074,085 +fallback=Weather_Thunderstorm_Fog_Day_Color,097,104,115 +fallback=Weather_Thunderstorm_Fog_Sunset_Color,070,074,085 +fallback=Weather_Thunderstorm_Fog_Night_Color,019,020,022 +fallback=Weather_Thunderstorm_Ambient_Sunrise_Color,054,054,054 +fallback=Weather_Thunderstorm_Ambient_Day_Color,090,090,090 +fallback=Weather_Thunderstorm_Ambient_Sunset_Color,054,054,054 +fallback=Weather_Thunderstorm_Ambient_Night_Color,049,051,054 +fallback=Weather_Thunderstorm_Sun_Sunrise_Color,091,099,122 +fallback=Weather_Thunderstorm_Sun_Day_Color,138,144,155 +fallback=Weather_Thunderstorm_Sun_Sunset_Color,096,101,117 +fallback=Weather_Thunderstorm_Sun_Night_Color,055,076,110 +fallback=Weather_Thunderstorm_Sun_Disc_Sunset_Color,128,128,128 +fallback=Weather_Thunderstorm_Land_Fog_Day_Depth,1 +fallback=Weather_Thunderstorm_Land_Fog_Night_Depth,1.15 +fallback=Weather_Thunderstorm_Wind_Speed,.5 +fallback=Weather_Thunderstorm_Cloud_Speed,3 +fallback=Weather_Thunderstorm_Glare_View,0 +fallback=Weather_Thunderstorm_Rain_Loop_Sound_ID,rain heavy +fallback=Weather_Thunderstorm_Using_Precip,1 +fallback=Weather_Thunderstorm_Rain_Diameter,600 +fallback=Weather_Thunderstorm_Rain_Height_Min,200 +fallback=Weather_Thunderstorm_Rain_Height_Max,700 +fallback=Weather_Thunderstorm_Rain_Threshold,0.6 +fallback=Weather_Thunderstorm_Max_Raindrops,650 +fallback=Weather_Thunderstorm_Rain_Entrance_Speed,5 +fallback=Weather_Thunderstorm_Ambient_Loop_Sound_ID,None +fallback=Weather_Thunderstorm_Flash_Decrement,4 +fallback=Weather_Rain_Cloud_Texture,Tx_Sky_Rainy.dds +fallback=Weather_Rain_Clouds_Maximum_Percent,0.66 +fallback=Weather_Rain_Transition_Delta,.015 +fallback=Weather_Rain_Sky_Sunrise_Color,071,074,075 +fallback=Weather_Rain_Sky_Day_Color,116,120,122 +fallback=Weather_Rain_Sky_Sunset_Color,073,073,073 +fallback=Weather_Rain_Sky_Night_Color,024,025,026 +fallback=Weather_Rain_Fog_Sunrise_Color,071,074,075 +fallback=Weather_Rain_Fog_Day_Color,116,120,122 +fallback=Weather_Rain_Fog_Sunset_Color,073,073,073 +fallback=Weather_Rain_Fog_Night_Color,024,025,026 +fallback=Weather_Rain_Ambient_Sunrise_Color,097,090,088 +fallback=Weather_Rain_Ambient_Day_Color,105,110,113 +fallback=Weather_Rain_Ambient_Sunset_Color,088,097,097 +fallback=Weather_Rain_Ambient_Night_Color,050,055,067 +fallback=Weather_Rain_Sun_Sunrise_Color,131,122,120 +fallback=Weather_Rain_Sun_Day_Color,149,157,170 +fallback=Weather_Rain_Sun_Sunset_Color,120,126,131 +fallback=Weather_Rain_Sun_Night_Color,050,062,101 +fallback=Weather_Rain_Sun_Disc_Sunset_Color,128,128,128 +fallback=Weather_Rain_Land_Fog_Day_Depth,.8 +fallback=Weather_Rain_Land_Fog_Night_Depth,.8 +fallback=Weather_Rain_Wind_Speed,.3 +fallback=Weather_Rain_Cloud_Speed,2 +fallback=Weather_Rain_Glare_View,0 +fallback=Weather_Rain_Rain_Loop_Sound_ID,Rain +fallback=Weather_Rain_Using_Precip,1 +fallback=Weather_Rain_Rain_Diameter,600 +fallback=Weather_Rain_Rain_Height_Min,200 +fallback=Weather_Rain_Rain_Height_Max,700 +fallback=Weather_Rain_Rain_Threshold,0.6 +fallback=Weather_Rain_Rain_Entrance_Speed,7 +fallback=Weather_Rain_Ambient_Loop_Sound_ID,None +fallback=Weather_Rain_Max_Raindrops,450 +fallback=Weather_Overcast_Cloud_Texture,Tx_Sky_Overcast.dds +fallback=Weather_Overcast_Clouds_Maximum_Percent,1.0 +fallback=Weather_Overcast_Transition_Delta,.015 +fallback=Weather_Overcast_Sky_Sunrise_Color,091,099,106 +fallback=Weather_Overcast_Sky_Day_Color,143,146,149 +fallback=Weather_Overcast_Sky_Sunset_Color,108,115,121 +fallback=Weather_Overcast_Sky_Night_Color,019,022,025 +fallback=Weather_Overcast_Fog_Sunrise_Color,091,099,106 +fallback=Weather_Overcast_Fog_Day_Color,143,146,149 +fallback=Weather_Overcast_Fog_Sunset_Color,108,115,121 +fallback=Weather_Overcast_Fog_Night_Color,019,022,025 +fallback=Weather_Overcast_Ambient_Sunrise_Color,084,088,092 +fallback=Weather_Overcast_Ambient_Day_Color,093,096,105 +fallback=Weather_Overcast_Ambient_Sunset_Color,083,077,075 +fallback=Weather_Overcast_Ambient_Night_Color,057,060,066 +fallback=Weather_Overcast_Sun_Sunrise_Color,087,125,163 +fallback=Weather_Overcast_Sun_Day_Color,163,169,183 +fallback=Weather_Overcast_Sun_Sunset_Color,085,103,157 +fallback=Weather_Overcast_Sun_Night_Color,032,054,100 +fallback=Weather_Overcast_Sun_Disc_Sunset_Color,128,128,128 +fallback=Weather_Overcast_Land_Fog_Day_Depth,.70 +fallback=Weather_Overcast_Land_Fog_Night_Depth,.70 +fallback=Weather_Overcast_Wind_Speed,.2 +fallback=Weather_Overcast_Cloud_Speed,1.5 +fallback=Weather_Overcast_Glare_View,0 +fallback=Weather_Overcast_Ambient_Loop_Sound_ID,None +fallback=Weather_Snow_Cloud_Texture,Tx_Sky_Snow.dds +fallback=Weather_Snow_Clouds_Maximum_Percent,1.0 +fallback=Weather_Snow_Transition_Delta,.015 +fallback=Weather_Snow_Sky_Sunrise_Color,106,091,091 +fallback=Weather_Snow_Sky_Day_Color,153,158,166 +fallback=Weather_Snow_Sky_Sunset_Color,096,115,134 +fallback=Weather_Snow_Sky_Night_Color,031,035,039 +fallback=Weather_Snow_Fog_Sunrise_Color,106,091,091 +fallback=Weather_Snow_Fog_Day_Color,153,158,166 +fallback=Weather_Snow_Fog_Sunset_Color,096,115,134 +fallback=Weather_Snow_Fog_Night_Color,031,035,039 +fallback=Weather_Snow_Ambient_Sunrise_Color,092,084,084 +fallback=Weather_Snow_Ambient_Day_Color,093,096,105 +fallback=Weather_Snow_Ambient_Sunset_Color,070,079,087 +fallback=Weather_Snow_Ambient_Night_Color,049,058,068 +fallback=Weather_Snow_Sun_Sunrise_Color,141,109,109 +fallback=Weather_Snow_Sun_Day_Color,163,169,183 +fallback=Weather_Snow_Sun_Sunset_Color,101,121,141 +fallback=Weather_Snow_Sun_Night_Color,055,066,077 +fallback=Weather_Snow_Sun_Disc_Sunset_Color,128,128,128 +fallback=Weather_Snow_Land_Fog_Day_Depth,1.0 +fallback=Weather_Snow_Land_Fog_Night_Depth,1.2 +fallback=Weather_Snow_Wind_Speed,0 +fallback=Weather_Snow_Cloud_Speed,1.5 +fallback=Weather_Snow_Glare_View,0 +fallback=Weather_Snow_Snow_Diameter,800 +fallback=Weather_Snow_Snow_Height_Min,400 +fallback=Weather_Snow_Snow_Height_Max,700 +fallback=Weather_Snow_Snow_Entrance_Speed,6 +fallback=Weather_Snow_Max_Snowflakes,750 +fallback=Weather_Snow_Ambient_Loop_Sound_ID,None +fallback=Weather_Snow_Snow_Threshold,0.5 +fallback=Weather_Blizzard_Cloud_Texture,Tx_Sky_Blizzard.dds +fallback=Weather_Blizzard_Clouds_Maximum_Percent,1.0 +fallback=Weather_Blizzard_Transition_Delta,.030 +fallback=Weather_Blizzard_Sky_Sunrise_Color,091,099,106 +fallback=Weather_Blizzard_Sky_Day_Color,121,133,145 +fallback=Weather_Blizzard_Sky_Sunset_Color,108,115,121 +fallback=Weather_Blizzard_Sky_Night_Color,027,029,031 +fallback=Weather_Blizzard_Fog_Sunrise_Color,091,099,106 +fallback=Weather_Blizzard_Fog_Day_Color,121,133,145 +fallback=Weather_Blizzard_Fog_Sunset_Color,108,115,121 +fallback=Weather_Blizzard_Fog_Night_Color,021,024,028 +fallback=Weather_Blizzard_Ambient_Sunrise_Color,084,088,092 +fallback=Weather_Blizzard_Ambient_Day_Color,093,096,105 +fallback=Weather_Blizzard_Ambient_Sunset_Color,083,077,075 +fallback=Weather_Blizzard_Ambient_Night_Color,053,062,070 +fallback=Weather_Blizzard_Sun_Sunrise_Color,114,128,146 +fallback=Weather_Blizzard_Sun_Day_Color,163,169,183 +fallback=Weather_Blizzard_Sun_Sunset_Color,106,114,136 +fallback=Weather_Blizzard_Sun_Night_Color,057,066,074 +fallback=Weather_Blizzard_Sun_Disc_Sunset_Color,128,128,128 +fallback=Weather_Blizzard_Land_Fog_Day_Depth,2.8 +fallback=Weather_Blizzard_Land_Fog_Night_Depth,3.0 +fallback=Weather_Blizzard_Wind_Speed,.9 +fallback=Weather_Blizzard_Cloud_Speed,7.5 +fallback=Weather_Blizzard_Glare_View,0 +fallback=Weather_Blizzard_Ambient_Loop_Sound_ID, Blizzard +fallback=Weather_Blizzard_Storm_Threshold,.50 From 7c8b82f45cb8228b9366aedb714ed7e0114794d0 Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Tue, 17 Sep 2019 20:30:37 +0200 Subject: [PATCH 30/48] move locking behaviour to cellref --- apps/openmw/mwclass/container.cpp | 2 +- apps/openmw/mwclass/door.cpp | 2 +- apps/openmw/mwmechanics/mechanicsmanagerimp.cpp | 2 +- apps/openmw/mwmechanics/security.cpp | 2 +- apps/openmw/mwmechanics/spellcasting.cpp | 4 ++-- apps/openmw/mwscript/miscextensions.cpp | 4 ++-- apps/openmw/mwworld/cellref.cpp | 13 +++++++++++++ apps/openmw/mwworld/cellref.hpp | 2 ++ apps/openmw/mwworld/class.cpp | 14 -------------- apps/openmw/mwworld/class.hpp | 6 ------ 10 files changed, 23 insertions(+), 28 deletions(-) diff --git a/apps/openmw/mwclass/container.cpp b/apps/openmw/mwclass/container.cpp index f77a9307cd..818f917353 100644 --- a/apps/openmw/mwclass/container.cpp +++ b/apps/openmw/mwclass/container.cpp @@ -181,7 +181,7 @@ namespace MWClass { MWBase::Environment::get().getWindowManager ()->messageBox (keyName + " #{sKeyUsed}"); if(isLocked) - unlock(ptr); + ptr.getCellRef().unlock(); // using a key disarms the trap if(isTrapped) { diff --git a/apps/openmw/mwclass/door.cpp b/apps/openmw/mwclass/door.cpp index b98a8cc994..ecb6ececfe 100644 --- a/apps/openmw/mwclass/door.cpp +++ b/apps/openmw/mwclass/door.cpp @@ -162,7 +162,7 @@ namespace MWClass if(actor == MWMechanics::getPlayer()) MWBase::Environment::get().getWindowManager()->messageBox(keyName + " #{sKeyUsed}"); if(isLocked) - unlock(ptr); //Call the function here. because that makes sense. + ptr.getCellRef().unlock(); //Call the function here. because that makes sense. // using a key disarms the trap if(isTrapped) { diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 7547f086b2..a1994da02e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1150,7 +1150,7 @@ namespace MWMechanics store.remove(*it, toMove, player); } // TODO: unhardcode the locklevel - targetContainer.getClass().lock(targetContainer,50); + targetContainer.getCellRef().lock(50); } void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, const MWWorld::Ptr& container, diff --git a/apps/openmw/mwmechanics/security.cpp b/apps/openmw/mwmechanics/security.cpp index 62169c84a8..cafc65b992 100644 --- a/apps/openmw/mwmechanics/security.cpp +++ b/apps/openmw/mwmechanics/security.cpp @@ -50,7 +50,7 @@ namespace MWMechanics { if (Misc::Rng::roll0to99() <= x) { - lock.getClass().unlock(lock); + lock.getCellRef().unlock(); resultMessage = "#{sLockSuccess}"; resultSound = "Open Lock"; mActor.getClass().skillUsageSucceeded(mActor, ESM::Skill::Security, 1); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 359e74fc69..2d979e034a 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -696,7 +696,7 @@ namespace MWMechanics { if (caster == getPlayer()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicLockSuccess}"); - target.getClass().lock(target, static_cast(magnitude)); + target.getCellRef().lock(static_cast(magnitude)); } return true; } @@ -716,7 +716,7 @@ namespace MWMechanics if (caster == getPlayer()) MWBase::Environment::get().getWindowManager()->messageBox("#{sMagicOpenSuccess}"); } - target.getClass().unlock(target); + target.getCellRef().unlock(); } else MWBase::Environment::get().getSoundManager()->playSound3D(target, "Open Lock Fail", 1.f, 1.f); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index 29a25c9978..e2506edb86 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -182,7 +182,7 @@ namespace MWScript runtime.pop(); } - ptr.getClass().lock (ptr, lockLevel); + ptr.getCellRef().lock (lockLevel); // Instantly reset door to closed state // This is done when using Lock in scripts, but not when using Lock spells. @@ -202,7 +202,7 @@ namespace MWScript { MWWorld::Ptr ptr = R()(runtime); - ptr.getClass().unlock (ptr); + ptr.getCellRef().unlock (); } }; diff --git a/apps/openmw/mwworld/cellref.cpp b/apps/openmw/mwworld/cellref.cpp index 094669bddf..fb9fd592a9 100644 --- a/apps/openmw/mwworld/cellref.cpp +++ b/apps/openmw/mwworld/cellref.cpp @@ -225,6 +225,19 @@ namespace MWWorld } } + void CellRef::lock(int lockLevel) + { + if(lockLevel != 0) + setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive + else + setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level + } + + void CellRef::unlock() + { + setLockLevel(-abs(mCellRef.mLockLevel)); //Makes lockLevel negative + } + std::string CellRef::getKey() const { return mCellRef.mKey; diff --git a/apps/openmw/mwworld/cellref.hpp b/apps/openmw/mwworld/cellref.hpp index 5646bafb04..04e807ce59 100644 --- a/apps/openmw/mwworld/cellref.hpp +++ b/apps/openmw/mwworld/cellref.hpp @@ -99,6 +99,8 @@ namespace MWWorld // For an unlocked door, it is set to -(previous locklevel) int getLockLevel() const; void setLockLevel(int lockLevel); + void lock(int lockLevel); + void unlock(); // Key and trap ID names, if any std::string getKey() const; std::string getTrap() const; diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 3efc00491b..cd1f719d6d 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -144,20 +144,6 @@ namespace MWWorld return false; } - void Class::lock (const Ptr& ptr, int lockLevel) const - { - if(lockLevel != 0) - ptr.getCellRef().setLockLevel(abs(lockLevel)); //Changes lock to locklevel, if positive - else - ptr.getCellRef().setLockLevel(ESM::UnbreakableLock); // If zero, set to max lock level - } - - void Class::unlock (const Ptr& ptr) const - { - int lockLevel = ptr.getCellRef().getLockLevel(); - ptr.getCellRef().setLockLevel(-abs(lockLevel)); //Makes lockLevel negative - } - bool Class::canLock(const ConstPtr &ptr) const { return false; diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 964ef19a5f..0d3a0e8075 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -163,12 +163,6 @@ namespace MWWorld virtual bool hasInventoryStore (const Ptr& ptr) const; ///< Does this object have an inventory store, i.e. equipment slots? (default implementation: false) - virtual void lock (const Ptr& ptr, int lockLevel) const; - ///< Lock object (default implementation: throw an exception) - - virtual void unlock (const Ptr& ptr) const; - ///< Unlock object (default implementation: throw an exception) - virtual bool canLock (const ConstPtr& ptr) const; virtual void setRemainingUsageTime (const Ptr& ptr, float duration) const; From 94a281370f6d4d29d60f1c74f5f8f6a6bebd7554 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 17 Sep 2019 22:40:51 +0400 Subject: [PATCH 31/48] Continue scripts execution after player's death (bug #5166) --- CHANGELOG.md | 3 ++- apps/openmw/engine.cpp | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebf884d860..b307e630db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -139,10 +139,11 @@ Bug #5134: Doors rotation by "Lock" console command is inconsistent Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime + Bug #5158: Objects without a name don't fallback to their ID Bug #5159: NiMaterialColorController can only control the diffuse color Bug #5161: Creature companions can't be activated when they are knocked down Bug #5164: Faction owned items handling is incorrect - Bug #5188: Objects without a name don't fallback to their ID + Bug #5166: Scripts still should be executed after player's death Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d5ab73213e..7c92236ed9 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -112,8 +112,8 @@ bool OMW::Engine::frame(float frametime) bool guiActive = mEnvironment.getWindowManager()->isGuiMode(); osg::Timer_t beforeScriptTick = osg::Timer::instance()->tick(); - if (mEnvironment.getStateManager()->getState()== - MWBase::StateManager::State_Running) + if (mEnvironment.getStateManager()->getState()!= + MWBase::StateManager::State_NoGame) { if (!paused) { From a4d196f33f2572ff580afcde5449afb54f0dd8d5 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 19 Sep 2019 21:48:43 +0400 Subject: [PATCH 32/48] Force view change when using Force1stPerson and Force3rdPerson commands (bug #5168) --- CHANGELOG.md | 1 + apps/openmw/mwbase/world.hpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 4 ++-- apps/openmw/mwrender/renderingmanager.hpp | 2 +- apps/openmw/mwscript/miscextensions.cpp | 4 ++-- apps/openmw/mwworld/worldimp.cpp | 4 ++-- apps/openmw/mwworld/worldimp.hpp | 2 +- 7 files changed, 10 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d9104199e..da7b60752b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,7 @@ Bug #5161: Creature companions can't be activated when they are knocked down Bug #5164: Faction owned items handling is incorrect Bug #5166: Scripts still should be executed after player's death + Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 955e77168d..261f296085 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -403,7 +403,7 @@ namespace MWBase virtual osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const = 0; - virtual void togglePOV() = 0; + virtual void togglePOV(bool force = false) = 0; virtual bool isFirstPerson() const = 0; virtual void togglePreviewMode(bool enable) = 0; virtual bool toggleVanityMode(bool enable) = 0; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index c361ddf031..ac4fb3a169 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -1333,9 +1333,9 @@ namespace MWRender return mCurrentCameraPos; } - void RenderingManager::togglePOV() + void RenderingManager::togglePOV(bool force) { - mCamera->toggleViewMode(); + mCamera->toggleViewMode(force); } void RenderingManager::togglePreviewMode(bool enable) diff --git a/apps/openmw/mwrender/renderingmanager.hpp b/apps/openmw/mwrender/renderingmanager.hpp index 49da50be36..fb94caec88 100644 --- a/apps/openmw/mwrender/renderingmanager.hpp +++ b/apps/openmw/mwrender/renderingmanager.hpp @@ -204,7 +204,7 @@ namespace MWRender float getCameraDistance() const; Camera* getCamera(); const osg::Vec3f& getCameraPosition() const; - void togglePOV(); + void togglePOV(bool force = false); void togglePreviewMode(bool enable); bool toggleVanityMode(bool enable); void allowVanityMode(bool allow); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index e2506edb86..906e5d0088 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -358,7 +358,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { if (!MWBase::Environment::get().getWorld()->isFirstPerson()) - MWBase::Environment::get().getWorld()->togglePOV(); + MWBase::Environment::get().getWorld()->togglePOV(true); } }; @@ -367,7 +367,7 @@ namespace MWScript virtual void execute (Interpreter::Runtime& runtime) { if (MWBase::Environment::get().getWorld()->isFirstPerson()) - MWBase::Environment::get().getWorld()->togglePOV(); + MWBase::Environment::get().getWorld()->togglePOV(true); } }; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 7aa9d6023a..6f2a6bf4cb 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2395,9 +2395,9 @@ namespace MWWorld return mPhysics->isOnGround(ptr); } - void World::togglePOV() + void World::togglePOV(bool force) { - mRendering->togglePOV(); + mRendering->togglePOV(force); } bool World::isFirstPerson() const diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 76d0154777..f803079fbd 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -518,7 +518,7 @@ namespace MWWorld osg::Matrixf getActorHeadTransform(const MWWorld::ConstPtr& actor) const override; - void togglePOV() override; + void togglePOV(bool force = false) override; bool isFirstPerson() const override; From 1bddbbcfa0f296d36900849ead682a5cd82ef21f Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 19 Sep 2019 22:43:53 +0400 Subject: [PATCH 33/48] Check if related menus are allowed when using cycle hotkeys (bug #5167) --- CHANGELOG.md | 1 + apps/openmw/mwinput/inputmanagerimp.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d9104199e..c65129702d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -145,6 +145,7 @@ Bug #5161: Creature companions can't be activated when they are knocked down Bug #5164: Faction owned items handling is incorrect Bug #5166: Scripts still should be executed after player's death + Bug #5167: Player can select and cast spells before magic menu is enabled Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index edc45b8842..c0ec740156 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -471,19 +471,19 @@ namespace MWInput quickLoad(); break; case A_CycleSpellLeft: - if (checkAllowedToUseItems()) + if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic)) MWBase::Environment::get().getWindowManager()->cycleSpell(false); break; case A_CycleSpellRight: - if (checkAllowedToUseItems()) + if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Magic)) MWBase::Environment::get().getWindowManager()->cycleSpell(true); break; case A_CycleWeaponLeft: - if (checkAllowedToUseItems()) + if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) MWBase::Environment::get().getWindowManager()->cycleWeapon(false); break; case A_CycleWeaponRight: - if (checkAllowedToUseItems()) + if (checkAllowedToUseItems() && MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory)) MWBase::Environment::get().getWindowManager()->cycleWeapon(true); break; case A_Sneak: From 7cb6a9c1e98bb283818fa74b57b84202b72b9a2e Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Thu, 19 Sep 2019 23:03:29 +0400 Subject: [PATCH 34/48] Do not allow to use quick keys during chargen --- apps/openmw/mwinput/inputmanagerimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index c0ec740156..6e0f3375b5 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -1312,6 +1312,9 @@ namespace MWInput if (!checkAllowedToUseItems()) return; + if (MWBase::Environment::get().getWorld()->getGlobalFloat ("chargenstate")!=-1) + return; + if (!MWBase::Environment::get().getWindowManager()->isGuiMode()) MWBase::Environment::get().getWindowManager()->activateQuickKey (index); } From 7c9a9d7de0c207b67665101fd71b9ad3478e0cd2 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Sat, 21 Sep 2019 14:29:38 +0300 Subject: [PATCH 35/48] Fix chance none logic for nested levelled lists (bug #5169) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/levelledlist.hpp | 10 ++++------ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dec315506c..811a276f13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -149,6 +149,7 @@ Bug #5166: Scripts still should be executed after player's death Bug #5167: Player can select and cast spells before magic menu is enabled Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change + Bug #5169: Nested levelled items/creatures have significantly higher chance not to spawn Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/apps/openmw/mwmechanics/levelledlist.hpp b/apps/openmw/mwmechanics/levelledlist.hpp index 45f7e86fec..697e2eda81 100644 --- a/apps/openmw/mwmechanics/levelledlist.hpp +++ b/apps/openmw/mwmechanics/levelledlist.hpp @@ -19,16 +19,14 @@ namespace MWMechanics { /// @return ID of resulting item, or empty if none - inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, unsigned char failChance=0) + inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature) { const std::vector& items = levItem->mList; const MWWorld::Ptr& player = getPlayer(); int playerLevel = player.getClass().getCreatureStats(player).getLevel(); - failChance += levItem->mChanceNone; - - if (Misc::Rng::roll0to99() < failChance) + if (Misc::Rng::roll0to99() < levItem->mChanceNone) return std::string(); std::vector candidates; @@ -76,9 +74,9 @@ namespace MWMechanics else { if (ref.getPtr().getTypeName() == typeid(ESM::ItemLevList).name()) - return getLevelledItem(ref.getPtr().get()->mBase, false, failChance); + return getLevelledItem(ref.getPtr().get()->mBase, false); else - return getLevelledItem(ref.getPtr().get()->mBase, true, failChance); + return getLevelledItem(ref.getPtr().get()->mBase, true); } } From 0a97dd8e84c99e8733de357a1184277ac63a1806 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Sat, 21 Sep 2019 15:05:12 +0300 Subject: [PATCH 36/48] [Regression] Fix horribly broken fallback loading --- components/fallback/validate.hpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/components/fallback/validate.hpp b/components/fallback/validate.hpp index a1d3f9601d..cef52e4624 100644 --- a/components/fallback/validate.hpp +++ b/components/fallback/validate.hpp @@ -39,10 +39,7 @@ namespace Fallback std::string key(temp.substr(0, sep)); std::string value(temp.substr(sep + 1)); - if (map->mMap.find(key) == map->mMap.end()) - { - map->mMap.insert(std::make_pair(key, value)); - } + map->mMap[key] = value; } } } From 3d3ffdfcd83ea44c66fda1afcf110774e810910e Mon Sep 17 00:00:00 2001 From: Evil Eye Date: Sat, 21 Sep 2019 16:24:05 +0200 Subject: [PATCH 37/48] override eraseStatic for dialogue --- apps/openmw/mwworld/store.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/apps/openmw/mwworld/store.cpp b/apps/openmw/mwworld/store.cpp index 4446502170..8ceab26b64 100644 --- a/apps/openmw/mwworld/store.cpp +++ b/apps/openmw/mwworld/store.cpp @@ -1091,6 +1091,18 @@ namespace MWWorld return RecordId(dialogue.mId, isDeleted); } + template<> + bool Store::eraseStatic(const std::string &id) + { + auto it = mStatic.find(Misc::StringUtils::lowerCase(id)); + + if (it != mStatic.end() && Misc::StringUtils::ciEqual(it->second.mId, id)) { + mStatic.erase(it); + } + + return true; + } + } template class MWWorld::Store; From 6450d84473300d98a7aaa4f90abc9a3e77106c52 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sat, 21 Sep 2019 20:22:45 +0400 Subject: [PATCH 38/48] Improve resurrection handling --- apps/openmw/mwbase/mechanicsmanager.hpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 26 +++++++++++-------- apps/openmw/mwmechanics/actors.hpp | 2 ++ apps/openmw/mwmechanics/creaturestats.cpp | 3 --- .../mwmechanics/mechanicsmanagerimp.cpp | 8 +++--- .../mwmechanics/mechanicsmanagerimp.hpp | 2 +- apps/openmw/mwscript/statsextensions.cpp | 2 +- 7 files changed, 25 insertions(+), 20 deletions(-) diff --git a/apps/openmw/mwbase/mechanicsmanager.hpp b/apps/openmw/mwbase/mechanicsmanager.hpp index d1bb5a83d9..ae898b24e5 100644 --- a/apps/openmw/mwbase/mechanicsmanager.hpp +++ b/apps/openmw/mwbase/mechanicsmanager.hpp @@ -225,7 +225,7 @@ namespace MWBase virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) = 0; /// Resurrects the player if necessary - virtual void keepPlayerAlive() = 0; + virtual void resurrect(const MWWorld::Ptr& ptr) = 0; virtual bool isCastingSpell (const MWWorld::Ptr& ptr) const = 0; virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0; diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 8cab2f00bd..86c50ab705 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -1637,6 +1637,20 @@ namespace MWMechanics ++mDeathCount[Misc::StringUtils::lowerCase(actor.getCellRef().getRefId())]; } + void Actors::resurrect(const MWWorld::Ptr &ptr) + { + PtrActorMap::iterator iter = mActors.find(ptr); + if(iter != mActors.end()) + { + if(iter->second->getCharacterController()->isDead()) + { + // Actor has been resurrected. Notify the CharacterController and re-enable collision. + MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true); + iter->second->getCharacterController()->resurrect(); + } + } + } + void Actors::killDeadActors() { for(PtrActorMap::iterator iter(mActors.begin()); iter != mActors.end(); ++iter) @@ -1645,17 +1659,7 @@ namespace MWMechanics CreatureStats &stats = cls.getCreatureStats(iter->first); if(!stats.isDead()) - { - if(iter->second->getCharacterController()->isDead()) - { - // Actor has been resurrected. Notify the CharacterController and re-enable collision. - MWBase::Environment::get().getWorld()->enableActorCollision(iter->first, true); - iter->second->getCharacterController()->resurrect(); - } - - if(!stats.isDead()) - continue; - } + continue; MWBase::Environment::get().getWorld()->removeActorPath(iter->first); CharacterController::KillResult killResult = iter->second->getCharacterController()->kill(); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 9621a8619b..68b3bb9767 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -94,6 +94,8 @@ namespace MWMechanics /// /// \note Ignored, if \a ptr is not a registered actor. + void resurrect (const MWWorld::Ptr& ptr); + void castSpell(const MWWorld::Ptr& ptr, const std::string spellId, bool manualSpell=false); void updateActor(const MWWorld::Ptr &old, const MWWorld::Ptr& ptr); diff --git a/apps/openmw/mwmechanics/creaturestats.cpp b/apps/openmw/mwmechanics/creaturestats.cpp index 7cc6ea7843..5a80779da9 100644 --- a/apps/openmw/mwmechanics/creaturestats.cpp +++ b/apps/openmw/mwmechanics/creaturestats.cpp @@ -198,9 +198,6 @@ namespace MWMechanics mDynamic[index].setModifier(0); mDynamic[index].setCurrentModifier(0); mDynamic[index].setCurrent(0); - - if (MWBase::Environment::get().getWorld()->getGodModeState()) - MWBase::Environment::get().getMechanicsManager()->keepPlayerAlive(); } } diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp index 137775481d..a1ba0a5e7e 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.cpp @@ -1820,12 +1820,14 @@ namespace MWMechanics return (fight >= 100); } - void MechanicsManager::keepPlayerAlive() + void MechanicsManager::resurrect(const MWWorld::Ptr &ptr) { - MWWorld::Ptr player = getPlayer(); - CreatureStats& stats = player.getClass().getCreatureStats(player); + CreatureStats& stats = ptr.getClass().getCreatureStats(ptr); if (stats.isDead()) + { stats.resurrect(); + mActors.resurrect(ptr); + } } bool MechanicsManager::isCastingSpell(const MWWorld::Ptr &ptr) const diff --git a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp index 9e8ce87d15..0ac9092e8f 100644 --- a/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp +++ b/apps/openmw/mwmechanics/mechanicsmanagerimp.hpp @@ -197,7 +197,7 @@ namespace MWMechanics virtual bool isAggressive (const MWWorld::Ptr& ptr, const MWWorld::Ptr& target) override; - virtual void keepPlayerAlive() override; + virtual void resurrect(const MWWorld::Ptr& ptr) override; virtual bool isCastingSpell (const MWWorld::Ptr& ptr) const override; diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index 847fe0bfc2..7ce3f1da39 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1184,7 +1184,7 @@ namespace MWScript if (ptr == MWMechanics::getPlayer()) { - ptr.getClass().getCreatureStats(ptr).resurrect(); + MWBase::Environment::get().getMechanicsManager()->resurrect(ptr); if (MWBase::Environment::get().getStateManager()->getState() == MWBase::StateManager::State_Ended) MWBase::Environment::get().getStateManager()->resumeGame(); } From 822b20ef464824d1b38485e209e30ae68a229148 Mon Sep 17 00:00:00 2001 From: Alexei Dobrohotov Date: Mon, 23 Sep 2019 20:38:42 +0300 Subject: [PATCH 39/48] Fix invalid strips-based collision shape transformation --- components/nifbullet/bulletnifloader.cpp | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/components/nifbullet/bulletnifloader.cpp b/components/nifbullet/bulletnifloader.cpp index 5993d04fdf..91f8494210 100644 --- a/components/nifbullet/bulletnifloader.cpp +++ b/components/nifbullet/bulletnifloader.cpp @@ -78,7 +78,7 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD continue; unsigned short a = strip[0], b = strip[0], c = strip[1]; - for (int i = 2; i < static_cast(strip.size()); i++) + for (size_t i = 2; i < strip.size(); i++) { a = b; b = c; @@ -86,9 +86,21 @@ void fillTriangleMeshWithTransform(btTriangleMesh& mesh, const Nif::NiTriStripsD if (a != b && b != c && a != c) { if (i%2==0) - mesh.addTriangle(getbtVector(vertices[a]), getbtVector(vertices[b]), getbtVector(vertices[c])); + { + mesh.addTriangle( + getbtVector(vertices[a] * transform), + getbtVector(vertices[b] * transform), + getbtVector(vertices[c] * transform) + ); + } else - mesh.addTriangle(getbtVector(vertices[a]), getbtVector(vertices[c]), getbtVector(vertices[b])); + { + mesh.addTriangle( + getbtVector(vertices[a] * transform), + getbtVector(vertices[c] * transform), + getbtVector(vertices[b] * transform) + ); + } } } } From 421a9d2e5097cd129ee39854b4b394bb6684fa34 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Mon, 23 Sep 2019 23:56:37 +0300 Subject: [PATCH 40/48] [Regression] Fix pickpocket crashes --- apps/openmw/mwgui/pickpocketitemmodel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/pickpocketitemmodel.cpp b/apps/openmw/mwgui/pickpocketitemmodel.cpp index e85715e87f..2a167be2dc 100644 --- a/apps/openmw/mwgui/pickpocketitemmodel.cpp +++ b/apps/openmw/mwgui/pickpocketitemmodel.cpp @@ -98,7 +98,7 @@ namespace MWGui if (pickpocket.finish()) { MWBase::Environment::get().getMechanicsManager()->commitCrime( - player, mActor, MWBase::MechanicsManager::OT_Pickpocket, 0, true); + player, mActor, MWBase::MechanicsManager::OT_Pickpocket, std::string(), 0, true); MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); mPickpocketDetected = true; } @@ -126,7 +126,7 @@ namespace MWGui if (pickpocket.pick(item, count)) { MWBase::Environment::get().getMechanicsManager()->commitCrime( - player, mActor, MWBase::MechanicsManager::OT_Pickpocket, 0, true); + player, mActor, MWBase::MechanicsManager::OT_Pickpocket, std::string(), 0, true); MWBase::Environment::get().getWindowManager()->removeGuiMode(MWGui::GM_Container); mPickpocketDetected = true; return false; From 48aba76ce904738d428e79f1ee24ce170f2a8309 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 24 Sep 2019 09:30:39 +0400 Subject: [PATCH 41/48] Implement vanilla-style AiActivate (bug #4456) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/aiactivate.cpp | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811a276f13..b1ac9fa79e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Bug #4383: Bow model obscures crosshair when arrow is drawn Bug #4384: Resist Normal Weapons only checks ammunition for ranged weapons Bug #4411: Reloading a saved game while falling prevents damage in some cases + Bug #4456: AiActivate should not be cancelled after target activation Bug #4540: Rain delay when exiting water Bug #4600: Crash when no sound output is available or --no-sound is used. Bug #4639: Black screen after completing first mages guild mission + training diff --git a/apps/openmw/mwmechanics/aiactivate.cpp b/apps/openmw/mwmechanics/aiactivate.cpp index e222c82bc0..c412a7ea1d 100644 --- a/apps/openmw/mwmechanics/aiactivate.cpp +++ b/apps/openmw/mwmechanics/aiactivate.cpp @@ -9,6 +9,7 @@ #include "creaturestats.hpp" #include "movement.hpp" +#include "steering.hpp" namespace MWMechanics { @@ -33,16 +34,18 @@ namespace MWMechanics if (target == MWWorld::Ptr() || !target.getRefData().getCount() || !target.getRefData().isEnabled()) return true; - //Set the target destination for the actor - const osg::Vec3f dest = target.getRefData().getPosition().asVec3(); + // Turn to target and move to it directly, without pathfinding. + const osg::Vec3f targetDir = target.getRefData().getPosition().asVec3() - actor.getRefData().getPosition().asVec3(); - if (pathTo(actor, dest, duration, MWBase::Environment::get().getWorld()->getMaxActivationDistance())) //Stop when you get in activation range + zTurn(actor, std::atan2(targetDir.x(), targetDir.y()), 0.f); + actor.getClass().getMovementSettings(actor).mPosition[1] = 1; + actor.getClass().getMovementSettings(actor).mPosition[0] = 0; + + if (MWBase::Environment::get().getWorld()->getMaxActivationDistance() >= targetDir.length()) { - // activate when reached + // Note: we intentionally do not cancel package after activation here for backward compatibility with original engine. MWBase::Environment::get().getWorld()->activate(target, actor); - return true; } - return false; } From 4d381d0804bd089c3a0d5a89243646206e2996ac Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Tue, 24 Sep 2019 22:42:04 +0300 Subject: [PATCH 42/48] Use random attack strength if there's no wind up anim (bug #5059) --- CHANGELOG.md | 1 + apps/openmw/mwmechanics/character.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 811a276f13..e1c51f0aaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -115,6 +115,7 @@ Bug #5050: Invalid spell effects are not handled gracefully Bug #5055: Mark, Recall, Intervention magic effect abilities have no effect when added and removed in the same frame Bug #5056: Calling Cast function on player doesn't equip the spell but casts it + Bug #5059: Modded animation with combined attack keys always does max damage and can double damage Bug #5060: Magic effect visuals stop when death animation begins instead of when it ends Bug #5063: Shape named "Tri Shadow" in creature mesh is visible if it isn't hidden Bug #5067: Ranged attacks on unaware opponents ("critical hits") differ from the vanilla engine diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 9b6c1e0c3b..2dbbfea359 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -1629,7 +1629,9 @@ bool CharacterController::updateWeaponState(CharacterState& idle) if(mUpperBodyState == UpperCharState_MinAttackToMaxAttack && !isKnockedDown()) { float attackStrength = complete; - if (!mPtr.getClass().isNpc()) + float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"min attack"); + float maxAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"max attack"); + if (minAttackTime == maxAttackTime) { // most creatures don't actually have an attack wind-up animation, so use a uniform random value // (even some creatures that can use weapons don't have a wind-up animation either, e.g. Rieklings) @@ -1735,7 +1737,7 @@ bool CharacterController::updateWeaponState(CharacterState& idle) { // If actor is already stopped preparing attack, do not play the "min attack -> max attack" part. // Happens if the player did not hold the attack button. - // Note: if the "min attack"->"max attack" is a stub, "play" it anyway. Attack strength will be 1. + // Note: if the "min attack"->"max attack" is a stub, "play" it anyway. Attack strength will be random. float minAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"min attack"); float maxAttackTime = mAnimation->getTextKeyTime(mCurrentWeapon+": "+mAttackType+" "+"max attack"); if (mAttackingOrSpell || minAttackTime == maxAttackTime) From 751accad0fc14f47edb98732081df690e318a9b5 Mon Sep 17 00:00:00 2001 From: elsid Date: Sat, 28 Sep 2019 14:26:52 +0200 Subject: [PATCH 43/48] Remove unused field QuadTreeBuilder::mLodFactor --- components/terrain/quadtreeworld.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/components/terrain/quadtreeworld.cpp b/components/terrain/quadtreeworld.cpp index b2f119b88f..b2cb7a3b80 100644 --- a/components/terrain/quadtreeworld.cpp +++ b/components/terrain/quadtreeworld.cpp @@ -210,7 +210,6 @@ public: private: Terrain::Storage* mStorage; - float mLodFactor; float mMinX, mMaxX, mMinY, mMaxY; float mMinSize; From ca46da8b048dbc1f88499307ab312589576290d0 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Sun, 29 Sep 2019 13:08:52 +0400 Subject: [PATCH 44/48] Do not stack initially added scripted items (bug #5136) --- CHANGELOG.md | 1 + apps/openmw/mwworld/containerstore.cpp | 78 +++++++++++++++----------- apps/openmw/mwworld/containerstore.hpp | 1 + 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1ac9fa79e..aaf052d053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -140,6 +140,7 @@ Bug #5124: Arrow remains attached to actor if pulling animation was cancelled Bug #5126: Swimming creatures without RunForward animations are motionless during combat Bug #5134: Doors rotation by "Lock" console command is inconsistent + Bug #5136: LegionUniform script: can not access local variables Bug #5137: Textures with Clamp Mode set to Clamp instead of Wrap are too dark outside the boundaries Bug #5149: Failing lock pick attempts isn't always a crime Bug #5155: Lock/unlock behavior differs from vanilla diff --git a/apps/openmw/mwworld/containerstore.cpp b/apps/openmw/mwworld/containerstore.cpp index 8c17dc0a9d..76555de02c 100644 --- a/apps/openmw/mwworld/containerstore.cpp +++ b/apps/openmw/mwworld/containerstore.cpp @@ -477,50 +477,64 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std:: int count, bool topLevel, const std::string& levItem) { if (count == 0) return; //Don't restock with nothing. - try { + try + { ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); - - if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name()) + if (ref.getPtr().getClass().getScript(ref.getPtr()).empty()) { - const ESM::ItemLevList* levItemList = ref.getPtr().get()->mBase; - - if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each) - { - for (int i=0; i 0 ? 1 : -1, true, levItemList->mId); - return; - } - else - { - std::string itemId = MWMechanics::getLevelledItem(ref.getPtr().get()->mBase, false); - if (itemId.empty()) - return; - addInitialItem(itemId, owner, count, false, levItemList->mId); - } + addInitialItemImp(ref.getPtr(), owner, count, topLevel, levItem); } else { - // A negative count indicates restocking items - // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks - if (!levItem.empty() && count < 0) - { - //If there is no item in map, insert it - std::map, int>::iterator itemInMap = - mLevelledItemMap.insert(std::make_pair(std::make_pair(id, levItem), 0)).first; - //Update spawned count - itemInMap->second += std::abs(count); - } - count = std::abs(count); - - ref.getPtr().getCellRef().setOwner(owner); - addImp (ref.getPtr(), count); + // Adding just one item per time to make sure there isn't a stack of scripted items + for (int i = 0; i < abs(count); i++) + addInitialItemImp(ref.getPtr(), owner, count < 0 ? -1 : 1, topLevel, levItem); } } catch (const std::exception& e) { Log(Debug::Warning) << "Warning: MWWorld::ContainerStore::addInitialItem: " << e.what(); } +} +void MWWorld::ContainerStore::addInitialItemImp(const MWWorld::Ptr& ptr, const std::string& owner, + int count, bool topLevel, const std::string& levItem) +{ + if (ptr.getTypeName()==typeid (ESM::ItemLevList).name()) + { + const ESM::ItemLevList* levItemList = ptr.get()->mBase; + + if (topLevel && std::abs(count) > 1 && levItemList->mFlags & ESM::ItemLevList::Each) + { + for (int i=0; i 0 ? 1 : -1, true, levItemList->mId); + return; + } + else + { + std::string itemId = MWMechanics::getLevelledItem(ptr.get()->mBase, false); + if (itemId.empty()) + return; + addInitialItem(itemId, owner, count, false, levItemList->mId); + } + } + else + { + // A negative count indicates restocking items + // For a restocking levelled item, remember what we spawned so we can delete it later when the merchant restocks + if (!levItem.empty() && count < 0) + { + //If there is no item in map, insert it + std::map, int>::iterator itemInMap = + mLevelledItemMap.insert(std::make_pair(std::make_pair(ptr.getCellRef().getRefId(), levItem), 0)).first; + //Update spawned count + itemInMap->second += std::abs(count); + } + count = std::abs(count); + + ptr.getCellRef().setOwner(owner); + addImp (ptr, count); + } } void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner) diff --git a/apps/openmw/mwworld/containerstore.hpp b/apps/openmw/mwworld/containerstore.hpp index b06e8b8ce6..1e1e4a844e 100644 --- a/apps/openmw/mwworld/containerstore.hpp +++ b/apps/openmw/mwworld/containerstore.hpp @@ -94,6 +94,7 @@ namespace MWWorld mutable bool mWeightUpToDate; ContainerStoreIterator addImp (const Ptr& ptr, int count); void addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = ""); + void addInitialItemImp (const MWWorld::Ptr& ptr, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = ""); template ContainerStoreIterator getState (CellRefList& collection, From 6253d2a7acf78b483baaf53e4aaf5285674175fd Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 29 Sep 2019 10:28:02 +0200 Subject: [PATCH 45/48] Undo door rotation once --- apps/openmw/mwworld/worldimp.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 6f2a6bf4cb..c914acfba7 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -1649,7 +1649,6 @@ namespace MWWorld } // we need to undo the rotation - rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot); reached = false; } } @@ -1671,6 +1670,8 @@ namespace MWWorld if (!closeSound.empty() && MWBase::Environment::get().getSoundManager()->getSoundPlaying(door, closeSound)) MWBase::Environment::get().getSoundManager()->stopSound3D(door, closeSound); } + + rotateObject(door, objPos.rot[0], objPos.rot[1], oldRot); } // the rotation order we want to use From 7fbc696d44e60c4caf24ba25c635cb86f3d5dd8e Mon Sep 17 00:00:00 2001 From: elsid Date: Sun, 25 Aug 2019 17:21:14 +0200 Subject: [PATCH 46/48] Change angle direction by rolling dice to avoid rotating door --- apps/openmw/mwmechanics/aiavoiddoor.cpp | 42 +++++++++++++++---------- apps/openmw/mwmechanics/aiavoiddoor.hpp | 10 ++++-- 2 files changed, 34 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwmechanics/aiavoiddoor.cpp b/apps/openmw/mwmechanics/aiavoiddoor.cpp index 793bd89ea1..c476c9b576 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.cpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.cpp @@ -1,5 +1,7 @@ #include "aiavoiddoor.hpp" +#include + #include "../mwbase/world.hpp" #include "../mwbase/environment.hpp" #include "../mwbase/mechanicsmanager.hpp" @@ -11,8 +13,10 @@ #include "actorutil.hpp" #include "steering.hpp" +static const int MAX_DIRECTIONS = 4; + MWMechanics::AiAvoidDoor::AiAvoidDoor(const MWWorld::ConstPtr& doorPtr) -: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mLastPos(ESM::Position()), mAdjAngle(0) +: AiPackage(), mDuration(1), mDoorPtr(doorPtr), mDirection(0) { } @@ -22,25 +26,18 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont ESM::Position pos = actor.getRefData().getPosition(); if(mDuration == 1) //If it just started, get the actor position as the stuck detection thing - mLastPos = pos; + mLastPos = pos.asVec3(); mDuration -= duration; //Update timer - if(mDuration < 0) { - float x = pos.pos[0] - mLastPos.pos[0]; - float y = pos.pos[1] - mLastPos.pos[1]; - float z = pos.pos[2] - mLastPos.pos[2]; - float distance = x * x + y * y + z * z; - if(distance < 10 * 10) { //Got stuck, didn't move - if(mAdjAngle == 0) //Try going in various directions - mAdjAngle = osg::PI / 2; - else if (mAdjAngle == osg::PI / 2) - mAdjAngle = -osg::PI / 2; - else - mAdjAngle = 0; + if (mDuration < 0) + { + if (isStuck(pos.asVec3())) + { + adjustDirection(); mDuration = 1; //reset timer } - else //Not stuck + else return true; // We have tried backing up for more than one second, we've probably cleared it } @@ -54,7 +51,7 @@ bool MWMechanics::AiAvoidDoor::execute (const MWWorld::Ptr& actor, CharacterCont actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, true); // Turn away from the door and move when turn completed - if (zTurn(actor, std::atan2(x,y) + mAdjAngle, osg::DegreesToRadians(5.f))) + if (zTurn(actor, std::atan2(x,y) + getAdjustedAngle(), osg::DegreesToRadians(5.f))) actor.getClass().getMovementSettings(actor).mPosition[1] = 1; else actor.getClass().getMovementSettings(actor).mPosition[1] = 0; @@ -90,4 +87,17 @@ unsigned int MWMechanics::AiAvoidDoor::getPriority() const return 2; } +bool MWMechanics::AiAvoidDoor::isStuck(const osg::Vec3f& actorPos) const +{ + return (actorPos - mLastPos).length2() < 10 * 10; +} +void MWMechanics::AiAvoidDoor::adjustDirection() +{ + mDirection = Misc::Rng::rollDice(MAX_DIRECTIONS); +} + +float MWMechanics::AiAvoidDoor::getAdjustedAngle() const +{ + return 2 * osg::PI / MAX_DIRECTIONS * mDirection; +} diff --git a/apps/openmw/mwmechanics/aiavoiddoor.hpp b/apps/openmw/mwmechanics/aiavoiddoor.hpp index 7344a1797c..4c8be29ebb 100644 --- a/apps/openmw/mwmechanics/aiavoiddoor.hpp +++ b/apps/openmw/mwmechanics/aiavoiddoor.hpp @@ -36,8 +36,14 @@ namespace MWMechanics private: float mDuration; MWWorld::ConstPtr mDoorPtr; - ESM::Position mLastPos; - float mAdjAngle; + osg::Vec3f mLastPos; + int mDirection; + + bool isStuck(const osg::Vec3f& actorPos) const; + + void adjustDirection(); + + float getAdjustedAngle() const; }; } #endif From 4efdc88f1ab820f9896181e17c54ea12a6274d7c Mon Sep 17 00:00:00 2001 From: AnyOldName3 Date: Wed, 2 Oct 2019 19:12:06 +0000 Subject: [PATCH 47/48] Change shadow settings pluralisation so it matches the setting section name It used to say *Shadow Settings* as they were the settings that controlled the shadow system, but that keeps confusing people and no other section titles use that convention, so they're now *Shadows Settings* as they're the settings that control shadows. --- docs/source/reference/modding/settings/shadows.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/source/reference/modding/settings/shadows.rst b/docs/source/reference/modding/settings/shadows.rst index 9b207c448f..8bcc0522b8 100644 --- a/docs/source/reference/modding/settings/shadows.rst +++ b/docs/source/reference/modding/settings/shadows.rst @@ -1,5 +1,5 @@ -Shadow Settings -############### +Shadows Settings +################ Main settings ************* From bde4a3818141fe55f24d5a52d40d00362844bec1 Mon Sep 17 00:00:00 2001 From: Capostrophic Date: Thu, 3 Oct 2019 23:15:25 +0300 Subject: [PATCH 48/48] Cast Random result to float (bug #5175) --- CHANGELOG.md | 1 + components/compiler/exprparser.cpp | 2 +- components/interpreter/miscopcodes.hpp | 4 +--- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07c7d5b36f..47e5bb4851 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -153,6 +153,7 @@ Bug #5167: Player can select and cast spells before magic menu is enabled Bug #5168: Force1stPerson and Force3rdPerson commands are not really force view change Bug #5169: Nested levelled items/creatures have significantly higher chance not to spawn + Bug #5175: Random script function returns an integer value Feature #1774: Handle AvoidNode Feature #2229: Improve pathfinding AI Feature #3025: Analogue gamepad movement controls diff --git a/components/compiler/exprparser.cpp b/components/compiler/exprparser.cpp index e3a306b8f3..017e363732 100644 --- a/components/compiler/exprparser.cpp +++ b/components/compiler/exprparser.cpp @@ -489,7 +489,7 @@ namespace Compiler parseArguments ("l", scanner); Generator::random (mCode); - mOperands.push_back ('l'); + mOperands.push_back ('f'); mNextOperand = false; return true; diff --git a/components/interpreter/miscopcodes.hpp b/components/interpreter/miscopcodes.hpp index 29d1c063b1..a77e0d7d89 100644 --- a/components/interpreter/miscopcodes.hpp +++ b/components/interpreter/miscopcodes.hpp @@ -190,9 +190,7 @@ namespace Interpreter throw std::runtime_error ( "random: argument out of range (Don't be so negative!)"); - Type_Integer value = Misc::Rng::rollDice(limit); // [o, limit) - - runtime[0].mInteger = value; + runtime[0].mFloat = static_cast(Misc::Rng::rollDice(limit)); // [o, limit) } };