mirror of
https://gitlab.com/OpenMW/openmw.git
synced 2025-01-31 15:32:45 +00:00
Merge branch 'master' of https://github.com/OpenMW/openmw into joystick
Conflicts: CMakeLists.txt
This commit is contained in:
commit
2b7287cbd2
@ -31,6 +31,7 @@ before_script:
|
||||
script:
|
||||
- cd ./build
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ]; then make -j4; fi
|
||||
- if [ "$COVERITY_SCAN_BRANCH" != 1 ] && [ "${TRAVIS_OS_NAME}" = "osx" ]; then make package; fi
|
||||
after_script:
|
||||
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then ./openmw_test_suite; fi
|
||||
notifications:
|
||||
|
@ -33,12 +33,13 @@ Programmers
|
||||
Douglas Diniz (Dgdiniz)
|
||||
Douglas Mencken (dougmencken)
|
||||
dreamer-dead
|
||||
dteviot
|
||||
David Teviotdale (dteviot)
|
||||
Edmondo Tommasina (edmondo)
|
||||
Eduard Cot (trombonecot)
|
||||
Eli2
|
||||
Emanuel Guével (potatoesmaster)
|
||||
eroen
|
||||
Evgeniy Mineev (sandstranger)
|
||||
Fil Krynicki (filkry)
|
||||
Gašper Sedej
|
||||
gugus/gus
|
||||
@ -75,20 +76,22 @@ Programmers
|
||||
Michał Bień (Glorf)
|
||||
Miroslav Puda (pakanek)
|
||||
MiroslavR
|
||||
naclander
|
||||
Narmo
|
||||
Nathan Jeffords (blunted2night)
|
||||
NeveHanter
|
||||
Nikolay Kasyanov (corristo)
|
||||
nobrakal
|
||||
Nolan Poe (nopoe)
|
||||
Paul McElroy (Greendogo)
|
||||
Pieter van der Kloet (pvdk)
|
||||
Radu-Marius Popovici (rpopovici)
|
||||
rdimesio
|
||||
riothamus
|
||||
Robert MacGregor (Ragora)
|
||||
Rohit Nirmal
|
||||
Roman Melnik (Kromgart)
|
||||
Roman Proskuryakov (humbug)
|
||||
sandstranger
|
||||
Sandy Carter (bwrsandman)
|
||||
Scott Howard
|
||||
Sebastian Wick (swick)
|
||||
|
124
CHANGELOG.md
124
CHANGELOG.md
@ -1,3 +1,127 @@
|
||||
0.35.0
|
||||
------
|
||||
|
||||
Bug #244: Clipping/static in relation to the ghostgate/fence sound.
|
||||
Bug #531: Missing transparent menu items
|
||||
Bug #811: Content Lists in openmw.cfg are overwritten
|
||||
Bug #925: OpenCS doesn't launch because it thinks its already started
|
||||
Bug #969: Water shader strange behaviour on AMD card
|
||||
Bug #1049: Partially highlighted word in dialogue may cause incorrect line break
|
||||
Bug #1069: omwlauncher.exe crashes due to file lock
|
||||
Bug #1192: It is possible to jump on top of hostile creatures in combat
|
||||
Bug #1342: Loud ambient sounds
|
||||
Bug #1431: Creatures can climb the player
|
||||
Bug #1605: Guard in CharGen doesn't turn around to face you when reaching stairs
|
||||
Bug #1624: Moon edges don't transition properly
|
||||
Bug #1634: Items dropped by PC have collision
|
||||
Bug #1637: Weird NPC behaviour in Vivec, Hlaalu Ancestral Vaults?
|
||||
Bug #1638: Cannot climb staircases
|
||||
Bug #1648: Enchanted equipment badly handled at game reload
|
||||
Bug #1663: Crash when casting spell at enemy near you
|
||||
Bug #1683: Scale doesn't apply to animated collision nodes
|
||||
Bug #1702: Active enchanted item forgotten
|
||||
Bug #1730: Scripts names starting with digit(s) fail to compile
|
||||
Bug #1743: Moons are transparent
|
||||
Bug #1745: Shadows crash: Assertion `mEffects.empty()' failed.
|
||||
Bug #1785: Can't equip two-handed weapon and shield
|
||||
Bug #1809: Player falls too easily
|
||||
Bug #1825: Sword of Perithia can´t run in OpenMW
|
||||
Bug #1899: The launcher resets any alterations you´ve made in the mod list order,
|
||||
Bug #1964: Idle voices/dialogs not triggered correctly
|
||||
Bug #1980: Please, change default click behavior in OpenMW Launchers Data Files list
|
||||
Bug #1984: Vampire corpses standing up when looting the first item
|
||||
Bug #1985: Calm spell does nothing
|
||||
Bug #1986: Spell name lights up on mouseover but spell cost does not
|
||||
Bug #1989: Tooltip still shown when menu toggled off
|
||||
Bug #2010: Raindrops Displayed While Underwater
|
||||
Bug #2023: Walking into plants causes massive framedrop
|
||||
Bug #2031: [MOD: Shrines - Restore Health and Cancel Options]: Restore health option doesn't work
|
||||
Bug #2039: Lake Fjalding pillar of fire not rendered
|
||||
Bug #2040: AI_follow should stop further from the target
|
||||
Bug #2076: Slaughterfish AI
|
||||
Bug #2077: Direction of long jump can be changed much more than it is possible in vanilla
|
||||
Bug #2078: error during rendering: Object '' not found (const)
|
||||
Bug #2105: Lockpicking causes screen sync glitch
|
||||
Bug #2113: [MOD: Julan Ashlander Companion] Julan does not act correctly within the Ghostfence.
|
||||
Bug #2123: Window glow mod: Collision issues
|
||||
Bug #2133: Missing collision for bridges in Balmora when using Morrowind Rebirth 2.81
|
||||
Bug #2135: Casting a summon spell while the summon is active does not reset the summon.
|
||||
Bug #2144: Changing equipment will unequip drawn arrows/bolts
|
||||
Bug #2169: Yellow on faces when using opengl renderer and mods from overhaul on windows
|
||||
Bug #2175: Pathgrid mods do not overwrite the existing pathgrid
|
||||
Bug #2176: Morrowind -Russian localization end add-on ChaosHeart. Error in framelistener;object ;frenzying toush; not found <const>
|
||||
Bug #2181: Mod Morrowind crafting merchants die.
|
||||
Bug #2182: mods changing skill progression double the bonus for class specialization
|
||||
Bug #2183: Editor: Skills "use value" only allows integer between 0 and 99
|
||||
Bug #2184: Animated Morrowind Expanded produces an error on Open MW Launch
|
||||
Bug #2185: Conditional Operator formats
|
||||
Bug #2193: Quest: Gateway Ghost
|
||||
Bug #2194: Cannot summon multiples of the same creature
|
||||
Bug #2195: Pathgrid in the (0,0) exterior cell not loaded
|
||||
Bug #2200: Outdoor NPCs can stray away and keep walking into a wall
|
||||
Bug #2201: Creatures do not receive fall damage
|
||||
Bug #2202: The enchantment the item can hold is calculated incorrectly
|
||||
Bug #2203: Having the mod Living Cities of Vvardenfall running causes the game world to fail to load after leaving the prison ship
|
||||
Bug #2204: Abot's Water Life - Book rendered incorrectly
|
||||
Bug #2205: sound_waterfall script no longer compiles
|
||||
Bug #2206: Dialogue script fails to compile (extra .)
|
||||
Bug #2207: Script using – instead of - character does not compile
|
||||
Bug #2208: Failing dialogue scripts in french Morrowind.esm
|
||||
Bug #2214: LGNPC Vivec Redoran 1.62 and The King Rat (Size and inventory Issues)
|
||||
Bug #2215: Beast races can use enchanted boots
|
||||
Bug #2218: Incorrect names body parts in 3D models for open helmet with skinning
|
||||
Bug #2219: Orcs in Ghorak Manor in Caldera don't attack if you pick their pockets.
|
||||
Bug #2220: Chargen race preview head incorrect orientation
|
||||
Bug #2223: Reseting rock falling animation
|
||||
Bug #2224: Fortify Attribute effects do not stack when Spellmaking.
|
||||
Bug #2226: OpenCS pseudo-crash
|
||||
Bug #2230: segfaulting when entering Ald'ruhn with a specific mod: "fermeture la nuit" (closed by night)
|
||||
Bug #2233: Area effect spells on touch do not have the area effect
|
||||
Bug #2234: Dwarven Crossbow clips through the ground when dropped
|
||||
Bug #2235: class SettingsBase<> reverses the order of entries with multiple keys.
|
||||
Bug #2236: Weird two handed longsword + torch interaction
|
||||
Bug #2237: Shooting arrows while sneaking do not agro
|
||||
Bug #2238: Bipedal creatures not using weapons are not handled properly
|
||||
Bug #2245: Incorrect topic highlighting in HT_SpyBaladas quest
|
||||
Bug #2252: Tab completion incomplete for places using COC from the console.
|
||||
Bug #2255: Camera reverts to first person on load
|
||||
Bug #2259: enhancement: the save/load progress bar is not very progressive
|
||||
Bug #2263: TogglePOV can not be bound to Alt key
|
||||
Bug #2267: dialogue disabling via mod
|
||||
Bug #2268: Highlighting Files with load order problems in Data Files tab of Launcher
|
||||
Bug #2276: [Mod]ShotN issues with Karthwasten
|
||||
Bug #2283: Count argument for PlaceAt functions not working
|
||||
Bug #2284: Local map notes should be visible on door marker leading to the cell with the note
|
||||
Bug #2293: There is a graphical glitch at the end of the spell's animation in 3rd Person (looking over the shoulder) view
|
||||
Bug #2294: When using Skyrim UI Overhaul, the tops of pinnable menus are invisible
|
||||
Bug #2302: Random leveled items repeat way too often in a single dungeon
|
||||
Bug #2306: Enchanted arrows should not be retrievable from corpses
|
||||
Bug #2308: No sound effect when drawing the next throwing knife
|
||||
Bug #2309: Guards chase see the player character even if they're invisible
|
||||
Bug #2319: Inverted controls and other issues after becoming a vampire
|
||||
Bug #2324: Spells cast when crossing cell border are imprinted on the local map
|
||||
Bug #2330: Actors with Drain Health effect retain health after dying
|
||||
Bug #2331: tgm (god mode) won't allow the player to cast spells if the player doesn't have enough mana
|
||||
Bug #2332: Error in framelistener: Need a skeleton to attach the arrow to
|
||||
Feature #114: ess-Importer
|
||||
Feature #504: Editor: Delete selected rows from result windows
|
||||
Feature #1024: Addition of remaining equipping hotkeys
|
||||
Feature #1067: Handle NIF interpolation type 4 (XYZ_ROTATION_KEY)
|
||||
Feature #1125: AI fast-forward
|
||||
Feature #1228: Drowning while knocked out
|
||||
Feature #1325: Editor: Opening window and User Settings window cleanup
|
||||
Feature #1537: Ability to change the grid size from 3x3 to 5x5 (or more with good pc)
|
||||
Feature #1546: Leveled list script functions
|
||||
Feature #1659: Test dialogue scripts in --script-all
|
||||
Feature #1720: NPC lookAt controller
|
||||
Feature #2178: Load initial particle system state from NIF files
|
||||
Feature #2197: Editor: When clicking on a script error in the report window set cursor in script editor to the respective line/column
|
||||
Feature #2261: Warn when loading save games with mod mismatch
|
||||
Feature #2313: ess-Importer: convert global map exploration overlay
|
||||
Feature #2318: Add commandline option to load a save game
|
||||
Task #810: Rename "profile" to "content list"
|
||||
Task #2196: Label local/global openmw.cfg files via comments
|
||||
|
||||
0.34.0
|
||||
------
|
||||
|
||||
|
@ -6,4 +6,4 @@ export CC=clang
|
||||
brew tap openmw/openmw
|
||||
brew update
|
||||
brew unlink boost
|
||||
brew install openmw-mygui openmw-bullet openmw-sdl2 openmw-ffmpeg qt unshield
|
||||
brew install openmw-mygui openmw-bullet openmw-sdl2 openmw-ffmpeg openmw/openmw/qt unshield
|
||||
|
@ -1,5 +1,12 @@
|
||||
project(OpenMW)
|
||||
|
||||
# If the user doesn't supply a CMAKE_BUILD_TYPE via command line, choose one for them.
|
||||
IF(NOT CMAKE_BUILD_TYPE)
|
||||
SET(CMAKE_BUILD_TYPE RelWithDebInfo CACHE STRING
|
||||
"Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel."
|
||||
FORCE)
|
||||
ENDIF()
|
||||
|
||||
if (APPLE)
|
||||
set(APP_BUNDLE_NAME "${CMAKE_PROJECT_NAME}.app")
|
||||
|
||||
@ -12,7 +19,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/)
|
||||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 34)
|
||||
set(OPENMW_VERSION_MINOR 35)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
@ -374,10 +381,8 @@ configure_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-mimeinfo.xml
|
||||
"${OpenMW_BINARY_DIR}/openmw-mimeinfo.xml")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/opencs.desktop
|
||||
"${OpenMW_BINARY_DIR}/opencs.desktop")
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw-cs.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw-cs.desktop")
|
||||
endif()
|
||||
|
||||
# Compiler settings
|
||||
@ -389,13 +394,19 @@ if (CMAKE_COMPILER_IS_GNUCC)
|
||||
if ("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
||||
SET(CMAKE_CXX_FLAGS "-Wno-unused-but-set-parameter ${CMAKE_CXX_FLAGS}")
|
||||
endif("${GCC_VERSION}" VERSION_GREATER 4.6 OR "${GCC_VERSION}" VERSION_EQUAL 4.6)
|
||||
elseif (MSVC)
|
||||
# Enable link-time code generation globally for all linking
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /GL")
|
||||
set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
set(CMAKE_STATIC_LINKER_FLAGS_RELEASE "${CMAKE_STATIC_LINKER_FLAGS_RELEASE} /LTCG")
|
||||
endif (CMAKE_COMPILER_IS_GNUCC)
|
||||
|
||||
IF(NOT WIN32 AND NOT APPLE)
|
||||
# Linux building
|
||||
# Paths
|
||||
SET(BINDIR "${CMAKE_INSTALL_PREFIX}/bin" CACHE PATH "Where to install binaries")
|
||||
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib" CACHE PATH "Where to install libraries")
|
||||
SET(LIBDIR "${CMAKE_INSTALL_PREFIX}/lib${LIB_SUFFIX}" CACHE PATH "Where to install libraries")
|
||||
SET(DATAROOTDIR "${CMAKE_INSTALL_PREFIX}/share" CACHE PATH "Sets the root of data directories to a non-default location")
|
||||
SET(GLOBAL_DATA_PATH "${DATAROOTDIR}/games/" CACHE PATH "Set data path prefix")
|
||||
SET(DATADIR "${GLOBAL_DATA_PATH}/openmw" CACHE PATH "Sets the openmw data directories to a non-default location")
|
||||
@ -411,7 +422,7 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||
# Install binaries
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw" DESTINATION "${BINDIR}" )
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/omwlauncher" DESTINATION "${BINDIR}" )
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-launcher" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_BSATOOL)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/bsatool" DESTINATION "${BINDIR}" )
|
||||
@ -420,13 +431,13 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/esmtool" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESMTOOL)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/mwiniimport" DESTINATION "${BINDIR}" )
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-iniimporter" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_ESSIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-essimporter" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_ESSIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/opencs" DESTINATION "${BINDIR}" )
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/openmw-cs" DESTINATION "${BINDIR}" )
|
||||
ENDIF(BUILD_OPENCS)
|
||||
IF(BUILD_NIFTEST)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/niftest" DESTINATION "${BINDIR}" )
|
||||
@ -443,25 +454,25 @@ IF(NOT WIN32 AND NOT APPLE)
|
||||
INSTALL(FILES "extern/shiny/License.txt" DESTINATION "${LICDIR}" RENAME "Shiny License.txt" )
|
||||
|
||||
# Install icon and desktop file
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-mimeinfo.xml" DESTINATION "${DATAROOTDIR}/mime/packages" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/launcher/images/openmw.png" DESTINATION "${ICONDIR}" COMPONENT "openmw")
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.desktop" DESTINATION "${DATAROOTDIR}/applications" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/opencs.png" DESTINATION "${ICONDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw-cs.desktop" DESTINATION "${DATAROOTDIR}/applications" COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_SOURCE_DIR}/files/opencs/openmw-cs.png" DESTINATION "${ICONDIR}" COMPONENT "opencs")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
|
||||
# Install global configuration files
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/settings-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/transparency-overrides.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ COMPONENT "opencs")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION "${SYSCONFDIR}" COMPONENT "opencs")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
|
||||
# Install resources
|
||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" FILE_PERMISSIONS OWNER_READ GROUP_READ WORLD_READ COMPONENT "Resources")
|
||||
INSTALL(DIRECTORY "${OpenMW_BINARY_DIR}/resources" DESTINATION "${DATADIR}" COMPONENT "Resources")
|
||||
INSTALL(DIRECTORY DESTINATION "${DATADIR}/data" COMPONENT "Resources")
|
||||
ENDIF(NOT WIN32 AND NOT APPLE)
|
||||
|
||||
@ -481,16 +492,16 @@ if(WIN32)
|
||||
DESTINATION ".")
|
||||
|
||||
IF(BUILD_LAUNCHER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/omwlauncher.exe" DESTINATION ".")
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-launcher.exe" DESTINATION ".")
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_MWINIIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/mwiniimport.exe" DESTINATION ".")
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-iniimporter.exe" DESTINATION ".")
|
||||
ENDIF(BUILD_MWINIIMPORTER)
|
||||
IF(BUILD_ESSIMPORTER)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-essimporter.exe" DESTINATION ".")
|
||||
ENDIF(BUILD_ESSIMPORTER)
|
||||
IF(BUILD_OPENCS)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/opencs.exe" DESTINATION ".")
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Release/openmw-cs.exe" DESTINATION ".")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/opencs.ini" DESTINATION ".")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
IF(BUILD_WIZARD)
|
||||
@ -511,10 +522,10 @@ if(WIN32)
|
||||
SET(CPACK_PACKAGE_VERSION_PATCH ${OPENMW_VERSION_RELEASE})
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "openmw;OpenMW")
|
||||
IF(BUILD_LAUNCHER)
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};omwlauncher;OpenMW Launcher")
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-launcher;OpenMW Launcher")
|
||||
ENDIF(BUILD_LAUNCHER)
|
||||
IF(BUILD_OPENCS)
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};opencs;OpenMW Construction Set")
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-cs;OpenMW Construction Set")
|
||||
ENDIF(BUILD_OPENCS)
|
||||
IF(BUILD_WIZARD)
|
||||
SET(CPACK_PACKAGE_EXECUTABLES "${CPACK_PACKAGE_EXECUTABLES};openmw-wizard;OpenMW Wizard")
|
||||
@ -530,7 +541,7 @@ if(WIN32)
|
||||
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}")
|
||||
SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\www.openmw.org")
|
||||
SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\www.openmw.org")
|
||||
SET(CPACK_NSIS_INSTALLED_ICON_NAME "omwlauncher.exe")
|
||||
SET(CPACK_NSIS_INSTALLED_ICON_NAME "openmw-launcher.exe")
|
||||
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
|
||||
SET(CPACK_NSIS_MUI_UNIICON "${OpenMW_SOURCE_DIR}/files/windows/openmw.ico")
|
||||
SET(CPACK_PACKAGE_ICON "${OpenMW_SOURCE_DIR}\\\\files\\\\openmw.bmp")
|
||||
@ -667,6 +678,7 @@ if (WIN32)
|
||||
4193 # #pragma warning(pop) : no matching '#pragma warning(push)'
|
||||
4251 # class 'XXXX' needs to have dll-interface to be used by clients of class 'YYYY'
|
||||
4275 # non dll-interface struct 'XXXX' used as base for dll-interface class 'YYYY'
|
||||
4315 # undocumented, 'this' pointer for member might not be aligned (OgreMemoryStlAllocator.h)
|
||||
|
||||
# caused by boost
|
||||
4191 # 'type cast' : unsafe conversion (1.56, thread_primitives.hpp, normally off)
|
||||
@ -674,6 +686,7 @@ if (WIN32)
|
||||
# OpenMW specific warnings
|
||||
4099 # Type mismatch, declared class or struct is defined with other type
|
||||
4100 # Unreferenced formal parameter (-Wunused-parameter)
|
||||
4101 # Unreferenced local variable (-Wunused-variable)
|
||||
4127 # Conditional expression is constant
|
||||
4242 # Storing value in a variable of a smaller type, possible loss of data
|
||||
4244 # Storing value of one type in variable of another (size_t in int, for example)
|
||||
@ -695,16 +708,18 @@ if (WIN32)
|
||||
# boost::wave has a few issues with signed / unsigned conversions, so we suppress those here
|
||||
set(SHINY_WARNINGS "${WARNINGS} /wd4245")
|
||||
set_target_properties(shiny PROPERTIES COMPILE_FLAGS "${SHINY_WARNINGS} ${MT_BUILD}")
|
||||
# there's an unreferenced local variable in the ogre platform, suppress it
|
||||
set(SHINY_OGRE_WARNINGS "${WARNINGS} /wd4101")
|
||||
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${SHINY_OGRE_WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(shiny.OgrePlatform PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(sdl4ogre PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
# oics uses tinyxml, which has an initialized but unused variable
|
||||
set(OICS_WARNINGS "${WARNINGS} /wd4189")
|
||||
set_target_properties(oics PROPERTIES COMPILE_FLAGS "${OICS_WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(ogre-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
if (BUILD_MYGUI_PLUGIN)
|
||||
set_target_properties(Plugin_MyGUI_OpenMW_Resources PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif (BUILD_MYGUI_PLUGIN)
|
||||
if (BUILD_LAUNCHER)
|
||||
set_target_properties(omwlauncher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(openmw-launcher PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif (BUILD_LAUNCHER)
|
||||
set_target_properties(openmw PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
if (BUILD_BSATOOL)
|
||||
@ -719,10 +734,13 @@ if (WIN32)
|
||||
if (BUILD_OPENCS)
|
||||
# QT triggers an informational warning that the object layout may differ when compiled with /vd2
|
||||
set(OPENCS_WARNINGS "${WARNINGS} ${MT_BUILD} /wd4435")
|
||||
set_target_properties(opencs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
|
||||
set_target_properties(openmw-cs PROPERTIES COMPILE_FLAGS ${OPENCS_WARNINGS})
|
||||
endif (BUILD_OPENCS)
|
||||
if (BUILD_ESSIMPORTER)
|
||||
set_target_properties(openmw-essimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif (BUILD_ESSIMPORTER)
|
||||
if (BUILD_MWINIIMPORTER)
|
||||
set_target_properties(mwiniimport PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
set_target_properties(openmw-iniimporter PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif (BUILD_MWINIIMPORTER)
|
||||
endif(MSVC)
|
||||
|
||||
@ -767,7 +785,7 @@ if (APPLE)
|
||||
|
||||
set(OPENMW_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${APP_BUNDLE_NAME}")
|
||||
|
||||
set(OPENCS_BUNDLE_NAME "OpenCS.app")
|
||||
set(OPENCS_BUNDLE_NAME "OpenMW-CS.app")
|
||||
set(OPENCS_APP "\${CMAKE_INSTALL_PREFIX}/${INSTALL_SUBDIR}/${OPENCS_BUNDLE_NAME}")
|
||||
|
||||
set(ABSOLUTE_PLUGINS "")
|
||||
|
53
README.md
53
README.md
@ -1,14 +1,12 @@
|
||||
OpenMW
|
||||
======
|
||||
|
||||
[![Build Status](https://travis-ci.org/OpenMW/openmw.svg?branch=coverity_scan)](https://travis-ci.org/OpenMW/openmw)
|
||||
|
||||
[![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg?style=plastic)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
|
||||
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
||||
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
||||
|
||||
* Version: 0.34.0
|
||||
* Version: 0.35.0
|
||||
* License: GPL (see docs/license/GPL3.txt for more information)
|
||||
* Website: http://www.openmw.org
|
||||
* IRC: #openmw on irc.freenode.net
|
||||
@ -41,26 +39,26 @@ Command line options
|
||||
--version print version information and quit
|
||||
--data arg (=data) set data directories (later directories
|
||||
have higher priority)
|
||||
--data-local arg set local data directory (highest
|
||||
--data-local arg set local data directory (highest
|
||||
priority)
|
||||
--fallback-archive arg (=fallback-archive)
|
||||
set fallback BSA archives (later
|
||||
set fallback BSA archives (later
|
||||
archives have higher priority)
|
||||
--resources arg (=resources) set resources directory
|
||||
--start arg set initial cell
|
||||
--content arg content file(s): esm/esp, or
|
||||
--content arg content file(s): esm/esp, or
|
||||
omwgame/omwaddon
|
||||
--no-sound [=arg(=1)] (=0) disable all sounds
|
||||
--script-verbose [=arg(=1)] (=0) verbose script output
|
||||
--script-all [=arg(=1)] (=0) compile all scripts (excluding dialogue
|
||||
scripts) at startup
|
||||
--script-all-dialogue [=arg(=1)] (=0) compile all dialogue scripts at startup
|
||||
--script-console [=arg(=1)] (=0) enable console-only script
|
||||
--script-console [=arg(=1)] (=0) enable console-only script
|
||||
functionality
|
||||
--script-run arg select a file containing a list of
|
||||
console commands that is executed on
|
||||
--script-run arg select a file containing a list of
|
||||
console commands that is executed on
|
||||
startup
|
||||
--script-warn [=arg(=1)] (=1) handling of warnings when compiling
|
||||
--script-warn [=arg(=1)] (=1) handling of warnings when compiling
|
||||
scripts
|
||||
0 - ignore warning
|
||||
1 - show warning but consider script as
|
||||
@ -70,29 +68,32 @@ Command line options
|
||||
of the blacklist is enabled)
|
||||
--script-blacklist-use [=arg(=1)] (=1)
|
||||
enable script blacklisting
|
||||
--load-savegame arg load a save game file on game startup
|
||||
--load-savegame arg load a save game file on game startup
|
||||
(specify an absolute filename or a
|
||||
filename relative to the current
|
||||
working directory)
|
||||
--skip-menu [=arg(=1)] (=0) skip main menu on game startup
|
||||
--new-game [=arg(=1)] (=0) run new game sequence (ignored if
|
||||
--new-game [=arg(=1)] (=0) run new game sequence (ignored if
|
||||
skip-menu=0)
|
||||
--fs-strict [=arg(=1)] (=0) strict file system handling (no case
|
||||
--fs-strict [=arg(=1)] (=0) strict file system handling (no case
|
||||
folding)
|
||||
--encoding arg (=win1252) Character encoding used in OpenMW game
|
||||
--encoding arg (=win1252) Character encoding used in OpenMW game
|
||||
messages:
|
||||
|
||||
win1250 - Central and Eastern European
|
||||
such as Polish, Czech, Slovak,
|
||||
Hungarian, Slovene, Bosnian, Croatian,
|
||||
Serbian (Latin script), Romanian and
|
||||
|
||||
win1250 - Central and Eastern European
|
||||
such as Polish, Czech, Slovak,
|
||||
Hungarian, Slovene, Bosnian, Croatian,
|
||||
Serbian (Latin script), Romanian and
|
||||
Albanian languages
|
||||
|
||||
win1251 - Cyrillic alphabet such as
|
||||
Russian, Bulgarian, Serbian Cyrillic
|
||||
|
||||
win1251 - Cyrillic alphabet such as
|
||||
Russian, Bulgarian, Serbian Cyrillic
|
||||
and other languages
|
||||
|
||||
win1252 - Western European (Latin)
|
||||
|
||||
win1252 - Western European (Latin)
|
||||
alphabet, used by default
|
||||
--fallback arg fallback values
|
||||
--no-grab Don't grab mouse cursor
|
||||
--export-fonts [=arg(=1)] (=0) Export Morrowind .fnt fonts to PNG
|
||||
--export-fonts [=arg(=1)] (=0) Export Morrowind .fnt fonts to PNG
|
||||
image and XML file in current directory
|
||||
--activate-dist arg (=-1) activation distance override
|
||||
|
@ -59,6 +59,7 @@ struct Arguments
|
||||
std::string outname;
|
||||
|
||||
std::vector<std::string> types;
|
||||
std::string name;
|
||||
|
||||
ESMData data;
|
||||
ESM::ESMReader reader;
|
||||
@ -78,6 +79,8 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
||||
("type,t", bpo::value< std::vector<std::string> >(),
|
||||
"Show only records of this type (four character record code). May "
|
||||
"be specified multiple times. Only affects dump mode.")
|
||||
("name,n", bpo::value<std::string>(),
|
||||
"Show only the record with this name. Only affects dump mode.")
|
||||
("plain,p", "Print contents of dialogs, books and scripts. "
|
||||
"(skipped by default)"
|
||||
"Only affects dump mode.")
|
||||
@ -148,7 +151,9 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
||||
}
|
||||
|
||||
if (variables.count("type") > 0)
|
||||
info.types = variables["type"].as< std::vector<std::string> >();
|
||||
info.types = variables["type"].as< std::vector<std::string> >();
|
||||
if (variables.count("name") > 0)
|
||||
info.name = variables["name"].as<std::string>();
|
||||
|
||||
info.mode = variables["mode"].as<std::string>();
|
||||
if (!(info.mode == "dump" || info.mode == "clone" || info.mode == "comp"))
|
||||
@ -265,6 +270,8 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
||||
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
||||
std::cout << " Deleted: " << deleted << std::endl;
|
||||
if (!ref.mKey.empty())
|
||||
std::cout << " Key: '" << ref.mKey << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@ -358,6 +365,9 @@ int load(Arguments& info)
|
||||
if (id.empty())
|
||||
id = esm.getHNOString("INAM");
|
||||
|
||||
if (!info.name.empty() && !Misc::StringUtils::ciEqual(info.name, id))
|
||||
interested = false;
|
||||
|
||||
if(!quiet && interested)
|
||||
std::cout << "\nRecord: " << n.toString()
|
||||
<< " '" << id << "'\n";
|
||||
@ -385,7 +395,7 @@ int load(Arguments& info)
|
||||
record->load(esm);
|
||||
if (!quiet && interested) record->print();
|
||||
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells) {
|
||||
if (record->getType().val == ESM::REC_CELL && loadCells && interested) {
|
||||
loadCell(record->cast<ESM::Cell>()->get(), esm, info);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include "labels.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <boost/format.hpp>
|
||||
|
||||
void printAIPackage(ESM::AIPackage p)
|
||||
@ -533,10 +535,10 @@ void Record<ESM::Class>::print()
|
||||
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization)
|
||||
<< " (" << mData.mData.mSpecialization << ")" << std::endl;
|
||||
for (int i = 0; i != 5; i++)
|
||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][0])
|
||||
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][0])
|
||||
<< " (" << mData.mData.mSkills[i][0] << ")" << std::endl;
|
||||
for (int i = 0; i != 5; i++)
|
||||
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
||||
<< " (" << mData.mData.mSkills[i][1] << ")" << std::endl;
|
||||
}
|
||||
|
||||
@ -752,7 +754,7 @@ void Record<ESM::DialInfo>::print()
|
||||
if (mData.mCell != "")
|
||||
std::cout << " Cell: " << mData.mCell << std::endl;
|
||||
if (mData.mData.mDisposition > 0)
|
||||
std::cout << " Disposition: " << mData.mData.mDisposition << std::endl;
|
||||
std::cout << " Disposition/Journal index: " << mData.mData.mDisposition << std::endl;
|
||||
if (mData.mData.mGender != ESM::DialInfo::NA)
|
||||
std::cout << " Gender: " << mData.mData.mGender << std::endl;
|
||||
if (mData.mSound != "")
|
||||
@ -812,7 +814,6 @@ void Record<ESM::Land>::print()
|
||||
{
|
||||
std::cout << " Coordinates: (" << mData.mX << "," << mData.mY << ")" << std::endl;
|
||||
std::cout << " Flags: " << landFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " HasData: " << mData.mHasData << std::endl;
|
||||
std::cout << " DataTypes: " << mData.mDataTypes << std::endl;
|
||||
|
||||
// Seems like this should done with reference counting in the
|
||||
@ -836,7 +837,7 @@ void Record<ESM::CreatureLevList>::print()
|
||||
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
|
||||
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
|
||||
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
|
||||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Creature: Level: " << iit->mLevel
|
||||
<< " Creature: " << iit->mId << std::endl;
|
||||
@ -848,7 +849,7 @@ void Record<ESM::ItemLevList>::print()
|
||||
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
|
||||
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
|
||||
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
|
||||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Inventory: Level: " << iit->mLevel
|
||||
<< " Item: " << iit->mId << std::endl;
|
||||
|
@ -24,6 +24,8 @@ set(ESSIMPORTER_FILES
|
||||
convertcrec.cpp
|
||||
convertcntc.cpp
|
||||
convertscri.cpp
|
||||
convertscpt.cpp
|
||||
convertplayer.cpp
|
||||
)
|
||||
|
||||
add_executable(openmw-essimporter
|
||||
|
@ -29,6 +29,12 @@ namespace ESSImport
|
||||
}
|
||||
cStats.mGoldPool = acdt.mGoldPool;
|
||||
cStats.mTalkedTo = acdt.mFlags & TalkedToPlayer;
|
||||
cStats.mAttacked = acdt.mFlags & Attacked;
|
||||
}
|
||||
|
||||
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats)
|
||||
{
|
||||
cStats.mDead = acsc.mFlags & Dead;
|
||||
}
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)
|
||||
|
@ -15,6 +15,7 @@ namespace ESSImport
|
||||
|
||||
|
||||
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats);
|
||||
void convertACSC (const ACSC& acsc, ESM::CreatureStats& cStats);
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats);
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdexcept>
|
||||
|
||||
#include <OgreImage.h>
|
||||
#include <OgreColourValue.h>
|
||||
|
||||
#include <components/esm/creaturestate.hpp>
|
||||
#include <components/esm/containerstate.hpp>
|
||||
@ -69,7 +70,65 @@ namespace ESSImport
|
||||
esm.getSubHeader();
|
||||
data.resize(esm.getSubSize());
|
||||
esm.getExact(&data[0], data.size());
|
||||
convertImage(&data[0], data.size(), maph.size, maph.size, Ogre::PF_BYTE_RGB, "map.tga");
|
||||
|
||||
Ogre::DataStreamPtr stream (new Ogre::MemoryDataStream(&data[0], data.size()));
|
||||
mGlobalMapImage.loadRawData(stream, maph.size, maph.size, 1, Ogre::PF_BYTE_RGB);
|
||||
// to match openmw size
|
||||
mGlobalMapImage.resize(maph.size*2, maph.size*2, Ogre::Image::FILTER_BILINEAR);
|
||||
}
|
||||
|
||||
void ConvertFMAP::write(ESM::ESMWriter &esm)
|
||||
{
|
||||
int numcells = mGlobalMapImage.getWidth() / 18; // NB truncating, doesn't divide perfectly
|
||||
// with the 512x512 map the game has by default
|
||||
int cellSize = mGlobalMapImage.getWidth()/numcells;
|
||||
|
||||
// Note the upper left corner of the (0,0) cell should be at (width/2, height/2)
|
||||
|
||||
mContext->mGlobalMapState.mBounds.mMinX = -numcells/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxX = (numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMinY = -(numcells-1)/2;
|
||||
mContext->mGlobalMapState.mBounds.mMaxY = numcells/2;
|
||||
|
||||
Ogre::Image image2;
|
||||
std::vector<Ogre::uint8> data;
|
||||
int width = cellSize*numcells;
|
||||
int height = cellSize*numcells;
|
||||
data.resize(width*height*4, 0);
|
||||
image2.loadDynamicImage(&data[0], width, height, Ogre::PF_BYTE_RGBA);
|
||||
|
||||
for (std::set<std::pair<int, int> >::const_iterator it = mContext->mExploredCells.begin(); it != mContext->mExploredCells.end(); ++it)
|
||||
{
|
||||
if (it->first > mContext->mGlobalMapState.mBounds.mMaxX
|
||||
|| it->first < mContext->mGlobalMapState.mBounds.mMinX
|
||||
|| it->second > mContext->mGlobalMapState.mBounds.mMaxY
|
||||
|| it->second < mContext->mGlobalMapState.mBounds.mMinY)
|
||||
{
|
||||
// out of bounds, I think this could happen, since the original engine had a fixed-size map
|
||||
continue;
|
||||
}
|
||||
|
||||
int imageLeftSrc = mGlobalMapImage.getWidth()/2;
|
||||
int imageTopSrc = mGlobalMapImage.getHeight()/2;
|
||||
imageLeftSrc += it->first * cellSize;
|
||||
imageTopSrc -= it->second * cellSize;
|
||||
int imageLeftDst = width/2;
|
||||
int imageTopDst = height/2;
|
||||
imageLeftDst += it->first * cellSize;
|
||||
imageTopDst -= it->second * cellSize;
|
||||
for (int x=0; x<cellSize; ++x)
|
||||
for (int y=0; y<cellSize; ++y)
|
||||
image2.setColourAt(mGlobalMapImage.getColourAt(imageLeftSrc+x, imageTopSrc+y, 0)
|
||||
, imageLeftDst+x, imageTopDst+y, 0);
|
||||
}
|
||||
|
||||
Ogre::DataStreamPtr encoded = image2.encode("png");
|
||||
mContext->mGlobalMapState.mImageData.resize(encoded->size());
|
||||
encoded->read(&mContext->mGlobalMapState.mImageData[0], encoded->size());
|
||||
|
||||
esm.startRecord(ESM::REC_GMAP);
|
||||
mContext->mGlobalMapState.save(esm);
|
||||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
void ConvertCell::read(ESM::ESMReader &esm)
|
||||
@ -103,6 +162,10 @@ namespace ESSImport
|
||||
// (probably offset of that specific fog texture?)
|
||||
while (esm.isNextSub("NAM8"))
|
||||
{
|
||||
if (cell.isExterior()) // TODO: NAM8 occasionally exists for cells that haven't been explored.
|
||||
// are there any flags marking explored cells?
|
||||
mContext->mExploredCells.insert(std::make_pair(cell.mData.mX, cell.mData.mY));
|
||||
|
||||
esm.getSubHeader();
|
||||
|
||||
if (esm.getSubSize() == 36)
|
||||
@ -211,6 +274,8 @@ namespace ESSImport
|
||||
const CellRef& cellref = *refIt;
|
||||
ESM::CellRef out (cellref);
|
||||
|
||||
// TODO: use mContext->mCreatures/mNpcs
|
||||
|
||||
if (!isIndexedRefId(cellref.mIndexedRefId))
|
||||
{
|
||||
// non-indexed RefNum, i.e. no CREC/NPCC/CNTC record associated with it
|
||||
@ -246,9 +311,12 @@ namespace ESSImport
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
// probably need more micromanagement here so we don't overwrite values
|
||||
// TODO: need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
if (cellref.mHasACDT)
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
if (cellref.mHasACSC)
|
||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||
convertNpcData(cellref, objstate.mNpcStats);
|
||||
convertNPCC(npccIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
@ -280,9 +348,12 @@ namespace ESSImport
|
||||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
// probably need more micromanagement here so we don't overwrite values
|
||||
// TODO: need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
if (cellref.mHasACDT)
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
if (cellref.mHasACSC)
|
||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||
convertCREC(crecIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
||||
@ -313,10 +384,6 @@ namespace ESSImport
|
||||
it->save(esm);
|
||||
esm.endRecord(ESM::REC_MARK);
|
||||
}
|
||||
|
||||
esm.startRecord(ESM::REC_GMAP);
|
||||
mContext->mGlobalMapState.save(esm);
|
||||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#ifndef OPENMW_ESSIMPORT_CONVERTER_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTER_H
|
||||
|
||||
#include <OgreImage.h>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
|
||||
@ -13,6 +15,10 @@
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/custommarkerstate.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/weatherstate.hpp>
|
||||
#include <components/esm/globalscript.hpp>
|
||||
#include <components/esm/queststate.hpp>
|
||||
#include <components/esm/stolenitems.hpp>
|
||||
|
||||
#include "importcrec.hpp"
|
||||
#include "importcntc.hpp"
|
||||
@ -29,6 +35,8 @@
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
#include "convertnpcc.hpp"
|
||||
#include "convertscpt.hpp"
|
||||
#include "convertplayer.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
@ -98,10 +106,10 @@ public:
|
||||
npc.load(esm);
|
||||
if (id != "player")
|
||||
{
|
||||
// TODO:
|
||||
// this should handle changes to the NPC struct, but since there is no index here
|
||||
// Handles changes to the NPC struct, but since there is no index here
|
||||
// it will apply to ALL instances of the class. seems to be the reason for the
|
||||
// "feature" in MW where changing AI settings of one guard will change it for all guards of that refID.
|
||||
mContext->mNpcs[Misc::StringUtils::lowerCase(id)] = npc;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -133,6 +141,7 @@ public:
|
||||
ESM::Creature creature;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
creature.load(esm);
|
||||
mContext->mCreatures[Misc::StringUtils::lowerCase(id)] = creature;
|
||||
}
|
||||
};
|
||||
|
||||
@ -206,7 +215,7 @@ public:
|
||||
else
|
||||
{
|
||||
int index = npcc.mNPDT.mIndex;
|
||||
mContext->mNpcChanges.insert(std::make_pair(std::make_pair(index,id), npcc)).second;
|
||||
mContext->mNpcChanges.insert(std::make_pair(std::make_pair(index,id), npcc));
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -253,32 +262,23 @@ private:
|
||||
class ConvertPCDT : public Converter
|
||||
{
|
||||
public:
|
||||
ConvertPCDT() : mFirstPersonCam(true) {}
|
||||
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
PCDT pcdt;
|
||||
pcdt.load(esm);
|
||||
|
||||
mContext->mPlayer.mBirthsign = pcdt.mBirthsign;
|
||||
mContext->mPlayer.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||
for (std::vector<PCDT::FNAM>::const_iterator it = pcdt.mFactions.begin(); it != pcdt.mFactions.end(); ++it)
|
||||
{
|
||||
ESM::NpcStats::Faction faction;
|
||||
faction.mExpelled = it->mFlags & 0x2;
|
||||
faction.mRank = it->mRank;
|
||||
faction.mReputation = it->mReputation;
|
||||
mContext->mPlayer.mObject.mNpcStats.mFactions[it->mFactionName.toString()] = faction;
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
mContext->mPlayer.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
mContext->mPlayer.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
|
||||
it != pcdt.mKnownDialogueTopics.end(); ++it)
|
||||
{
|
||||
mContext->mDialogueState.mKnownTopics.push_back(Misc::StringUtils::lowerCase(*it));
|
||||
}
|
||||
|
||||
convertPCDT(pcdt, mContext->mPlayer, mContext->mDialogueState.mKnownTopics, mFirstPersonCam);
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
esm.startRecord(ESM::REC_CAM_);
|
||||
esm.writeHNT("FIRS", mFirstPersonCam);
|
||||
esm.endRecord(ESM::REC_CAM_);
|
||||
}
|
||||
private:
|
||||
bool mFirstPersonCam;
|
||||
};
|
||||
|
||||
class ConvertCNTC : public Converter
|
||||
@ -308,6 +308,10 @@ class ConvertFMAP : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader &esm);
|
||||
virtual void write(ESM::ESMWriter &esm);
|
||||
|
||||
private:
|
||||
Ogre::Image mGlobalMapImage;
|
||||
};
|
||||
|
||||
class ConvertCell : public Converter
|
||||
@ -384,29 +388,55 @@ public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string itemid = esm.getHNString("NAME");
|
||||
Misc::StringUtils::toLower(itemid);
|
||||
|
||||
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
|
||||
{
|
||||
if (esm.retSubName().toString() == "FNAM")
|
||||
{
|
||||
std::string factionid = esm.getHString();
|
||||
mFactionStolenItems.insert(std::make_pair(itemid, factionid));
|
||||
mStolenItems[itemid].insert(std::make_pair(Misc::StringUtils::lowerCase(factionid), true));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string ownerid = esm.getHString();
|
||||
mStolenItems.insert(std::make_pair(itemid, ownerid));
|
||||
mStolenItems[itemid].insert(std::make_pair(Misc::StringUtils::lowerCase(ownerid), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
ESM::StolenItems items;
|
||||
for (std::map<std::string, std::set<Owner> >::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
|
||||
{
|
||||
std::map<std::pair<std::string, bool>, int> owners;
|
||||
for (std::set<Owner>::const_iterator ownerIt = it->second.begin(); ownerIt != it->second.end(); ++ownerIt)
|
||||
{
|
||||
owners.insert(std::make_pair(std::make_pair(ownerIt->first, ownerIt->second)
|
||||
// Since OpenMW doesn't suffer from the owner contamination bug,
|
||||
// it needs a count argument. But for legacy savegames, we don't know
|
||||
// this count, so must assume all items of that ID are stolen,
|
||||
// like vanilla MW did.
|
||||
,std::numeric_limits<int>::max()));
|
||||
}
|
||||
|
||||
items.mStolenItems.insert(std::make_pair(it->first, owners));
|
||||
}
|
||||
|
||||
esm.startRecord(ESM::REC_STLN);
|
||||
items.write(esm);
|
||||
esm.endRecord(ESM::REC_STLN);
|
||||
}
|
||||
|
||||
private:
|
||||
std::multimap<std::string, std::string> mStolenItems;
|
||||
std::multimap<std::string, std::string> mFactionStolenItems;
|
||||
typedef std::pair<std::string, bool> Owner; // <owner id, bool isFaction>
|
||||
|
||||
std::map<std::string, std::set<Owner> > mStolenItems;
|
||||
};
|
||||
|
||||
/// Seen responses for a dialogue topic?
|
||||
/// Each DIAL record is followed by a number of INFO records, I believe, just like in ESMs
|
||||
/// Dialogue conversion problems (probably have to adjust OpenMW format) -
|
||||
/// Dialogue conversion problems:
|
||||
/// - Journal is stored in one continuous HTML markup rather than each entry separately with associated info ID.
|
||||
/// - Seen dialogue responses only store the INFO id, rather than the fulltext.
|
||||
/// - Quest stages only store the INFO id, rather than the journal entry fulltext.
|
||||
@ -428,7 +458,24 @@ public:
|
||||
std::string id = esm.getHNString("NAME");
|
||||
DIAL dial;
|
||||
dial.load(esm);
|
||||
if (dial.mIndex > 0)
|
||||
mDials[id] = dial;
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
for (std::map<std::string, DIAL>::const_iterator it = mDials.begin(); it != mDials.end(); ++it)
|
||||
{
|
||||
esm.startRecord(ESM::REC_QUES);
|
||||
ESM::QuestState state;
|
||||
state.mFinished = 0;
|
||||
state.mState = it->second.mIndex;
|
||||
state.mTopic = Misc::StringUtils::lowerCase(it->first);
|
||||
state.save(esm);
|
||||
esm.endRecord(ESM::REC_QUES);
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::map<std::string, DIAL> mDials;
|
||||
};
|
||||
|
||||
class ConvertQUES : public Converter
|
||||
@ -455,11 +502,69 @@ public:
|
||||
class ConvertGAME : public Converter
|
||||
{
|
||||
public:
|
||||
ConvertGAME() : mHasGame(false) {}
|
||||
|
||||
std::string toString(int weatherId)
|
||||
{
|
||||
switch (weatherId)
|
||||
{
|
||||
case 0:
|
||||
return "clear";
|
||||
case 1:
|
||||
return "cloudy";
|
||||
case 2:
|
||||
return "foggy";
|
||||
case 3:
|
||||
return "overcast";
|
||||
case 4:
|
||||
return "rain";
|
||||
case 5:
|
||||
return "thunderstorm";
|
||||
case 6:
|
||||
return "ashstorm";
|
||||
case 7:
|
||||
return "blight";
|
||||
case 8:
|
||||
return "snow";
|
||||
case 9:
|
||||
return "blizzard";
|
||||
case -1:
|
||||
return "";
|
||||
default:
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "unknown weather id: " << weatherId;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
GAME game;
|
||||
game.load(esm);
|
||||
mGame.load(esm);
|
||||
mHasGame = true;
|
||||
}
|
||||
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
if (!mHasGame)
|
||||
return;
|
||||
esm.startRecord(ESM::REC_WTHR);
|
||||
ESM::WeatherState weather;
|
||||
weather.mCurrentWeather = toString(mGame.mGMDT.mCurrentWeather);
|
||||
weather.mNextWeather = toString(mGame.mGMDT.mNextWeather);
|
||||
weather.mRemainingTransitionTime = mGame.mGMDT.mWeatherTransition/100.f*(0.015*24*3600);
|
||||
weather.mHour = mContext->mHour;
|
||||
weather.mWindSpeed = 0.f;
|
||||
weather.mTimePassed = 0.0;
|
||||
weather.mFirstUpdate = false;
|
||||
weather.save(esm);
|
||||
esm.endRecord(ESM::REC_WTHR);
|
||||
}
|
||||
|
||||
private:
|
||||
bool mHasGame;
|
||||
GAME mGame;
|
||||
};
|
||||
|
||||
/// Running global script
|
||||
@ -470,7 +575,21 @@ public:
|
||||
{
|
||||
SCPT script;
|
||||
script.load(esm);
|
||||
ESM::GlobalScript out;
|
||||
convertSCPT(script, out);
|
||||
mScripts.push_back(out);
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
for (std::vector<ESM::GlobalScript>::const_iterator it = mScripts.begin(); it != mScripts.end(); ++it)
|
||||
{
|
||||
esm.startRecord(ESM::REC_GSCR);
|
||||
it->save(esm);
|
||||
esm.endRecord(ESM::REC_GSCR);
|
||||
}
|
||||
}
|
||||
private:
|
||||
std::vector<ESM::GlobalScript> mScripts;
|
||||
};
|
||||
|
||||
}
|
||||
|
38
apps/essimporter/convertplayer.cpp
Normal file
38
apps/essimporter/convertplayer.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
#include "convertplayer.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam)
|
||||
{
|
||||
out.mBirthsign = pcdt.mBirthsign;
|
||||
out.mObject.mNpcStats.mBounty = pcdt.mBounty;
|
||||
for (std::vector<PCDT::FNAM>::const_iterator it = pcdt.mFactions.begin(); it != pcdt.mFactions.end(); ++it)
|
||||
{
|
||||
ESM::NpcStats::Faction faction;
|
||||
faction.mExpelled = (it->mFlags & 0x2) != 0;
|
||||
faction.mRank = it->mRank;
|
||||
faction.mReputation = it->mReputation;
|
||||
out.mObject.mNpcStats.mFactions[Misc::StringUtils::lowerCase(it->mFactionName.toString())] = faction;
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
for (int i=0; i<27; ++i)
|
||||
out.mObject.mNpcStats.mSkills[i].mRegular.mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||
out.mObject.mCreatureStats.mDrawState = 1;
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Spell)
|
||||
out.mObject.mCreatureStats.mDrawState = 2;
|
||||
|
||||
firstPersonCam = (pcdt.mPNAM.mCameraState == PCDT::CameraState_FirstPerson);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
|
||||
it != pcdt.mKnownDialogueTopics.end(); ++it)
|
||||
{
|
||||
outDialogueTopics.push_back(Misc::StringUtils::lowerCase(*it));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
15
apps/essimporter/convertplayer.hpp
Normal file
15
apps/essimporter/convertplayer.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef OPENMW_ESSIMPORT_CONVERTPLAYER_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTPLAYER_H
|
||||
|
||||
#include "importplayer.hpp"
|
||||
|
||||
#include <components/esm/player.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertPCDT(const PCDT& pcdt, ESM::Player& out, std::vector<std::string>& outDialogueTopics, bool& firstPersonCam);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
17
apps/essimporter/convertscpt.cpp
Normal file
17
apps/essimporter/convertscpt.cpp
Normal file
@ -0,0 +1,17 @@
|
||||
#include "convertscpt.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "convertscri.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT &scpt, ESM::GlobalScript &out)
|
||||
{
|
||||
out.mId = Misc::StringUtils::lowerCase(scpt.mSCHD.mName.toString());
|
||||
out.mRunning = scpt.mRunning;
|
||||
convertSCRI(scpt.mSCRI, out.mLocals);
|
||||
}
|
||||
|
||||
}
|
15
apps/essimporter/convertscpt.hpp
Normal file
15
apps/essimporter/convertscpt.hpp
Normal file
@ -0,0 +1,15 @@
|
||||
#ifndef OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTSCPT_H
|
||||
|
||||
#include <components/esm/globalscript.hpp>
|
||||
|
||||
#include "importscpt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCPT(const SCPT& scpt, ESM::GlobalScript& out);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -20,12 +20,22 @@ namespace ESSImport
|
||||
|
||||
ESM::CellRef::loadData(esm);
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
esm.getHNOT(mACDT, "ACDT");
|
||||
mHasACDT = false;
|
||||
if (esm.isNextSub("ACDT"))
|
||||
{
|
||||
mHasACDT = true;
|
||||
esm.getHT(mACDT);
|
||||
}
|
||||
|
||||
ACSC acsc;
|
||||
esm.getHNOT(acsc, "ACSC");
|
||||
esm.getHNOT(acsc, "ACSL");
|
||||
mHasACSC = false;
|
||||
if (esm.isNextSub("ACSC"))
|
||||
{
|
||||
mHasACSC = true;
|
||||
esm.getHT(mACSC);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("ACSL"))
|
||||
esm.skipHSubSize(112);
|
||||
|
||||
if (esm.isNextSub("CSTN"))
|
||||
esm.skipHSub(); // "PlayerSaveGame", link to some object?
|
||||
@ -60,10 +70,6 @@ namespace ESSImport
|
||||
if (esm.isNextSub("PWPS"))
|
||||
esm.skipHSub();
|
||||
|
||||
// unsure at which point between LSTN and CHRD
|
||||
if (esm.isNextSub("APUD"))
|
||||
esm.skipHSub(); // 40 bytes, starts with string "ancestor guardian". maybe spellcasting in progress?
|
||||
|
||||
if (esm.isNextSub("WNAM"))
|
||||
{
|
||||
std::string id = esm.getHString();
|
||||
@ -77,6 +83,20 @@ namespace ESSImport
|
||||
esm.skipHSub(); // 4 byte, 0
|
||||
}
|
||||
|
||||
while (esm.isNextSub("APUD"))
|
||||
{
|
||||
// used power
|
||||
esm.getSubHeader();
|
||||
std::string id = esm.getString(32);
|
||||
(void)id;
|
||||
// timestamp can't be used: this is the total hours passed, calculated by
|
||||
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
|
||||
// unfortunately cumulativeDays[month] is not clearly defined,
|
||||
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
|
||||
double timestamp;
|
||||
esm.getT(timestamp);
|
||||
}
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
if (esm.isNextSub("CHRD")) // npc only
|
||||
esm.getHExact(mSkills, 27*2*sizeof(int));
|
||||
|
@ -9,7 +9,7 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
@ -17,7 +17,13 @@ namespace ESSImport
|
||||
|
||||
enum ACDTFlags
|
||||
{
|
||||
TalkedToPlayer = 0x4
|
||||
TalkedToPlayer = 0x4,
|
||||
Attacked = 0x100,
|
||||
Unknown = 0x200
|
||||
};
|
||||
enum ACSCFlags
|
||||
{
|
||||
Dead = 0x2
|
||||
};
|
||||
|
||||
/// Actor data, shared by (at least) REFR and CellRef
|
||||
@ -28,24 +34,38 @@ namespace ESSImport
|
||||
// Note, not stored at *all*:
|
||||
// - Level changes are lost on reload, except for the player (there it's in the NPC record).
|
||||
unsigned char mUnknown[12];
|
||||
unsigned char mFlags; // ACDTFlags
|
||||
unsigned char mUnknown1[3];
|
||||
unsigned int mFlags;
|
||||
float mBreathMeter; // Seconds left before drowning
|
||||
unsigned char mUnknown2[20];
|
||||
float mDynamic[3][2];
|
||||
unsigned char mUnknown3[16];
|
||||
float mAttributes[8][2];
|
||||
unsigned char mUnknown4[112];
|
||||
float mMagicEffects[27]; // Effect attributes: https://wiki.openmw.org/index.php?title=Research:Magic#Effect_attributes
|
||||
unsigned char mUnknown4[4];
|
||||
unsigned int mGoldPool;
|
||||
unsigned char mUnknown5[4];
|
||||
unsigned char mCountDown; // seen the same value as in ACSC.mCorpseClearCountdown, maybe
|
||||
// this one is for respawning?
|
||||
unsigned char mUnknown5[3];
|
||||
};
|
||||
struct ACSC
|
||||
{
|
||||
unsigned char mUnknown1[17];
|
||||
unsigned char mFlags; // ACSCFlags
|
||||
unsigned char mUnknown2[22];
|
||||
unsigned char mCorpseClearCountdown; // hours?
|
||||
unsigned char mUnknown3[71];
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct ActorData : public ESM::CellRef
|
||||
{
|
||||
bool mHasACDT;
|
||||
ACDT mACDT;
|
||||
|
||||
int mSkills[27][2];
|
||||
bool mHasACSC;
|
||||
ACSC mACSC;
|
||||
|
||||
int mSkills[27][2]; // skills, base and modified
|
||||
|
||||
// creature combat stats, base and modified
|
||||
// I think these can be ignored in the conversion, because it is not possible
|
||||
@ -60,12 +80,6 @@ namespace ESSImport
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
/// Unknown, shared by (at least) REFR and CellRef
|
||||
struct ACSC
|
||||
{
|
||||
unsigned char unknown[112];
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,7 +22,7 @@ namespace ESSImport
|
||||
ActorData::load(esm);
|
||||
if (esm.isNextSub("LVCR"))
|
||||
{
|
||||
// occurs on leveled creature spawner references
|
||||
// occurs on levelled creature spawner references
|
||||
// probably some identifier for the creature that has been spawned?
|
||||
unsigned char lvcr;
|
||||
esm.getHT(lvcr);
|
||||
@ -32,7 +32,7 @@ namespace ESSImport
|
||||
mEnabled = true;
|
||||
esm.getHNOT(mEnabled, "ZNAM");
|
||||
|
||||
// DATA should occur for all references, except leveled creature spawners
|
||||
// DATA should occur for all references, except levelled creature spawners
|
||||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||
// alarmvoi0000.ess
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
|
@ -14,10 +14,10 @@ namespace ESSImport
|
||||
float scale;
|
||||
esm.getHNOT(scale, "XSCL");
|
||||
|
||||
// FIXME: use AiPackageList, need to fix getSubName()
|
||||
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
esm.skipHSub();
|
||||
mAiPackages.add(esm);
|
||||
|
||||
mInventory.load(esm);
|
||||
}
|
||||
|
@ -2,6 +2,7 @@
|
||||
#define OPENMW_ESSIMPORT_CREC_H
|
||||
|
||||
#include "importinventory.hpp"
|
||||
#include <components/esm/aipackage.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
@ -17,6 +18,7 @@ namespace ESSImport
|
||||
int mIndex;
|
||||
|
||||
Inventory mInventory;
|
||||
ESM::AIPackageList mAiPackages;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
@ -2,7 +2,7 @@
|
||||
#define OPENMW_ESSIMPORT_IMPORTDIAL_H
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "importer.hpp"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
|
||||
@ -20,6 +21,8 @@
|
||||
#include <components/esm/loadlevlist.hpp>
|
||||
#include <components/esm/loadglob.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
#include "importercontext.hpp"
|
||||
|
||||
#include "converter.hpp"
|
||||
@ -43,9 +46,10 @@ namespace
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
Importer::Importer(const std::string &essfile, const std::string &outfile)
|
||||
Importer::Importer(const std::string &essfile, const std::string &outfile, const std::string &encoding)
|
||||
: mEssFile(essfile)
|
||||
, mOutFile(outfile)
|
||||
, mEncoding(encoding)
|
||||
{
|
||||
|
||||
}
|
||||
@ -166,14 +170,30 @@ namespace ESSImport
|
||||
std::cout << "Data 1:" << std::endl;
|
||||
for (unsigned int k=0; k<sub.mData.size(); ++k)
|
||||
{
|
||||
bool different = false;
|
||||
if (k >= sub2.mData.size() || sub2.mData[k] != sub.mData[k])
|
||||
different = true;
|
||||
|
||||
if (different)
|
||||
std::cout << "\033[033m";
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)sub.mData[k] << " ";
|
||||
if (different)
|
||||
std::cout << "\033[0m";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
std::cout << "Data 2:" << std::endl;
|
||||
for (unsigned int k=0; k<sub2.mData.size(); ++k)
|
||||
{
|
||||
bool different = false;
|
||||
if (k >= sub.mData.size() || sub.mData[k] != sub2.mData[k])
|
||||
different = true;
|
||||
|
||||
if (different)
|
||||
std::cout << "\033[033m";
|
||||
std::cout << std::hex << std::setw(2) << std::setfill('0') << (int)sub2.mData[k] << " ";
|
||||
if (different)
|
||||
std::cout << "\033[0m";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@ -187,10 +207,10 @@ namespace ESSImport
|
||||
Ogre::LogManager logman;
|
||||
Ogre::Root root;
|
||||
|
||||
// TODO: set up encoding on ESMReader based on openmw.cfg / --encoding switch
|
||||
|
||||
ToUTF8::Utf8Encoder encoder(ToUTF8::calculateEncoding(mEncoding));
|
||||
ESM::ESMReader esm;
|
||||
esm.open(mEssFile);
|
||||
esm.setEncoder(&encoder);
|
||||
|
||||
Context context;
|
||||
|
||||
@ -341,8 +361,8 @@ namespace ESSImport
|
||||
{
|
||||
// exterior cell -> determine cell coordinates based on position
|
||||
const int cellSize = 8192;
|
||||
int cellX = std::floor(context.mPlayer.mObject.mPosition.pos[0]/cellSize);
|
||||
int cellY = std::floor(context.mPlayer.mObject.mPosition.pos[1]/cellSize);
|
||||
int cellX = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[0]/cellSize));
|
||||
int cellY = static_cast<int>(std::floor(context.mPlayer.mObject.mPosition.pos[1] / cellSize));
|
||||
context.mPlayer.mCellId.mIndex.mX = cellX;
|
||||
context.mPlayer.mCellId.mIndex.mY = cellY;
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace ESSImport
|
||||
class Importer
|
||||
{
|
||||
public:
|
||||
Importer(const std::string& essfile, const std::string& outfile);
|
||||
Importer(const std::string& essfile, const std::string& outfile, const std::string& encoding);
|
||||
|
||||
void run();
|
||||
|
||||
@ -18,6 +18,7 @@ namespace ESSImport
|
||||
private:
|
||||
std::string mEssFile;
|
||||
std::string mOutFile;
|
||||
std::string mEncoding;
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/globalmap.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
|
||||
#include "importnpcc.hpp"
|
||||
#include "importcrec.hpp"
|
||||
@ -15,6 +17,7 @@
|
||||
|
||||
|
||||
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
@ -29,6 +32,9 @@ namespace ESSImport
|
||||
|
||||
ESM::DialogueState mDialogueState;
|
||||
|
||||
// cells which should show an explored overlay on the global map
|
||||
std::set<std::pair<int, int> > mExploredCells;
|
||||
|
||||
ESM::GlobalMap mGlobalMapState;
|
||||
|
||||
int mDay, mMonth, mYear;
|
||||
@ -39,6 +45,9 @@ namespace ESSImport
|
||||
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
|
||||
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
|
||||
|
||||
std::map<std::string, ESM::Creature> mCreatures;
|
||||
std::map<std::string, ESM::NPC> mNpcs;
|
||||
|
||||
Context()
|
||||
{
|
||||
mPlayer.mAutoMove = 0;
|
||||
|
@ -7,7 +7,23 @@ namespace ESSImport
|
||||
|
||||
void GAME::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mGMDT, "GMDT");
|
||||
esm.getSubNameIs("GMDT");
|
||||
esm.getSubHeader();
|
||||
if (esm.getSubSize() == 92)
|
||||
{
|
||||
esm.getExact(&mGMDT, 92);
|
||||
mGMDT.mSecundaPhase = 0;
|
||||
}
|
||||
else if (esm.getSubSize() == 96)
|
||||
{
|
||||
esm.getT(mGMDT);
|
||||
}
|
||||
else
|
||||
esm.fail("unexpected subrecord size for GAME.GMDT");
|
||||
|
||||
mGMDT.mWeatherTransition &= (0x000000ff);
|
||||
mGMDT.mSecundaPhase &= (0x000000ff);
|
||||
mGMDT.mMasserPhase &= (0x000000ff);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,7 +20,7 @@ namespace ESSImport
|
||||
int mCurrentWeather, mNextWeather;
|
||||
int mWeatherTransition; // 0-100 transition between weathers, top 3 bytes may be garbage
|
||||
float mTimeOfNextTransition; // weather changes when gamehour == timeOfNextTransition
|
||||
int masserPhase, secundaPhase; // top 3 bytes may be garbage
|
||||
int mMasserPhase, mSecundaPhase; // top 3 bytes may be garbage
|
||||
};
|
||||
|
||||
GMDT mGMDT;
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
|
@ -9,10 +9,9 @@ namespace ESSImport
|
||||
{
|
||||
esm.getHNT(mNPDT, "NPDT");
|
||||
|
||||
// FIXME: use AiPackageList, need to fix getSubName()
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
esm.skipHSub();
|
||||
mAiPackages.add(esm);
|
||||
|
||||
mInventory.load(esm);
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ namespace ESSImport
|
||||
} mNPDT;
|
||||
|
||||
Inventory mInventory;
|
||||
ESM::AIPackageList mAiPackages;
|
||||
|
||||
void load(ESM::ESMReader &esm);
|
||||
};
|
||||
|
@ -38,6 +38,17 @@ struct PCDT
|
||||
|
||||
std::vector<std::string> mKnownDialogueTopics;
|
||||
|
||||
enum DrawState_
|
||||
{
|
||||
DrawState_Weapon = 0x80,
|
||||
DrawState_Spell = 0x100
|
||||
};
|
||||
enum CameraState
|
||||
{
|
||||
CameraState_FirstPerson = 0x8,
|
||||
CameraState_ThirdPerson = 0xa
|
||||
};
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
struct FNAM
|
||||
@ -49,11 +60,13 @@ struct PCDT
|
||||
unsigned char mUnknown2[3];
|
||||
ESM::NAME32 mFactionName;
|
||||
};
|
||||
|
||||
struct PNAM
|
||||
{
|
||||
unsigned char mUnknown1[4];
|
||||
unsigned char mLevelProgress;
|
||||
unsigned char mUnknown2[111];
|
||||
short mDrawState; // DrawState
|
||||
short mCameraState; // CameraState
|
||||
unsigned int mLevelProgress;
|
||||
float mSkillProgress[27]; // skill progress, non-uniform scaled
|
||||
unsigned char mSkillIncreases[8]; // number of skill increases for each attribute
|
||||
unsigned char mUnknown3[88];
|
||||
};
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
|
@ -13,8 +13,14 @@ namespace ESSImport
|
||||
|
||||
mSCRI.load(esm);
|
||||
|
||||
mRNAM = -1;
|
||||
esm.getHNOT(mRNAM, "RNAM");
|
||||
mRefNum = -1;
|
||||
if (esm.isNextSub("RNAM"))
|
||||
{
|
||||
mRunning = true;
|
||||
esm.getHT(mRefNum);
|
||||
}
|
||||
else
|
||||
mRunning = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ namespace ESSImport
|
||||
{
|
||||
|
||||
// A running global script
|
||||
// TODO: test how targeted scripts are saved
|
||||
struct SCPT
|
||||
{
|
||||
ESM::Script::SCHD mSCHD;
|
||||
@ -22,7 +21,8 @@ namespace ESSImport
|
||||
// values of local variables
|
||||
SCRI mSCRI;
|
||||
|
||||
int mRNAM; // unknown, seems to be -1 for some scripts, some huge integer for others
|
||||
bool mRunning;
|
||||
int mRefNum; // Targeted reference, -1: no reference
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include "importer.hpp"
|
||||
|
||||
namespace bpo = boost::program_options;
|
||||
@ -23,31 +25,36 @@ int main(int argc, char** argv)
|
||||
("mwsave,m", bpo::value<std::string>(), "morrowind .ess save file")
|
||||
("output,o", bpo::value<std::string>(), "output file (.omwsave)")
|
||||
("compare,c", "compare two .ess files")
|
||||
("encoding", boost::program_options::value<std::string>()->default_value("win1252"), "encoding of the save file")
|
||||
;
|
||||
p_desc.add("mwsave", 1).add("output", 1);
|
||||
|
||||
bpo::variables_map vm;
|
||||
bpo::variables_map variables;
|
||||
|
||||
bpo::parsed_options parsed = bpo::command_line_parser(argc, argv)
|
||||
.options(desc)
|
||||
.positional(p_desc)
|
||||
.run();
|
||||
|
||||
bpo::store(parsed, vm);
|
||||
bpo::store(parsed, variables);
|
||||
|
||||
if(vm.count("help") || !vm.count("mwsave") || !vm.count("output")) {
|
||||
if(variables.count("help") || !variables.count("mwsave") || !variables.count("output")) {
|
||||
std::cout << desc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bpo::notify(vm);
|
||||
bpo::notify(variables);
|
||||
|
||||
std::string essFile = vm["mwsave"].as<std::string>();
|
||||
std::string outputFile = vm["output"].as<std::string>();
|
||||
Files::ConfigurationManager cfgManager(true);
|
||||
cfgManager.readConfiguration(variables, desc);
|
||||
|
||||
ESSImport::Importer importer(essFile, outputFile);
|
||||
std::string essFile = variables["mwsave"].as<std::string>();
|
||||
std::string outputFile = variables["output"].as<std::string>();
|
||||
std::string encoding = variables["encoding"].as<std::string>();
|
||||
|
||||
if (vm.count("compare"))
|
||||
ESSImport::Importer importer(essFile, outputFile, encoding);
|
||||
|
||||
if (variables.count("compare"))
|
||||
importer.compare();
|
||||
else
|
||||
{
|
||||
|
@ -78,7 +78,7 @@ if(NOT WIN32)
|
||||
endif(NOT WIN32)
|
||||
|
||||
# Main executable
|
||||
add_executable(omwlauncher
|
||||
add_executable(openmw-launcher
|
||||
${GUI_TYPE}
|
||||
${LAUNCHER}
|
||||
${LAUNCHER_HEADER}
|
||||
@ -87,7 +87,7 @@ add_executable(omwlauncher
|
||||
${UI_HDRS}
|
||||
)
|
||||
|
||||
target_link_libraries(omwlauncher
|
||||
target_link_libraries(openmw-launcher
|
||||
${Boost_LIBRARIES}
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
@ -99,6 +99,6 @@ target_link_libraries(omwlauncher
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(omwlauncher gcov)
|
||||
target_link_libraries(openmw-launcher gcov)
|
||||
endif()
|
||||
|
||||
|
@ -20,6 +20,9 @@
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include "utils/profilescombobox.hpp"
|
||||
|
||||
|
||||
const char *Launcher::DataFilesPage::mDefaultContentListName = "Default";
|
||||
|
||||
Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings, Config::LauncherSettings &launcherSettings, QWidget *parent)
|
||||
: mCfgMgr(cfg)
|
||||
, mGameSettings(gameSettings)
|
||||
@ -48,9 +51,9 @@ void Launcher::DataFilesPage::buildView()
|
||||
ui.deleteProfileButton->setToolTip ("Delete an existing Content List");
|
||||
|
||||
//combo box
|
||||
ui.profilesComboBox->addItem ("Default");
|
||||
ui.profilesComboBox->addItem(mDefaultContentListName);
|
||||
ui.profilesComboBox->setPlaceholderText (QString("Select a Content List..."));
|
||||
ui.profilesComboBox->setCurrentIndex(ui.profilesComboBox->findText(QLatin1String("Default")));
|
||||
ui.profilesComboBox->setCurrentIndex(ui.profilesComboBox->findText(QLatin1String(mDefaultContentListName)));
|
||||
|
||||
// Add the actions to the toolbuttons
|
||||
ui.newProfileButton->setDefaultAction (ui.newProfileAction);
|
||||
@ -69,19 +72,6 @@ void Launcher::DataFilesPage::buildView()
|
||||
|
||||
bool Launcher::DataFilesPage::loadSettings()
|
||||
{
|
||||
QStringList paths = mGameSettings.getDataDirs();
|
||||
|
||||
foreach (const QString &path, paths)
|
||||
mSelector->addFiles(path);
|
||||
|
||||
mDataLocal = mGameSettings.getDataLocal();
|
||||
|
||||
if (!mDataLocal.isEmpty())
|
||||
mSelector->addFiles(mDataLocal);
|
||||
|
||||
paths.insert (0, mDataLocal);
|
||||
PathIterator pathIterator (paths);
|
||||
|
||||
QStringList profiles = mLauncherSettings.getContentLists();
|
||||
QString currentProfile = mLauncherSettings.getCurrentContentListName();
|
||||
|
||||
@ -94,11 +84,27 @@ bool Launcher::DataFilesPage::loadSettings()
|
||||
if (!currentProfile.isEmpty())
|
||||
addProfile(currentProfile, true);
|
||||
|
||||
mSelector->setProfileContent(filesInProfile(currentProfile, pathIterator));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::populateFileViews(const QString& contentModelName)
|
||||
{
|
||||
QStringList paths = mGameSettings.getDataDirs();
|
||||
|
||||
foreach(const QString &path, paths)
|
||||
mSelector->addFiles(path);
|
||||
|
||||
mDataLocal = mGameSettings.getDataLocal();
|
||||
|
||||
if (!mDataLocal.isEmpty())
|
||||
mSelector->addFiles(mDataLocal);
|
||||
|
||||
paths.insert(0, mDataLocal);
|
||||
PathIterator pathIterator(paths);
|
||||
|
||||
mSelector->setProfileContent(filesInProfile(contentModelName, pathIterator));
|
||||
}
|
||||
|
||||
QStringList Launcher::DataFilesPage::filesInProfile(const QString& profileName, PathIterator& pathIterator)
|
||||
{
|
||||
QStringList files = mLauncherSettings.getContentListFiles(profileName);
|
||||
@ -175,7 +181,7 @@ void Launcher::DataFilesPage::setProfile (const QString &previous, const QString
|
||||
|
||||
ui.profilesComboBox->setCurrentProfile (ui.profilesComboBox->findText (current));
|
||||
|
||||
loadSettings();
|
||||
populateFileViews(current);
|
||||
|
||||
checkForDefaultProfile();
|
||||
}
|
||||
@ -229,13 +235,6 @@ void Launcher::DataFilesPage::on_newProfileAction_triggered()
|
||||
mLauncherSettings.setCurrentContentListName(profile);
|
||||
|
||||
addProfile(profile, true);
|
||||
mSelector->clearCheckStates();
|
||||
|
||||
mSelector->setGameFile();
|
||||
|
||||
saveSettings();
|
||||
|
||||
emit signalProfileChanged (ui.profilesComboBox->findText(profile));
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::addProfile (const QString &profile, bool setAsCurrent)
|
||||
@ -262,15 +261,13 @@ void Launcher::DataFilesPage::on_deleteProfileAction_triggered()
|
||||
|
||||
// this should work since the Default profile can't be deleted and is always index 0
|
||||
int next = ui.profilesComboBox->currentIndex()-1;
|
||||
|
||||
// changing the profile forces a reload of plugin file views.
|
||||
ui.profilesComboBox->setCurrentIndex(next);
|
||||
|
||||
removeProfile(profile);
|
||||
ui.profilesComboBox->removeItem(ui.profilesComboBox->findText(profile));
|
||||
|
||||
saveSettings();
|
||||
|
||||
loadSettings();
|
||||
|
||||
checkForDefaultProfile();
|
||||
}
|
||||
|
||||
@ -290,7 +287,7 @@ void Launcher::DataFilesPage::updateOkButton(const QString &text)
|
||||
void Launcher::DataFilesPage::checkForDefaultProfile()
|
||||
{
|
||||
//don't allow deleting "Default" profile
|
||||
bool success = (ui.profilesComboBox->currentText() != "Default");
|
||||
bool success = (ui.profilesComboBox->currentText() != mDefaultContentListName);
|
||||
|
||||
ui.deleteProfileAction->setEnabled (success);
|
||||
ui.profilesComboBox->setEditEnabled (success);
|
||||
|
@ -58,6 +58,10 @@ namespace Launcher
|
||||
void on_newProfileAction_triggered();
|
||||
void on_deleteProfileAction_triggered();
|
||||
|
||||
public:
|
||||
/// Content List that is always present
|
||||
const static char *mDefaultContentListName;
|
||||
|
||||
private:
|
||||
|
||||
TextInputDialog *mProfileDialog;
|
||||
@ -82,6 +86,7 @@ namespace Launcher
|
||||
bool showDeleteMessageBox (const QString &text);
|
||||
void addProfile (const QString &profile, bool setAsCurrent);
|
||||
void checkForDefaultProfile();
|
||||
void populateFileViews(const QString& contentModelName);
|
||||
|
||||
class PathIterator
|
||||
{
|
||||
|
@ -10,7 +10,7 @@
|
||||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_video.h>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderSystem.h>
|
||||
@ -67,7 +67,7 @@ bool Launcher::GraphicsPage::setupOgre()
|
||||
}
|
||||
catch(Ogre::Exception &ex)
|
||||
{
|
||||
QString ogreError = QString::fromStdString(ex.getFullDescription().c_str());
|
||||
QString ogreError = QString::fromUtf8(ex.getFullDescription().c_str());
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle("Error creating Ogre::Root");
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
@ -135,7 +135,7 @@ bool Launcher::GraphicsPage::setupSDL()
|
||||
msgBox.setWindowTitle(tr("Error receiving number of screens"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromStdString(SDL_GetError()) + "<br>");
|
||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||
msgBox.exec();
|
||||
return false;
|
||||
}
|
||||
@ -237,7 +237,7 @@ QStringList Launcher::GraphicsPage::getAvailableOptions(const QString &key, Ogre
|
||||
opt_it != i->second.possibleValues.end(); ++opt_it, ++idx)
|
||||
{
|
||||
if (strcmp (key.toStdString().c_str(), i->first.c_str()) == 0) {
|
||||
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromStdString((*opt_it).c_str()).simplified();
|
||||
result << ((key == "FSAA") ? QString("MSAA ") : QString("")) + QString::fromUtf8((*opt_it).c_str()).simplified();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,7 +266,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromStdString(SDL_GetError()) + "<br>");
|
||||
msgBox.setText(tr("<br><b>SDL_GetNumDisplayModes failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||
msgBox.exec();
|
||||
return result;
|
||||
}
|
||||
@ -279,7 +279,7 @@ QStringList Launcher::GraphicsPage::getAvailableResolutions(int screen)
|
||||
msgBox.setWindowTitle(tr("Error receiving resolutions"));
|
||||
msgBox.setIcon(QMessageBox::Critical);
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setText(tr("<br><b>SDL_GetDisplayMode failed:</b><br><br>") + QString::fromStdString(SDL_GetError()) + "<br>");
|
||||
msgBox.setText(tr("<br><b>SDL_GetDisplayMode failed:</b><br><br>") + QString::fromUtf8(SDL_GetError()) + "<br>");
|
||||
msgBox.exec();
|
||||
return result;
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <iostream>
|
||||
#include <csignal>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
@ -23,9 +24,11 @@ int main(int argc, char *argv[])
|
||||
SDL_SetMainReady();
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
{
|
||||
qDebug() << "SDL_Init failed: " << QString::fromStdString(SDL_GetError());
|
||||
qDebug() << "SDL_Init failed: " << QString::fromUtf8(SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
||||
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
|
@ -27,25 +27,6 @@ using namespace Process;
|
||||
Launcher::MainDialog::MainDialog(QWidget *parent)
|
||||
: mGameSettings(mCfgMgr), QMainWindow (parent)
|
||||
{
|
||||
// Install the stylesheet font
|
||||
QFile file;
|
||||
QFontDatabase fontDatabase;
|
||||
|
||||
const QStringList fonts = fontDatabase.families();
|
||||
|
||||
// Check if the font is installed
|
||||
if (!fonts.contains("EB Garamond")) {
|
||||
|
||||
QString font = QString::fromUtf8(mCfgMgr.getGlobalDataPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||
file.setFileName(font);
|
||||
|
||||
if (!file.exists()) {
|
||||
font = QString::fromUtf8(mCfgMgr.getLocalPath().string().c_str()) + QString("resources/mygui/EBGaramond-Regular.ttf");
|
||||
}
|
||||
|
||||
fontDatabase.addApplicationFont(font);
|
||||
}
|
||||
|
||||
setupUi(this);
|
||||
|
||||
mGameInvoker = new ProcessInvoker();
|
||||
@ -80,6 +61,7 @@ Launcher::MainDialog::MainDialog(QWidget *parent)
|
||||
QString revision(OPENMW_VERSION_COMMITHASH);
|
||||
QString tag(OPENMW_VERSION_TAGHASH);
|
||||
|
||||
versionLabel->setTextInteractionFlags(Qt::TextSelectableByMouse);
|
||||
if (!revision.isEmpty() && !tag.isEmpty())
|
||||
{
|
||||
if (revision == tag) {
|
||||
@ -257,24 +239,8 @@ void Launcher::MainDialog::changePage(QListWidgetItem *current, QListWidgetItem
|
||||
current = previous;
|
||||
|
||||
int currentIndex = iconWidget->row(current);
|
||||
// int previousIndex = iconWidget->row(previous);
|
||||
|
||||
pagesWidget->setCurrentIndex(currentIndex);
|
||||
|
||||
// DataFilesPage *previousPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(previousIndex));
|
||||
// DataFilesPage *currentPage = dynamic_cast<DataFilesPage *>(pagesWidget->widget(currentIndex));
|
||||
|
||||
// //special call to update/save data files page list view when it's displayed/hidden.
|
||||
// if (previousPage)
|
||||
// {
|
||||
// if (previousPage->objectName() == "DataFilesPage")
|
||||
// previousPage->saveSettings();
|
||||
// }
|
||||
// else if (currentPage)
|
||||
// {
|
||||
// if (currentPage->objectName() == "DataFilesPage")
|
||||
// currentPage->loadSettings();
|
||||
// }
|
||||
mSettingsPage->resetProgressBar();
|
||||
}
|
||||
|
||||
bool Launcher::MainDialog::setupLauncherSettings()
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <components/config/launchersettings.hpp>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include "datafilespage.hpp"
|
||||
|
||||
using namespace Process;
|
||||
|
||||
@ -38,6 +39,7 @@ Launcher::SettingsPage::SettingsPage(Files::ConfigurationManager &cfg,
|
||||
|
||||
mWizardInvoker = new ProcessInvoker();
|
||||
mImporterInvoker = new ProcessInvoker();
|
||||
resetProgressBar();
|
||||
|
||||
connect(mWizardInvoker->getProcess(), SIGNAL(started()),
|
||||
this, SLOT(wizardStarted()));
|
||||
@ -93,7 +95,7 @@ Launcher::SettingsPage::~SettingsPage()
|
||||
|
||||
void Launcher::SettingsPage::on_wizardButton_clicked()
|
||||
{
|
||||
saveSettings();
|
||||
mMain->writeSettings();
|
||||
|
||||
if (!mWizardInvoker->startProcess(QLatin1String("openmw-wizard"), false))
|
||||
return;
|
||||
@ -101,7 +103,7 @@ void Launcher::SettingsPage::on_wizardButton_clicked()
|
||||
|
||||
void Launcher::SettingsPage::on_importerButton_clicked()
|
||||
{
|
||||
saveSettings();
|
||||
mMain->writeSettings();
|
||||
|
||||
// Create the file if it doesn't already exist, else the importer will fail
|
||||
QString path(QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str()));
|
||||
@ -140,8 +142,13 @@ void Launcher::SettingsPage::on_importerButton_clicked()
|
||||
|
||||
qDebug() << "arguments " << arguments;
|
||||
|
||||
if (!mImporterInvoker->startProcess(QLatin1String("mwiniimport"), arguments, false))
|
||||
return;
|
||||
// start the progress bar as a "bouncing ball"
|
||||
progressBar->setMaximum(0);
|
||||
progressBar->setValue(0);
|
||||
if (!mImporterInvoker->startProcess(QLatin1String("openmw-iniimporter"), arguments, false))
|
||||
{
|
||||
resetProgressBar();
|
||||
}
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::on_browseButton_clicked()
|
||||
@ -196,27 +203,35 @@ void Launcher::SettingsPage::importerStarted()
|
||||
void Launcher::SettingsPage::importerFinished(int exitCode, QProcess::ExitStatus exitStatus)
|
||||
{
|
||||
if (exitCode != 0 || exitStatus == QProcess::CrashExit)
|
||||
return;
|
||||
|
||||
// Re-read the settings in their current state
|
||||
mMain->reloadSettings();
|
||||
|
||||
// Import selected data files from openmw.cfg
|
||||
if (addonsCheckBox->isChecked())
|
||||
{
|
||||
if (mProfileDialog->exec() == QDialog::Accepted)
|
||||
{
|
||||
const QString profile(mProfileDialog->lineEdit()->text());
|
||||
const QStringList files(mGameSettings.getContentList());
|
||||
mLauncherSettings.setCurrentContentListName(profile);
|
||||
mLauncherSettings.setContentList(profile, files);
|
||||
}
|
||||
resetProgressBar();
|
||||
|
||||
QMessageBox msgBox;
|
||||
msgBox.setWindowTitle(tr("Importer finished"));
|
||||
msgBox.setStandardButtons(QMessageBox::Ok);
|
||||
msgBox.setIcon(QMessageBox::Warning);
|
||||
msgBox.setText(tr("Failed to import settings from INI file."));
|
||||
msgBox.exec();
|
||||
}
|
||||
else
|
||||
{
|
||||
// indicate progress finished
|
||||
progressBar->setMaximum(1);
|
||||
progressBar->setValue(1);
|
||||
|
||||
// Importer may have changed settings, so refresh
|
||||
mMain->reloadSettings();
|
||||
}
|
||||
|
||||
mMain->reloadSettings();
|
||||
importerButton->setEnabled(true);
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::resetProgressBar()
|
||||
{
|
||||
// set progress bar to 0 %
|
||||
progressBar->reset();
|
||||
}
|
||||
|
||||
void Launcher::SettingsPage::updateOkButton(const QString &text)
|
||||
{
|
||||
// We do this here because we need to access the profiles
|
||||
|
@ -29,6 +29,9 @@ namespace Launcher
|
||||
|
||||
void saveSettings();
|
||||
bool loadSettings();
|
||||
|
||||
/// set progress bar on page to 0%
|
||||
void resetProgressBar();
|
||||
|
||||
private slots:
|
||||
|
||||
@ -57,7 +60,6 @@ namespace Launcher
|
||||
MainDialog *mMain;
|
||||
TextInputDialog *mProfileDialog;
|
||||
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -9,16 +9,16 @@ set(MWINIIMPORT_HEADER
|
||||
|
||||
source_group(launcher FILES ${MWINIIMPORT} ${MWINIIMPORT_HEADER})
|
||||
|
||||
add_executable(mwiniimport
|
||||
add_executable(openmw-iniimporter
|
||||
${MWINIIMPORT}
|
||||
)
|
||||
|
||||
target_link_libraries(mwiniimport
|
||||
target_link_libraries(openmw-iniimporter
|
||||
${Boost_LIBRARIES}
|
||||
components
|
||||
)
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
add_definitions (--coverage)
|
||||
target_link_libraries(mwiniimport gcov)
|
||||
target_link_libraries(openmw-iniimporter gcov)
|
||||
endif()
|
||||
|
@ -8,7 +8,8 @@
|
||||
#include <sstream>
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/version.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
namespace bfs = boost::filesystem;
|
||||
@ -660,7 +661,7 @@ std::string MwIniImporter::numberToString(int n) {
|
||||
return str.str();
|
||||
}
|
||||
|
||||
MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filename) const {
|
||||
MwIniImporter::multistrmap MwIniImporter::loadIniFile(const boost::filesystem::path& filename) const {
|
||||
std::cout << "load ini file: " << filename << std::endl;
|
||||
|
||||
std::string section("");
|
||||
@ -719,7 +720,7 @@ MwIniImporter::multistrmap MwIniImporter::loadIniFile(const std::string& filenam
|
||||
return map;
|
||||
}
|
||||
|
||||
MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const std::string& filename) {
|
||||
MwIniImporter::multistrmap MwIniImporter::loadCfgFile(const boost::filesystem::path& filename) {
|
||||
std::cout << "load cfg file: " << filename << std::endl;
|
||||
|
||||
MwIniImporter::multistrmap map;
|
||||
@ -825,10 +826,14 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
|
||||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) const {
|
||||
std::vector<std::string> contentFiles;
|
||||
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, const boost::filesystem::path& iniFilename) const {
|
||||
std::vector<std::pair<std::time_t, std::string> > contentFiles;
|
||||
std::string baseGameFile("Game Files:GameFile");
|
||||
std::string gameFile("");
|
||||
std::time_t defaultTime = 0;
|
||||
|
||||
// assume the Game Files are all in a "Data Files" directory under the directory holding Morrowind.ini
|
||||
const boost::filesystem::path gameFilesDir(iniFilename.parent_path() /= "Data Files");
|
||||
|
||||
multistrmap::const_iterator it = ini.begin();
|
||||
for(int i=0; it != ini.end(); i++) {
|
||||
@ -845,18 +850,20 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini) co
|
||||
Misc::StringUtils::toLower(filetype);
|
||||
|
||||
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
|
||||
contentFiles.push_back(*entry);
|
||||
boost::filesystem::path filepath(gameFilesDir);
|
||||
filepath /= *entry;
|
||||
contentFiles.push_back(std::make_pair(lastWriteTime(filepath, defaultTime), *entry));
|
||||
}
|
||||
}
|
||||
|
||||
gameFile = "";
|
||||
}
|
||||
|
||||
cfg.erase("content");
|
||||
cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
|
||||
|
||||
for(std::vector<std::string>::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
|
||||
cfg["content"].push_back(*it);
|
||||
// this will sort files by time order first, then alphabetical (maybe), I suspect non ASCII filenames will be stuffed.
|
||||
sort(contentFiles.begin(), contentFiles.end());
|
||||
for(std::vector<std::pair<std::time_t, std::string> >::const_iterator it=contentFiles.begin(); it!=contentFiles.end(); ++it) {
|
||||
cfg["content"].push_back(it->second);
|
||||
}
|
||||
}
|
||||
|
||||
@ -873,3 +880,27 @@ void MwIniImporter::setInputEncoding(const ToUTF8::FromType &encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
}
|
||||
|
||||
std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime)
|
||||
{
|
||||
std::time_t writeTime(defaultTime);
|
||||
if (boost::filesystem::exists(filename))
|
||||
{
|
||||
// FixMe: remove #if when Boost dependency for Linux builds updated
|
||||
// This allows Linux to build until then
|
||||
#if (BOOST_VERSION >= 104800)
|
||||
// need to resolve any symlinks so that we get time of file, not symlink
|
||||
boost::filesystem::path resolved = boost::filesystem::canonical(filename);
|
||||
#else
|
||||
boost::filesystem::path resolved = filename;
|
||||
#endif
|
||||
writeTime = boost::filesystem::last_write_time(resolved);
|
||||
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
|
||||
") " << asctime(localtime(&writeTime)) << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "content file: " << filename << " not found" << std::endl;
|
||||
}
|
||||
return writeTime;
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
#include <vector>
|
||||
#include <exception>
|
||||
#include <iosfwd>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
|
||||
#include <components/to_utf8/to_utf8.hpp>
|
||||
|
||||
@ -17,17 +18,22 @@ class MwIniImporter {
|
||||
MwIniImporter();
|
||||
void setInputEncoding(const ToUTF8::FromType& encoding);
|
||||
void setVerbose(bool verbose);
|
||||
multistrmap loadIniFile(const std::string& filename) const;
|
||||
static multistrmap loadCfgFile(const std::string& filename);
|
||||
multistrmap loadIniFile(const boost::filesystem::path& filename) const;
|
||||
static multistrmap loadCfgFile(const boost::filesystem::path& filename);
|
||||
void merge(multistrmap &cfg, const multistrmap &ini) const;
|
||||
void mergeFallback(multistrmap &cfg, const multistrmap &ini) const;
|
||||
void importGameFiles(multistrmap &cfg, const multistrmap &ini) const;
|
||||
void importGameFiles(multistrmap &cfg, const multistrmap &ini,
|
||||
const boost::filesystem::path& iniFilename) const;
|
||||
void importArchives(multistrmap &cfg, const multistrmap &ini) const;
|
||||
static void writeToFile(std::ostream &out, const multistrmap &cfg);
|
||||
|
||||
private:
|
||||
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
|
||||
static std::string numberToString(int n);
|
||||
|
||||
/// \return file's "last modified time", used in original MW to determine plug-in load order
|
||||
static std::time_t lastWriteTime(const boost::filesystem::path& filename, std::time_t defaultTime);
|
||||
|
||||
bool mVerbose;
|
||||
strmap mMergeMap;
|
||||
std::vector<std::string> mMergeFallback;
|
||||
|
@ -59,7 +59,7 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||
|
||||
try
|
||||
{
|
||||
bpo::options_description desc("Syntax: mwiniimporter <options> inifile configfile\nAllowed options");
|
||||
bpo::options_description desc("Syntax: openmw-iniimporter <options> inifile configfile\nAllowed options");
|
||||
bpo::positional_options_description p_desc;
|
||||
desc.add_options()
|
||||
("help,h", "produce help message")
|
||||
@ -93,8 +93,8 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||
|
||||
bpo::notify(vm);
|
||||
|
||||
std::string iniFile = vm["ini"].as<std::string>();
|
||||
std::string cfgFile = vm["cfg"].as<std::string>();
|
||||
boost::filesystem::path iniFile(vm["ini"].as<std::string>());
|
||||
boost::filesystem::path cfgFile(vm["cfg"].as<std::string>());
|
||||
|
||||
// if no output is given, write back to cfg file
|
||||
std::string outputFile(vm["output"].as<std::string>());
|
||||
@ -123,7 +123,7 @@ int wmain(int argc, wchar_t *wargv[]) {
|
||||
importer.mergeFallback(cfg, ini);
|
||||
|
||||
if(vm.count("game-files")) {
|
||||
importer.importGameFiles(cfg, ini);
|
||||
importer.importGameFiles(cfg, ini, iniFile);
|
||||
}
|
||||
|
||||
if(!vm.count("no-archives")) {
|
||||
|
@ -4,8 +4,6 @@ set (OPENCS_SRC main.cpp
|
||||
|
||||
opencs_units (. editor)
|
||||
|
||||
set (CMAKE_BUILD_TYPE DEBUG)
|
||||
|
||||
opencs_units (model/doc
|
||||
document operation saving documentmanager loader runner
|
||||
)
|
||||
@ -41,7 +39,7 @@ opencs_units (model/tools
|
||||
|
||||
opencs_units_noqt (model/tools
|
||||
mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
|
||||
birthsigncheck spellcheck referenceablecheck scriptcheck bodypartcheck
|
||||
birthsigncheck spellcheck referencecheck referenceablecheck scriptcheck bodypartcheck
|
||||
)
|
||||
|
||||
|
||||
@ -146,7 +144,7 @@ set (OPENCS_UI
|
||||
${CMAKE_SOURCE_DIR}/files/ui/filedialog.ui
|
||||
)
|
||||
|
||||
source_group (opencs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
||||
source_group (openmw-cs FILES ${OPENCS_SRC} ${OPENCS_HDR})
|
||||
|
||||
if(WIN32)
|
||||
set(QT_USE_QTMAIN TRUE)
|
||||
@ -169,12 +167,12 @@ qt4_add_resources(OPENCS_RES_SRC ${OPENCS_RES})
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${BULLET_INCLUDE_DIRS})
|
||||
|
||||
if(APPLE)
|
||||
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/opencs.icns)
|
||||
set (OPENCS_MAC_ICON ${CMAKE_SOURCE_DIR}/files/mac/openmw-cs.icns)
|
||||
else()
|
||||
set (OPENCS_MAC_ICON "")
|
||||
endif(APPLE)
|
||||
|
||||
add_executable(opencs
|
||||
add_executable(openmw-cs
|
||||
MACOSX_BUNDLE
|
||||
${OENGINE_BULLET}
|
||||
${OPENCS_SRC}
|
||||
@ -185,10 +183,10 @@ add_executable(opencs
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
set_target_properties(opencs PROPERTIES
|
||||
set_target_properties(openmw-cs PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY "${OpenMW_BINARY_DIR}"
|
||||
OUTPUT_NAME "OpenCS"
|
||||
MACOSX_BUNDLE_ICON_FILE "opencs.icns"
|
||||
OUTPUT_NAME "OpenMW-CS"
|
||||
MACOSX_BUNDLE_ICON_FILE "openmw-cs.icns"
|
||||
MACOSX_BUNDLE_BUNDLE_NAME "OpenCS"
|
||||
MACOSX_BUNDLE_GUI_IDENTIFIER "org.openmw.opencs"
|
||||
MACOSX_BUNDLE_SHORT_VERSION_STRING ${OPENMW_VERSION}
|
||||
@ -199,7 +197,7 @@ if(APPLE)
|
||||
MACOSX_PACKAGE_LOCATION Resources)
|
||||
endif(APPLE)
|
||||
|
||||
target_link_libraries(opencs
|
||||
target_link_libraries(openmw-cs
|
||||
${OGRE_LIBRARIES}
|
||||
${OGRE_Overlay_LIBRARIES}
|
||||
${OGRE_STATIC_PLUGINS}
|
||||
@ -211,5 +209,5 @@ target_link_libraries(opencs
|
||||
)
|
||||
|
||||
if(APPLE)
|
||||
INSTALL(TARGETS opencs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
INSTALL(TARGETS openmw-cs BUNDLE DESTINATION OpenMW COMPONENT BUNDLE)
|
||||
endif()
|
||||
|
@ -96,7 +96,7 @@ void CS::Editor::setupDataFiles (const Files::PathContainer& dataDirs)
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > CS::Editor::readConfig()
|
||||
{
|
||||
boost::program_options::variables_map variables;
|
||||
boost::program_options::options_description desc("Syntax: opencs <options>\nAllowed options");
|
||||
boost::program_options::options_description desc("Syntax: openmw-cs <options>\nAllowed options");
|
||||
|
||||
desc.add_options()
|
||||
("data", boost::program_options::value<Files::PathContainer>()->default_value(Files::PathContainer(), "data")->multitoken()->composing())
|
||||
@ -249,7 +249,7 @@ bool CS::Editor::makeIPCServer()
|
||||
try
|
||||
{
|
||||
mPid = boost::filesystem::temp_directory_path();
|
||||
mPid /= "opencs.pid";
|
||||
mPid /= "openmw-cs.pid";
|
||||
bool pidExists = boost::filesystem::exists(mPid);
|
||||
|
||||
mPidFile.open(mPid);
|
||||
|
@ -78,7 +78,7 @@ int main(int argc, char *argv[])
|
||||
application.setLibraryPaths(libraryPaths);
|
||||
#endif
|
||||
|
||||
application.setWindowIcon (QIcon (":./opencs.png"));
|
||||
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
||||
|
||||
CS::Editor editor (ogreInit);
|
||||
|
||||
|
110
apps/opencs/model/tools/referencecheck.cpp
Normal file
110
apps/opencs/model/tools/referencecheck.cpp
Normal file
@ -0,0 +1,110 @@
|
||||
#include "referencecheck.hpp"
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
||||
const CSMWorld::RefCollection& references,
|
||||
const CSMWorld::RefIdCollection& referencables,
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& cells,
|
||||
const CSMWorld::IdCollection<ESM::Faction>& factions)
|
||||
:
|
||||
mReferences(references),
|
||||
mReferencables(referencables),
|
||||
mDataSet(referencables.getDataSet()),
|
||||
mCells(cells),
|
||||
mFactions(factions)
|
||||
{
|
||||
}
|
||||
|
||||
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
|
||||
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const CSMWorld::CellRef& cellRef = record.get();
|
||||
const CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Reference, cellRef.mId);
|
||||
|
||||
// Check for empty reference id
|
||||
if (cellRef.mRefID.empty()) {
|
||||
messages.push_back(std::make_pair(id, " is an empty reference"));
|
||||
} else {
|
||||
// Check for non existing referenced object
|
||||
if (mReferencables.searchId(cellRef.mRefID) == -1) {
|
||||
messages.push_back(std::make_pair(id, " is referencing non existing object " + cellRef.mRefID));
|
||||
} else {
|
||||
// Check if reference charge is valid for it's proper referenced type
|
||||
CSMWorld::RefIdData::LocalIndex localIndex = mDataSet.searchId(cellRef.mRefID);
|
||||
bool isLight = localIndex.second == CSMWorld::UniversalId::Type_Light;
|
||||
if ((isLight && cellRef.mChargeFloat < -1) || (!isLight && cellRef.mChargeInt < -1)) {
|
||||
std::string str = " has invalid charge ";
|
||||
if (localIndex.second == CSMWorld::UniversalId::Type_Light)
|
||||
str += boost::lexical_cast<std::string>(cellRef.mChargeFloat);
|
||||
else
|
||||
str += boost::lexical_cast<std::string>(cellRef.mChargeInt);
|
||||
messages.push_back(std::make_pair(id, id.getId() + str));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if referenced object is in valid cell
|
||||
if (mCells.searchId(cellRef.mCell) == -1)
|
||||
messages.push_back(std::make_pair(id, " is referencing object from non existing cell " + cellRef.mCell));
|
||||
|
||||
// If object have owner, check if that owner reference is valid
|
||||
if (!cellRef.mOwner.empty() && mReferencables.searchId(cellRef.mOwner) == -1)
|
||||
messages.push_back(std::make_pair(id, " has non existing owner " + cellRef.mOwner));
|
||||
|
||||
// If object have creature soul trapped, check if that creature reference is valid
|
||||
if (!cellRef.mSoul.empty())
|
||||
if (mReferencables.searchId(cellRef.mSoul) == -1)
|
||||
messages.push_back(std::make_pair(id, " has non existing trapped soul " + cellRef.mSoul));
|
||||
|
||||
bool hasFaction = !cellRef.mFaction.empty();
|
||||
|
||||
// If object have faction, check if that faction reference is valid
|
||||
if (hasFaction)
|
||||
if (mFactions.searchId(cellRef.mFaction) == -1)
|
||||
messages.push_back(std::make_pair(id, " has non existing faction " + cellRef.mFaction));
|
||||
|
||||
// Check item's faction rank
|
||||
if (hasFaction && cellRef.mFactionRank < -1)
|
||||
messages.push_back(std::make_pair(id, " has faction set but has invalid faction rank " + cellRef.mFactionRank));
|
||||
else if (!hasFaction && cellRef.mFactionRank != -2)
|
||||
messages.push_back(std::make_pair(id, " has invalid faction rank " + cellRef.mFactionRank));
|
||||
|
||||
// If door have destination cell, check if that reference is valid
|
||||
if (!cellRef.mDestCell.empty())
|
||||
if (mCells.searchId(cellRef.mDestCell) == -1)
|
||||
messages.push_back(std::make_pair(id, " has non existing destination cell " + cellRef.mDestCell));
|
||||
|
||||
// Check if scale isn't negative
|
||||
if (cellRef.mScale < 0)
|
||||
{
|
||||
std::string str = " has negative scale ";
|
||||
str += boost::lexical_cast<std::string>(cellRef.mScale);
|
||||
messages.push_back(std::make_pair(id, id.getId() + str));
|
||||
}
|
||||
|
||||
// Check if enchantement points aren't negative or are at full (-1)
|
||||
if (cellRef.mEnchantmentCharge < 0 && cellRef.mEnchantmentCharge != -1)
|
||||
{
|
||||
std::string str = " has negative enchantment points ";
|
||||
str += boost::lexical_cast<std::string>(cellRef.mEnchantmentCharge);
|
||||
messages.push_back(std::make_pair(id, id.getId() + str));
|
||||
}
|
||||
|
||||
// Check if gold value isn't negative
|
||||
if (cellRef.mGoldValue < 0)
|
||||
{
|
||||
std::string str = " has negative gold value ";
|
||||
str += cellRef.mGoldValue;
|
||||
messages.push_back(std::make_pair(id, id.getId() + str));
|
||||
}
|
||||
}
|
||||
|
||||
int CSMTools::ReferenceCheckStage::setup()
|
||||
{
|
||||
return mReferences.getSize();
|
||||
}
|
29
apps/opencs/model/tools/referencecheck.hpp
Normal file
29
apps/opencs/model/tools/referencecheck.hpp
Normal file
@ -0,0 +1,29 @@
|
||||
#ifndef CSM_TOOLS_REFERENCECHECK_H
|
||||
#define CSM_TOOLS_REFERENCECHECK_H
|
||||
|
||||
#include "../doc/state.hpp"
|
||||
#include "../doc/document.hpp"
|
||||
|
||||
namespace CSMTools
|
||||
{
|
||||
class ReferenceCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
public:
|
||||
ReferenceCheckStage (const CSMWorld::RefCollection& references,
|
||||
const CSMWorld::RefIdCollection& referencables,
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& cells,
|
||||
const CSMWorld::IdCollection<ESM::Faction>& factions);
|
||||
|
||||
virtual void perform(int stage, CSMDoc::Messages& messages);
|
||||
virtual int setup();
|
||||
|
||||
private:
|
||||
const CSMWorld::RefCollection& mReferences;
|
||||
const CSMWorld::RefIdCollection& mReferencables;
|
||||
const CSMWorld::RefIdData& mDataSet;
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
|
||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // CSM_TOOLS_REFERENCECHECK_H
|
@ -23,6 +23,7 @@
|
||||
#include "referenceablecheck.hpp"
|
||||
#include "scriptcheck.hpp"
|
||||
#include "bodypartcheck.hpp"
|
||||
#include "referencecheck.hpp"
|
||||
|
||||
CSMDoc::Operation *CSMTools::Tools::get (int type)
|
||||
{
|
||||
@ -57,9 +58,6 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
||||
mandatoryIds.push_back ("GameHour");
|
||||
mandatoryIds.push_back ("Month");
|
||||
mandatoryIds.push_back ("PCRace");
|
||||
mandatoryIds.push_back ("PCVampire");
|
||||
mandatoryIds.push_back ("PCWerewolf");
|
||||
mandatoryIds.push_back ("PCYear");
|
||||
|
||||
mVerifier->appendStage (new MandatoryIdStage (mData.getGlobals(),
|
||||
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Globals), mandatoryIds));
|
||||
@ -82,6 +80,8 @@ CSMDoc::Operation *CSMTools::Tools::getVerifier()
|
||||
|
||||
mVerifier->appendStage (new ReferenceableCheckStage (mData.getReferenceables().getDataSet(), mData.getRaces(), mData.getClasses(), mData.getFactions()));
|
||||
|
||||
mVerifier->appendStage (new ReferenceCheckStage(mData.getReferences(), mData.getReferenceables(), mData.getCells(), mData.getFactions()));
|
||||
|
||||
mVerifier->appendStage (new ScriptCheckStage (mDocument));
|
||||
|
||||
mVerifier->appendStage(
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
#include "cell.hpp"
|
||||
#include "idcollection.hpp"
|
||||
#include "pathgrid.hpp"
|
||||
|
||||
#include <sstream>
|
||||
|
@ -6,11 +6,12 @@
|
||||
|
||||
#include <components/esm/loadpgrd.hpp>
|
||||
|
||||
#include "idcollection.hpp"
|
||||
#include "cell.hpp"
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
struct Cell;
|
||||
template<typename T, typename AT>
|
||||
class IdCollection;
|
||||
|
||||
/// \brief Wrapper for Pathgrid record
|
||||
///
|
||||
/// \attention The mData.mX and mData.mY fields of the ESM::Pathgrid struct are not used.
|
||||
|
@ -1,10 +1,17 @@
|
||||
#ifndef CSM_WOLRD_SUBCOLLECTION_H
|
||||
#define CSM_WOLRD_SUBCOLLECTION_H
|
||||
|
||||
#include "idcollection.hpp"
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace CSMWorld
|
||||
{
|
||||
struct Cell;
|
||||
template<typename T, typename AT>
|
||||
class IdCollection;
|
||||
|
||||
/// \brief Single type collection of top level records that are associated with cells
|
||||
template<typename ESXRecordT, typename IdAccessorT = IdAccessor<ESXRecordT> >
|
||||
class SubCellCollection : public IdCollection<ESXRecordT, IdAccessorT>
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <string>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/algorithm/string/case_conv.hpp>
|
||||
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
@ -72,8 +73,11 @@ void CSVDoc::AdjusterWidget::setName (const QString& name, bool addon)
|
||||
{
|
||||
boost::filesystem::path path (name.toUtf8().data());
|
||||
|
||||
bool isLegacyPath = (path.extension() == ".esm" ||
|
||||
path.extension() == ".esp");
|
||||
std::string extension = path.extension().string();
|
||||
boost::algorithm::to_lower(extension);
|
||||
|
||||
bool isLegacyPath = (extension == ".esm" ||
|
||||
extension == ".esp");
|
||||
|
||||
bool isFilePathChanged = (path.parent_path().string() != mLocalData.string());
|
||||
|
||||
|
@ -96,7 +96,7 @@ QWidget *CSVDoc::StartupDialogue::createTools()
|
||||
|
||||
CSVDoc::StartupDialogue::StartupDialogue() : mWidth (0), mColumn (2)
|
||||
{
|
||||
setWindowTitle ("Open CS");
|
||||
setWindowTitle ("OpenMW-CS");
|
||||
|
||||
QVBoxLayout *layout = new QVBoxLayout (this);
|
||||
|
||||
|
@ -9,7 +9,9 @@
|
||||
|
||||
#include <OgreVector3.h>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <components/terrain/terraingrid.hpp>
|
||||
#endif
|
||||
|
||||
#include "object.hpp"
|
||||
|
||||
|
@ -3,7 +3,9 @@
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#ifndef Q_MOC_RUN
|
||||
#include <components/nifogre/ogrenifloader.hpp>
|
||||
#endif
|
||||
|
||||
class QModelIndex;
|
||||
|
||||
|
@ -41,7 +41,7 @@ add_openmw_dir (mwgui
|
||||
itemmodel containeritemmodel inventoryitemmodel sortfilteritemmodel itemview
|
||||
tradeitemmodel companionitemmodel pickpocketitemmodel controllers savegamedialog
|
||||
recharge mode videowidget backgroundimage itemwidget screenfader debugwindow spellmodel spellview
|
||||
draganddrop
|
||||
draganddrop timeadvancer jailscreen
|
||||
)
|
||||
|
||||
add_openmw_dir (mwdialogue
|
||||
|
@ -109,11 +109,14 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||
{
|
||||
if (!paused)
|
||||
{
|
||||
// local scripts
|
||||
executeLocalScripts();
|
||||
if (MWBase::Environment::get().getWorld()->getScriptsEnabled())
|
||||
{
|
||||
// local scripts
|
||||
executeLocalScripts();
|
||||
|
||||
// global scripts
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
||||
// global scripts
|
||||
MWBase::Environment::get().getScriptManager()->getGlobalScripts().run();
|
||||
}
|
||||
|
||||
MWBase::Environment::get().getWorld()->markCellAsUnchanged();
|
||||
}
|
||||
@ -170,7 +173,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
||||
|
||||
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||
: mOgre (0)
|
||||
, mFpsLevel(0)
|
||||
, mVerboseScripts (false)
|
||||
, mSkipMenu (false)
|
||||
, mUseSound (true)
|
||||
@ -292,16 +294,10 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
||||
else
|
||||
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
|
||||
|
||||
// load user settings if they exist, otherwise just load the default settings as user settings
|
||||
// load user settings if they exist
|
||||
const std::string settingspath = mCfgMgr.getUserConfigPath().string() + "/settings.cfg";
|
||||
if (boost::filesystem::exists(settingspath))
|
||||
settings.loadUser(settingspath);
|
||||
else if (boost::filesystem::exists(localdefault))
|
||||
settings.loadUser(localdefault);
|
||||
else if (boost::filesystem::exists(globaldefault))
|
||||
settings.loadUser(globaldefault);
|
||||
|
||||
mFpsLevel = settings.getInt("fps", "HUD");
|
||||
|
||||
// load nif overrides
|
||||
NifOverrides::Overrides nifOverrides;
|
||||
@ -349,6 +345,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||
addResourcesDirectory(mResDir / "mygui");
|
||||
addResourcesDirectory(mResDir / "water");
|
||||
addResourcesDirectory(mResDir / "shadows");
|
||||
addResourcesDirectory(mResDir / "materials");
|
||||
|
||||
OEngine::Render::WindowSettings windowSettings;
|
||||
windowSettings.fullscreen = settings.getBool("fullscreen", "Video");
|
||||
@ -397,7 +394,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
||||
mEnvironment.setInputManager (input);
|
||||
|
||||
MWGui::WindowManager* window = new MWGui::WindowManager(
|
||||
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
|
||||
mExtensions, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
|
||||
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap);
|
||||
mEnvironment.setWindowManager (window);
|
||||
|
||||
@ -598,11 +595,6 @@ void OMW::Engine::setSoundUsage(bool soundUsage)
|
||||
mUseSound = soundUsage;
|
||||
}
|
||||
|
||||
void OMW::Engine::showFPS(int level)
|
||||
{
|
||||
mFpsLevel = level;
|
||||
}
|
||||
|
||||
void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
|
@ -71,7 +71,6 @@ namespace OMW
|
||||
OEngine::Render::OgreRenderer *mOgre;
|
||||
std::string mCellName;
|
||||
std::vector<std::string> mContentFiles;
|
||||
int mFpsLevel;
|
||||
bool mVerboseScripts;
|
||||
bool mSkipMenu;
|
||||
bool mUseSound;
|
||||
@ -151,9 +150,6 @@ namespace OMW
|
||||
*/
|
||||
void addContentFile(const std::string& file);
|
||||
|
||||
/// Enable fps counter
|
||||
void showFPS(int level);
|
||||
|
||||
/// Enable or disable verbose script output
|
||||
void setScriptsVerbosity(bool scriptsVerbosity);
|
||||
|
||||
|
@ -153,7 +153,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||
->default_value(true), "enable script blacklisting")
|
||||
|
||||
("load-savegame", bpo::value<std::string>()->default_value(""),
|
||||
"load a save game file on game startup")
|
||||
"load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)")
|
||||
|
||||
("skip-menu", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "skip main menu on game startup")
|
||||
@ -190,29 +190,23 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||
bpo::store(valid_opts, variables);
|
||||
bpo::notify(variables);
|
||||
|
||||
bool run = true;
|
||||
|
||||
if (variables.count ("help"))
|
||||
{
|
||||
std::cout << desc << std::endl;
|
||||
run = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::cout << "OpenMW version " << OPENMW_VERSION;
|
||||
std::string rev = OPENMW_VERSION_COMMITHASH;
|
||||
std::string tag = OPENMW_VERSION_TAGHASH;
|
||||
if (!rev.empty() && !tag.empty())
|
||||
{
|
||||
rev = rev.substr(0, 10);
|
||||
std::cout << " (revision " << rev << ")";
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
if (variables.count ("version"))
|
||||
{
|
||||
std::cout << "OpenMW version " << OPENMW_VERSION << std::endl;
|
||||
|
||||
std::string rev = OPENMW_VERSION_COMMITHASH;
|
||||
std::string tag = OPENMW_VERSION_TAGHASH;
|
||||
if (!rev.empty() && !tag.empty())
|
||||
{
|
||||
rev = rev.substr(0, 10);
|
||||
std::cout << "Revision " << rev << std::endl;
|
||||
}
|
||||
run = false;
|
||||
}
|
||||
|
||||
if (!run)
|
||||
return false;
|
||||
|
||||
cfgMgr.readConfiguration(variables, desc);
|
||||
@ -396,12 +390,12 @@ int main(int argc, char**argv)
|
||||
catch (std::exception &e)
|
||||
{
|
||||
#if OGRE_PLATFORM == OGRE_PLATFORM_LINUX || OGRE_PLATFORM == OGRE_PLATFORM_APPLE
|
||||
if (isatty(fileno(stdin)))
|
||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||
else
|
||||
if (!isatty(fileno(stdin)))
|
||||
#endif
|
||||
SDL_ShowSimpleMessageBox(0, "OpenMW: Fatal error", e.what(), NULL);
|
||||
|
||||
std::cerr << "\nERROR: " << e.what() << std::endl;
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#ifndef GAME_BASE_INVIRONMENT_H
|
||||
#define GAME_BASE_INVIRONMENT_H
|
||||
#ifndef GAME_BASE_ENVIRONMENT_H
|
||||
#define GAME_BASE_ENVIRONMENT_H
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
|
@ -2,8 +2,8 @@
|
||||
#define GAME_MWBASE_INPUTMANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
@ -29,7 +29,7 @@ namespace MWBase
|
||||
|
||||
virtual void changeInputMode(bool guiMode) = 0;
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||
|
||||
virtual void setDragDrop(bool dragDrop) = 0;
|
||||
|
||||
|
@ -129,16 +129,15 @@ namespace MWBase
|
||||
/// @return false if the attack was considered a "friendly hit" and forgiven
|
||||
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
|
||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
|
||||
/// @param container The container the item is in; may be empty for an item in the world
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||
int count) = 0;
|
||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
|
||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||
/// @return was it illegal, and someone saw you doing it?
|
||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
|
||||
|
||||
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) = 0;
|
||||
|
||||
enum PersuasionType
|
||||
{
|
||||
PT_Admire,
|
||||
@ -203,6 +202,15 @@ namespace MWBase
|
||||
virtual void keepPlayerAlive() = 0;
|
||||
|
||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
||||
|
||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
||||
|
||||
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).
|
||||
/// <Owner, item count>
|
||||
virtual std::vector<std::pair<std::string, int> > getStolenItemOwners(const std::string& itemid) = 0;
|
||||
|
||||
/// Has the player stolen this item from the given owner?
|
||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,9 @@
|
||||
#define GAME_MWBASE_SOUNDMANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace Ogre
|
||||
@ -74,7 +72,7 @@ namespace MWBase
|
||||
|
||||
virtual ~SoundManager() {}
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& settings) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& settings) = 0;
|
||||
|
||||
virtual void stopMusic() = 0;
|
||||
///< Stops music if it's playing
|
||||
|
@ -1,20 +1,24 @@
|
||||
#ifndef GAME_MWBASE_WINDOWMANAGER_H
|
||||
#define GAME_MWBASE_WINDOWMANAGER_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
#include <set>
|
||||
|
||||
#include "../mwgui/mode.hpp"
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace Translation
|
||||
{
|
||||
class Storage;
|
||||
}
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Gui;
|
||||
@ -35,6 +39,15 @@ namespace ESM
|
||||
struct Class;
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
struct CellId;
|
||||
}
|
||||
|
||||
namespace MWMechanics
|
||||
{
|
||||
class AttributeValue;
|
||||
template<typename T>
|
||||
class DynamicStat;
|
||||
class SkillValue;
|
||||
}
|
||||
|
||||
namespace MWWorld
|
||||
@ -58,6 +71,7 @@ namespace MWGui
|
||||
class ContainerWindow;
|
||||
class DialogueWindow;
|
||||
class WindowModal;
|
||||
class JailScreen;
|
||||
|
||||
enum ShowInDialogueMode {
|
||||
ShowInDialogueMode_IfPossible,
|
||||
@ -109,6 +123,8 @@ namespace MWBase
|
||||
virtual void removeGuiMode (MWGui::GuiMode mode) = 0;
|
||||
///< can be anywhere in the stack
|
||||
|
||||
virtual void goToJail(int days) = 0;
|
||||
|
||||
virtual void updatePlayer() = 0;
|
||||
|
||||
virtual MWGui::GuiMode getMode() const = 0;
|
||||
@ -266,7 +282,7 @@ namespace MWBase
|
||||
*/
|
||||
virtual std::string getGameSettingString(const std::string &id, const std::string &default_) = 0;
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||
|
||||
virtual void windowResized(int x, int y) = 0;
|
||||
|
||||
|
@ -3,24 +3,23 @@
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <set>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <components/esm/cellid.hpp>
|
||||
|
||||
#include "../mwworld/globals.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Quaternion;
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace OEngine
|
||||
namespace Loading
|
||||
{
|
||||
namespace Physic
|
||||
{
|
||||
class PhysicEngine;
|
||||
}
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
@ -33,7 +32,6 @@ namespace ESM
|
||||
struct Potion;
|
||||
struct Spell;
|
||||
struct NPC;
|
||||
struct CellId;
|
||||
struct Armor;
|
||||
struct Weapon;
|
||||
struct Clothing;
|
||||
@ -92,6 +90,7 @@ namespace MWBase
|
||||
{
|
||||
std::string name;
|
||||
float x, y; // world position
|
||||
ESM::CellId dest;
|
||||
};
|
||||
|
||||
World() {}
|
||||
@ -269,6 +268,8 @@ namespace MWBase
|
||||
virtual MWWorld::Ptr getFacedObject() = 0;
|
||||
///< Return pointer to the object the player is looking at, if it is within activation range
|
||||
|
||||
virtual float getMaxActivationDistance() = 0;
|
||||
|
||||
/// Returns a pointer to the object the provided object would hit (if within the
|
||||
/// specified distance), and the point where the hit occurs. This will attempt to
|
||||
/// use the "Head" node, or alternatively the "Bip01 Head" node as a basis.
|
||||
@ -388,7 +389,7 @@ namespace MWBase
|
||||
virtual bool canPlaceObject (float cursorX, float cursorY) = 0;
|
||||
///< @return true if it is possible to place on object at specified cursor location
|
||||
|
||||
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
|
||||
virtual void processChangedSettings (const std::set< std::pair<std::string, std::string> >& settings) = 0;
|
||||
|
||||
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
|
||||
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
|
||||
@ -453,6 +454,7 @@ namespace MWBase
|
||||
|
||||
/// \todo Probably shouldn't be here
|
||||
virtual MWRender::Animation* getAnimation(const MWWorld::Ptr &ptr) = 0;
|
||||
virtual void reattachPlayerCamera() = 0;
|
||||
|
||||
/// \todo this does not belong here
|
||||
virtual void frameStarted (float dt, bool paused) = 0;
|
||||
@ -489,6 +491,9 @@ namespace MWBase
|
||||
|
||||
virtual bool toggleGodMode() = 0;
|
||||
|
||||
virtual bool toggleScripts() = 0;
|
||||
virtual bool getScriptsEnabled() const = 0;
|
||||
|
||||
/**
|
||||
* @brief startSpellCast attempt to start casting a spell. Might fail immediately if conditions are not met.
|
||||
* @param actor
|
||||
@ -548,7 +553,7 @@ namespace MWBase
|
||||
virtual void spawnEffect (const std::string& model, const std::string& textureOverride, const Ogre::Vector3& worldPos) = 0;
|
||||
|
||||
virtual void explodeSpell (const Ogre::Vector3& origin, const ESM::EffectList& effects,
|
||||
const MWWorld::Ptr& caster, int rangeType, const std::string& id, const std::string& sourceName) = 0;
|
||||
const MWWorld::Ptr& caster, ESM::RangeType rangeType, const std::string& id, const std::string& sourceName) = 0;
|
||||
|
||||
virtual void activate (const MWWorld::Ptr& object, const MWWorld::Ptr& actor) = 0;
|
||||
|
||||
|
@ -59,8 +59,10 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Container> *ref =
|
||||
ptr.get<ESM::Container>();
|
||||
|
||||
// setting ownership not needed, since taking items from a container inherits the
|
||||
// container's owner automatically
|
||||
data->mContainerStore.fill(
|
||||
ref->mBase->mInventory, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank(), MWBase::Environment::get().getWorld()->getStore());
|
||||
ref->mBase->mInventory, "");
|
||||
|
||||
// store
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
@ -82,7 +84,10 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank());
|
||||
|
||||
// setting ownership not needed, since taking items from a container inherits the
|
||||
// container's owner automatically
|
||||
store.restock(list, ptr, "");
|
||||
}
|
||||
|
||||
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
|
||||
|
@ -139,8 +139,7 @@ namespace MWClass
|
||||
// store
|
||||
ptr.getRefData().setCustomData(data.release());
|
||||
|
||||
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "", -1,
|
||||
MWBase::Environment::get().getWorld()->getStore());
|
||||
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr));
|
||||
|
||||
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||
getInventoryStore(ptr).autoEquip(ptr);
|
||||
@ -228,18 +227,7 @@ namespace MWClass
|
||||
weapon = *weaponslot;
|
||||
}
|
||||
|
||||
// Reduce fatigue
|
||||
// somewhat of a guess, but using the weapon weight makes sense
|
||||
const float fFatigueAttackBase = gmst.find("fFatigueAttackBase")->getFloat();
|
||||
const float fFatigueAttackMult = gmst.find("fFatigueAttackMult")->getFloat();
|
||||
const float fWeaponFatigueMult = gmst.find("fWeaponFatigueMult")->getFloat();
|
||||
MWMechanics::DynamicStat<float> fatigue = stats.getFatigue();
|
||||
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||
if (!weapon.isEmpty())
|
||||
fatigueLoss += weapon.getClass().getWeight(weapon) * stats.getAttackStrength() * fWeaponFatigueMult;
|
||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||
stats.setFatigue(fatigue);
|
||||
MWMechanics::applyFatigueLoss(ptr, weapon);
|
||||
|
||||
// TODO: where is the distance defined?
|
||||
float dist = 200.f;
|
||||
@ -897,7 +885,7 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId());
|
||||
}
|
||||
|
||||
int Creature::getBaseFightRating(const MWWorld::Ptr &ptr) const
|
||||
|
@ -52,7 +52,7 @@ namespace MWClass
|
||||
registerClass (typeid (ESM::CreatureLevList).name(), instance);
|
||||
}
|
||||
|
||||
void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, MWRender::RenderingInterface &renderingInterface) const
|
||||
void CreatureLevList::insertObjectRendering(const MWWorld::Ptr &ptr, const std::string& model, MWRender::RenderingInterface &renderingInterface) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
|
@ -20,7 +20,7 @@ namespace MWClass
|
||||
|
||||
static void registerSelf();
|
||||
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const;
|
||||
virtual void insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const;
|
||||
///< Add reference into a cell for rendering
|
||||
|
||||
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
|
@ -93,9 +93,6 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::Door> *ref =
|
||||
ptr.get<ESM::Door>();
|
||||
|
||||
if (ptr.getCellRef().getTeleport() && !ptr.getCellRef().getDestCell().empty()) // TODO doors that lead to exteriors
|
||||
return ptr.getCellRef().getDestCell();
|
||||
|
||||
return ref->mBase->mName;
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "../mwworld/ptr.hpp"
|
||||
#include "../mwworld/actiontake.hpp"
|
||||
#include "../mwworld/cellstore.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/physicssystem.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/nullaction.hpp"
|
||||
|
@ -296,25 +296,6 @@ namespace MWClass
|
||||
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
// NPC stats
|
||||
if (!ref->mBase->mFaction.empty())
|
||||
{
|
||||
std::string faction = ref->mBase->mFaction;
|
||||
if (const ESM::Faction* fact = MWBase::Environment::get().getWorld()->getStore().get<ESM::Faction>().search(faction))
|
||||
{
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
data->mNpcStats.setFactionRank(fact->mId, (int)ref->mBase->mNpdt52.mRank);
|
||||
}
|
||||
else
|
||||
{
|
||||
data->mNpcStats.setFactionRank(fact->mId, (int)ref->mBase->mNpdt12.mRank);
|
||||
}
|
||||
}
|
||||
else
|
||||
std::cerr << "Warning: ignoring nonexistent faction '" << faction << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
||||
}
|
||||
|
||||
// creature stats
|
||||
int gold=0;
|
||||
if(ref->mBase->mNpdtType != ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
@ -371,13 +352,13 @@ namespace MWClass
|
||||
std::cerr << "Warning: ignoring nonexistent race power '" << *iter << "' on NPC '" << ref->mBase->mId << "'" << std::endl;
|
||||
}
|
||||
|
||||
if (data->mNpcStats.getFactionRanks().size())
|
||||
if (!ref->mBase->mFaction.empty())
|
||||
{
|
||||
static const int iAutoRepFacMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepFacMod")->getInt();
|
||||
static const int iAutoRepLevMod = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>()
|
||||
.find("iAutoRepLevMod")->getInt();
|
||||
int rank = data->mNpcStats.getFactionRanks().begin()->second;
|
||||
int rank = ref->mBase->getFactionRank();
|
||||
|
||||
data->mNpcStats.setReputation(iAutoRepFacMod * (rank+1) + iAutoRepLevMod * (data->mNpcStats.getLevel()-1));
|
||||
}
|
||||
@ -403,8 +384,8 @@ namespace MWClass
|
||||
}
|
||||
|
||||
// inventory
|
||||
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", -1,
|
||||
MWBase::Environment::get().getWorld()->getStore());
|
||||
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items
|
||||
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr));
|
||||
|
||||
data->mNpcStats.setGoldPool(gold);
|
||||
|
||||
@ -505,18 +486,7 @@ namespace MWClass
|
||||
if(!weapon.isEmpty() && weapon.getTypeName() != typeid(ESM::Weapon).name())
|
||||
weapon = MWWorld::Ptr();
|
||||
|
||||
// Reduce fatigue
|
||||
// somewhat of a guess, but using the weapon weight makes sense
|
||||
const float fFatigueAttackBase = store.find("fFatigueAttackBase")->getFloat();
|
||||
const float fFatigueAttackMult = store.find("fFatigueAttackMult")->getFloat();
|
||||
const float fWeaponFatigueMult = store.find("fWeaponFatigueMult")->getFloat();
|
||||
MWMechanics::DynamicStat<float> fatigue = getCreatureStats(ptr).getFatigue();
|
||||
const float normalizedEncumbrance = getNormalizedEncumbrance(ptr);
|
||||
float fatigueLoss = fFatigueAttackBase + normalizedEncumbrance * fFatigueAttackMult;
|
||||
if (!weapon.isEmpty())
|
||||
fatigueLoss += weapon.getClass().getWeight(weapon) * getNpcStats(ptr).getAttackStrength() * fWeaponFatigueMult;
|
||||
fatigue.setCurrent(fatigue.getCurrent() - fatigueLoss);
|
||||
getCreatureStats(ptr).setFatigue(fatigue);
|
||||
MWMechanics::applyFatigueLoss(ptr, weapon);
|
||||
|
||||
const float fCombatDistance = store.find("fCombatDistance")->getFloat();
|
||||
float dist = fCombatDistance * (!weapon.isEmpty() ?
|
||||
@ -1358,7 +1328,7 @@ namespace MWClass
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId());
|
||||
}
|
||||
|
||||
int Npc::getBaseFightRating (const MWWorld::Ptr& ptr) const
|
||||
@ -1371,4 +1341,16 @@ namespace MWClass
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Npc::getPrimaryFaction (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
return ref->mBase->mFaction;
|
||||
}
|
||||
|
||||
int Npc::getPrimaryFactionRank (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
return ref->mBase->getFactionRank();
|
||||
}
|
||||
}
|
||||
|
@ -189,6 +189,9 @@ namespace MWClass
|
||||
virtual void restock (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual int getBaseFightRating (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual std::string getPrimaryFaction(const MWWorld::Ptr &ptr) const;
|
||||
virtual int getPrimaryFactionRank(const MWWorld::Ptr &ptr) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -189,9 +189,8 @@ namespace MWClass
|
||||
{
|
||||
return std::string("Item Weapon Longblade Up");
|
||||
}
|
||||
// Shortblade and thrown weapons
|
||||
// thrown weapons may not be entirely correct
|
||||
if (type == 0 || type == 11)
|
||||
// Shortblade
|
||||
if (type == 0)
|
||||
{
|
||||
return std::string("Item Weapon Shortblade Up");
|
||||
}
|
||||
@ -200,8 +199,8 @@ namespace MWClass
|
||||
{
|
||||
return std::string("Item Weapon Spear Up");
|
||||
}
|
||||
// Blunts and Axes
|
||||
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
|
||||
// Blunts, Axes and Thrown weapons
|
||||
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8 || type == 11)
|
||||
{
|
||||
return std::string("Item Weapon Blunt Up");
|
||||
}
|
||||
@ -235,9 +234,8 @@ namespace MWClass
|
||||
{
|
||||
return std::string("Item Weapon Longblade Down");
|
||||
}
|
||||
// Shortblade and thrown weapons
|
||||
// thrown weapons may not be entirely correct
|
||||
if (type == 0 || type == 11)
|
||||
// Shortblade
|
||||
if (type == 0)
|
||||
{
|
||||
return std::string("Item Weapon Shortblade Down");
|
||||
}
|
||||
@ -246,8 +244,8 @@ namespace MWClass
|
||||
{
|
||||
return std::string("Item Weapon Spear Down");
|
||||
}
|
||||
// Blunts and Axes
|
||||
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8)
|
||||
// Blunts, Axes and Thrown weapons
|
||||
if (type == 3 || type == 4 || type == 5 || type == 7 || type == 8 || type == 11)
|
||||
{
|
||||
return std::string("Item Weapon Blunt Down");
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <cstdlib>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <list>
|
||||
|
||||
#include <components/esm/loaddial.hpp>
|
||||
#include <components/esm/loadinfo.hpp>
|
||||
@ -78,7 +79,7 @@ namespace MWDialogue
|
||||
|
||||
void DialogueManager::addTopic (const std::string& topic)
|
||||
{
|
||||
mKnownTopics[Misc::StringUtils::lowerCase(topic)] = true;
|
||||
mKnownTopics.insert( Misc::StringUtils::lowerCase(topic) );
|
||||
}
|
||||
|
||||
void DialogueManager::parseText (const std::string& text)
|
||||
@ -102,8 +103,8 @@ namespace MWDialogue
|
||||
if (tok->isImplicitKeyword() && mTranslationDataStorage.hasTranslation())
|
||||
continue;
|
||||
|
||||
if (std::find(mActorKnownTopics.begin(), mActorKnownTopics.end(), topicId) != mActorKnownTopics.end())
|
||||
mKnownTopics[topicId] = true;
|
||||
if (mActorKnownTopics.count( topicId ))
|
||||
mKnownTopics.insert( topicId );
|
||||
}
|
||||
|
||||
updateTopics();
|
||||
@ -341,10 +342,10 @@ namespace MWDialogue
|
||||
if (filter.responseAvailable (*iter))
|
||||
{
|
||||
std::string lower = Misc::StringUtils::lowerCase(iter->mId);
|
||||
mActorKnownTopics.push_back (lower);
|
||||
mActorKnownTopics.insert (lower);
|
||||
|
||||
//does the player know the topic?
|
||||
if (mKnownTopics.find (lower) != mKnownTopics.end())
|
||||
if (mKnownTopics.count(lower))
|
||||
{
|
||||
keywordList.push_back (iter->mId);
|
||||
}
|
||||
@ -635,10 +636,11 @@ namespace MWDialogue
|
||||
{
|
||||
ESM::DialogueState state;
|
||||
|
||||
for (std::map<std::string, bool>::const_iterator iter (mKnownTopics.begin());
|
||||
for (std::set<std::string>::const_iterator iter (mKnownTopics.begin());
|
||||
iter!=mKnownTopics.end(); ++iter)
|
||||
if (iter->second)
|
||||
state.mKnownTopics.push_back (iter->first);
|
||||
{
|
||||
state.mKnownTopics.push_back (*iter);
|
||||
}
|
||||
|
||||
state.mChangedFactionReaction = mChangedFactionReaction;
|
||||
|
||||
@ -659,7 +661,7 @@ namespace MWDialogue
|
||||
for (std::vector<std::string>::const_iterator iter (state.mKnownTopics.begin());
|
||||
iter!=state.mKnownTopics.end(); ++iter)
|
||||
if (store.get<ESM::Dialogue>().search (*iter))
|
||||
mKnownTopics.insert (std::make_pair (*iter, true));
|
||||
mKnownTopics.insert (*iter);
|
||||
|
||||
mChangedFactionReaction = state.mChangedFactionReaction;
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
#include "../mwbase/dialoguemanager.hpp"
|
||||
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <set>
|
||||
|
||||
#include <components/compiler/streamerrorhandler.hpp>
|
||||
#include <components/translation/translation.hpp>
|
||||
@ -23,13 +23,13 @@ namespace MWDialogue
|
||||
class DialogueManager : public MWBase::DialogueManager
|
||||
{
|
||||
std::map<std::string, ESM::Dialogue> mDialogueMap;
|
||||
std::map<std::string, bool> mKnownTopics;// Those are the topics the player knows.
|
||||
std::set<std::string> mKnownTopics;// Those are the topics the player knows.
|
||||
|
||||
// Modified faction reactions. <Faction1, <Faction2, Difference> >
|
||||
typedef std::map<std::string, std::map<std::string, int> > ModFactionReactionMap;
|
||||
ModFactionReactionMap mChangedFactionReaction;
|
||||
|
||||
std::list<std::string> mActorKnownTopics;
|
||||
std::set<std::string> mActorKnownTopics;
|
||||
|
||||
Translation::Storage& mTranslationDataStorage;
|
||||
MWScript::CompilerContext mCompilerContext;
|
||||
|
@ -67,14 +67,11 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
|
||||
if (isCreature)
|
||||
return false;
|
||||
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor);
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find ( Misc::StringUtils::lowerCase (info.mFaction));
|
||||
|
||||
if (iter==stats.getFactionRanks().end())
|
||||
if (!Misc::StringUtils::ciEqual(mActor.getClass().getPrimaryFaction(mActor), info.mFaction))
|
||||
return false;
|
||||
|
||||
// check rank
|
||||
if (iter->second < info.mData.mRank)
|
||||
if (mActor.getClass().getPrimaryFactionRank(mActor) < info.mData.mRank)
|
||||
return false;
|
||||
}
|
||||
else if (info.mData.mRank != -1)
|
||||
@ -83,13 +80,8 @@ bool MWDialogue::Filter::testActor (const ESM::DialInfo& info) const
|
||||
return false;
|
||||
|
||||
// Rank requirement, but no faction given. Use the actor's faction, if there is one.
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats (mActor);
|
||||
|
||||
if (!stats.getFactionRanks().size())
|
||||
return false;
|
||||
|
||||
// check rank
|
||||
if (stats.getFactionRanks().begin()->second < info.mData.mRank)
|
||||
if (mActor.getClass().getPrimaryFactionRank(mActor) < info.mData.mRank)
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -336,12 +328,10 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
|
||||
case SelectWrapper::Function_RankRequirement:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
if (faction.empty())
|
||||
return 0;
|
||||
|
||||
std::string faction =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
|
||||
int rank = getFactionRank (player, faction);
|
||||
|
||||
if (rank>=9)
|
||||
@ -376,15 +366,14 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
|
||||
case SelectWrapper::Function_FactionRankDiff:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
if (faction.empty())
|
||||
return 0;
|
||||
|
||||
const std::pair<std::string, int> faction =
|
||||
*mActor.getClass().getNpcStats (mActor).getFactionRanks().begin();
|
||||
|
||||
int rank = getFactionRank (player, faction.first);
|
||||
|
||||
return rank-faction.second;
|
||||
int rank = getFactionRank (player, faction);
|
||||
int npcRank = mActor.getClass().getPrimaryFactionRank(mActor);
|
||||
return rank-npcRank;
|
||||
}
|
||||
|
||||
case SelectWrapper::Function_WerewolfKills:
|
||||
@ -396,11 +385,10 @@ int MWDialogue::Filter::getSelectStructInteger (const SelectWrapper& select) con
|
||||
{
|
||||
bool low = select.getFunction()==SelectWrapper::Function_RankLow;
|
||||
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
return 0;
|
||||
std::string factionId = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
std::string factionId =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
if (factionId.empty())
|
||||
return 0;
|
||||
|
||||
int value = 0;
|
||||
|
||||
@ -454,7 +442,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_NotFaction:
|
||||
|
||||
return !Misc::StringUtils::ciEqual(mActor.get<ESM::NPC>()->mBase->mFaction, select.getName());
|
||||
return !Misc::StringUtils::ciEqual(mActor.getClass().getPrimaryFaction(mActor), select.getName());
|
||||
|
||||
case SelectWrapper::Function_NotClass:
|
||||
|
||||
@ -494,8 +482,7 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_SameFaction:
|
||||
|
||||
return mActor.getClass().getNpcStats (mActor).isSameFaction (
|
||||
player.getClass().getNpcStats (player));
|
||||
return player.getClass().getNpcStats (player).isInFaction(mActor.getClass().getPrimaryFaction(mActor));
|
||||
|
||||
case SelectWrapper::Function_PcCommonDisease:
|
||||
|
||||
@ -512,11 +499,10 @@ bool MWDialogue::Filter::getSelectStructBoolean (const SelectWrapper& select) co
|
||||
|
||||
case SelectWrapper::Function_PcExpelled:
|
||||
{
|
||||
if (mActor.getClass().getNpcStats (mActor).getFactionRanks().empty())
|
||||
return false;
|
||||
std::string faction = mActor.getClass().getPrimaryFaction(mActor);
|
||||
|
||||
std::string faction =
|
||||
mActor.getClass().getNpcStats (mActor).getFactionRanks().begin()->first;
|
||||
if (faction.empty())
|
||||
return false;
|
||||
|
||||
return player.getClass().getNpcStats(player).getExpelled(faction);
|
||||
}
|
||||
@ -561,7 +547,7 @@ int MWDialogue::Filter::getFactionRank (const MWWorld::Ptr& actor, const std::st
|
||||
{
|
||||
MWMechanics::NpcStats& stats = actor.getClass().getNpcStats (actor);
|
||||
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (factionId);
|
||||
std::map<std::string, int>::const_iterator iter = stats.getFactionRanks().find (Misc::StringUtils::lowerCase(factionId));
|
||||
|
||||
if (iter==stats.getFactionRanks().end())
|
||||
return -1;
|
||||
|
@ -89,7 +89,7 @@ namespace MWDialogue
|
||||
|
||||
for (ESM::Dialogue::InfoContainer::const_iterator iter (dialogue->mInfo.begin());
|
||||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mData.mDisposition==index) /// \todo cleanup info structure
|
||||
if (iter->mData.mJournalIndex==index)
|
||||
{
|
||||
return iter->mId;
|
||||
}
|
||||
|
@ -259,7 +259,12 @@ namespace MWDialogue
|
||||
record.load (reader);
|
||||
|
||||
if (isThere (record.mTopic))
|
||||
mQuests.insert (std::make_pair (record.mTopic, record));
|
||||
{
|
||||
std::pair<TQuestContainer::iterator, bool> result = mQuests.insert (std::make_pair (record.mTopic, record));
|
||||
// reapply quest index, this is to handle users upgrading from only
|
||||
// Morrowind.esm (no quest states) to Morrowind.esm + Tribunal.esm
|
||||
result.first->second.setIndex(record.mState);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -161,7 +161,7 @@ public:
|
||||
while (matches.size())
|
||||
{
|
||||
int longestKeywordSize = 0;
|
||||
typename std::vector<Match>::iterator longestKeyword;
|
||||
typename std::vector<Match>::iterator longestKeyword = matches.begin();
|
||||
for (typename std::vector<Match>::iterator it = matches.begin(); it != matches.end(); ++it)
|
||||
{
|
||||
int size = it->mEnd - it->mBeg;
|
||||
|
@ -75,7 +75,7 @@ namespace MWDialogue
|
||||
iter!=dialogue->mInfo.end(); ++iter)
|
||||
if (iter->mId == entry.mInfoId)
|
||||
{
|
||||
index = iter->mData.mDisposition; /// \todo cleanup info structure
|
||||
index = iter->mData.mJournalIndex;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "scripttest.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
@ -5,14 +5,14 @@
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
void BackgroundImage::setBackgroundImage (const std::string& image, bool fixedRatio, bool correct)
|
||||
void BackgroundImage::setBackgroundImage (const std::string& image, bool fixedRatio, bool stretch)
|
||||
{
|
||||
if (mChild)
|
||||
{
|
||||
MyGUI::Gui::getInstance().destroyWidget(mChild);
|
||||
mChild = NULL;
|
||||
}
|
||||
if (correct)
|
||||
if (!stretch)
|
||||
{
|
||||
setImageTexture("black.png");
|
||||
|
||||
|
@ -18,9 +18,9 @@ namespace MWGui
|
||||
|
||||
/**
|
||||
* @param fixedRatio Use a fixed ratio of 4:3, regardless of the image dimensions
|
||||
* @param correct Add black bars?
|
||||
* @param stretch Stretch to fill the whole screen, or add black bars?
|
||||
*/
|
||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool correct=true);
|
||||
void setBackgroundImage (const std::string& image, bool fixedRatio=true, bool stretch=true);
|
||||
|
||||
virtual void setSize (const MyGUI::IntSize &_value);
|
||||
virtual void setCoord (const MyGUI::IntCoord &_value);
|
||||
|
@ -195,8 +195,20 @@ struct TypesetBookImpl : TypesetBook
|
||||
|
||||
struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
{
|
||||
struct PartialText {
|
||||
StyleImpl *mStyle;
|
||||
Utf8Stream::Point mBegin;
|
||||
Utf8Stream::Point mEnd;
|
||||
int mWidth;
|
||||
|
||||
PartialText( StyleImpl *style, Utf8Stream::Point begin, Utf8Stream::Point end, int width) :
|
||||
mStyle(style), mBegin(begin), mEnd(end), mWidth(width)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef TypesetBookImpl Book;
|
||||
typedef boost::shared_ptr <Book> BookPtr;
|
||||
typedef std::vector<PartialText>::const_iterator PartialTextConstIterator;
|
||||
|
||||
int mPageWidth;
|
||||
int mPageHeight;
|
||||
@ -207,6 +219,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
Run * mRun;
|
||||
|
||||
std::vector <Alignment> mSectionAlignment;
|
||||
std::vector <PartialText> mPartialWhitespace;
|
||||
std::vector <PartialText> mPartialWord;
|
||||
|
||||
Book::Content const * mCurrentContent;
|
||||
Alignment mCurrentAlignment;
|
||||
@ -273,6 +287,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
|
||||
intptr_t addContent (Utf8Span text, bool select)
|
||||
{
|
||||
add_partial_text();
|
||||
|
||||
Contents::iterator i = mBook->mContents.insert (mBook->mContents.end (), Content (text.first, text.second));
|
||||
|
||||
if (select)
|
||||
@ -283,6 +299,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
|
||||
void selectContent (intptr_t contentHandle)
|
||||
{
|
||||
add_partial_text();
|
||||
|
||||
mCurrentContent = reinterpret_cast <Content const *> (contentHandle);
|
||||
}
|
||||
|
||||
@ -302,12 +320,16 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
{
|
||||
assert (margin == 0); //TODO: figure out proper behavior here...
|
||||
|
||||
add_partial_text();
|
||||
|
||||
mRun = NULL;
|
||||
mLine = NULL;
|
||||
}
|
||||
|
||||
void sectionBreak (float margin)
|
||||
{
|
||||
add_partial_text();
|
||||
|
||||
if (mBook->mSections.size () > 0)
|
||||
{
|
||||
mRun = NULL;
|
||||
@ -321,6 +343,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
|
||||
void setSectionAlignment (Alignment sectionAlignment)
|
||||
{
|
||||
add_partial_text();
|
||||
|
||||
if (mSection != NULL)
|
||||
mSectionAlignment.back () = sectionAlignment;
|
||||
mCurrentAlignment = sectionAlignment;
|
||||
@ -331,6 +355,8 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
int curPageStart = 0;
|
||||
int curPageStop = 0;
|
||||
|
||||
add_partial_text();
|
||||
|
||||
std::vector <Alignment>::iterator sa = mSectionAlignment.begin ();
|
||||
for (Sections::iterator i = mBook->mSections.begin (); i != mBook->mSections.end (); ++i, ++sa)
|
||||
{
|
||||
@ -415,23 +441,23 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
|
||||
void writeImpl (StyleImpl * style, Utf8Stream::Point _begin, Utf8Stream::Point _end)
|
||||
{
|
||||
int line_height = style->mFont->getDefaultHeight ();
|
||||
|
||||
Utf8Stream stream (_begin, _end);
|
||||
|
||||
while (!stream.eof ())
|
||||
{
|
||||
if (ucsLineBreak (stream.peek ()))
|
||||
{
|
||||
add_partial_text();
|
||||
stream.consume ();
|
||||
mLine = NULL, mRun = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ucsBreakingSpace (stream.peek ()) && !mPartialWord.empty())
|
||||
add_partial_text();
|
||||
|
||||
int word_width = 0;
|
||||
int word_height = 0;
|
||||
int space_width = 0;
|
||||
int character_count = 0;
|
||||
|
||||
Utf8Stream::Point lead = stream.current ();
|
||||
|
||||
@ -450,8 +476,6 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
MyGUI::GlyphInfo* gi = style->mFont->getGlyphInfo (stream.peek ());
|
||||
if (gi)
|
||||
word_width += gi->advance + gi->bearingX;
|
||||
word_height = line_height;
|
||||
++character_count;
|
||||
stream.consume ();
|
||||
}
|
||||
|
||||
@ -460,21 +484,57 @@ struct TypesetBookImpl::Typesetter : BookTypesetter
|
||||
if (lead == extent)
|
||||
break;
|
||||
|
||||
int left = mLine ? mLine->mRect.right : 0;
|
||||
if ( lead != origin )
|
||||
mPartialWhitespace.push_back (PartialText (style, lead, origin, space_width));
|
||||
if ( origin != extent )
|
||||
mPartialWord.push_back (PartialText (style, origin, extent, word_width));
|
||||
}
|
||||
}
|
||||
|
||||
if (left + space_width + word_width > mPageWidth)
|
||||
{
|
||||
mLine = NULL, mRun = NULL;
|
||||
void add_partial_text ()
|
||||
{
|
||||
if (mPartialWhitespace.empty() && mPartialWord.empty())
|
||||
return;
|
||||
|
||||
append_run (style, origin, extent, extent - origin, word_width, mBook->mRect.bottom + word_height);
|
||||
}
|
||||
else
|
||||
int space_width = 0;
|
||||
int word_width = 0;
|
||||
|
||||
for (PartialTextConstIterator i = mPartialWhitespace.begin (); i != mPartialWhitespace.end (); ++i)
|
||||
space_width += i->mWidth;
|
||||
for (PartialTextConstIterator i = mPartialWord.begin (); i != mPartialWord.end (); ++i)
|
||||
word_width += i->mWidth;
|
||||
|
||||
int left = mLine ? mLine->mRect.right : 0;
|
||||
|
||||
if (left + space_width + word_width > mPageWidth)
|
||||
{
|
||||
mLine = NULL, mRun = NULL, left = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (PartialTextConstIterator i = mPartialWhitespace.begin (); i != mPartialWhitespace.end (); ++i)
|
||||
{
|
||||
int top = mLine ? mLine->mRect.top : mBook->mRect.bottom;
|
||||
int line_height = i->mStyle->mFont->getDefaultHeight ();
|
||||
|
||||
append_run (style, lead, extent, extent - origin, left + space_width + word_width, top + word_height);
|
||||
append_run ( i->mStyle, i->mBegin, i->mEnd, 0, left + i->mWidth, top + line_height);
|
||||
|
||||
left = mLine->mRect.right;
|
||||
}
|
||||
}
|
||||
|
||||
for (PartialTextConstIterator i = mPartialWord.begin (); i != mPartialWord.end (); ++i)
|
||||
{
|
||||
int top = mLine ? mLine->mRect.top : mBook->mRect.bottom;
|
||||
int line_height = i->mStyle->mFont->getDefaultHeight ();
|
||||
|
||||
append_run (i->mStyle, i->mBegin, i->mEnd, i->mEnd - i->mBegin, left + i->mWidth, top + line_height);
|
||||
|
||||
left = mLine->mRect.right;
|
||||
}
|
||||
|
||||
mPartialWhitespace.clear();
|
||||
mPartialWord.clear();
|
||||
}
|
||||
|
||||
void append_run (StyleImpl * style, Utf8Stream::Point begin, Utf8Stream::Point end, int pc, int right, int bottom)
|
||||
|
@ -3,6 +3,22 @@
|
||||
#include "../mwmechanics/npcstats.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
void modifyProfit(const MWWorld::Ptr& actor, int diff)
|
||||
{
|
||||
std::string script = actor.getClass().getScript(actor);
|
||||
if (!script.empty())
|
||||
{
|
||||
int profit = actor.getRefData().getLocals().getIntVar(script, "minimumprofit");
|
||||
profit += diff;
|
||||
actor.getRefData().getLocals().setVarByInt(script, "minimumprofit", profit);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
CompanionItemModel::CompanionItemModel(const MWWorld::Ptr &actor)
|
||||
@ -12,23 +28,25 @@ namespace MWGui
|
||||
|
||||
MWWorld::Ptr CompanionItemModel::copyItem (const ItemStack& item, size_t count, bool setNewOwner=false)
|
||||
{
|
||||
if (mActor.getClass().isNpc())
|
||||
{
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor);
|
||||
stats.modifyProfit(item.mBase.getClass().getValue(item.mBase) * count);
|
||||
}
|
||||
if (hasProfit(mActor))
|
||||
modifyProfit(mActor, item.mBase.getClass().getValue(item.mBase) * count);
|
||||
|
||||
return InventoryItemModel::copyItem(item, count, setNewOwner);
|
||||
}
|
||||
|
||||
void CompanionItemModel::removeItem (const ItemStack& item, size_t count)
|
||||
{
|
||||
if (mActor.getClass().isNpc())
|
||||
{
|
||||
MWMechanics::NpcStats& stats = mActor.getClass().getNpcStats(mActor);
|
||||
stats.modifyProfit(-item.mBase.getClass().getValue(item.mBase) * count);
|
||||
}
|
||||
if (hasProfit(mActor))
|
||||
modifyProfit(mActor, -item.mBase.getClass().getValue(item.mBase) * count);
|
||||
|
||||
InventoryItemModel::removeItem(item, count);
|
||||
}
|
||||
|
||||
bool CompanionItemModel::hasProfit(const MWWorld::Ptr &actor)
|
||||
{
|
||||
std::string script = actor.getClass().getScript(actor);
|
||||
if (script.empty())
|
||||
return false;
|
||||
return actor.getRefData().getLocals().hasVar(script, "minimumprofit");
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ namespace MWGui
|
||||
|
||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner);
|
||||
virtual void removeItem (const ItemStack& item, size_t count);
|
||||
|
||||
bool hasProfit(const MWWorld::Ptr& actor);
|
||||
};
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,21 @@
|
||||
#include "draganddrop.hpp"
|
||||
#include "countdialog.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
int getProfit(const MWWorld::Ptr& actor)
|
||||
{
|
||||
std::string script = actor.getClass().getScript(actor);
|
||||
if (!script.empty())
|
||||
{
|
||||
return actor.getRefData().getLocals().getIntVar(script, "minimumprofit");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace MWGui
|
||||
{
|
||||
|
||||
@ -116,13 +131,12 @@ void CompanionWindow::updateEncumbranceBar()
|
||||
float encumbrance = mPtr.getClass().getEncumbrance(mPtr);
|
||||
mEncumbranceBar->setValue(encumbrance, capacity);
|
||||
|
||||
if (mPtr.getTypeName() != typeid(ESM::NPC).name())
|
||||
mProfitLabel->setCaption("");
|
||||
else
|
||||
if (mModel && mModel->hasProfit(mPtr))
|
||||
{
|
||||
MWMechanics::NpcStats& stats = mPtr.getClass().getNpcStats(mPtr);
|
||||
mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + MyGUI::utility::toString(stats.getProfit()));
|
||||
mProfitLabel->setCaptionWithReplacing("#{sProfitValue} " + MyGUI::utility::toString(getProfit(mPtr)));
|
||||
}
|
||||
else
|
||||
mProfitLabel->setCaption("");
|
||||
}
|
||||
|
||||
void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||
@ -132,7 +146,7 @@ void CompanionWindow::onCloseButtonClicked(MyGUI::Widget* _sender)
|
||||
|
||||
void CompanionWindow::exit()
|
||||
{
|
||||
if (mPtr.getTypeName() == typeid(ESM::NPC).name() && mPtr.getClass().getNpcStats(mPtr).getProfit() < 0)
|
||||
if (mModel && mModel->hasProfit(mPtr) && getProfit(mPtr) < 0)
|
||||
{
|
||||
std::vector<std::string> buttons;
|
||||
buttons.push_back("#{sCompanionWarningButtonOne}");
|
||||
@ -148,9 +162,6 @@ void CompanionWindow::onMessageBoxButtonClicked(int button)
|
||||
{
|
||||
if (button == 0)
|
||||
{
|
||||
mPtr.getRefData().getLocals().setVarByInt(mPtr.getClass().getScript(mPtr),
|
||||
"minimumprofit", mPtr.getClass().getNpcStats(mPtr).getProfit());
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Companion);
|
||||
// Important for Calvus' contract script to work properly
|
||||
MWBase::Environment::get().getWindowManager()->removeGuiMode(GM_Dialogue);
|
||||
|
@ -290,7 +290,8 @@ namespace MWGui
|
||||
|
||||
// Add the command to the history, and set the current pointer to
|
||||
// the end of the list
|
||||
mCommandHistory.push_back(cm);
|
||||
if (mCommandHistory.empty() || mCommandHistory.back() != cm)
|
||||
mCommandHistory.push_back(cm);
|
||||
mCurrent = mCommandHistory.end();
|
||||
mEditString.clear();
|
||||
|
||||
|
@ -154,8 +154,6 @@ namespace MWGui
|
||||
|
||||
MWBase::Environment::get().getWindowManager()->setKeyFocusWidget(mCloseButton);
|
||||
|
||||
// Careful here. setTitle may cause size updates, causing itemview redraw, so make sure to do it last
|
||||
// or we end up using a possibly invalid model.
|
||||
setTitle(container.getClass().getName(container));
|
||||
}
|
||||
|
||||
@ -287,7 +285,7 @@ namespace MWGui
|
||||
if (mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead())
|
||||
return true;
|
||||
else
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, mPtr, count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -339,7 +339,8 @@ namespace MWGui
|
||||
for (int i=0; i<2; ++i)
|
||||
{
|
||||
MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
|
||||
if (Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(),
|
||||
mPtr.getCellRef().getRefId()))
|
||||
{
|
||||
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
|
||||
if (msg.find("%s") != std::string::npos)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <MyGUI_ScrollView.h>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
@ -182,6 +183,10 @@ namespace MWGui
|
||||
|
||||
HUD::~HUD()
|
||||
{
|
||||
mMainWidget->eventMouseLostFocus.clear();
|
||||
mMainWidget->eventMouseMove.clear();
|
||||
mMainWidget->eventMouseButtonClick.clear();
|
||||
|
||||
delete mSpellIcons;
|
||||
}
|
||||
|
||||
@ -666,4 +671,14 @@ namespace MWGui
|
||||
mEnemyHealthTimer = -1;
|
||||
}
|
||||
|
||||
void HUD::customMarkerCreated(MyGUI::Widget *marker)
|
||||
{
|
||||
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||
}
|
||||
|
||||
void HUD::doorMarkerCreated(MyGUI::Widget *marker)
|
||||
{
|
||||
marker->eventMouseButtonClick += MyGUI::newDelegate(this, &HUD::onMapClicked);
|
||||
}
|
||||
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user