forked from mirror/openmw-tes3mp
Compare commits
No commits in common. "0.7.0" and "0.6.1-openmw-updates" have entirely different histories.
0.7.0
...
0.6.1-open
1186 changed files with 27324 additions and 37973 deletions
|
@ -9,8 +9,3 @@ insert_final_newline = true
|
|||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = true
|
||||
|
||||
[*.glsl]
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
insert_final_newline = false
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -82,5 +82,6 @@ moc_*.cxx
|
|||
*ui_playpage.h
|
||||
*.[ao]
|
||||
*.so
|
||||
gamecontrollerdb.txt
|
||||
openmw.appdata.xml
|
||||
venv/
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
stages:
|
||||
- build
|
||||
|
||||
Debian:
|
||||
tags:
|
||||
- docker
|
||||
- linux
|
||||
image: gcc
|
||||
cache:
|
||||
key: apt-cache
|
||||
paths:
|
||||
- apt-cache/
|
||||
before_script:
|
||||
- export APT_CACHE_DIR=`pwd`/apt-cache && mkdir -pv $APT_CACHE_DIR
|
||||
- apt-get update -yq
|
||||
- apt-get -o dir::cache::archives="$APT_CACHE_DIR" install -y cmake libboost-filesystem-dev libboost-program-options-dev libboost-system-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev libswresample-dev libsdl2-dev libqt4-dev libopenal-dev libopenscenegraph-3.4-dev libunshield-dev libtinyxml-dev
|
||||
# - apt-get install -y libmygui-dev libbullet-dev # to be updated to latest below because stretch is too old
|
||||
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet-dev_2.87+dfsg-2_amd64.deb -o libbullet-dev_2.87+dfsg-2_amd64.deb
|
||||
- curl http://ftp.us.debian.org/debian/pool/main/b/bullet/libbullet2.87_2.87+dfsg-2_amd64.deb -o libbullet2.87_2.87+dfsg-2_amd64.deb
|
||||
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb -o libmygui.openglplatform0debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb -o libmyguiengine3debian1v5_3.2.2+dfsg-1_amd64.deb
|
||||
- curl http://ftp.us.debian.org/debian/pool/main/m/mygui/libmygui-dev_3.2.2+dfsg-1_amd64.deb -o libmygui-dev_3.2.2+dfsg-1_amd64.deb
|
||||
- dpkg --ignore-depends=libmygui.ogreplatform0debian1v5 -i *.deb
|
||||
stage: build
|
||||
script:
|
||||
- cores_to_use=$((`nproc`-2)); if (( $cores_to_use < 1 )); then cores_to_use=1; fi
|
||||
- mkdir build; cd build; cmake -DCMAKE_BUILD_TYPE=MinSizeRel ../
|
||||
- make -j$cores_to_use
|
||||
- DESTDIR=artifacts make install
|
||||
artifacts:
|
||||
paths:
|
||||
- build/artifacts/
|
||||
MacOS:
|
||||
tags:
|
||||
- macos
|
||||
- xcode
|
||||
except:
|
||||
- branches # because our CI VMs are not public, MRs can't use them and timeout
|
||||
stage: build
|
||||
allow_failure: true
|
||||
script:
|
||||
- rm -fr build/* # remove anything in the build directory
|
||||
- CI/before_install.osx.sh
|
||||
- CI/before_script.osx.sh
|
||||
- cd build; make -j2 package
|
||||
artifacts:
|
||||
paths:
|
||||
- build/OpenMW-*.dmg
|
||||
|
||||
Windows:
|
||||
tags:
|
||||
- win10
|
||||
- msvc2017
|
||||
except:
|
||||
- branches # because our CI VMs are not public, MRs can't use them and timeout
|
||||
stage: build
|
||||
allow_failure: true
|
||||
script:
|
||||
# - env # turn on for debugging
|
||||
- sh %CI_PROJECT_DIR%/CI/before_script.msvc.sh -c Release -p x64 -v 2017 -V
|
||||
- SET msBuildLocation="C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\msbuild.exe"
|
||||
- call %msBuildLocation% MSVC2017_64\OpenMW.sln /t:Build /p:Configuration=Release /m:%NUMBER_OF_PROCESSORS%
|
||||
- 7z a OpenMW_MSVC2017_64_%CI_BUILD_REF_NAME%_%CI_BUILD_ID%.zip %CI_PROJECT_DIR%\MSVC2017_64\Release\
|
||||
cache:
|
||||
paths:
|
||||
- deps
|
||||
artifacts:
|
||||
paths:
|
||||
- "*.zip"
|
38
.travis.yml
38
.travis.yml
|
@ -1,51 +1,48 @@
|
|||
os:
|
||||
- linux
|
||||
# - osx
|
||||
osx_image: xcode9.4
|
||||
osx_image: xcode8.3
|
||||
language: cpp
|
||||
sudo: required
|
||||
dist: xenial
|
||||
dist: trusty
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
- coverity_scan
|
||||
- /openmw-.*$/
|
||||
- /^[0-9]+\.[0-9]+\.[0-9]+.*$/
|
||||
env:
|
||||
global:
|
||||
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
|
||||
# via the "travis encrypt" command using the project repo's public key
|
||||
- secure: 1QK0yVyoOB+gf2I7XzvhXu9w/5lq4stBXIwJbVCTjz4Q4XVHCosURaW1MAgKzMrPnbFEwjyn5uQ8BwsvvfkuN1AZD0YXITgc7gyI+J1wQ/p/ljxRxglakU6WEgsTs2J5z9UmGac4YTXg+quK7YP3rv+zuGim2I2rhzImejyzp0Ym3kRCnNcy+SGBsiRaevRJMe00Ch8zGAbEhduQGeSoS6W0rcu02DNlQKiq5NktWsXR+TWWWVfIeIlQR/lbPsCd0pdxMaMv2QCY0rVbwrYxWJwr/Qe45dAdWp+8/C3PbXpeMSGxlLa33nJNX4Lf/djxbjm8KWk6edaXPajrjR/0iwcpwq0jg2Jt6XfEdnJt35F1gpXlc04sxStjG45uloOKCFYT0wdhIO1Lq+hDP54wypQl+JInd5qC001O7pwhVxO36EgKWqo8HD+BqGDBwsNj2engy9Qcp3wO6G0rLBPB3CrZsk9wrHVv5cSiQSLMhId3Xviu3ZI2qEDA+kgTvxrKrsnMj4bILVCyG5Ka2Mj22wIDW9e8oIab9oTdujax3DTN1GkD6QuOAGzwDsNwGASsgfoeZ+FUhgM75RlBWGMilgkmnF7EJ0oAXLEpjtABnEr2d4qHv+y08kOuTDBLB9ExzCIj024dYYYNLZrqPKx0ncHuCMG2QNj2aJAJEZtj1rQ=
|
||||
|
||||
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg=
|
||||
- macos_qt_formula=qt
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- sourceline: 'ppa:openmw/openmw'
|
||||
- sourceline: 'ppa:rakhimov/boost'
|
||||
- ubuntu-toolchain-r-test
|
||||
- llvm-toolchain-precise-3.6
|
||||
packages: [
|
||||
# Dev
|
||||
cmake, clang-6.0, libunshield-dev, libtinyxml-dev,
|
||||
g++-8,
|
||||
cmake, clang-3.6, libunshield-dev, libtinyxml-dev,
|
||||
g++-6,
|
||||
# Tests
|
||||
libgtest-dev, google-mock,
|
||||
# Boost
|
||||
libboost-filesystem1.61-dev, libboost-program-options1.61-dev, libboost-system1.61-dev,
|
||||
libboost-filesystem-dev, libboost-program-options-dev, libboost-system-dev,
|
||||
# FFmpeg
|
||||
libavcodec-dev, libavformat-dev, libavutil-dev, libswscale-dev,
|
||||
# Audio & Video
|
||||
libsdl2-dev, qtbase5-dev, libopenal-dev,
|
||||
# The other ones from OpenMW ppa
|
||||
libbullet-dev, libswresample-dev, libopenscenegraph-3.4-dev, libmygui-dev,
|
||||
# tes3mp stuff
|
||||
libboost1.61-dev, libqt5opengl5-dev, libluajit-5.1-dev
|
||||
libbullet-dev, libswresample-dev, libopenscenegraph-3.4-dev, libmygui-dev
|
||||
]
|
||||
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "TES3MP/openmw-tes3mp"
|
||||
description: "<Your project description here>"
|
||||
notification_email: koncord@tes3mp.com
|
||||
notification_email: stas5978@gmail.com
|
||||
build_command_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE"
|
||||
build_command: "make -j3"
|
||||
branch_pattern: coverity_scan
|
||||
|
@ -53,21 +50,10 @@ matrix:
|
|||
include:
|
||||
- os: linux
|
||||
env:
|
||||
- ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
|
||||
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
|
||||
compiler: clang
|
||||
- os: linux
|
||||
env:
|
||||
- MATRIX_CC="CC=gcc-8 && CXX=g++-8"
|
||||
- os: linux
|
||||
env:
|
||||
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
allow_failures:
|
||||
- env:
|
||||
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
- env:
|
||||
- ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
|
||||
- MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
|
||||
- env: ANALYZE="scan-build-3.6 --use-cc clang-3.6 --use-c++ clang++-3.6 "
|
||||
|
||||
before_install:
|
||||
- ./CI/before_install.${TRAVIS_OS_NAME}.sh
|
||||
|
|
13
AUTHORS.md
13
AUTHORS.md
|
@ -15,14 +15,12 @@ Programmers
|
|||
Adam Hogan (aurix)
|
||||
Aesylwinn
|
||||
aegis
|
||||
AHSauge
|
||||
Aleksandar Jovanov
|
||||
Alex Haddad (rainChu)
|
||||
Alex McKibben
|
||||
alexanderkjall
|
||||
Alexander Nadeau (wareya)
|
||||
Alexander Olofsson (Ace)
|
||||
Alex S (docwest)
|
||||
Allofich
|
||||
Andrei Kortunov (akortunov)
|
||||
AnyOldName3
|
||||
|
@ -38,15 +36,12 @@ Programmers
|
|||
Britt Mathis (galdor557)
|
||||
Capostrophic
|
||||
cc9cii
|
||||
Cédric Mocquillon
|
||||
Chris Boyce (slothlife)
|
||||
Chris Robinson (KittyCat)
|
||||
Cory F. Cohen (cfcohen)
|
||||
Cris Mihalache (Mirceam)
|
||||
crussell187
|
||||
DanielVukelich
|
||||
darkf
|
||||
David Cernat (davidcernat)
|
||||
devnexen
|
||||
Dieho
|
||||
Dmitry Shkurskiy (endorph)
|
||||
|
@ -64,8 +59,6 @@ Programmers
|
|||
Evgeniy Mineev (sandstranger)
|
||||
Federico Guerra (FedeWar)
|
||||
Fil Krynicki (filkry)
|
||||
Finbar Crago (finbar-crago)
|
||||
Florian Weber (Florianjw)
|
||||
Gašper Sedej
|
||||
gugus/gus
|
||||
Hallfaer Tuilinn
|
||||
|
@ -143,7 +136,6 @@ Programmers
|
|||
Rohit Nirmal
|
||||
Roman Melnik (Kromgart)
|
||||
Roman Proskuryakov (kpp)
|
||||
Roman Siromakha (elsid)
|
||||
Sandy Carter (bwrsandman)
|
||||
Scott Howard
|
||||
scrawl
|
||||
|
@ -163,8 +155,6 @@ Programmers
|
|||
terrorfisch
|
||||
thegriglat
|
||||
Thomas Luppi (Digmaster)
|
||||
tri4ng1e
|
||||
unelsson
|
||||
Will Herrmann (Thunderforge)
|
||||
Tom Mason (wheybags)
|
||||
Torben Leif Carrington (TorbenC)
|
||||
|
@ -176,7 +166,6 @@ Programmers
|
|||
Documentation
|
||||
-------------
|
||||
|
||||
Adam Bowen (adamnbowen)
|
||||
Alejandro Sanchez (HiPhish)
|
||||
Bodillium
|
||||
Bret Curtis (psi29a)
|
||||
|
@ -235,7 +224,7 @@ Artwork
|
|||
|
||||
Necrod - OpenMW Logo
|
||||
Mickey Lyle (raevol) - Wordpress Theme
|
||||
Tom Koenderink (Okulo), SirHerrbatka, crysthala, Shnatsel, Lamoot - OpenMW Editor Icons
|
||||
Tom Koenderink (Okulo), SirHerrbatka, crysthala, Shnatsel - OpenMW Editor Icons
|
||||
|
||||
Inactive Contributors
|
||||
---------------------
|
||||
|
|
212
CHANGELOG.md
212
CHANGELOG.md
|
@ -1,215 +1,3 @@
|
|||
0.45.0
|
||||
------
|
||||
|
||||
Bug #1990: Sunrise/sunset not set correct
|
||||
Bug #2131: Lustidrike's spell misses the player every time
|
||||
Bug #2222: Fatigue's effect on selling price is backwards
|
||||
Bug #2326: After a bound item expires the last equipped item of that type is not automatically re-equipped
|
||||
Bug #2455: Creatures attacks degrade armor
|
||||
Bug #2562: Forcing AI to activate a teleport door sometimes causes a crash
|
||||
Bug #2626: Resurrecting the player does not resume the game
|
||||
Bug #2772: Non-existing class or faction freezes the game
|
||||
Bug #2835: Player able to slowly move when overencumbered
|
||||
Bug #2852: No murder bounty when a player follower commits murder
|
||||
Bug #2862: [macOS] Can't quit launcher using Command-Q or OpenMW->Quit
|
||||
Bug #2872: Tab completion in console doesn't work with explicit reference
|
||||
Bug #2971: Compiler did not reject lines with naked expressions beginning with x.y
|
||||
Bug #3249: Fixed revert function not updating views properly
|
||||
Bug #3374: Touch spells not hitting kwama foragers
|
||||
Bug #3486: [Mod] NPC Commands does not work
|
||||
Bug #3591: Angled hit distance too low
|
||||
Bug #3629: DB assassin attack never triggers creature spawning
|
||||
Bug #3876: Landscape texture painting is misaligned
|
||||
Bug #3897: Have Goodbye give all choices the effects of Goodbye
|
||||
Bug #3911: [macOS] Typing in the "Content List name" dialog box produces double characters
|
||||
Bug #3950: FLATTEN_STATIC_TRANSFORMS optimization breaks animated collision shapes
|
||||
Bug #3993: Terrain texture blending map is not upscaled
|
||||
Bug #3997: Almalexia doesn't pace
|
||||
Bug #4036: Weird behaviour of AI packages if package target has non-unique ID
|
||||
Bug #4047: OpenMW not reporting its version number in MacOS; OpenMW-CS not doing it fully
|
||||
Bug #4110: Fixed undo / redo menu text losing the assigned shortcuts
|
||||
Bug #4125: OpenMW logo cropped on bugtracker
|
||||
Bug #4215: OpenMW shows book text after last EOL tag
|
||||
Bug #4221: Characters get stuck in V-shaped terrain
|
||||
Bug #4230: AiTravel package issues break some Tribunal quests
|
||||
Bug #4251: Stationary NPCs do not return to their position after combat
|
||||
Bug #4274: Pre-0.43 death animations are not forward-compatible with 0.43+
|
||||
Bug #4286: Scripted animations can be interrupted
|
||||
Bug #4291: Non-persistent actors that started the game as dead do not play death animations
|
||||
Bug #4293: Faction members are not aware of faction ownerships in barter
|
||||
Bug #4307: World cleanup should remove dead bodies only if death animation is finished
|
||||
Bug #4311: OpenMW does not handle RootCollisionNode correctly
|
||||
Bug #4327: Missing animations during spell/weapon stance switching
|
||||
Bug #4358: Running animation is interrupted when magic mode is toggled
|
||||
Bug #4368: Settings window ok button doesn't have key focus by default
|
||||
Bug #4378: On-self absorb spells restore stats
|
||||
Bug #4393: NPCs walk back to where they were after using ResetActors
|
||||
Bug #4416: Handle exception if we try to play non-music file
|
||||
Bug #4419: MRK NiStringExtraData is handled incorrectly
|
||||
Bug #4426: RotateWorld behavior is incorrect
|
||||
Bug #4429: [Windows] Error on build INSTALL.vcxproj project (debug) with cmake 3.7.2
|
||||
Bug #4431: "Lock 0" console command is a no-op
|
||||
Bug #4432: Guards behaviour is incorrect if they do not have AI packages
|
||||
Bug #4433: Guard behaviour is incorrect with Alarm = 0
|
||||
Bug #4451: Script fails to compile when using "Begin, [ScriptName]" syntax
|
||||
Bug #4452: Default terrain texture bleeds through texture transitions
|
||||
Bug #4453: Quick keys behaviour is invalid for equipment
|
||||
Bug #4454: AI opens doors too slow
|
||||
Bug #4457: Item without CanCarry flag prevents shield autoequipping in dark areas
|
||||
Bug #4458: AiWander console command handles idle chances incorrectly
|
||||
Bug #4459: NotCell dialogue condition doesn't support partial matches
|
||||
Bug #4460: Script function "Equip" doesn't bypass beast restrictions
|
||||
Bug #4461: "Open" spell from non-player caster isn't a crime
|
||||
Bug #4464: OpenMW keeps AiState cached storages even after we cancel AI packages
|
||||
Bug #4469: Abot Silt Striders – Model turn 90 degrees on horizontal
|
||||
Bug #4474: No fallback when getVampireHead fails
|
||||
Bug #4475: Scripted animations should not cause movement
|
||||
Bug #4479: "Game" category on Advanced page is getting too long
|
||||
Bug #4480: Segfault in QuickKeysMenu when item no longer in inventory
|
||||
Bug #4489: Goodbye doesn't block dialogue hyperlinks
|
||||
Bug #4490: PositionCell on player gives "Error: tried to add local script twice"
|
||||
Bug #4494: Training cap based off Base Skill instead of Modified Skill
|
||||
Bug #4495: Crossbow animations blending is buggy
|
||||
Bug #4496: SpellTurnLeft and SpellTurnRight animation groups are unused
|
||||
Bug #4497: File names starting with x or X are not classified as animation
|
||||
Bug #4503: Cast and ExplodeSpell commands increase alteration skill
|
||||
Bug #4510: Division by zero in MWMechanics::CreatureStats::setAttribute
|
||||
Bug #4519: Knockdown does not discard movement in the 1st-person mode
|
||||
Bug #4539: Paper Doll is affected by GUI scaling
|
||||
Bug #4545: Creatures flee from werewolves
|
||||
Bug #4551: Replace 0 sound range with default range separately
|
||||
Bug #4553: Forcegreeting on non-actor opens a dialogue window which cannot be closed
|
||||
Bug #4557: Topics with reserved names are handled differently from vanilla
|
||||
Bug #4558: Mesh optimizer: check for reserved node name is case-sensitive
|
||||
Bug #4563: Fast travel price logic checks destination cell instead of service actor cell
|
||||
Bug #4565: Underwater view distance should be limited
|
||||
Bug #4573: Player uses headtracking in the 1st-person mode
|
||||
Bug #4574: Player turning animations are twitchy
|
||||
Bug #4575: Weird result of attack animation blending with movement animations
|
||||
Bug #4576: Reset of idle animations when attack can not be started
|
||||
Feature #2606: Editor: Implemented (optional) case sensitive global search
|
||||
Feature #3083: Play animation when NPC is casting spell via script
|
||||
Feature #3103: Provide option for disposition to get increased by successful trade
|
||||
Feature #3276: Editor: Search - Show number of (remaining) search results and indicate a search without any results
|
||||
Feature #3641: Editor: Limit FPS in 3d preview window
|
||||
Feature #3703: Ranged sneak attack criticals
|
||||
Feature #4012: Editor: Write a log file if OpenCS crashes
|
||||
Feature #4222: 360° screenshots
|
||||
Feature #4256: Implement ToggleBorders (TB) console command
|
||||
Feature #4324: Add CFBundleIdentifier in Info.plist to allow for macOS function key shortcuts
|
||||
Feature #4345: Add equivalents for the command line commands to Launcher
|
||||
Feature #4404: Editor: All EnumDelegate fields should have their items sorted alphabetically
|
||||
Feature #4444: Per-group KF-animation files support
|
||||
Feature #4466: Editor: Add option to ignore "Base" records when running verifier
|
||||
Feature #4488: Make water shader rougher during rain
|
||||
Feature #4509: Show count of enchanted items in stack in the spells list
|
||||
Feature #4512: Editor: Use markers for lights and creatures levelled lists
|
||||
Feature #4548: Weapon priority: use the actual chance to hit the target instead of weapon skill
|
||||
Feature #4549: Weapon priority: use the actual damage in weapon rating calculations
|
||||
Feature #4550: Weapon priority: make ranged weapon bonus more sensible
|
||||
Task #2490: Don't open command prompt window on Release-mode builds automatically
|
||||
Task #4545: Enable is_pod string test
|
||||
|
||||
0.44.0
|
||||
------
|
||||
|
||||
Bug #1428: Daedra summoning scripts aren't executed when the item is taken through the inventory
|
||||
Bug #1987: Some glyphs are not supported
|
||||
Bug #2254: Magic related visual effects are not rendered when loading a saved game
|
||||
Bug #2485: Journal alphabetical index doesn't match "Morrowind content language" setting
|
||||
Bug #2703: OnPCHitMe is not handled correctly
|
||||
Bug #2829: Incorrect order for content list consisting of a game file and an esp without dependencies
|
||||
Bug #2841: "Total eclipse" happens if weather settings are not defined.
|
||||
Bug #2897: Editor: Rename "Original creature" field
|
||||
Bug #3278: Editor: Unchecking "Auto Calc" flag changes certain values
|
||||
Bug #3343: Editor: ID sorting is case-sensitive in certain tables
|
||||
Bug #3557: Resource priority confusion when using the local data path as installation root
|
||||
Bug #3587: Pathgrid and Flying Creatures wrong behaviour – abotWhereAreAllBirdsGoing
|
||||
Bug #3603: SetPos should not skip weather transitions
|
||||
Bug #3618: Myar Aranath total conversion can't be started due to capital-case extension of the master file
|
||||
Bug #3638: Fast forwarding can move NPC inside objects
|
||||
Bug #3664: Combat music does not start in dialogue
|
||||
Bug #3696: Newlines are accompanied by empty rectangle glyph in dialogs
|
||||
Bug #3708: Controllers broken on macOS
|
||||
Bug #3726: Items with suppressed activation can be picked up via the inventory menu
|
||||
Bug #3783: [Mod] Abot's Silt Striders 1.16 - silt strider "falls" to ground and glides on floor during travel
|
||||
Bug #3863: Can be forced to not resist arrest if you cast Calm Humanoid on aggroed death warrant guards
|
||||
Bug #3884: Incorrect enemy behavior when exhausted
|
||||
Bug #3926: Installation Wizard places Morrowind.esm after Tribunal/Bloodmoon if it has a later file creation date
|
||||
Bug #4061: Scripts error on special token included in name
|
||||
Bug #4111: Crash when mouse over soulgem with a now-missing soul
|
||||
Bug #4122: Swim animation should not be interrupted during underwater attack
|
||||
Bug #4134: Battle music behaves different than vanilla
|
||||
Bug #4135: Reflecting an absorb spell different from vanilla
|
||||
Bug #4136: Enchanted weapons without "ignore normal weapons" flag don't bypass creature "ignore normal weapons" effect
|
||||
Bug #4143: Antialiasing produces graphical artifacts when used with shader lighting
|
||||
Bug #4159: NPCs' base skeleton files should not be optimized
|
||||
Bug #4177: Jumping/landing animation interference/flickering
|
||||
Bug #4179: NPCs do not face target
|
||||
Bug #4180: Weapon switch sound playing even though no weapon is switched
|
||||
Bug #4184: Guards can initiate dialogue even though you are far above them
|
||||
Bug #4190: Enchanted clothes changes visibility with Chameleon on equip/unequip
|
||||
Bug #4191: "screenshot saved" message also appears in the screenshot image
|
||||
Bug #4192: Archers in OpenMW have shorter attack range than archers in Morrowind
|
||||
Bug #4210: Some dialogue topics are not highlighted on first encounter
|
||||
Bug #4211: FPS drops after minimizing the game during rainy weather
|
||||
Bug #4216: Thrown weapon projectile doesn't rotate
|
||||
Bug #4223: Displayed spell casting chance must be 0 if player doesn't have enough magicka to cast it
|
||||
Bug #4225: Double "Activate" key presses with Mouse and Gamepad.
|
||||
Bug #4226: The current player's class should be default value in the class select menu
|
||||
Bug #4229: Tribunal/Bloodmoon summoned creatures fight other summons
|
||||
Bug #4233: W and A keys override S and D Keys
|
||||
Bug #4235: Wireframe mode affects local map
|
||||
Bug #4239: Quick load from container screen causes crash
|
||||
Bug #4242: Crime greetings display in Journal
|
||||
Bug #4245: Merchant NPCs sell ingredients growing on potted plants they own
|
||||
Bug #4246: Take armor condition into account when calcuting armor rating
|
||||
Bug #4250: Jumping is not as fluid as it was pre-0.43.0
|
||||
Bug #4252: "Error in frame: FFmpeg exception: Failed to allocate input stream" message spam if OpenMW encounter non-music file in the Music folder
|
||||
Bug #4261: Magic effects from eaten ingredients always have 1 sec duration
|
||||
Bug #4263: Arrow position is incorrect in 3rd person view during attack for beast races
|
||||
Bug #4264: Player in god mode can be affected by some negative spell effects
|
||||
Bug #4269: Crash when hovering the faction section and the 'sAnd' GMST is missing (as in MW 1.0)
|
||||
Bug #4272: Root note transformations are discarded again
|
||||
Bug #4279: Sometimes cells are not marked as explored on the map
|
||||
Bug #4298: Problem with MessageBox and chargen menu interaction order
|
||||
Bug #4301: Optimizer breaks LOD nodes
|
||||
Bug #4308: PlaceAtMe doesn't inherit scale of calling object
|
||||
Bug #4309: Only harmful effects with resistance effect set are resistable
|
||||
Bug #4313: Non-humanoid creatures are capable of opening doors
|
||||
Bug #4314: Rainy weather slows down the game when changing from indoors/outdoors
|
||||
Bug #4319: Collisions for certain meshes are incorrectly ignored
|
||||
Bug #4320: Using mouse 1 to move forward causes selection dialogues to jump selections forward.
|
||||
Bug #4322: NPC disposition: negative faction reaction modifier doesn't take PC rank into account
|
||||
Bug #4328: Ownership by dead actors is not cleared from picked items
|
||||
Bug #4334: Torch and shield usage inconsistent with original game
|
||||
Bug #4336: Wizard: Incorrect Morrowind assets path autodetection
|
||||
Bug #4343: Error message for coc and starting cell shouldn't imply that it only works for interior cells
|
||||
Bug #4346: Count formatting does not work well with very high numbers
|
||||
Bug #4351: Using AddSoulgem fills all soul gems of the specified type
|
||||
Bug #4391: No visual indication is provided when an unavailable spell fails to be chosen via a quick key
|
||||
Bug #4392: Inventory filter breaks after loading a game
|
||||
Bug #4405: No default terrain in empty cells when distant terrain is enabled
|
||||
Bug #4410: [Mod] Arktwend: OpenMW does not use default marker definitions
|
||||
Bug #4412: openmw-iniimporter ignores data paths from config
|
||||
Bug #4413: Moving with 0 strength uses all of your fatigue
|
||||
Bug #4420: Camera flickering when I open up and close menus while sneaking
|
||||
Bug #4424: [macOS] Cursor is either empty or garbage when compiled against macOS 10.13 SDK
|
||||
Bug #4435: Item health is considered a signed integer
|
||||
Bug #4441: Adding items to currently disabled weapon-wielding creatures crashes the game
|
||||
Feature #1786: Round up encumbrance value in the encumbrance bar
|
||||
Feature #2694: Editor: rename "model" column to make its purpose clear
|
||||
Feature #3870: Editor: Terrain Texture Brush Button
|
||||
Feature #3872: Editor: Edit functions in terrain texture editing mode
|
||||
Feature #4054: Launcher: Create menu for settings.cfg options
|
||||
Feature #4064: Option for fast travel services to charge for the first companion
|
||||
Feature #4142: Implement fWereWolfHealth GMST
|
||||
Feature #4174: Multiple quicksaves
|
||||
Feature #4407: Support NiLookAtController
|
||||
Feature #4423: Rebalance soul gem values
|
||||
Task #4015: Use AppVeyor build artifact features to make continuous builds available
|
||||
Editor: New (and more complete) icon set
|
||||
|
||||
0.43.0
|
||||
------
|
||||
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
#!/bin/sh
|
||||
echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca-
|
||||
|
||||
# Set up compilers
|
||||
if [ ! -z "${MATRIX_CC}" ]; then
|
||||
eval "${MATRIX_CC}"
|
||||
fi
|
||||
sudo ln -s /usr/bin/clang-3.6 /usr/local/bin/clang
|
||||
sudo ln -s /usr/bin/clang++-3.6 /usr/local/bin/clang++
|
||||
|
||||
# build libgtest & libgtest_main
|
||||
sudo mkdir /usr/src/gtest/build
|
||||
|
@ -15,8 +12,13 @@ sudo ln -s /usr/src/gtest/build/libgtest.so /usr/lib/libgtest.so
|
|||
sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
|
||||
|
||||
cd ~/
|
||||
git clone https://github.com/TES3MP/CrabNet
|
||||
cd CrabNet
|
||||
cmake . -DCRABNET_ENABLE_DLL=OFF -DCRABNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
|
||||
make -j3
|
||||
git clone https://github.com/TES3MP/RakNet
|
||||
cd RakNet
|
||||
cmake . -DRAKNET_ENABLE_DLL=OFF -DRAKNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
|
||||
mkdir ./lib
|
||||
make -j3 install
|
||||
cp ./Lib/RakNetLibStatic/libRakNetLibStatic.a ./lib
|
||||
cd ..
|
||||
|
||||
wget https://github.com/zdevito/terra/releases/download/release-2016-03-25/terra-Linux-x86_64-332a506.zip
|
||||
unzip terra-Linux-x86_64-332a506.zip
|
||||
|
|
|
@ -4,7 +4,7 @@ brew update
|
|||
|
||||
brew outdated cmake || brew upgrade cmake
|
||||
brew outdated pkgconfig || brew upgrade pkgconfig
|
||||
brew install qt
|
||||
brew install $macos_qt_formula
|
||||
|
||||
curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-100d2e0.zip -o ~/openmw-deps.zip
|
||||
unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||
curl https://downloads.openmw.org/osx/dependencies/openmw-deps-c40905f.zip -o ~/openmw-deps.zip
|
||||
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null
|
||||
|
|
|
@ -3,37 +3,15 @@
|
|||
free -m
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# Set up compilers
|
||||
if [ ! -z "${MATRIX_CC}" ]; then
|
||||
eval "${MATRIX_CC}"
|
||||
export CODE_COVERAGE=1
|
||||
export RAKNET_ROOT=~/RakNet
|
||||
export Terra_ROOT=~/terra-Linux-x86_64-332a506
|
||||
export BUILD_SERVER=OFF
|
||||
if [ "${CC}" = "clang" ]; then export CODE_COVERAGE=0;
|
||||
else
|
||||
export COMPILER_NAME=gcc
|
||||
export CXX=g++-6
|
||||
export CC=gcc-6
|
||||
export BUILD_SERVER=ON
|
||||
fi
|
||||
|
||||
export RAKNET_ROOT=~/CrabNet
|
||||
|
||||
export CODE_COVERAGE=0
|
||||
if [ ! -z "${ANALYZE}" ]; then
|
||||
CODE_COVERAGE=1
|
||||
fi
|
||||
|
||||
${ANALYZE}cmake .. \
|
||||
-DDESIRED_QT_VERSION=5 \
|
||||
-DBUILD_OPENMW_MP=ON \
|
||||
-DBUILD_BROWSER=ON \
|
||||
-DBUILD_MASTER=ON \
|
||||
-DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} \
|
||||
-DBUILD_BSATOOL=OFF \
|
||||
-DBUILD_ESMTOOL=OFF \
|
||||
-DBUILD_ESSIMPORTER=OFF \
|
||||
-DBUILD_LAUNCHER=OFF \
|
||||
-DBUILD_MWINIIMPORTER=OFF \
|
||||
-DBUILD_MYGUI_PLUGIN=OFF \
|
||||
-DBUILD_OPENCS=OFF \
|
||||
-DBUILD_WIZARD=OFF \
|
||||
-DBUILD_UNITTESTS=1 \
|
||||
-DCMAKE_INSTALL_PREFIX=/usr \
|
||||
-DBINDIR=/usr/games \
|
||||
-DCMAKE_BUILD_TYPE="None" \
|
||||
-DUSE_SYSTEM_TINYXML=TRUE \
|
||||
-DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a \
|
||||
-DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a
|
||||
${ANALYZE}cmake .. -DBUILD_OPENMW_MP=${BUILD_SERVER} -DBUILD_WITH_CODE_COVERAGE=${CODE_COVERAGE} -DBUILD_BSATOOL=OFF -DBUILD_ESMTOOL=OFF -DBUILD_ESSIMPORTER=OFF -DBUILD_LAUNCHER=OFF -DBUILD_MWINIIMPORTER=OFF -DBUILD_MYGUI_PLUGIN=OFF -DBUILD_OPENCS=OFF -DBUILD_WIZARD=OFF -DBUILD_BROWSER=OFF -DBUILD_UNITTESTS=1 -DCMAKE_INSTALL_PREFIX=/usr -DBINDIR=/usr/games -DCMAKE_BUILD_TYPE="None" -DUSE_SYSTEM_TINYXML=TRUE -DRakNet_LIBRARY_RELEASE=~/RakNet/lib/libRakNetLibStatic.a -DRakNet_LIBRARY_DEBUG=~/RakNet/lib/libRakNetLibStatic.a
|
||||
|
|
|
@ -1,22 +1,4 @@
|
|||
#!/bin/bash
|
||||
# set -x # turn-on for debugging
|
||||
|
||||
MISSINGTOOLS=0
|
||||
|
||||
command -v 7z >/dev/null 2>&1 || { echo "Error: 7z (7zip) is not on the path."; MISSINGTOOLS=1; }
|
||||
command -v cmake >/dev/null 2>&1 || { echo "Error: cmake (CMake) is not on the path."; MISSINGTOOLS=1; }
|
||||
|
||||
if [ $MISSINGTOOLS -ne 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
WORKINGDIR="$(pwd)"
|
||||
case "$WORKINGDIR" in
|
||||
*[[:space:]]*)
|
||||
echo "Error: Working directory contains spaces."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
|
@ -77,6 +59,7 @@ while [ $# -gt 0 ]; do
|
|||
h )
|
||||
cat <<EOF
|
||||
Usage: $0 [-cdehkpuvV]
|
||||
|
||||
Options:
|
||||
-c <Release/Debug>
|
||||
Set the configuration, can also be set with environment variable CONFIGURATION.
|
||||
|
@ -232,9 +215,8 @@ fi
|
|||
case $VS_VERSION in
|
||||
15|15.0|2017 )
|
||||
GENERATOR="Visual Studio 15 2017"
|
||||
TOOLSET="vc141"
|
||||
MSVC_REAL_VER="15"
|
||||
MSVC_VER="14.1"
|
||||
TOOLSET="vc140"
|
||||
MSVC_VER="14"
|
||||
MSVC_YEAR="2015"
|
||||
MSVC_DISPLAY_YEAR="2017"
|
||||
;;
|
||||
|
@ -242,8 +224,7 @@ case $VS_VERSION in
|
|||
14|14.0|2015 )
|
||||
GENERATOR="Visual Studio 14 2015"
|
||||
TOOLSET="vc140"
|
||||
MSVC_REAL_VER="14"
|
||||
MSVC_VER="14.0"
|
||||
MSVC_VER="14"
|
||||
MSVC_YEAR="2015"
|
||||
MSVC_DISPLAY_YEAR="2015"
|
||||
;;
|
||||
|
@ -251,8 +232,7 @@ case $VS_VERSION in
|
|||
12|12.0|2013 )
|
||||
GENERATOR="Visual Studio 12 2013"
|
||||
TOOLSET="vc120"
|
||||
MSVC_REAL_VER="12"
|
||||
MSVC_VER="12.0"
|
||||
MSVC_VER="12"
|
||||
MSVC_YEAR="2013"
|
||||
MSVC_DISPLAY_YEAR="2013"
|
||||
;;
|
||||
|
@ -322,26 +302,26 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
|||
|
||||
# Boost
|
||||
if [ -z $APPVEYOR ]; then
|
||||
download "Boost 1.67.0" \
|
||||
"https://sourceforge.net/projects/boost/files/boost-binaries/1.67.0/boost_1_67_0-msvc-${MSVC_VER}-${BITS}.exe" \
|
||||
"boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe"
|
||||
download "Boost 1.61.0" \
|
||||
"http://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \
|
||||
"boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe"
|
||||
fi
|
||||
|
||||
# Bullet
|
||||
download "Bullet 2.86" \
|
||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"http://www.lysator.liu.se/~ace/OpenMW/deps/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z"
|
||||
|
||||
# FFmpeg
|
||||
download "FFmpeg 3.2.4" \
|
||||
"https://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \
|
||||
"http://ffmpeg.zeranoe.com/builds/win${BITS}/shared/ffmpeg-3.2.4-win${BITS}-shared.zip" \
|
||||
"ffmpeg-3.2.4-win${BITS}.zip" \
|
||||
"https://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \
|
||||
"http://ffmpeg.zeranoe.com/builds/win${BITS}/dev/ffmpeg-3.2.4-win${BITS}-dev.zip" \
|
||||
"ffmpeg-3.2.4-dev-win${BITS}.zip"
|
||||
|
||||
# MyGUI
|
||||
download "MyGUI 3.2.2" \
|
||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"http://www.lysator.liu.se/~ace/OpenMW/deps/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z"
|
||||
|
||||
# OpenAL
|
||||
|
@ -351,7 +331,7 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
|||
|
||||
# OSG
|
||||
download "OpenSceneGraph 3.4.1-scrawl" \
|
||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"http://www.lysator.liu.se/~ace/OpenMW/deps/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" \
|
||||
"OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z"
|
||||
|
||||
# Qt
|
||||
|
@ -362,10 +342,10 @@ if [ -z $SKIP_DOWNLOAD ]; then
|
|||
QT_SUFFIX=""
|
||||
fi
|
||||
|
||||
download "Qt 5.7.0" \
|
||||
"https://download.qt.io/archive/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
|
||||
download "Qt 5.7.2" \
|
||||
"http://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \
|
||||
"qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
|
||||
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
||||
"http://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
|
||||
"qt-5-install.qs"
|
||||
fi
|
||||
|
||||
|
@ -400,12 +380,12 @@ echo
|
|||
|
||||
# Boost
|
||||
if [ -z $APPVEYOR ]; then
|
||||
printf "Boost 1.67.0... "
|
||||
printf "Boost 1.61.0... "
|
||||
else
|
||||
if [ $MSVC_VER -eq 12.0 ]; then
|
||||
if [ $MSVC_VER -eq 12 ]; then
|
||||
printf "Boost 1.58.0 AppVeyor... "
|
||||
else
|
||||
printf "Boost 1.67.0 AppVeyor... "
|
||||
printf "Boost 1.60.0 AppVeyor... "
|
||||
fi
|
||||
fi
|
||||
{
|
||||
|
@ -414,44 +394,27 @@ fi
|
|||
|
||||
BOOST_SDK="$(real_pwd)/Boost"
|
||||
|
||||
# Boost's installer is still based on ms-dos API that doesn't support larger than 260 char path names
|
||||
# We work around this by installing to root of the current working drive and then move it to our deps
|
||||
# get the current working drive's root, we'll install to that temporarily
|
||||
CWD_DRIVE_ROOT="$(powershell -command '(get-location).Drive.Root')Boost_temp"
|
||||
CWD_DRIVE_ROOT_BASH=$(echo "$CWD_DRIVE_ROOT" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
|
||||
if [ -d CWD_DRIVE_ROOT_BASH ]; then
|
||||
printf "Cannot continue, ${CWD_DRIVE_ROOT_BASH} aka ${CWD_DRIVE_ROOT} already exists. Please remove before re-running. ";
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
if [ -d ${BOOST_SDK} ] && grep "BOOST_VERSION 106700" Boost/boost/version.hpp > /dev/null; then
|
||||
if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf Boost
|
||||
CI_EXTRA_INNO_OPTIONS=""
|
||||
[ -n "$CI" ] && CI_EXTRA_INNO_OPTIONS="//SUPPRESSMSGBOXES //LOG='boost_install.log'"
|
||||
"${DEPS}/boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe" //DIR="${CWD_DRIVE_ROOT}" //VERYSILENT //NORESTART ${CI_EXTRA_INNO_OPTIONS}
|
||||
mv "${CWD_DRIVE_ROOT_BASH}" "${BOOST_SDK}"
|
||||
fi
|
||||
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \
|
||||
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}"
|
||||
add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
|
||||
echo Done.
|
||||
else
|
||||
# Appveyor unstable has all the boost we need already
|
||||
if [ $MSVC_REAL_VER -eq 12 ]; then
|
||||
BOOST_SDK="c:/Libraries/boost_1_58_0"
|
||||
else
|
||||
BOOST_SDK="c:/Libraries/boost_1_67_0"
|
||||
fi
|
||||
if [ $MSVC_REAL_VER -eq 15 ]; then
|
||||
LIB_SUFFIX="1"
|
||||
else
|
||||
LIB_SUFFIX="0"
|
||||
"${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent
|
||||
fi
|
||||
|
||||
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \
|
||||
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.${LIB_SUFFIX}"
|
||||
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.0"
|
||||
add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
|
||||
|
||||
echo Done.
|
||||
else
|
||||
# Appveyor unstable has all the boost we need already
|
||||
if [ $MSVC_VER -eq 12 ]; then
|
||||
BOOST_SDK="c:/Libraries/boost_1_58_0"
|
||||
else
|
||||
BOOST_SDK="c:/Libraries/boost_1_60_0"
|
||||
fi
|
||||
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \
|
||||
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.0"
|
||||
add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
|
||||
|
||||
echo Done.
|
||||
|
@ -459,10 +422,12 @@ fi
|
|||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# Bullet
|
||||
printf "Bullet 2.86... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
if [ -d Bullet ]; then
|
||||
printf -- "Exists. (No version checking) "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
|
@ -470,38 +435,49 @@ printf "Bullet 2.86... "
|
|||
eval 7z x -y "${DEPS}/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
||||
mv "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}" Bullet
|
||||
fi
|
||||
|
||||
export BULLET_ROOT="$(real_pwd)/Bullet"
|
||||
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# FFmpeg
|
||||
printf "FFmpeg 3.2.4... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf FFmpeg
|
||||
|
||||
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-win${BITS}.zip" $STRIP
|
||||
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-dev-win${BITS}.zip" $STRIP
|
||||
|
||||
mv "ffmpeg-3.2.4-win${BITS}-shared" FFmpeg
|
||||
cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/
|
||||
rm -rf "ffmpeg-3.2.4-win${BITS}-dev"
|
||||
fi
|
||||
|
||||
export FFMPEG_HOME="$(real_pwd)/FFmpeg"
|
||||
add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll
|
||||
|
||||
if [ $BITS -eq 32 ]; then
|
||||
add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\""
|
||||
fi
|
||||
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# MyGUI
|
||||
printf "MyGUI 3.2.2... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
if [ -d MyGUI ] && \
|
||||
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||
grep "MYGUI_VERSION_MINOR 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
|
||||
|
@ -513,17 +489,21 @@ printf "MyGUI 3.2.2... "
|
|||
eval 7z x -y "${DEPS}/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
||||
mv "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}" MyGUI
|
||||
fi
|
||||
|
||||
export MYGUI_HOME="$(real_pwd)/MyGUI"
|
||||
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
SUFFIX="_d"
|
||||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll"
|
||||
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# OpenAL
|
||||
printf "OpenAL-Soft 1.17.2... "
|
||||
{
|
||||
|
@ -533,18 +513,24 @@ printf "OpenAL-Soft 1.17.2... "
|
|||
rm -rf openal-soft-1.17.2-bin
|
||||
eval 7z x -y OpenAL-Soft-1.17.2.zip $STRIP
|
||||
fi
|
||||
|
||||
OPENAL_SDK="$(real_pwd)/openal-soft-1.17.2-bin"
|
||||
|
||||
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
|
||||
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib"
|
||||
|
||||
add_runtime_dlls "$(pwd)/openal-soft-1.17.2-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
|
||||
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# OSG
|
||||
printf "OSG 3.4.1-scrawl... "
|
||||
{
|
||||
cd $DEPS_INSTALL
|
||||
|
||||
if [ -d OSG ] && \
|
||||
grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \
|
||||
grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \
|
||||
|
@ -556,26 +542,33 @@ printf "OSG 3.4.1-scrawl... "
|
|||
eval 7z x -y "${DEPS}/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP
|
||||
mv "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}" OSG
|
||||
fi
|
||||
|
||||
OSG_SDK="$(real_pwd)/OSG"
|
||||
|
||||
add_cmake_opts -DOSG_DIR="$OSG_SDK"
|
||||
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
SUFFIX="d"
|
||||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
|
||||
add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng*}${SUFFIX}.dll \
|
||||
"$(pwd)/OSG/bin/osg"{,Animation,DB,FX,GA,Particle,Text,Util,Viewer}${SUFFIX}.dll
|
||||
|
||||
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_"{bmp,dds,jpeg,osg,png,tga}${SUFFIX}.dll
|
||||
add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer}${SUFFIX}.dll
|
||||
|
||||
echo Done.
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# Qt
|
||||
if [ -z $APPVEYOR ]; then
|
||||
printf "Qt 5.7.0... "
|
||||
else
|
||||
printf "Qt 5.10 AppVeyor... "
|
||||
printf "Qt 5.7 AppVeyor... "
|
||||
fi
|
||||
{
|
||||
if [ $BITS -eq 64 ]; then
|
||||
|
@ -583,53 +576,61 @@ fi
|
|||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
|
||||
if [ -z $APPVEYOR ]; then
|
||||
cd $DEPS_INSTALL
|
||||
QT_SDK="$(real_pwd)/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}"
|
||||
|
||||
if [ -d Qt ] && head -n2 Qt/InstallationLog.txt | grep "5.7.0" > /dev/null; then
|
||||
printf "Exists. "
|
||||
elif [ -z $SKIP_EXTRACT ]; then
|
||||
rm -rf Qt
|
||||
cp "${DEPS}/qt-5-install.qs" qt-install.qs
|
||||
|
||||
|
||||
sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" qt-install.qs
|
||||
sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs
|
||||
|
||||
printf -- "(Installation might take a while) "
|
||||
"${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent
|
||||
|
||||
mv qt-install.qs Qt/
|
||||
|
||||
echo Done.
|
||||
printf " Cleaning up extraneous data... "
|
||||
rm -r "$(real_pwd)/Qt/"{dist,Docs,Examples,Tools,vcredist,components.xml,MaintenanceTool.dat,MaintenanceTool.exe,MaintenanceTool.ini,network.xml,qt-install.qs}
|
||||
fi
|
||||
|
||||
cd $QT_SDK
|
||||
|
||||
add_cmake_opts -DDESIRED_QT_VERSION=5 \
|
||||
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||
-DCMAKE_PREFIX_PATH="$QT_SDK"
|
||||
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
SUFFIX="d"
|
||||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
|
||||
|
||||
add_runtime_dlls "$(pwd)/bin/lib"{EGL,GLESv2}${SUFFIX}.dll \
|
||||
"$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
|
||||
add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll"
|
||||
|
||||
echo Done.
|
||||
else
|
||||
QT_SDK="C:/Qt/5.10/msvc${MSVC_DISPLAY_YEAR}${SUFFIX}"
|
||||
QT_SDK="C:/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}"
|
||||
|
||||
add_cmake_opts -DDESIRED_QT_VERSION=5 \
|
||||
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
|
||||
-DCMAKE_PREFIX_PATH="$QT_SDK"
|
||||
if [ $CONFIGURATION == "Debug" ]; then
|
||||
SUFFIX="d"
|
||||
else
|
||||
SUFFIX=""
|
||||
fi
|
||||
DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
|
||||
add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
|
||||
add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll"
|
||||
|
||||
echo Done.
|
||||
fi
|
||||
}
|
||||
cd $DEPS
|
||||
echo
|
||||
|
||||
# SDL2
|
||||
printf "SDL 2.0.7... "
|
||||
{
|
||||
|
@ -639,18 +640,26 @@ printf "SDL 2.0.7... "
|
|||
rm -rf SDL2-2.0.7
|
||||
eval 7z x -y SDL2-2.0.7.zip $STRIP
|
||||
fi
|
||||
|
||||
export SDL2DIR="$(real_pwd)/SDL2-2.0.7"
|
||||
|
||||
add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll"
|
||||
|
||||
echo Done.
|
||||
}
|
||||
echo
|
||||
|
||||
|
||||
cd $DEPS_INSTALL/..
|
||||
|
||||
echo
|
||||
echo "Setting up OpenMW build..."
|
||||
|
||||
add_cmake_opts -DBUILD_BSATOOL=no \
|
||||
-DBUILD_ESMTOOL=no \
|
||||
-DBUILD_MYGUI_PLUGIN=no \
|
||||
-DOPENMW_MP_BUILD=on
|
||||
|
||||
if [ ! -z $CI ]; then
|
||||
case $STEP in
|
||||
components )
|
||||
|
@ -662,6 +671,7 @@ if [ ! -z $CI ]; then
|
|||
-DBUILD_OPENMW=no \
|
||||
-DBUILD_WIZARD=no
|
||||
;;
|
||||
|
||||
openmw )
|
||||
echo " Building subproject: OpenMW."
|
||||
add_cmake_opts -DBUILD_ESSIMPORTER=no \
|
||||
|
@ -670,6 +680,7 @@ if [ ! -z $CI ]; then
|
|||
-DBUILD_OPENCS=no \
|
||||
-DBUILD_WIZARD=no
|
||||
;;
|
||||
|
||||
opencs )
|
||||
echo " Building subproject: OpenCS."
|
||||
add_cmake_opts -DBUILD_ESSIMPORTER=no \
|
||||
|
@ -678,6 +689,7 @@ if [ ! -z $CI ]; then
|
|||
-DBUILD_OPENMW=no \
|
||||
-DBUILD_WIZARD=no
|
||||
;;
|
||||
|
||||
misc )
|
||||
echo " Building subprojects: Misc."
|
||||
add_cmake_opts -DBUILD_OPENCS=no \
|
||||
|
@ -685,21 +697,25 @@ if [ ! -z $CI ]; then
|
|||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# NOTE: Disable this when/if we want to run test cases
|
||||
#if [ -z $CI ]; then
|
||||
if [ -z $CI ]; then
|
||||
echo "- Copying Runtime DLLs..."
|
||||
mkdir -p $BUILD_CONFIG
|
||||
for DLL in $RUNTIME_DLLS; do
|
||||
TARGET="$(basename "$DLL")"
|
||||
if [[ "$DLL" == *":"* ]]; then
|
||||
IFS=':'; SPLIT=( ${DLL} ); unset IFS
|
||||
|
||||
DLL=${SPLIT[0]}
|
||||
TARGET=${SPLIT[1]}
|
||||
fi
|
||||
|
||||
echo " ${TARGET}."
|
||||
cp "$DLL" "$BUILD_CONFIG/$TARGET"
|
||||
done
|
||||
echo
|
||||
|
||||
echo "- OSG Plugin DLLs..."
|
||||
mkdir -p $BUILD_CONFIG/osgPlugins-3.4.1
|
||||
for DLL in $OSG_PLUGINS; do
|
||||
|
@ -707,6 +723,7 @@ fi
|
|||
cp "$DLL" $BUILD_CONFIG/osgPlugins-3.4.1
|
||||
done
|
||||
echo
|
||||
|
||||
echo "- Qt Platform DLLs..."
|
||||
mkdir -p ${BUILD_CONFIG}/platforms
|
||||
for DLL in $QT_PLATFORMS; do
|
||||
|
@ -714,14 +731,17 @@ fi
|
|||
cp "$DLL" "${BUILD_CONFIG}/platforms"
|
||||
done
|
||||
echo
|
||||
#fi
|
||||
fi
|
||||
|
||||
if [ -z $VERBOSE ]; then
|
||||
printf -- "- Configuring... "
|
||||
else
|
||||
echo "- cmake .. $CMAKE_OPTS"
|
||||
fi
|
||||
|
||||
run_cmd cmake .. $CMAKE_OPTS
|
||||
RET=$?
|
||||
|
||||
if [ -z $VERBOSE ]; then
|
||||
if [ $RET -eq 0 ]; then
|
||||
echo Done.
|
||||
|
@ -729,4 +749,5 @@ if [ -z $VERBOSE ]; then
|
|||
echo Failed.
|
||||
fi
|
||||
fi
|
||||
|
||||
exit $RET
|
||||
|
|
|
@ -4,14 +4,14 @@ export CXX=clang++
|
|||
export CC=clang
|
||||
|
||||
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
|
||||
QT_PATH=`brew --prefix qt`
|
||||
QT_PATH=`brew --prefix $macos_qt_formula`
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
cmake \
|
||||
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
|
||||
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \
|
||||
-D CMAKE_OSX_SYSROOT="macosx10.13" \
|
||||
-D CMAKE_OSX_SYSROOT="macosx10.12" \
|
||||
-D CMAKE_BUILD_TYPE=Release \
|
||||
-D OPENMW_OSX_DEPLOYMENT=TRUE \
|
||||
-D DESIRED_QT_VERSION=5 \
|
||||
|
|
|
@ -6,6 +6,4 @@ DATE=`date +'%d%m%Y'`
|
|||
SHORT_COMMIT=`git rev-parse --short ${TRAVIS_COMMIT}`
|
||||
TARGET_FILENAME="OpenMW-${DATE}-${SHORT_COMMIT}.dmg"
|
||||
|
||||
if ! curl --ssl -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}" --silent | grep $SHORT_COMMIT > /dev/null; then
|
||||
curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}${TARGET_FILENAME}"
|
||||
fi
|
||||
curl --ssl --ftp-create-dirs -T *.dmg -u $OSX_FTP_USER:$OSX_FTP_PASSWORD "${OSX_FTP_URL}${TARGET_FILENAME}"
|
||||
|
|
|
@ -57,7 +57,7 @@ endif()
|
|||
message(STATUS "Configuring OpenMW...")
|
||||
|
||||
set(OPENMW_VERSION_MAJOR 0)
|
||||
set(OPENMW_VERSION_MINOR 44)
|
||||
set(OPENMW_VERSION_MINOR 43)
|
||||
set(OPENMW_VERSION_RELEASE 0)
|
||||
|
||||
set(OPENMW_VERSION_COMMITHASH "")
|
||||
|
@ -141,8 +141,6 @@ find_package(RakNet REQUIRED)
|
|||
include_directories(${RakNet_INCLUDES})
|
||||
|
||||
# Dependencies
|
||||
find_package(OpenGL REQUIRED)
|
||||
|
||||
if (USE_QT)
|
||||
message(STATUS "Using Qt${DESIRED_QT_VERSION}")
|
||||
|
||||
|
@ -192,6 +190,12 @@ if (NOT WIN32 AND BUILD_WIZARD) # windows users can just run the morrowind insta
|
|||
set(OPENMW_USE_UNSHIELD TRUE)
|
||||
endif()
|
||||
|
||||
option(OPENGL_ES "enable opengl es support" FALSE )
|
||||
|
||||
if (OPENGL_ES)
|
||||
add_definitions(-DOPENGL_ES)
|
||||
endif(OPENGL_ES)
|
||||
|
||||
# Fix for not visible pthreads functions for linker with glibc 2.15
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package (Threads)
|
||||
|
@ -250,8 +254,7 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
|
|||
find_package(SDL2 REQUIRED)
|
||||
find_package(OpenAL REQUIRED)
|
||||
find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath)
|
||||
ELSE()
|
||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}) # HACK: DO NOT MOVE THIS. Used for server only build, kept here to avoid merge conflicts above.
|
||||
|
||||
ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
||||
|
||||
|
||||
|
@ -344,12 +347,6 @@ copy_resource_file(${OpenMW_SOURCE_DIR}/files/opencs/defaultfilters
|
|||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb.txt
|
||||
"${OpenMW_BINARY_DIR}" "gamecontrollerdb.txt")
|
||||
|
||||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb_204.txt
|
||||
"${OpenMW_BINARY_DIR}" "gamecontrollerdb_204.txt")
|
||||
|
||||
configure_resource_file(${OpenMW_SOURCE_DIR}/files/gamecontrollerdb_205.txt
|
||||
"${OpenMW_BINARY_DIR}" "gamecontrollerdb_205.txt")
|
||||
|
||||
if (NOT WIN32 AND NOT APPLE)
|
||||
configure_file(${OpenMW_SOURCE_DIR}/files/openmw.desktop
|
||||
"${OpenMW_BINARY_DIR}/openmw.desktop")
|
||||
|
@ -362,9 +359,9 @@ if (NOT WIN32 AND NOT APPLE)
|
|||
endif()
|
||||
|
||||
# CXX Compiler settings
|
||||
set(CMAKE_CXX_STANDARD 14)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
if (CMAKE_CXX_COMPILER_ID STREQUAL GNU OR CMAKE_CXX_COMPILER_ID STREQUAL Clang)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -pedantic -Wno-long-long")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wundef -Wno-unused-parameter -std=c++11 -pedantic -Wno-long-long")
|
||||
add_definitions( -DBOOST_NO_CXX11_SCOPED_ENUMS=ON )
|
||||
|
||||
if (APPLE)
|
||||
|
@ -454,8 +451,6 @@ IF(NOT WIN32 AND NOT APPLE)
|
|||
INSTALL(FILES "${OpenMW_BINARY_DIR}/openmw.cfg.install" DESTINATION "${SYSCONFDIR}" RENAME "openmw.cfg" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/resources/version" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb_204.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/gamecontrollerdb_205.txt" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/tes3mp-client-default.cfg" DESTINATION "${SYSCONFDIR}" COMPONENT "openmw")
|
||||
#INSTALL(FILES "${OpenMW_BINARY_DIR}/tes3mp-client.install" DESTINATION "${SYSCONFDIR}" RENAME "tes3mp-client.cfg" COMPONENT "openmw")
|
||||
|
@ -491,10 +486,6 @@ if(WIN32)
|
|||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/tes3mp-client-default.cfg" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Debug)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb_204.txt" DESTINATION "." CONFIGURATIONS Debug)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb_204.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Debug/gamecontrollerdb_205.txt" DESTINATION "." CONFIGURATIONS Debug)
|
||||
INSTALL(FILES "${OpenMW_BINARY_DIR}/Release/gamecontrollerdb_205.txt" DESTINATION "." CONFIGURATIONS Release;RelWithDebInfo;MinSizeRel)
|
||||
|
||||
if(BUILD_MYGUI_PLUGIN)
|
||||
INSTALL(PROGRAMS "${OpenMW_BINARY_DIR}/Debug/Plugin_MyGUI_OpenMW_Resources.dll" DESTINATION "." CONFIGURATIONS Debug)
|
||||
|
@ -543,8 +534,8 @@ if(WIN32)
|
|||
SET(CPACK_PACKAGE_DESCRIPTION_FILE "${OpenMW_SOURCE_DIR}/README.md")
|
||||
SET(CPACK_NSIS_EXECUTABLES_DIRECTORY ".")
|
||||
SET(CPACK_NSIS_DISPLAY_NAME "OpenMW ${OPENMW_VERSION}")
|
||||
SET(CPACK_NSIS_HELP_LINK "https:\\\\\\\\www.openmw.org")
|
||||
SET(CPACK_NSIS_URL_INFO_ABOUT "https:\\\\\\\\www.openmw.org")
|
||||
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 "openmw-launcher.exe")
|
||||
SET(CPACK_NSIS_MUI_FINISHPAGE_RUN "openmw-launcher.exe")
|
||||
SET(CPACK_NSIS_MUI_ICON "${OpenMW_SOURCE_DIR}/files/tes3mp/tes3mp.ico")
|
||||
|
@ -589,6 +580,11 @@ ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
|
|||
# Components
|
||||
add_subdirectory (components)
|
||||
|
||||
# Plugins
|
||||
#if (BUILD_MYGUI_PLUGIN)
|
||||
# add_subdirectory(plugins/mygui_resource_plugin)
|
||||
#endif()
|
||||
|
||||
# Apps and tools
|
||||
if (BUILD_OPENMW_MP)
|
||||
add_subdirectory( apps/openmw-mp )
|
||||
|
@ -666,10 +662,10 @@ if (WIN32)
|
|||
endif()
|
||||
|
||||
if (BUILD_OPENMW)
|
||||
# Release builds don't use the debug console
|
||||
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
|
||||
set_target_properties(tes3mp PROPERTIES COMPILE_DEFINITIONS_RELEASE "_WINDOWS")
|
||||
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
|
||||
# Release builds use the debug console
|
||||
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE")
|
||||
set_target_properties(tes3mp PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE")
|
||||
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE")
|
||||
endif()
|
||||
|
||||
# Play a bit with the warning levels
|
||||
|
@ -680,8 +676,7 @@ if (WIN32)
|
|||
# Warnings that aren't enabled normally and don't need to be enabled
|
||||
# They're unneeded and sometimes completely retarded warnings that /Wall enables
|
||||
# Not going to bother commenting them as they tend to warn on every standard library file
|
||||
4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625
|
||||
4626 4628 4640 4668 4710 4711 4768 4820 4826 4917 4946 5032 5039 5045
|
||||
4061 4263 4264 4266 4350 4371 4435 4514 4548 4571 4610 4619 4623 4625 4626 4628 4640 4668 4710 4711 4820 4826 4917 4946
|
||||
|
||||
# Warnings that are thrown on standard libraries and not OpenMW
|
||||
4347 # Non-template function with same name and parameter count as template function
|
||||
|
@ -702,7 +697,6 @@ if (WIN32)
|
|||
|
||||
# caused by MyGUI
|
||||
4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception'
|
||||
4297 # function assumed not to throw an exception but does
|
||||
|
||||
# OpenMW specific warnings
|
||||
4099 # Type mismatch, declared class or struct is defined with other type
|
||||
|
@ -736,10 +730,7 @@ if (WIN32)
|
|||
endforeach(d)
|
||||
|
||||
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
|
||||
if (BUILD_OPENMW)
|
||||
set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
endif()
|
||||
set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
|
||||
if (BUILD_BSATOOL)
|
||||
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
|
@ -770,7 +761,8 @@ if (WIN32)
|
|||
endif()
|
||||
|
||||
if (BUILD_OPENMW)
|
||||
if (OPENMW_UNITY_BUILD)
|
||||
# Very specific issue this, only needed on 32-bit VS2015 during unity builds.
|
||||
if (MSVC_VERSION GREATER 1800 AND CMAKE_SIZEOF_VOID_P EQUAL 4 AND OPENMW_UNITY_BUILD)
|
||||
set_target_properties(tes3mp PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD} /bigobj")
|
||||
else()
|
||||
set_target_properties(tes3mp PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
|
||||
|
@ -898,3 +890,4 @@ if (DOXYGEN_FOUND)
|
|||
WORKING_DIRECTORY ${OpenMW_BINARY_DIR}
|
||||
COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM)
|
||||
endif ()
|
||||
|
||||
|
|
|
@ -3,14 +3,15 @@ How to contribute to OpenMW
|
|||
|
||||
Not sure what to do with all your free time? Pick out a task from here:
|
||||
|
||||
https://gitlab.com/OpenMW/openmw/issues
|
||||
http://bugs.openmw.org/
|
||||
|
||||
Currently, we are focused on completing the MW game experience and general polishing. Features out of this scope may be approved in some cases, but you should probably start a discussion first.
|
||||
|
||||
Note:
|
||||
* Tasks set to 'openmw-future' are usually out of the current scope of the project and can't be started yet.
|
||||
* Bugs that are not 'Confirmed' should be confirmed first.
|
||||
* Often, it's best to start a discussion about possible solutions before you jump into coding, especially for larger features.
|
||||
- Tasks set to 'openmw-future' are usually out of the current scope of the project and can't be started yet.
|
||||
- Bugs that are not 'Confirmed' should be confirmed first.
|
||||
- Larger Features should have a discussion before you start implementing.
|
||||
- In many cases, it's best to have a discussion about possible solutions before you jump into coding.
|
||||
|
||||
Aside from coding, you can also help by triaging the issues list. Check for bugs that are 'Unconfirmed' and try to confirm them on your end, working out any details that may be necessary. Check for bugs that do not conform to [Bug reporting guidelines](https://wiki.openmw.org/index.php?title=Bug_Reporting_Guidelines) and improve them to do so!
|
||||
|
||||
|
@ -19,21 +20,20 @@ There are various [Tools](https://wiki.openmw.org/index.php?title=Tools) to faci
|
|||
Pull Request Guidelines
|
||||
=======================
|
||||
|
||||
To facilitate the review process, your pull request description should include the following, if applicable:
|
||||
Thought of a change? Great! To facilitate the review process, your pull request description should include the following (if applicable):
|
||||
|
||||
* A link back to the bug report or forum discussion that prompted the change. Note: when linking bugs, use the syntax ```[Bug #xyz](https://bugs.openmw.org/issues/#xyz)``` to create a clickable link. Writing only 'Bug #xyz' will unfortunately create a link to the Github pull request with that number instead.
|
||||
* A link back to the bug report or forum discussion that prompted the change
|
||||
* Summary of the changes made
|
||||
* Reasoning / motivation behind the change
|
||||
* What testing you have carried out to verify the change
|
||||
|
||||
Furthermore, we advise to:
|
||||
|
||||
* Avoid stuffing unrelated commits into one pull request. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time.
|
||||
* Separate your work into multiple pull requests whenever possible. As a rule of thumb, each feature and each bugfix should go into a separate PR, unless they are closely related or dependent upon each other. Small pull requests are easier to review, and are less likely to require further changes before we can merge them. A "mega" pull request with lots of unrelated commits in it is likely to get held up in review for a long time.
|
||||
* Feel free to submit incomplete pull requests. Even if the work can not be merged yet, pull requests are a great place to collect early feedback. Just make sure to mark it as *[Incomplete]* or *[Do not merge yet]* in the title.
|
||||
* If you plan on contributing often, please read the [Developer Reference](https://wiki.openmw.org/index.php?title=Developer_Reference) on our wiki, especially the [Policies and Standards](https://wiki.openmw.org/index.php?title=Policies_and_Standards).
|
||||
* Make sure each of your changes has a clear objective. Unnecessary changes may lead to merge conflicts, clutter the commit history and slow down review. Code formatting 'fixes' should be avoided, unless you were already changing that particular line anyway.
|
||||
* Reference the bug / feature ticket(s) in your commit message (e.g. 'Bug #123') to make it easier to keep track of what we changed for what reason. Our bugtracker will show those commits next to the ticket. If your commit message includes 'Fixes #123', that bug/feature will automatically be set to 'Closed' when your commit is merged.
|
||||
* When pulling changes from master, prefer rebase over merge. Consider using a merge if there are conflicts or for long-running PRs.
|
||||
|
||||
Guidelines for original engine "fixes"
|
||||
=================================
|
||||
|
@ -47,7 +47,7 @@ Unfortunately, the definition of what is a "bug" is not so clear. Consider that
|
|||
* Many people will actually <i>like</i> these "bugs" because that is what they remember the game for.
|
||||
* Exploits may be part of the fun of an open-world game - they reward knowledge with power. There are too many of them to plug them all, anyway.
|
||||
|
||||
OpenMW, in its default configuration, is meant to be a faithful reimplementation of Morrowind, minus things like crash bugs, stability issues and severe design errors. However, we try to avoid touching anything that affects the core gameplay, the balancing of the game or introduces incompatibilities with existing mod content.
|
||||
OpenMW, in its default configuration, is meant to be a faithful reimplementation of Morrowind, minus things like crash bugs, stability issues and design errors. However, we try to avoid touching anything that affects the core gameplay, the balancing of the game or introduces incompatibilities with existing mod content.
|
||||
|
||||
That said, we may sometimes evaluate such issues on an individual basis. Common exceptions to the above would be:
|
||||
|
||||
|
@ -62,54 +62,10 @@ We get it, you have waited so long for feature XYZ to be available in Morrowind
|
|||
|
||||
Unfortunately, since maintaining features comes at a cost and our resources are limited, we have to be a little selective in what features we allow into the main repository. Generally:
|
||||
|
||||
* Features should be as generic and non-redundant as possible.
|
||||
* Any feature that is also possible with modding should be done as a mod instead.
|
||||
* In the future, OpenMW plans to expand the scope of what is possible with modding, e.g. by moving certain game logic into editable scripts.
|
||||
* Currently, modders can edit OpenMW's GUI skins and layout XML files, although there are still a few missing hooks (e.g. scripting support) in order to make this into a powerful way of modding.
|
||||
* If a feature introduces new game UI strings, that reduces its chance of being accepted because we do not currently have any way of localizing these to the user's Morrowind installation language.
|
||||
- Features should be as generic and non-redundant as possible.
|
||||
- Any feature that is also possible with modding should be done as a mod instead.
|
||||
- In the future, OpenMW plans to expand the scope of what is possible with modding, e.g. by moving certain game logic into editable scripts.
|
||||
- Currently, modders can edit OpenMW's GUI skins and layout XML files, although there are still a few missing hooks (e.g. scripting support) in order to make this into a powerful way of modding.
|
||||
- If a feature introduces new game UI strings, that reduces its chance of being accepted because we do not currently have any way of localizing these to the user's Morrowind installation language.
|
||||
|
||||
If you are in doubt of your feature being within our scope, it is probably best to start a forum discussion first. See the [settings documentation](https://openmw.readthedocs.io/en/stable/reference/modding/settings/index.html) and [Features list](https://wiki.openmw.org/index.php?title=Features) for some examples of features that were deemed acceptable.
|
||||
|
||||
Reviewing pull requests
|
||||
=======================
|
||||
|
||||
We welcome any help in reviewing open PRs. You don't need to be a developer to comment on new features. We also encourage ["junior" developers to review senior's work](https://pagefault.blog/2018/04/08/why-junior-devs-should-review-seniors-commits/).
|
||||
|
||||
This review process is divided into two sections because complaining about code or style issues hardly makes sense until the functionality of the PR is deemed OK. Anyone can help with the Functionality Review while most parts of the Code Review require you to have programming experience.
|
||||
|
||||
In addition to the checklist below, make sure to check that the Pull Request Guidelines (first half of this document) were followed.
|
||||
|
||||
First review
|
||||
============
|
||||
|
||||
1. Ask for missing information or clarifications. Compare against the project's design goals and roadmap.
|
||||
2. Check if the automated tests are passing. If they are not, make the PR author aware of the issue and potentially link to the error line on Travis CI or Appveyor. If the error appears unrelated to the PR and/or the master branch is failing with the same error, our CI has broken and needs to be fixed independently of any open PRs. Raise this issue on the forums, bug tracker or with the relevant maintainer. The PR can be merged in this case as long as you've built it yourself to make sure it does build.
|
||||
3. Make sure that the new code has been tested thoroughly, either by asking the author or, preferably, testing yourself. In a complex project like OpenMW, it is easy to make mistakes, typos, etc. Therefore, prefer testing all code changes, no matter how trivial they look. When you have tested a PR that no one has tested so far, post a comment letting us know.
|
||||
4. On long running PRs, request the author to update its description with the current state or a checklist of things left to do.
|
||||
|
||||
Code Review
|
||||
===========
|
||||
|
||||
1. Carefully review each line for issues the author may not have thought of, paying special attention to 'special' cases. Often, people build their code with a particular mindset and forget about other configurations or unexpected interactions.
|
||||
2. If any changes are workarounds for an issue in an upstream library, make sure the issue was reported upstream so we can eventually drop the workaround when the issue is fixed and the new version of that library is a build dependency.
|
||||
3. Make sure PRs do not turn into arguments about hardly related issues. If the PR author disagrees with an established part of the project (e.g. supported build environments), they should open a forum discussion or bug report and in the meantime adjust the PR to adhere to the established way, rather than leaving the PR hanging on a dispute.
|
||||
4. Check if the code matches our style guidelines.
|
||||
5. Check to make sure the commit history is clean. Squashing should be considered if the review process has made the commit history particularly long. Commits that don't build should be avoided because they are a nuisance for ```git bisect```.
|
||||
|
||||
Merging
|
||||
=======
|
||||
|
||||
To be able to merge PRs, commit priviledges are required. If you do not have the priviledges, just ping someone that does have them with a short comment like "Looks good to me @user".
|
||||
|
||||
The person to merge the PR may either use github's Merge button or if using the command line, use the ```--no-ff``` flag (so a merge commit is created, just like with Github's merge button) and include the pull request number in the commit description.
|
||||
|
||||
Dealing with regressions
|
||||
========================
|
||||
|
||||
The master branch should always be in a working state that is not worse than the previous release in any way. If a regression is found, the first and foremost priority should be to get the regression fixed quickly, either by reverting the change that caused it or finding a better solution. Please avoid leaving the project in the 'broken' state for an extensive period of time while proper solutions are found. If the solution takes more than a day or so then it is usually better to revert the offending change first and reapply it later when fixed.
|
||||
|
||||
Other resources
|
||||
===============
|
||||
|
||||
[GitHub blog - how to write the perfect pull request](https://blog.github.com/2015-01-21-how-to-write-the-perfect-pull-request/)
|
||||
|
||||
|
|
8
LICENSE
8
LICENSE
|
@ -1,7 +1,7 @@
|
|||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
|
@ -645,7 +645,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
|||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
|
@ -664,11 +664,11 @@ might be different; for a GUI interface, you would use an "about box".
|
|||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
<http://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
|
56
README.md
56
README.md
|
@ -1,49 +1,45 @@
|
|||
TES3MP
|
||||
======
|
||||
|
||||
Copyright (c) 2008-2015, OpenMW Team
|
||||
Copyright (c) 2016-2019, Stanislav Zhukov & David Cernat
|
||||
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||
|
||||
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=0.7.0)](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||
TES3MP is a project aiming to add multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), a free and open source engine recreation of the popular Bethesda Softworks game "The Elder Scrolls III: Morrowind".
|
||||
|
||||
TES3MP is a project adding multiplayer functionality to [OpenMW](https://github.com/OpenMW/openmw), an open-source game engine that supports playing "The Elder Scrolls III: Morrowind" by Bethesda Softworks.
|
||||
|
||||
* TES3MP version: 0.7.0-alpha
|
||||
* OpenMW version: 0.44.0
|
||||
* TES3MP version: 0.6.1
|
||||
* OpenMW version: 0.43.0
|
||||
* License: GPLv3 (see [LICENSE](https://github.com/TES3MP/openmw-tes3mp/blob/master/LICENSE) for more information)
|
||||
|
||||
Font Licenses:
|
||||
* DejaVuLGCSansMono.ttf: custom (see [files/mygui/DejaVu Font License.txt](https://github.com/TES3MP/openmw-tes3mp/blob/master/files/mygui/DejaVu%20Font%20License.txt) for more information)
|
||||
|
||||
Project status
|
||||
Project Status
|
||||
--------------
|
||||
|
||||
[Version changelog](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-changelog.md)
|
||||
|
||||
As of version 0.7.0, TES3MP is fully playable, providing very extensive player, NPC, world and quest synchronization, as well as state saving and loading, all of which are highly customizable via [serverside Lua scripts](https://github.com/TES3MP/CoreScripts).
|
||||
TES3MP is now playable in most respects. Player and NPC movement, animations, combat and spell casting are properly synchronized with small exceptions, as is picking up and dropping items in the world, using doors and levers, and adding and removing items from containers. Journal entries, faction stats and dialogue topics are also synchronized, allowing the majority of quests to work fine.
|
||||
|
||||
Remaining gameplay problems mostly relate to AI and the synchronization of clientside script variables.
|
||||
[Serverside Lua scripts](https://github.com/TES3MP/CoreScripts) are used to save and load the state of most of the aforementioned.
|
||||
|
||||
Contributing
|
||||
--------------
|
||||
|
||||
Development has been relatively fast, but any contribution regarding [code](https://github.com/TES3MP/openmw-tes3mp/blob/master/CONTRIBUTING.md), documentation, bug hunting or video showcases is greatly appreciated.
|
||||
|
||||
Test sessions are often advertised on [our Discord server](https://discord.gg/ECJk293) or in [our Steam group](https://steamcommunity.com/groups/mwmulti).
|
||||
|
||||
Feel free to contact the [team members](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-credits.md) for any questions you might have.
|
||||
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
* [Quickstart guide](https://github.com/TES3MP/openmw-tes3mp/wiki/Quickstart-guide)
|
||||
* [Steam group](https://steamcommunity.com/groups/mwmulti) and its [detailed FAQ](http://steamcommunity.com/groups/mwmulti/discussions/1/353916184342480541/)
|
||||
* [TES3MP section on OpenMW forums](https://forum.openmw.org/viewforum.php?f=44)
|
||||
* [Subreddit](https://www.reddit.com/r/tes3mp)
|
||||
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
|
||||
|
||||
Donations
|
||||
---------------
|
||||
|
||||
You can benefit the project by donating on Patreon to our two developers, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).
|
||||
|
||||
Contributing
|
||||
---------------
|
||||
|
||||
Helping us with documentation, bug hunting and video showcases is always greatly appreciated.
|
||||
|
||||
For code contributions, it's best to start out with modestly sized fixes and features and work your way up. There are so many different possible implementations of more major features – many of which would cause undesirable code or vision conflicts with OpenMW – that those should be talked over in advance with the existing developers before effort is spent on them.
|
||||
|
||||
Feel free to contact the [team members](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-credits.md) for any questions you might have.
|
||||
|
||||
Getting started
|
||||
---------------
|
||||
|
||||
* [Quickstart guide](https://github.com/TES3MP/openmw-tes3mp/wiki/Quickstart-guide)
|
||||
* [Steam group](https://steamcommunity.com/groups/mwmulti) and its [detailed FAQ](https://steamcommunity.com/groups/mwmulti/discussions/1/353916184342480541/)
|
||||
* [TES3MP section on OpenMW forums](https://forum.openmw.org/viewforum.php?f=45)
|
||||
* [Discord server](https://discord.gg/ECJk293)
|
||||
* [Subreddit](https://www.reddit.com/r/tes3mp)
|
||||
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
|
||||
You can benefit the project by contributing to the Patreon pages of our two developers, [Koncord](https://www.patreon.com/Koncord) and [David Cernat](https://www.patreon.com/davidcernat), as well as by supporting [OpenMW](https://openmw.org).
|
||||
|
|
|
@ -54,7 +54,6 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
connect(tblServerBrowser, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(play()));
|
||||
connect(cBoxNotFull, SIGNAL(toggled(bool)), this, SLOT(notFullSwitch(bool)));
|
||||
connect(cBoxWithPlayers, SIGNAL(toggled(bool)), this, SLOT(havePlayersSwitch(bool)));
|
||||
connect(cBBoxWOPass, SIGNAL(toggled(bool)), this, SLOT(noPasswordSwitch(bool)));
|
||||
connect(comboLatency, SIGNAL(currentIndexChanged(int)), this, SLOT(maxLatencyChanged(int)));
|
||||
connect(leGamemode, SIGNAL(textChanged(const QString &)), this, SLOT(gamemodeChanged(const QString &)));
|
||||
loadFavorites();
|
||||
|
@ -66,7 +65,7 @@ MainWindow::~MainWindow()
|
|||
delete mGameInvoker;
|
||||
}
|
||||
|
||||
void MainWindow::addServerAndUpdate(const QString &addr)
|
||||
void MainWindow::addServerAndUpdate(QString addr)
|
||||
{
|
||||
favorites->insertRow(0);
|
||||
QModelIndex mi = favorites->index(0, ServerData::ADDR);
|
||||
|
@ -122,26 +121,28 @@ void MainWindow::play()
|
|||
if (id < 0)
|
||||
return;
|
||||
|
||||
|
||||
ServerInfoDialog infoDialog(this);
|
||||
ServerModel *sm = ((ServerModel*)proxyModel->sourceModel());
|
||||
|
||||
int sourceId = proxyModel->mapToSource(proxyModel->index(id, ServerData::ADDR)).row();
|
||||
ServerInfoDialog infoDialog(sm->myData[sourceId].addr, this);
|
||||
infoDialog.Server(sm->myData[sourceId].addr);
|
||||
|
||||
if (!infoDialog.refresh())
|
||||
{
|
||||
queryHelper->refresh();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!infoDialog.exec())
|
||||
return;
|
||||
|
||||
if (!infoDialog.isUpdated())
|
||||
return;
|
||||
|
||||
QStringList arguments;
|
||||
arguments.append(QLatin1String("--connect=") + sm->myData[sourceId].addr.toLatin1());
|
||||
|
||||
if (sm->myData[sourceId].GetPassword() == 1)
|
||||
{
|
||||
bool ok;
|
||||
QString passw = QInputDialog::getText(this, tr("Connecting to: ") + sm->myData[sourceId].addr, tr("Password: "),
|
||||
QLineEdit::Password, "", &ok);
|
||||
QString passw = QInputDialog::getText(this, "Connecting to: " + sm->myData[sourceId].addr, "Password: ", QLineEdit::Password, "", &ok);
|
||||
if (!ok)
|
||||
return;
|
||||
arguments.append(QLatin1String("--password=") + passw.toLatin1());
|
||||
|
@ -227,11 +228,6 @@ void MainWindow::havePlayersSwitch(bool state)
|
|||
proxyModel->filterEmptyServers(state);
|
||||
}
|
||||
|
||||
void MainWindow::noPasswordSwitch(bool state)
|
||||
{
|
||||
proxyModel->filterPassworded(state);
|
||||
}
|
||||
|
||||
void MainWindow::maxLatencyChanged(int index)
|
||||
{
|
||||
int maxLatency = index * 50;
|
||||
|
|
|
@ -17,11 +17,11 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow() override;
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
virtual ~MainWindow();
|
||||
protected:
|
||||
void closeEvent(QCloseEvent * event) Q_DECL_OVERRIDE;
|
||||
void addServerAndUpdate(const QString &addr);
|
||||
void addServerAndUpdate(QString addr);
|
||||
protected slots:
|
||||
void tabSwitched(int index);
|
||||
void addServer();
|
||||
|
@ -31,7 +31,6 @@ protected slots:
|
|||
void serverSelected();
|
||||
void notFullSwitch(bool state);
|
||||
void havePlayersSwitch(bool state);
|
||||
void noPasswordSwitch(bool state);
|
||||
void maxLatencyChanged(int index);
|
||||
void gamemodeChanged(const QString &text);
|
||||
private:
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "ServerModel.hpp"
|
||||
|
||||
#include <qdebug.h>
|
||||
#include <apps/browser/netutils/Utils.hpp>
|
||||
|
||||
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
||||
{
|
||||
|
@ -14,49 +13,26 @@ bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &
|
|||
QModelIndex pingIndex = sourceModel()->index(sourceRow, ServerData::PING, sourceParent);
|
||||
QModelIndex plIndex = sourceModel()->index(sourceRow, ServerData::PLAYERS, sourceParent);
|
||||
QModelIndex maxPlIndex = sourceModel()->index(sourceRow, ServerData::MAX_PLAYERS, sourceParent);
|
||||
QModelIndex passwordIndex = sourceModel()->index(sourceRow, ServerData::PASSW, sourceParent);
|
||||
|
||||
bool pingOk;
|
||||
int ping = sourceModel()->data(pingIndex).toInt(&pingOk);
|
||||
int ping = sourceModel()->data(pingIndex).toInt();
|
||||
int players = sourceModel()->data(plIndex).toInt();
|
||||
int maxPlayers = sourceModel()->data(maxPlIndex).toInt();
|
||||
|
||||
if (maxPing > 0 && (ping == -1 || ping > maxPing || !pingOk))
|
||||
if (maxPing > 0 && (ping == -1 || ping > maxPing))
|
||||
return false;
|
||||
if (filterEmpty && players == 0)
|
||||
return false;
|
||||
if (filterFull && players >= maxPlayers)
|
||||
return false;
|
||||
if(filterPasswEnabled && sourceModel()->data(passwordIndex).toString() == "Yes")
|
||||
return false;
|
||||
|
||||
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent);
|
||||
}
|
||||
|
||||
bool MySortFilterProxyModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
|
||||
{
|
||||
if(sortColumn() == ServerData::PING)
|
||||
{
|
||||
bool valid;
|
||||
|
||||
int pingright = sourceModel()->data(source_right).toInt(&valid);
|
||||
pingright = valid ? pingright : PING_UNREACHABLE;
|
||||
|
||||
int pingleft = sourceModel()->data(source_left).toInt(&valid);
|
||||
pingleft = valid ? pingleft : PING_UNREACHABLE;
|
||||
return pingleft < pingright;
|
||||
}
|
||||
else
|
||||
return QSortFilterProxyModel::lessThan(source_left, source_right);
|
||||
}
|
||||
|
||||
MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
|
||||
{
|
||||
filterEmpty = false;
|
||||
filterFull = false;
|
||||
filterPasswEnabled = false;
|
||||
maxPing = 0;
|
||||
setSortCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||
}
|
||||
|
||||
void MySortFilterProxyModel::filterEmptyServers(bool state)
|
||||
|
@ -76,9 +52,3 @@ void MySortFilterProxyModel::pingLessThan(int maxPing)
|
|||
this->maxPing = maxPing;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
||||
void MySortFilterProxyModel::filterPassworded(bool state)
|
||||
{
|
||||
filterPasswEnabled = state;
|
||||
invalidateFilter();
|
||||
}
|
||||
|
|
|
@ -13,15 +13,13 @@ class MySortFilterProxyModel : public QSortFilterProxyModel
|
|||
Q_OBJECT
|
||||
protected:
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_FINAL;
|
||||
bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_FINAL;
|
||||
public:
|
||||
explicit MySortFilterProxyModel(QObject *parent);
|
||||
MySortFilterProxyModel(QObject *parent);
|
||||
void filterFullServer(bool state);
|
||||
void filterEmptyServers(bool state);
|
||||
void filterPassworded(bool state);
|
||||
void pingLessThan(int maxPing);
|
||||
private:
|
||||
bool filterEmpty, filterFull, filterPasswEnabled;
|
||||
bool filterEmpty, filterFull;
|
||||
int maxPing;
|
||||
};
|
||||
|
||||
|
|
|
@ -7,19 +7,13 @@
|
|||
#include <QDebug>
|
||||
#include "PingUpdater.hpp"
|
||||
|
||||
void PingHelper::Add(int row, const AddrPair &addrPair)
|
||||
void PingHelper::Add(int row, AddrPair addrPair)
|
||||
{
|
||||
pingUpdater->addServer(row, addrPair);
|
||||
if (!pingThread->isRunning())
|
||||
pingThread->start();
|
||||
}
|
||||
|
||||
void PingHelper::Reset()
|
||||
{
|
||||
//if (pingThread->isRunning())
|
||||
Stop();
|
||||
}
|
||||
|
||||
void PingHelper::Stop()
|
||||
{
|
||||
emit pingUpdater->stop();
|
||||
|
@ -41,8 +35,9 @@ PingHelper &PingHelper::Get()
|
|||
return helper;
|
||||
}
|
||||
|
||||
PingHelper::PingHelper() : QObject()
|
||||
PingHelper::PingHelper()
|
||||
{
|
||||
QObject();
|
||||
pingThread = new QThread;
|
||||
pingUpdater = new PingUpdater;
|
||||
pingUpdater->moveToThread(pingThread);
|
||||
|
@ -53,4 +48,11 @@ PingHelper::PingHelper() : QObject()
|
|||
connect(this, SIGNAL(stop()), pingUpdater, SLOT(stop()));
|
||||
//connect(pingUpdater, SIGNAL(finished()), pingUpdater, SLOT(deleteLater()));
|
||||
connect(pingUpdater, SIGNAL(updateModel(int, unsigned)), this, SLOT(update(int, unsigned)));
|
||||
|
||||
|
||||
}
|
||||
|
||||
PingHelper::~PingHelper()
|
||||
{
|
||||
|
||||
}
|
||||
|
|
|
@ -17,17 +17,17 @@ class PingHelper : public QObject
|
|||
Q_OBJECT
|
||||
public:
|
||||
|
||||
void Reset();
|
||||
void Add(int row, const AddrPair &addrPair);
|
||||
void Add(int row, AddrPair addrPair);
|
||||
void Stop();
|
||||
void SetModel(QAbstractTableModel *model);
|
||||
//void UpdateImmedialy(PingUpdater::AddrPair addrPair);
|
||||
static PingHelper &Get();
|
||||
private:
|
||||
PingHelper();
|
||||
~PingHelper();
|
||||
|
||||
PingHelper(const PingHelper&) = delete;
|
||||
PingHelper& operator=(const PingHelper&) = delete;
|
||||
private:
|
||||
PingHelper();
|
||||
signals:
|
||||
void stop();
|
||||
public slots:
|
||||
|
|
|
@ -14,7 +14,7 @@ void PingUpdater::stop()
|
|||
run = false;
|
||||
}
|
||||
|
||||
void PingUpdater::addServer(int row, const AddrPair &addr)
|
||||
void PingUpdater::addServer(int row, AddrPair addr)
|
||||
{
|
||||
servers.push_back({row, addr});
|
||||
run = true;
|
||||
|
@ -42,7 +42,7 @@ void PingUpdater::process()
|
|||
unsigned ping = PingRakNetServer(server.second.first.toLatin1(), server.second.second);
|
||||
|
||||
qDebug() << "Pong from" << server.second.first + "|" + QString::number(server.second.second)
|
||||
<< ":" << ping << "ms" << "Sizeof servers: " << servers.size();
|
||||
<< ":" << ping << "ms";
|
||||
|
||||
emit updateModel(server.first, ping);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ class PingUpdater : public QObject
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
void addServer(int row, const AddrPair &addrPair);
|
||||
void addServer(int row, AddrPair addrPair);
|
||||
public slots:
|
||||
void stop();
|
||||
void process();
|
||||
|
|
|
@ -19,8 +19,8 @@ QueryHelper::QueryHelper(QAbstractItemModel *model)
|
|||
connect(queryThread, SIGNAL(started()), queryUpdate, SLOT(process()));
|
||||
connect(queryUpdate, SIGNAL(finished()), queryThread, SLOT(quit()));
|
||||
connect(queryUpdate, &QueryUpdate::finished, [this](){emit finished();});
|
||||
connect(queryUpdate, SIGNAL(updateModel(const QString&, unsigned short, const QueryData&)),
|
||||
this, SLOT(update(const QString&, unsigned short, const QueryData&)));
|
||||
connect(queryUpdate, SIGNAL(updateModel(QString, unsigned short, QueryData)),
|
||||
this, SLOT(update(QString, unsigned short, QueryData)));
|
||||
queryUpdate->moveToThread(queryThread);
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,6 @@ void QueryHelper::refresh()
|
|||
if (!queryThread->isRunning())
|
||||
{
|
||||
_model->removeRows(0, _model->rowCount());
|
||||
PingHelper::Get().Stop();
|
||||
queryThread->start();
|
||||
emit started();
|
||||
}
|
||||
|
@ -40,7 +39,7 @@ void QueryHelper::terminate()
|
|||
queryThread->terminate();
|
||||
}
|
||||
|
||||
void QueryHelper::update(const QString &addr, unsigned short port, const QueryData& data)
|
||||
void QueryHelper::update(QString addr, unsigned short port, QueryData data)
|
||||
{
|
||||
ServerModel *model = ((ServerModel*)_model);
|
||||
model->insertRow(model->rowCount());
|
||||
|
@ -81,7 +80,7 @@ void QueryUpdate::process()
|
|||
return;
|
||||
}
|
||||
|
||||
for (const auto &server : data)
|
||||
for (auto server : data)
|
||||
emit updateModel(server.first.ToString(false), server.first.GetPort(), server.second);
|
||||
emit finished();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ public slots:
|
|||
void refresh();
|
||||
void terminate();
|
||||
private slots:
|
||||
void update(const QString &addr, unsigned short port, const QueryData& data);
|
||||
void update(QString addr, unsigned short port, QueryData data);
|
||||
signals:
|
||||
void finished();
|
||||
void started();
|
||||
|
@ -38,7 +38,7 @@ class QueryUpdate : public QObject
|
|||
Q_OBJECT
|
||||
signals:
|
||||
void finished();
|
||||
void updateModel(const QString &addr, unsigned short port, const QueryData& data);
|
||||
void updateModel(QString addr, unsigned short port, QueryData data);
|
||||
public slots:
|
||||
void process();
|
||||
};
|
||||
|
|
|
@ -6,65 +6,32 @@
|
|||
#include "qdebug.h"
|
||||
|
||||
#include "ServerInfoDialog.hpp"
|
||||
#include <apps/browser/netutils/Utils.hpp>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <QThread>
|
||||
|
||||
using namespace std;
|
||||
using namespace RakNet;
|
||||
|
||||
ThrWorker::ThrWorker(ServerInfoDialog *dialog, QString addr, unsigned short port): addr(std::move(addr)), port(port), stopped(false)
|
||||
{
|
||||
this->dialog = dialog;
|
||||
}
|
||||
|
||||
void ThrWorker::process()
|
||||
{
|
||||
stopped = false;
|
||||
auto newSD = QueryClient::Get().Update(SystemAddress(addr.toUtf8(), port));
|
||||
if (dialog != nullptr)
|
||||
dialog->setData(newSD);
|
||||
stopped = true;
|
||||
emit finished();
|
||||
}
|
||||
|
||||
ServerInfoDialog::ServerInfoDialog(const QString &addr, QWidget *parent): QDialog(parent)
|
||||
ServerInfoDialog::ServerInfoDialog(QWidget *parent): QDialog(parent)
|
||||
{
|
||||
setupUi(this);
|
||||
refreshThread = new QThread;
|
||||
|
||||
QStringList list = addr.split(':');
|
||||
worker = new ThrWorker(this, list[0].toLatin1(), list[1].toUShort());
|
||||
worker->moveToThread(refreshThread);
|
||||
connect(refreshThread, SIGNAL(started()), worker, SLOT(process()));
|
||||
connect(worker, SIGNAL(finished()), refreshThread, SLOT(quit()));
|
||||
connect(refreshThread, SIGNAL(finished()), this, SLOT(refresh()));
|
||||
|
||||
connect(btnRefresh, &QPushButton::clicked, [this]{
|
||||
if (!refreshThread->isRunning())
|
||||
refreshThread->start();
|
||||
});
|
||||
connect(btnRefresh, SIGNAL(clicked()), this, SLOT(refresh()));
|
||||
}
|
||||
|
||||
ServerInfoDialog::~ServerInfoDialog()
|
||||
{
|
||||
worker->dialog = nullptr;
|
||||
if (!refreshThread->isRunning())
|
||||
refreshThread->terminate();
|
||||
|
||||
}
|
||||
|
||||
bool ServerInfoDialog::isUpdated()
|
||||
void ServerInfoDialog::Server(QString addr)
|
||||
{
|
||||
return sd.first != UNASSIGNED_SYSTEM_ADDRESS;
|
||||
this->addr = addr;
|
||||
}
|
||||
|
||||
void ServerInfoDialog::setData(std::pair<RakNet::SystemAddress, QueryData> &newSD)
|
||||
{
|
||||
sd = newSD;
|
||||
}
|
||||
|
||||
void ServerInfoDialog::refresh()
|
||||
bool ServerInfoDialog::refresh()
|
||||
{
|
||||
QStringList list = addr.split(':');
|
||||
auto sd = QueryClient::Get().Update(SystemAddress(list[0].toLatin1(), list[1].toUShort()));
|
||||
if (sd.first != UNASSIGNED_SYSTEM_ADDRESS)
|
||||
{
|
||||
leAddr->setText(sd.first.ToString(true, ':'));
|
||||
|
@ -74,16 +41,17 @@ void ServerInfoDialog::refresh()
|
|||
btnConnect->setDisabled(ping == PING_UNREACHABLE);
|
||||
|
||||
listPlayers->clear();
|
||||
for (const auto &player : sd.second.players)
|
||||
|
||||
for (auto player : sd.second.players)
|
||||
listPlayers->addItem(QString::fromStdString(player));
|
||||
|
||||
listPlugins->clear();
|
||||
for (const auto &plugin : sd.second.plugins)
|
||||
for (auto plugin : sd.second.plugins)
|
||||
listPlugins->addItem(QString::fromStdString(plugin.name));
|
||||
|
||||
listRules->clear();
|
||||
const static vector<std::string> defaultRules {"gamemode", "maxPlayers", "name", "passw", "players", "version"};
|
||||
for (auto &rule : sd.second.rules)
|
||||
for (auto rule : sd.second.rules)
|
||||
{
|
||||
if (::find(defaultRules.begin(), defaultRules.end(), rule.first) != defaultRules.end())
|
||||
continue;
|
||||
|
@ -96,12 +64,7 @@ void ServerInfoDialog::refresh()
|
|||
}
|
||||
|
||||
lblPlayers->setText(QString::number(sd.second.players.size()) + " / " + QString::number(sd.second.GetMaxPlayers()));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
int ServerInfoDialog::exec()
|
||||
{
|
||||
if (!refreshThread->isRunning())
|
||||
refreshThread->start();
|
||||
return QDialog::exec();
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -6,45 +6,18 @@
|
|||
#define NEWLAUNCHER_SERVERINFODIALOG_HPP
|
||||
|
||||
#include "ui_ServerInfo.h"
|
||||
#include <apps/browser/netutils/Utils.hpp>
|
||||
#include <RakNetTypes.h>
|
||||
#include <components/openmw-mp/Master/MasterData.hpp>
|
||||
|
||||
class ThrWorker;
|
||||
|
||||
class ServerInfoDialog : public QDialog, public Ui::Dialog
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ServerInfoDialog(const QString &addr, QWidget *parent = nullptr);
|
||||
~ServerInfoDialog() override;
|
||||
bool isUpdated();
|
||||
void setData(std::pair<RakNet::SystemAddress, QueryData> &newSD);
|
||||
explicit ServerInfoDialog(QWidget *parent = 0);
|
||||
virtual ~ServerInfoDialog();
|
||||
void Server(QString addr);
|
||||
public slots:
|
||||
void refresh();
|
||||
int exec() Q_DECL_OVERRIDE;
|
||||
private:
|
||||
QThread *refreshThread;
|
||||
ThrWorker* worker;
|
||||
std::pair<RakNet::SystemAddress, QueryData> sd;
|
||||
};
|
||||
|
||||
class ThrWorker: public QObject
|
||||
{
|
||||
friend class ServerInfoDialog;
|
||||
Q_OBJECT
|
||||
public:
|
||||
ThrWorker(ServerInfoDialog *dialog, QString addr, unsigned short port);
|
||||
|
||||
public slots:
|
||||
void process();
|
||||
signals:
|
||||
void finished();
|
||||
bool refresh();
|
||||
private:
|
||||
QString addr;
|
||||
unsigned short port;
|
||||
bool stopped;
|
||||
ServerInfoDialog *dialog;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
#include <qmessagebox.h>
|
||||
#include "ServerModel.hpp"
|
||||
#include <qdebug.h>
|
||||
#include <apps/browser/netutils/Utils.hpp>
|
||||
|
||||
ServerModel::ServerModel(QObject *parent) : QAbstractTableModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
ServerModel::~ServerModel()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*QHash<int, QByteArray> ServerModel::roleNames() const
|
||||
{
|
||||
return roles;
|
||||
|
@ -44,7 +49,7 @@ QVariant ServerModel::data(const QModelIndex &index, int role) const
|
|||
var = QString(sd.rules.at("name").str.c_str());
|
||||
break;
|
||||
case ServerData::PING:
|
||||
var = sd.ping == PING_UNREACHABLE ? QVariant("Unreachable") : sd.ping;
|
||||
var = sd.ping;
|
||||
break;
|
||||
case ServerData::MODNAME:
|
||||
if (sd.rules.at("gamemode").str == "")
|
||||
|
@ -131,7 +136,7 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
|
|||
sd.SetPassword(value.toBool());
|
||||
break;
|
||||
case ServerData::VERSION:
|
||||
sd.SetVersion(value.toString().toUtf8());
|
||||
sd.SetVersion(value.toString().toLatin1());
|
||||
ok = !sd.addr.isEmpty();
|
||||
break;
|
||||
case ServerData::PLAYERS:
|
||||
|
@ -141,14 +146,14 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
|
|||
sd.SetMaxPlayers(value.toInt(&ok));
|
||||
break;
|
||||
case ServerData::HOSTNAME:
|
||||
sd.SetName(value.toString().toUtf8());
|
||||
sd.SetName(value.toString().toLatin1());
|
||||
ok = !sd.addr.isEmpty();
|
||||
break;
|
||||
case ServerData::PING:
|
||||
sd.ping = value.toInt(&ok);
|
||||
break;
|
||||
case ServerData::MODNAME:
|
||||
sd.SetGameMode(value.toString().toUtf8());
|
||||
sd.SetGameMode(value.toString().toLatin1());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
|
@ -165,7 +170,9 @@ bool ServerModel::insertRows(int position, int count, const QModelIndex &index)
|
|||
Q_UNUSED(index);
|
||||
beginInsertRows(QModelIndex(), position, position + count - 1);
|
||||
|
||||
myData.insert(position, count, {});
|
||||
for (int row = 0; row < count; ++row) {
|
||||
myData.insert(position, {});
|
||||
}
|
||||
|
||||
endInsertRows();
|
||||
return true;
|
||||
|
|
|
@ -29,7 +29,8 @@ class ServerModel: public QAbstractTableModel
|
|||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ServerModel(QObject *parent = nullptr);
|
||||
explicit ServerModel(QObject *parent = 0);
|
||||
~ServerModel();
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_FINAL;
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_FINAL;
|
||||
int columnCount(const QModelIndex &parent) const Q_DECL_FINAL;
|
||||
|
|
|
@ -36,11 +36,6 @@ int main(int argc, char *argv[])
|
|||
std::string addr = mgr.getString("address", "Master");
|
||||
int port = mgr.getInt("port", "Master");
|
||||
|
||||
// Is this an attempt to connect to the official master server at the old port? If so,
|
||||
// redirect it to the correct port for the currently used fork of RakNet
|
||||
if (Misc::StringUtils::ciEqual(addr, "master.tes3mp.com") && port == 25560)
|
||||
port = 25561;
|
||||
|
||||
// initialize resources, if needed
|
||||
// Q_INIT_RESOURCE(resfile);
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ QueryClient::~QueryClient()
|
|||
RakPeerInterface::DestroyInstance(peer);
|
||||
}
|
||||
|
||||
void QueryClient::SetServer(const string &addr, unsigned short port)
|
||||
void QueryClient::SetServer(std::string addr, unsigned short port)
|
||||
{
|
||||
masterAddr = SystemAddress(addr.c_str(), port);
|
||||
}
|
||||
|
@ -83,7 +83,7 @@ map<SystemAddress, QueryData> QueryClient::Query()
|
|||
return query;
|
||||
}
|
||||
|
||||
pair<SystemAddress, QueryData> QueryClient::Update(const RakNet::SystemAddress &addr)
|
||||
pair<SystemAddress, QueryData> QueryClient::Update(RakNet::SystemAddress addr)
|
||||
{
|
||||
qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
|
||||
pair<SystemAddress, QueryData> server;
|
||||
|
@ -179,7 +179,7 @@ ConnectionState QueryClient::Connect()
|
|||
{
|
||||
|
||||
ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW,
|
||||
strlen(TES3MP_MASTERSERVER_PASSW), nullptr, 0, 5, 500);
|
||||
strlen(TES3MP_MASTERSERVER_PASSW), 0, 0, 5, 500);
|
||||
|
||||
while (true)
|
||||
{
|
||||
|
|
|
@ -14,16 +14,16 @@
|
|||
|
||||
class QueryClient
|
||||
{
|
||||
public:
|
||||
private:
|
||||
QueryClient(QueryClient const &) = delete;
|
||||
QueryClient(QueryClient &&) = delete;
|
||||
QueryClient &operator=(QueryClient const &) = delete;
|
||||
QueryClient &operator=(QueryClient &&) = delete;
|
||||
|
||||
public:
|
||||
static QueryClient &Get();
|
||||
void SetServer(const std::string &addr, unsigned short port);
|
||||
void SetServer(std::string addr, unsigned short port);
|
||||
std::map<RakNet::SystemAddress, QueryData> Query();
|
||||
std::pair<RakNet::SystemAddress, QueryData> Update(const RakNet::SystemAddress &addr);
|
||||
std::pair<RakNet::SystemAddress, QueryData> Update(RakNet::SystemAddress addr);
|
||||
int Status();
|
||||
private:
|
||||
RakNet::ConnectionState Connect();
|
||||
|
|
|
@ -44,15 +44,11 @@ unsigned int PingRakNetServer(const char *addr, unsigned short port)
|
|||
break;
|
||||
case ID_CONNECTED_PING:
|
||||
case ID_UNCONNECTED_PONG:
|
||||
{
|
||||
RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
|
||||
bsIn.Read(time);
|
||||
time = now - time;
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
peer->DeallocatePacket(packet);
|
||||
}
|
||||
|
@ -73,9 +69,9 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
|
|||
sstr << TES3MP_VERSION;
|
||||
sstr << TES3MP_PROTO_VERSION;
|
||||
|
||||
std::string msg;
|
||||
std::string msg = "";
|
||||
|
||||
if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), nullptr, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED)
|
||||
if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), 0, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED)
|
||||
msg = "Connection attempt failed.\n";
|
||||
|
||||
|
||||
|
@ -146,14 +142,14 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
|
|||
{
|
||||
RakNet::RakString str;
|
||||
bs.Read(str);
|
||||
data.players.emplace_back(str.C_String());
|
||||
data.players.push_back(str.C_String());
|
||||
}
|
||||
bs.Read(length);
|
||||
for (size_t i = 0; i < length; i++)
|
||||
{
|
||||
RakNet::RakString str;
|
||||
bs.Read(str);
|
||||
data.plugins.emplace_back(str.C_String());
|
||||
data.plugins.push_back(str.C_String());
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
|
|
@ -694,7 +694,7 @@ void Record<ESM::Dialogue>::print()
|
|||
// loads, rather than loading and then dumping. :-( Anyone mind if
|
||||
// I change this?
|
||||
ESM::Dialogue::InfoContainer::iterator iit;
|
||||
for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); ++iit)
|
||||
for (iit = mData.mInfo.begin(); iit != mData.mInfo.end(); iit++)
|
||||
std::cout << "INFO!" << iit->mId << std::endl;
|
||||
}
|
||||
|
||||
|
@ -1040,47 +1040,45 @@ void Record<ESM::NPC>::print()
|
|||
|
||||
if (mData.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS)
|
||||
{
|
||||
std::cout << " Level: " << mData.mNpdt.mLevel << std::endl;
|
||||
std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl;
|
||||
std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl;
|
||||
std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl;
|
||||
//Why do we want to print these fields? They are padding in the struct and contain
|
||||
// nothing of real value. Now we don't deal with NPDTstruct12 in runtime either...
|
||||
//std::cout << " Unknown1: "
|
||||
// << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl;
|
||||
//std::cout << " Unknown2: "
|
||||
// << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl;
|
||||
//std::cout << " Unknown3: "
|
||||
// << (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl;
|
||||
std::cout << " Gold: " << mData.mNpdt.mGold << std::endl;
|
||||
std::cout << " Level: " << mData.mNpdt12.mLevel << std::endl;
|
||||
std::cout << " Reputation: " << (int)mData.mNpdt12.mReputation << std::endl;
|
||||
std::cout << " Disposition: " << (int)mData.mNpdt12.mDisposition << std::endl;
|
||||
std::cout << " Rank: " << (int)mData.mNpdt12.mRank << std::endl;
|
||||
std::cout << " Unknown1: "
|
||||
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown1) << std::endl;
|
||||
std::cout << " Unknown2: "
|
||||
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl;
|
||||
std::cout << " Unknown3: "
|
||||
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl;
|
||||
std::cout << " Gold: " << mData.mNpdt12.mGold << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << " Level: " << mData.mNpdt.mLevel << std::endl;
|
||||
std::cout << " Reputation: " << (int)mData.mNpdt.mReputation << std::endl;
|
||||
std::cout << " Disposition: " << (int)mData.mNpdt.mDisposition << std::endl;
|
||||
std::cout << " Rank: " << (int)mData.mNpdt.mRank << std::endl;
|
||||
std::cout << " FactionID: " << (int)mData.mNpdt.mFactionID << std::endl;
|
||||
std::cout << " Level: " << mData.mNpdt52.mLevel << std::endl;
|
||||
std::cout << " Reputation: " << (int)mData.mNpdt52.mReputation << std::endl;
|
||||
std::cout << " Disposition: " << (int)mData.mNpdt52.mDisposition << std::endl;
|
||||
std::cout << " Rank: " << (int)mData.mNpdt52.mRank << std::endl;
|
||||
std::cout << " FactionID: " << (int)mData.mNpdt52.mFactionID << std::endl;
|
||||
|
||||
std::cout << " Attributes:" << std::endl;
|
||||
std::cout << " Strength: " << (int)mData.mNpdt.mStrength << std::endl;
|
||||
std::cout << " Intelligence: " << (int)mData.mNpdt.mIntelligence << std::endl;
|
||||
std::cout << " Willpower: " << (int)mData.mNpdt.mWillpower << std::endl;
|
||||
std::cout << " Agility: " << (int)mData.mNpdt.mAgility << std::endl;
|
||||
std::cout << " Speed: " << (int)mData.mNpdt.mSpeed << std::endl;
|
||||
std::cout << " Endurance: " << (int)mData.mNpdt.mEndurance << std::endl;
|
||||
std::cout << " Personality: " << (int)mData.mNpdt.mPersonality << std::endl;
|
||||
std::cout << " Luck: " << (int)mData.mNpdt.mLuck << std::endl;
|
||||
std::cout << " Strength: " << (int)mData.mNpdt52.mStrength << std::endl;
|
||||
std::cout << " Intelligence: " << (int)mData.mNpdt52.mIntelligence << std::endl;
|
||||
std::cout << " Willpower: " << (int)mData.mNpdt52.mWillpower << std::endl;
|
||||
std::cout << " Agility: " << (int)mData.mNpdt52.mAgility << std::endl;
|
||||
std::cout << " Speed: " << (int)mData.mNpdt52.mSpeed << std::endl;
|
||||
std::cout << " Endurance: " << (int)mData.mNpdt52.mEndurance << std::endl;
|
||||
std::cout << " Personality: " << (int)mData.mNpdt52.mPersonality << std::endl;
|
||||
std::cout << " Luck: " << (int)mData.mNpdt52.mLuck << std::endl;
|
||||
|
||||
std::cout << " Skills:" << std::endl;
|
||||
for (int i = 0; i != ESM::Skill::Length; i++)
|
||||
std::cout << " " << skillLabel(i) << ": "
|
||||
<< (int)(mData.mNpdt.mSkills[i]) << std::endl;
|
||||
<< (int)(mData.mNpdt52.mSkills[i]) << std::endl;
|
||||
|
||||
std::cout << " Health: " << mData.mNpdt.mHealth << std::endl;
|
||||
std::cout << " Magicka: " << mData.mNpdt.mMana << std::endl;
|
||||
std::cout << " Fatigue: " << mData.mNpdt.mFatigue << std::endl;
|
||||
std::cout << " Unknown: " << (int)mData.mNpdt.mUnknown << std::endl;
|
||||
std::cout << " Gold: " << mData.mNpdt.mGold << std::endl;
|
||||
std::cout << " Health: " << mData.mNpdt52.mHealth << std::endl;
|
||||
std::cout << " Magicka: " << mData.mNpdt52.mMana << std::endl;
|
||||
std::cout << " Fatigue: " << mData.mNpdt52.mFatigue << std::endl;
|
||||
std::cout << " Unknown: " << (int)mData.mNpdt52.mUnknown << std::endl;
|
||||
std::cout << " Gold: " << mData.mNpdt52.mGold << std::endl;
|
||||
}
|
||||
|
||||
std::vector<ESM::ContItem>::iterator cit;
|
||||
|
@ -1125,7 +1123,7 @@ void Record<ESM::Pathgrid>::print()
|
|||
|
||||
int i = 0;
|
||||
ESM::Pathgrid::PointList::iterator pit;
|
||||
for (pit = mData.mPoints.begin(); pit != mData.mPoints.end(); ++pit)
|
||||
for (pit = mData.mPoints.begin(); pit != mData.mPoints.end(); pit++)
|
||||
{
|
||||
std::cout << " Point[" << i << "]:" << std::endl;
|
||||
std::cout << " Coordinates: (" << pit->mX << ","
|
||||
|
@ -1137,7 +1135,7 @@ void Record<ESM::Pathgrid>::print()
|
|||
}
|
||||
i = 0;
|
||||
ESM::Pathgrid::EdgeList::iterator eit;
|
||||
for (eit = mData.mEdges.begin(); eit != mData.mEdges.end(); ++eit)
|
||||
for (eit = mData.mEdges.begin(); eit != mData.mEdges.end(); eit++)
|
||||
{
|
||||
std::cout << " Edge[" << i << "]: " << eit->mV0 << " -> " << eit->mV1 << std::endl;
|
||||
if (eit->mV0 >= mData.mData.mS2 || eit->mV1 >= mData.mData.mS2)
|
||||
|
|
|
@ -122,7 +122,7 @@ public:
|
|||
}
|
||||
else
|
||||
{
|
||||
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt.mLevel;
|
||||
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel;
|
||||
mContext->mPlayerBase = npc;
|
||||
ESM::SpellState::SpellParams empty;
|
||||
// FIXME: player start spells and birthsign spells aren't listed here,
|
||||
|
|
|
@ -377,7 +377,7 @@ namespace ESSImport
|
|||
profile.mPlayerClassName = context.mCustomPlayerClassName;
|
||||
else
|
||||
profile.mPlayerClassId = context.mPlayerBase.mClass;
|
||||
profile.mPlayerLevel = context.mPlayerBase.mNpdt.mLevel;
|
||||
profile.mPlayerLevel = context.mPlayerBase.mNpdt52.mLevel;
|
||||
profile.mPlayerName = header.mGameData.mPlayerName.toString();
|
||||
|
||||
writeScreenshot(header, profile);
|
||||
|
|
|
@ -20,7 +20,6 @@ namespace ESSImport
|
|||
item.mId = contItem.mItem.toString();
|
||||
item.mCount = contItem.mCount;
|
||||
item.mRelativeEquipmentSlot = -1;
|
||||
item.mLockLevel = 0;
|
||||
|
||||
unsigned int itemCount = std::abs(item.mCount);
|
||||
bool separateStacks = false;
|
||||
|
|
|
@ -6,9 +6,7 @@ set(LAUNCHER
|
|||
playpage.cpp
|
||||
textslotmsgbox.cpp
|
||||
settingspage.cpp
|
||||
advancedpage.cpp
|
||||
|
||||
utils/cellnameloader.cpp
|
||||
utils/profilescombobox.cpp
|
||||
utils/textinputdialog.cpp
|
||||
utils/lineedit.cpp
|
||||
|
@ -23,9 +21,7 @@ set(LAUNCHER_HEADER
|
|||
playpage.hpp
|
||||
textslotmsgbox.hpp
|
||||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/lineedit.hpp
|
||||
|
@ -39,9 +35,7 @@ set(LAUNCHER_HEADER_MOC
|
|||
playpage.hpp
|
||||
textslotmsgbox.hpp
|
||||
settingspage.hpp
|
||||
advancedpage.hpp
|
||||
|
||||
utils/cellnameloader.hpp
|
||||
utils/textinputdialog.hpp
|
||||
utils/profilescombobox.hpp
|
||||
utils/lineedit.hpp
|
||||
|
@ -55,7 +49,6 @@ set(LAUNCHER_UI
|
|||
${CMAKE_SOURCE_DIR}/files/ui/playpage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/contentselector.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/settingspage.ui
|
||||
${CMAKE_SOURCE_DIR}/files/ui/advancedpage.ui
|
||||
)
|
||||
|
||||
source_group(launcher FILES ${LAUNCHER} ${LAUNCHER_HEADER})
|
||||
|
@ -109,7 +102,7 @@ if (DESIRED_QT_VERSION MATCHES 4)
|
|||
target_link_libraries(openmw-launcher ${QT_QTMAIN_LIBRARY})
|
||||
endif(WIN32)
|
||||
else()
|
||||
target_link_libraries(openmw-launcher Qt5::Widgets Qt5::Core)
|
||||
qt5_use_modules(openmw-launcher Widgets Core)
|
||||
endif()
|
||||
|
||||
if (BUILD_WITH_CODE_COVERAGE)
|
||||
|
|
|
@ -1,176 +0,0 @@
|
|||
#include "advancedpage.hpp"
|
||||
|
||||
#include <components/config/gamesettings.hpp>
|
||||
#include <components/config/launchersettings.hpp>
|
||||
#include <QFileDialog>
|
||||
#include <QCompleter>
|
||||
#include <components/contentselector/view/contentselector.hpp>
|
||||
#include <components/contentselector/model/esmfile.hpp>
|
||||
|
||||
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg,
|
||||
Config::GameSettings &gameSettings,
|
||||
Settings::Manager &engineSettings, QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, mCfgMgr(cfg)
|
||||
, mGameSettings(gameSettings)
|
||||
, mEngineSettings(engineSettings)
|
||||
{
|
||||
setObjectName ("AdvancedPage");
|
||||
setupUi(this);
|
||||
|
||||
loadSettings();
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadCellsForAutocomplete(QStringList cellNames) {
|
||||
// Set up an auto-completer for the "Start default character at" field
|
||||
auto *completer = new QCompleter(cellNames);
|
||||
completer->setCompletionMode(QCompleter::PopupCompletion);
|
||||
completer->setCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
|
||||
startDefaultCharacterAtField->setCompleter(completer);
|
||||
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::on_skipMenuCheckBox_stateChanged(int state) {
|
||||
startDefaultCharacterAtLabel->setEnabled(state == Qt::Checked);
|
||||
startDefaultCharacterAtField->setEnabled(state == Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::on_runScriptAfterStartupBrowseButton_clicked()
|
||||
{
|
||||
QString scriptFile = QFileDialog::getOpenFileName(
|
||||
this,
|
||||
QObject::tr("Select script file"),
|
||||
QDir::currentPath(),
|
||||
QString(tr("Text file (*.txt)")));
|
||||
|
||||
if (scriptFile.isEmpty())
|
||||
return;
|
||||
|
||||
QFileInfo info(scriptFile);
|
||||
|
||||
if (!info.exists() || !info.isReadable())
|
||||
return;
|
||||
|
||||
const QString path(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
runScriptAfterStartupField->setText(path);
|
||||
}
|
||||
|
||||
bool Launcher::AdvancedPage::loadSettings()
|
||||
{
|
||||
// Testing
|
||||
bool skipMenu = mGameSettings.value("skip-menu").toInt() == 1;
|
||||
if (skipMenu) {
|
||||
skipMenuCheckBox->setCheckState(Qt::Checked);
|
||||
}
|
||||
startDefaultCharacterAtLabel->setEnabled(skipMenu);
|
||||
startDefaultCharacterAtField->setEnabled(skipMenu);
|
||||
|
||||
startDefaultCharacterAtField->setText(mGameSettings.value("start"));
|
||||
runScriptAfterStartupField->setText(mGameSettings.value("script-run"));
|
||||
|
||||
// Game Settings
|
||||
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||
loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
|
||||
// Input Settings
|
||||
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
loadSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
loadSettingBool(toggleSneakCheckBox, "toggle sneak", "Input");
|
||||
|
||||
// Saves Settings
|
||||
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "Saves"));
|
||||
|
||||
// User Interface Settings
|
||||
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
int showOwnedIndex = mEngineSettings.getInt("show owned", "Game");
|
||||
// Match the index with the option (only 0, 1, 2, or 3 are valid). Will default to 0 if invalid.
|
||||
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
|
||||
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
|
||||
|
||||
// Other Settings
|
||||
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
|
||||
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
|
||||
screenshotFormatComboBox->addItem(screenshotFormatString);
|
||||
screenshotFormatComboBox->setCurrentIndex(screenshotFormatComboBox->findText(screenshotFormatString));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettings()
|
||||
{
|
||||
// Ensure we only set the new settings if they changed. This is to avoid cluttering the
|
||||
// user settings file (which by definition should only contain settings the user has touched)
|
||||
|
||||
// Testing
|
||||
int skipMenu = skipMenuCheckBox->checkState() == Qt::Checked;
|
||||
if (skipMenu != mGameSettings.value("skip-menu").toInt())
|
||||
mGameSettings.setValue("skip-menu", QString::number(skipMenu));
|
||||
|
||||
QString startCell = startDefaultCharacterAtField->text();
|
||||
if (startCell != mGameSettings.value("start")) {
|
||||
mGameSettings.setValue("start", startCell);
|
||||
}
|
||||
QString scriptRun = runScriptAfterStartupField->text();
|
||||
if (scriptRun != mGameSettings.value("script-run"))
|
||||
mGameSettings.setValue("script-run", scriptRun);
|
||||
|
||||
// Game Settings
|
||||
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
|
||||
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
|
||||
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
|
||||
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
|
||||
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
|
||||
saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
|
||||
saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
|
||||
|
||||
// Input Settings
|
||||
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
|
||||
saveSettingBool(grabCursorCheckBox, "grab cursor", "Input");
|
||||
saveSettingBool(toggleSneakCheckBox, "toggle sneak", "Input");
|
||||
|
||||
// Saves Settings
|
||||
saveSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
|
||||
int maximumQuicksaves = maximumQuicksavesComboBox->value();
|
||||
if (maximumQuicksaves != mEngineSettings.getInt("max quicksaves", "Saves")) {
|
||||
mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves);
|
||||
}
|
||||
|
||||
// User Interface Settings
|
||||
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
|
||||
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
|
||||
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
|
||||
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
|
||||
int showOwnedCurrentIndex = showOwnedComboBox->currentIndex();
|
||||
if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game"))
|
||||
mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex);
|
||||
|
||||
// Other Settings
|
||||
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
|
||||
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
|
||||
mEngineSettings.setString("screenshot format", "General", screenshotFormatString);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::loadSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) {
|
||||
if (mEngineSettings.getBool(setting, group))
|
||||
checkbox->setCheckState(Qt::Checked);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::string &setting, const std::string &group) {
|
||||
bool cValue = checkbox->checkState();
|
||||
if (cValue != mEngineSettings.getBool(setting, group))
|
||||
mEngineSettings.setBool(setting, group, cValue);
|
||||
}
|
||||
|
||||
void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames)
|
||||
{
|
||||
loadCellsForAutocomplete(cellNames);
|
||||
}
|
|
@ -1,47 +0,0 @@
|
|||
#ifndef ADVANCEDPAGE_H
|
||||
#define ADVANCEDPAGE_H
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
#include "ui_advancedpage.h"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
namespace Files { struct ConfigurationManager; }
|
||||
namespace Config { class GameSettings; }
|
||||
|
||||
namespace Launcher
|
||||
{
|
||||
class AdvancedPage : public QWidget, private Ui::AdvancedPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings,
|
||||
Settings::Manager &engineSettings, QWidget *parent = 0);
|
||||
|
||||
bool loadSettings();
|
||||
void saveSettings();
|
||||
|
||||
public slots:
|
||||
void slotLoadedCellsChanged(QStringList cellNames);
|
||||
|
||||
private slots:
|
||||
void on_skipMenuCheckBox_stateChanged(int state);
|
||||
void on_runScriptAfterStartupBrowseButton_clicked();
|
||||
|
||||
private:
|
||||
Files::ConfigurationManager &mCfgMgr;
|
||||
Config::GameSettings &mGameSettings;
|
||||
Settings::Manager &mEngineSettings;
|
||||
|
||||
/**
|
||||
* Load the cells associated with the given content files for use in autocomplete
|
||||
* @param filePaths the file paths of the content files to be examined
|
||||
*/
|
||||
void loadCellsForAutocomplete(QStringList filePaths);
|
||||
void loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
||||
void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -7,10 +7,7 @@
|
|||
#include <QCheckBox>
|
||||
#include <QMenu>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
|
||||
#include <apps/launcher/utils/cellnameloader.hpp>
|
||||
#include <components/files/configurationmanager.hpp>
|
||||
|
||||
#include <components/contentselector/model/esmfile.hpp>
|
||||
|
@ -19,7 +16,6 @@
|
|||
|
||||
#include <components/config/gamesettings.hpp>
|
||||
#include <components/config/launchersettings.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "utils/textinputdialog.hpp"
|
||||
#include "utils/profilescombobox.hpp"
|
||||
|
@ -44,13 +40,6 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
|
|||
|
||||
buildView();
|
||||
loadSettings();
|
||||
|
||||
// Connect signal and slot after the settings have been loaded. We only care about the user changing
|
||||
// the addons and don't want to get signals of the system doing it during startup.
|
||||
connect(mSelector, SIGNAL(signalAddonDataChanged(QModelIndex,QModelIndex)),
|
||||
this, SLOT(slotAddonDataChanged()));
|
||||
// Call manually to indicate all changes to addon data during startup.
|
||||
slotAddonDataChanged();
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::buildView()
|
||||
|
@ -153,17 +142,6 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile)
|
|||
mGameSettings.setContentList(fileNames);
|
||||
}
|
||||
|
||||
QStringList Launcher::DataFilesPage::selectedFilePaths()
|
||||
{
|
||||
//retrieve the files selected for the profile
|
||||
ContentSelectorModel::ContentFileList items = mSelector->selectedFiles();
|
||||
QStringList filePaths;
|
||||
foreach(const ContentSelectorModel::EsmFile *item, items) {
|
||||
filePaths.append(item->filePath());
|
||||
}
|
||||
return filePaths;
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::removeProfile(const QString &profile)
|
||||
{
|
||||
mLauncherSettings.removeContentList(profile);
|
||||
|
@ -330,31 +308,3 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
|
|||
|
||||
return (msgBox.clickedButton() == deleteButton);
|
||||
}
|
||||
|
||||
void Launcher::DataFilesPage::slotAddonDataChanged()
|
||||
{
|
||||
QStringList selectedFiles = selectedFilePaths();
|
||||
if (previousSelectedFiles != selectedFiles) {
|
||||
previousSelectedFiles = selectedFiles;
|
||||
// Loading cells for core Morrowind + Expansions takes about 0.2 seconds, which is enough to cause a
|
||||
// barely perceptible UI lag. Splitting into its own thread to alleviate that.
|
||||
std::thread loadCellsThread(&DataFilesPage::reloadCells, this, selectedFiles);
|
||||
loadCellsThread.detach();
|
||||
}
|
||||
}
|
||||
|
||||
// Mutex lock to run reloadCells synchronously.
|
||||
std::mutex _reloadCellsMutex;
|
||||
|
||||
void Launcher::DataFilesPage::reloadCells(QStringList selectedFiles)
|
||||
{
|
||||
// Use a mutex lock so that we can prevent two threads from executing the rest of this code at the same time
|
||||
// Based on https://stackoverflow.com/a/5429695/531762
|
||||
std::unique_lock<std::mutex> lock(_reloadCellsMutex);
|
||||
|
||||
// The following code will run only if there is not another thread currently running it
|
||||
CellNameLoader cellNameLoader;
|
||||
QStringList cellNamesList = QStringList::fromSet(cellNameLoader.getCellNames(selectedFiles));
|
||||
std::sort(cellNamesList.begin(), cellNamesList.end());
|
||||
emit signalLoadedCellsChanged(cellNamesList);
|
||||
}
|
|
@ -7,7 +7,6 @@
|
|||
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QStringList>
|
||||
|
||||
class QSortFilterProxyModel;
|
||||
class QAbstractItemModel;
|
||||
|
@ -42,15 +41,8 @@ namespace Launcher
|
|||
void saveSettings(const QString &profile = "");
|
||||
bool loadSettings();
|
||||
|
||||
/**
|
||||
* Returns the file paths of all selected content files
|
||||
* @return the file paths of all selected content files
|
||||
*/
|
||||
QStringList selectedFilePaths();
|
||||
|
||||
signals:
|
||||
void signalProfileChanged (int index);
|
||||
void signalLoadedCellsChanged(QStringList selectedFiles);
|
||||
|
||||
public slots:
|
||||
void slotProfileChanged (int index);
|
||||
|
@ -60,7 +52,6 @@ namespace Launcher
|
|||
void slotProfileChangedByUser(const QString &previous, const QString ¤t);
|
||||
void slotProfileRenamed(const QString &previous, const QString ¤t);
|
||||
void slotProfileDeleted(const QString &item);
|
||||
void slotAddonDataChanged ();
|
||||
|
||||
void updateOkButton(const QString &text);
|
||||
|
||||
|
@ -81,7 +72,7 @@ namespace Launcher
|
|||
Config::LauncherSettings &mLauncherSettings;
|
||||
|
||||
QString mPreviousProfile;
|
||||
QStringList previousSelectedFiles;
|
||||
|
||||
QString mDataLocal;
|
||||
|
||||
void setPluginsCheckstates(Qt::CheckState state);
|
||||
|
@ -96,7 +87,6 @@ namespace Launcher
|
|||
void addProfile (const QString &profile, bool setAsCurrent);
|
||||
void checkForDefaultProfile();
|
||||
void populateFileViews(const QString& contentModelName);
|
||||
void reloadCells(QStringList selectedFiles);
|
||||
|
||||
class PathIterator
|
||||
{
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#include "graphicspage.hpp"
|
||||
|
||||
#include <boost/math/common_factor.hpp>
|
||||
#include <csignal>
|
||||
#include <QDesktopWidget>
|
||||
#include <QMessageBox>
|
||||
#include <QDir>
|
||||
|
@ -12,7 +11,6 @@
|
|||
#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 <components/files/configurationmanager.hpp>
|
||||
|
@ -48,28 +46,8 @@ Launcher::GraphicsPage::GraphicsPage(Files::ConfigurationManager &cfg, Settings:
|
|||
|
||||
}
|
||||
|
||||
bool Launcher::GraphicsPage::connectToSdl() {
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||
SDL_SetMainReady();
|
||||
// Required for determining screen resolution and such on the Graphics tab
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
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.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Launcher::GraphicsPage::setupSDL()
|
||||
{
|
||||
bool sdlConnectSuccessful = connectToSdl();
|
||||
if (!sdlConnectSuccessful)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int displays = SDL_GetNumVideoDisplays();
|
||||
|
||||
if (displays < 0)
|
||||
|
@ -89,9 +67,6 @@ bool Launcher::GraphicsPage::setupSDL()
|
|||
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
|
||||
}
|
||||
|
||||
// Disconnect from SDL processes
|
||||
SDL_Quit();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,11 +37,6 @@ namespace Launcher
|
|||
QStringList getAvailableResolutions(int screen);
|
||||
QRect getMaximumResolution();
|
||||
|
||||
/**
|
||||
* Connect to the SDL so that we can use it to determine graphics
|
||||
* @return whether or not connecting to SDL is successful
|
||||
*/
|
||||
bool connectToSdl();
|
||||
bool setupSDL();
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <iostream>
|
||||
#include <csignal>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
|
@ -11,12 +12,24 @@
|
|||
#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 "maindialog.hpp"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
try
|
||||
{
|
||||
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
|
||||
SDL_SetMainReady();
|
||||
if (SDL_Init(SDL_INIT_VIDEO) != 0)
|
||||
{
|
||||
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);
|
||||
|
||||
// Now we make sure the current dir is set to application path
|
||||
|
@ -33,7 +46,9 @@ int main(int argc, char *argv[])
|
|||
if (result == Launcher::FirstRunDialogResultContinue)
|
||||
mainWin.show();
|
||||
|
||||
return app.exec();
|
||||
int returnValue = app.exec();
|
||||
SDL_Quit();
|
||||
return returnValue;
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
#include <components/version/version.hpp>
|
||||
|
||||
#include <QLabel>
|
||||
#include <QDate>
|
||||
#include <QTime>
|
||||
#include <QMessageBox>
|
||||
#include <QPushButton>
|
||||
#include <QFontDatabase>
|
||||
|
@ -10,6 +12,8 @@
|
|||
#include <QFileDialog>
|
||||
#include <QCloseEvent>
|
||||
#include <QTextCodec>
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
|
@ -17,7 +21,6 @@
|
|||
#include "graphicspage.hpp"
|
||||
#include "datafilespage.hpp"
|
||||
#include "settingspage.hpp"
|
||||
#include "advancedpage.hpp"
|
||||
|
||||
using namespace Process;
|
||||
|
||||
|
@ -90,23 +93,17 @@ void Launcher::MainDialog::createIcons()
|
|||
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget);
|
||||
graphicsButton->setIcon(QIcon(":/images/preferences-video.png"));
|
||||
graphicsButton->setIcon(QIcon::fromTheme("video-display"));
|
||||
graphicsButton->setText(tr("Graphics"));
|
||||
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
|
||||
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
QListWidgetItem *settingsButton = new QListWidgetItem(iconWidget);
|
||||
settingsButton->setIcon(QIcon(":/images/preferences.png"));
|
||||
settingsButton->setIcon(QIcon::fromTheme("preferences-system"));
|
||||
settingsButton->setText(tr("Settings"));
|
||||
settingsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
settingsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
QListWidgetItem *advancedButton = new QListWidgetItem(iconWidget);
|
||||
advancedButton->setIcon(QIcon(":/images/preferences-advanced.png"));
|
||||
advancedButton->setText(tr("Advanced"));
|
||||
advancedButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
|
||||
advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
|
||||
|
||||
connect(iconWidget,
|
||||
SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)),
|
||||
this, SLOT(changePage(QListWidgetItem*,QListWidgetItem*)));
|
||||
|
@ -119,7 +116,6 @@ void Launcher::MainDialog::createPages()
|
|||
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this);
|
||||
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
|
||||
mAdvancedPage = new AdvancedPage(mCfgMgr, mGameSettings, mEngineSettings, this);
|
||||
|
||||
// Set the combobox of the play page to imitate the combobox on the datafilespage
|
||||
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
|
||||
|
@ -130,7 +126,6 @@ void Launcher::MainDialog::createPages()
|
|||
pagesWidget->addWidget(mDataFilesPage);
|
||||
pagesWidget->addWidget(mGraphicsPage);
|
||||
pagesWidget->addWidget(mSettingsPage);
|
||||
pagesWidget->addWidget(mAdvancedPage);
|
||||
|
||||
// Select the first page
|
||||
iconWidget->setCurrentItem(iconWidget->item(0), QItemSelectionModel::Select);
|
||||
|
@ -139,8 +134,6 @@ void Launcher::MainDialog::createPages()
|
|||
|
||||
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
|
||||
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(int)));
|
||||
// Using Qt::QueuedConnection because signal is emitted in a subthread and slot is in the main thread
|
||||
connect(mDataFilesPage, SIGNAL(signalLoadedCellsChanged(QStringList)), mAdvancedPage, SLOT(slotLoadedCellsChanged(QStringList)), Qt::QueuedConnection);
|
||||
|
||||
}
|
||||
|
||||
|
@ -252,9 +245,6 @@ bool Launcher::MainDialog::reloadSettings()
|
|||
if (!mGraphicsPage->loadSettings())
|
||||
return false;
|
||||
|
||||
if (!mAdvancedPage->loadSettings())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -493,7 +483,6 @@ bool Launcher::MainDialog::writeSettings()
|
|||
mDataFilesPage->saveSettings();
|
||||
mGraphicsPage->saveSettings();
|
||||
mSettingsPage->saveSettings();
|
||||
mAdvancedPage->saveSettings();
|
||||
|
||||
QString userPath = QString::fromUtf8(mCfgMgr.getUserConfigPath().string().c_str());
|
||||
QDir dir(userPath);
|
||||
|
|
|
@ -30,7 +30,6 @@ namespace Launcher
|
|||
class DataFilesPage;
|
||||
class UnshieldThread;
|
||||
class SettingsPage;
|
||||
class AdvancedPage;
|
||||
|
||||
enum FirstRunDialogResult
|
||||
{
|
||||
|
@ -89,7 +88,6 @@ namespace Launcher
|
|||
GraphicsPage *mGraphicsPage;
|
||||
DataFilesPage *mDataFilesPage;
|
||||
SettingsPage *mSettingsPage;
|
||||
AdvancedPage *mAdvancedPage;
|
||||
|
||||
Process::ProcessInvoker *mGameInvoker;
|
||||
Process::ProcessInvoker *mWizardInvoker;
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
#include "cellnameloader.hpp"
|
||||
|
||||
#include <components/esm/loadcell.hpp>
|
||||
#include <components/contentselector/view/contentselector.hpp>
|
||||
|
||||
QSet<QString> CellNameLoader::getCellNames(QStringList &contentPaths)
|
||||
{
|
||||
QSet<QString> cellNames;
|
||||
ESM::ESMReader esmReader;
|
||||
|
||||
// Loop through all content files
|
||||
for (auto &contentPath : contentPaths) {
|
||||
esmReader.open(contentPath.toStdString());
|
||||
|
||||
// Loop through all records
|
||||
while(esmReader.hasMoreRecs())
|
||||
{
|
||||
ESM::NAME recordName = esmReader.getRecName();
|
||||
esmReader.getRecHeader();
|
||||
|
||||
if (isCellRecord(recordName)) {
|
||||
QString cellName = getCellName(esmReader);
|
||||
if (!cellName.isEmpty()) {
|
||||
cellNames.insert(cellName);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop loading content for this record and continue to the next
|
||||
esmReader.skipRecord();
|
||||
}
|
||||
}
|
||||
|
||||
return cellNames;
|
||||
}
|
||||
|
||||
bool CellNameLoader::isCellRecord(ESM::NAME &recordName)
|
||||
{
|
||||
return recordName.intval == ESM::REC_CELL;
|
||||
}
|
||||
|
||||
QString CellNameLoader::getCellName(ESM::ESMReader &esmReader)
|
||||
{
|
||||
ESM::Cell cell;
|
||||
bool isDeleted = false;
|
||||
cell.loadNameAndData(esmReader, isDeleted);
|
||||
|
||||
return QString::fromStdString(cell.mName);
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
#ifndef OPENMW_CELLNAMELOADER_H
|
||||
#define OPENMW_CELLNAMELOADER_H
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSet>
|
||||
#include <QString>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESM {class ESMReader; struct Cell;}
|
||||
namespace ContentSelectorView {class ContentSelector;}
|
||||
|
||||
class CellNameLoader {
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
* Returns the names of all cells contained within the given content files
|
||||
* @param contentPaths the file paths of each content file to be examined
|
||||
* @return the names of all cells
|
||||
*/
|
||||
QSet<QString> getCellNames(QStringList &contentPaths);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns whether or not the given record is of type "Cell"
|
||||
* @param name The name associated with the record
|
||||
* @return whether or not the given record is of type "Cell"
|
||||
*/
|
||||
bool isCellRecord(ESM::NAME &name);
|
||||
|
||||
/**
|
||||
* Returns the name of the cell
|
||||
* @param esmReader the reader currently pointed to a loaded cell
|
||||
* @return the name of the cell
|
||||
*/
|
||||
QString getCellName(ESM::ESMReader &esmReader);
|
||||
};
|
||||
|
||||
|
||||
#endif //OPENMW_CELLNAMELOADER_H
|
|
@ -3,7 +3,6 @@
|
|||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <components/misc/stringops.hpp>
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
@ -654,6 +653,12 @@ void MwIniImporter::setVerbose(bool verbose) {
|
|||
mVerbose = verbose;
|
||||
}
|
||||
|
||||
std::string MwIniImporter::numberToString(int n) {
|
||||
std::stringstream str;
|
||||
str << n;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
MwIniImporter::multistrmap MwIniImporter::loadIniFile(const boost::filesystem::path& filename) const {
|
||||
std::cout << "load ini file: " << filename << std::endl;
|
||||
|
||||
|
@ -795,7 +800,7 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
|
|||
multistrmap::const_iterator it = ini.begin();
|
||||
for(int i=0; it != ini.end(); i++) {
|
||||
archive = baseArchive;
|
||||
archive.append(std::to_string(i));
|
||||
archive.append(this->numberToString(i));
|
||||
|
||||
it = ini.find(archive);
|
||||
if(it == ini.end()) {
|
||||
|
@ -819,104 +824,33 @@ void MwIniImporter::importArchives(multistrmap &cfg, const multistrmap &ini) con
|
|||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::dependencySortStep(std::string& element, MwIniImporter::dependencyList& source, std::vector<std::string>& result)
|
||||
{
|
||||
auto iter = std::find_if(
|
||||
source.begin(),
|
||||
source.end(),
|
||||
[&element](std::pair< std::string, std::vector<std::string> >& sourceElement)
|
||||
{
|
||||
return sourceElement.first == element;
|
||||
}
|
||||
);
|
||||
if (iter != source.end())
|
||||
{
|
||||
auto foundElement = std::move(*iter);
|
||||
source.erase(iter);
|
||||
for (auto name : foundElement.second)
|
||||
{
|
||||
MwIniImporter::dependencySortStep(name, source, result);
|
||||
}
|
||||
result.push_back(std::move(foundElement.first));
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::string> MwIniImporter::dependencySort(MwIniImporter::dependencyList source)
|
||||
{
|
||||
std::vector<std::string> result;
|
||||
while (!source.empty())
|
||||
{
|
||||
MwIniImporter::dependencySortStep(source.begin()->first, source, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<std::string>::iterator MwIniImporter::findString(std::vector<std::string>& source, const std::string& string)
|
||||
{
|
||||
return std::find_if(source.begin(), source.end(), [&string](const std::string& sourceString)
|
||||
{
|
||||
return Misc::StringUtils::ciEqual(sourceString, string);
|
||||
});
|
||||
}
|
||||
|
||||
void MwIniImporter::addPaths(std::vector<boost::filesystem::path>& output, std::vector<std::string> input) {
|
||||
for (auto& path : input) {
|
||||
if (path.front() == '"')
|
||||
{
|
||||
path.erase(path.begin());
|
||||
path.erase(path.end() - 1);
|
||||
}
|
||||
output.emplace_back(path);
|
||||
}
|
||||
}
|
||||
|
||||
void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, const boost::filesystem::path& iniFilename) const
|
||||
{
|
||||
std::vector<std::pair<std::time_t, boost::filesystem::path>> 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;
|
||||
ToUTF8::Utf8Encoder encoder(mEncoding);
|
||||
|
||||
std::vector<boost::filesystem::path> dataPaths;
|
||||
if (cfg.count("data"))
|
||||
addPaths(dataPaths, cfg["data"]);
|
||||
|
||||
if (cfg.count("data-local"))
|
||||
addPaths(dataPaths, cfg["data-local"]);
|
||||
|
||||
dataPaths.push_back(iniFilename.parent_path() /= "Data Files");
|
||||
// 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++)
|
||||
{
|
||||
std::string gameFile = baseGameFile;
|
||||
gameFile.append(std::to_string(i));
|
||||
for(int i=0; it != ini.end(); i++) {
|
||||
gameFile = baseGameFile;
|
||||
gameFile.append(this->numberToString(i));
|
||||
|
||||
it = ini.find(gameFile);
|
||||
if(it == ini.end())
|
||||
if(it == ini.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
for(std::vector<std::string>::const_iterator entry = it->second.begin(); entry!=it->second.end(); ++entry)
|
||||
{
|
||||
for(std::vector<std::string>::const_iterator entry = it->second.begin(); entry!=it->second.end(); ++entry) {
|
||||
std::string filetype(entry->substr(entry->length()-3));
|
||||
Misc::StringUtils::lowerCaseInPlace(filetype);
|
||||
|
||||
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0)
|
||||
{
|
||||
bool found = false;
|
||||
for (auto & dataPath : dataPaths)
|
||||
{
|
||||
boost::filesystem::path path = dataPath / *entry;
|
||||
std::time_t time = lastWriteTime(path, defaultTime);
|
||||
if (time != defaultTime)
|
||||
{
|
||||
contentFiles.push_back({time, path});
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
std::cout << "Warning: " << *entry << " not found, ignoring" << std::endl;
|
||||
if(filetype.compare("esm") == 0 || filetype.compare("esp") == 0) {
|
||||
boost::filesystem::path filepath(gameFilesDir);
|
||||
filepath /= *entry;
|
||||
contentFiles.push_back(std::make_pair(lastWriteTime(filepath, defaultTime), *entry));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -924,46 +858,11 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co
|
|||
cfg.erase("content");
|
||||
cfg.insert( std::make_pair("content", std::vector<std::string>() ) );
|
||||
|
||||
// sort by timestamp
|
||||
// this will sort files by time order first, then alphabetical (maybe), I suspect non ASCII filenames will be stuffed.
|
||||
sort(contentFiles.begin(), contentFiles.end());
|
||||
|
||||
MwIniImporter::dependencyList unsortedFiles;
|
||||
|
||||
ESM::ESMReader reader;
|
||||
reader.setEncoder(&encoder);
|
||||
for (auto& file : contentFiles)
|
||||
{
|
||||
reader.open(file.second.string());
|
||||
std::vector<std::string> dependencies;
|
||||
for (auto& gameFile : reader.getGameFiles())
|
||||
{
|
||||
dependencies.push_back(gameFile.name);
|
||||
}
|
||||
unsortedFiles.emplace_back(boost::filesystem::path(reader.getName()).filename().string(), dependencies);
|
||||
reader.close();
|
||||
for(std::vector<std::pair<std::time_t, std::string> >::const_iterator iter=contentFiles.begin(); iter!=contentFiles.end(); ++iter) {
|
||||
cfg["content"].push_back(iter->second);
|
||||
}
|
||||
|
||||
auto sortedFiles = dependencySort(unsortedFiles);
|
||||
|
||||
// hard-coded dependency Morrowind - Tribunal - Bloodmoon
|
||||
if(findString(sortedFiles, "Morrowind.esm") != sortedFiles.end())
|
||||
{
|
||||
auto tribunalIter = findString(sortedFiles, "Tribunal.esm");
|
||||
auto bloodmoonIter = findString(sortedFiles, "Bloodmoon.esm");
|
||||
|
||||
if (bloodmoonIter != sortedFiles.end() && tribunalIter != sortedFiles.end())
|
||||
{
|
||||
size_t bloodmoonIndex = std::distance(sortedFiles.begin(), bloodmoonIter);
|
||||
size_t tribunalIndex = std::distance(sortedFiles.begin(), tribunalIter);
|
||||
if (bloodmoonIndex < tribunalIndex)
|
||||
tribunalIndex++;
|
||||
sortedFiles.insert(bloodmoonIter, *tribunalIter);
|
||||
sortedFiles.erase(sortedFiles.begin() + tribunalIndex);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& file : sortedFiles)
|
||||
cfg["content"].push_back(file);
|
||||
}
|
||||
|
||||
void MwIniImporter::writeToFile(std::ostream &out, const multistrmap &cfg) {
|
||||
|
@ -1002,5 +901,9 @@ std::time_t MwIniImporter::lastWriteTime(const boost::filesystem::path& filename
|
|||
std::cout << "content file: " << resolved << " timestamp = (" << writeTime <<
|
||||
") " << timeStrBuffer << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "content file: " << filename << " not found" << std::endl;
|
||||
}
|
||||
return writeTime;
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ class MwIniImporter {
|
|||
public:
|
||||
typedef std::map<std::string, std::string> strmap;
|
||||
typedef std::map<std::string, std::vector<std::string> > multistrmap;
|
||||
typedef std::vector< std::pair< std::string, std::vector<std::string> > > dependencyList;
|
||||
|
||||
MwIniImporter();
|
||||
void setInputEncoding(const ToUTF8::FromType& encoding);
|
||||
|
@ -28,14 +27,9 @@ class MwIniImporter {
|
|||
void importArchives(multistrmap &cfg, const multistrmap &ini) const;
|
||||
static void writeToFile(std::ostream &out, const multistrmap &cfg);
|
||||
|
||||
static std::vector<std::string> dependencySort(MwIniImporter::dependencyList source);
|
||||
|
||||
private:
|
||||
static void dependencySortStep(std::string& element, MwIniImporter::dependencyList& source, std::vector<std::string>& result);
|
||||
static std::vector<std::string>::iterator findString(std::vector<std::string>& source, const std::string& string);
|
||||
|
||||
static void insertMultistrmap(multistrmap &cfg, const std::string& key, const std::string& value);
|
||||
static void addPaths(std::vector<boost::filesystem::path>& output, std::vector<std::string> input);
|
||||
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);
|
||||
|
@ -46,4 +40,5 @@ class MwIniImporter {
|
|||
ToUTF8::FromType mEncoding;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,12 +33,12 @@ bool hasExtension(std::string filename, std::string extensionToFind)
|
|||
}
|
||||
|
||||
///See if the file has the "nif" extension.
|
||||
bool isNIF(const std::string & filename)
|
||||
bool isNIF(std::string filename)
|
||||
{
|
||||
return hasExtension(filename,"nif");
|
||||
}
|
||||
///See if the file has the "bsa" extension.
|
||||
bool isBSA(const std::string & filename)
|
||||
bool isBSA(std::string filename)
|
||||
{
|
||||
return hasExtension(filename,"bsa");
|
||||
}
|
||||
|
|
|
@ -81,14 +81,14 @@ opencs_units_noqt (view/world
|
|||
|
||||
opencs_units (view/widget
|
||||
scenetoolbar scenetool scenetoolmode pushbutton scenetooltoggle scenetoolrun modebutton
|
||||
scenetooltoggle2 scenetooltexturebrush completerpopup coloreditor colorpickerpopup droplineedit
|
||||
scenetooltoggle2 completerpopup coloreditor colorpickerpopup droplineedit
|
||||
)
|
||||
|
||||
opencs_units (view/render
|
||||
scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget
|
||||
previewwidget editmode instancemode instanceselectionmode instancemovemode
|
||||
orbitcameramode pathgridmode selectionmode pathgridselectionmode cameracontroller
|
||||
cellwater terraintexturemode
|
||||
cellwater
|
||||
)
|
||||
|
||||
opencs_units_noqt (view/render
|
||||
|
@ -246,7 +246,7 @@ if (DESIRED_QT_VERSION MATCHES 4)
|
|||
target_link_libraries(openmw-cs ${QT_QTMAIN_LIBRARY})
|
||||
endif()
|
||||
else()
|
||||
target_link_libraries(openmw-cs Qt5::Widgets Qt5::Core Qt5::Network Qt5::OpenGL)
|
||||
qt5_use_modules(openmw-cs Widgets Core Network OpenGL)
|
||||
endif()
|
||||
|
||||
if (WIN32)
|
||||
|
|
|
@ -5,9 +5,6 @@
|
|||
#include <QLocalSocket>
|
||||
#include <QMessageBox>
|
||||
|
||||
|
||||
#include <components/crashcatcher/crashcatcher.hpp>
|
||||
|
||||
#include <components/fallback/validate.hpp>
|
||||
|
||||
#include <components/nifosg/nifloader.hpp>
|
||||
|
@ -21,16 +18,12 @@
|
|||
|
||||
using namespace Fallback;
|
||||
|
||||
CS::Editor::Editor (int argc, char **argv)
|
||||
CS::Editor::Editor ()
|
||||
: mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr),
|
||||
mViewManager (mDocumentManager), mPid(""),
|
||||
mLock(), mMerge (mDocumentManager),
|
||||
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL)
|
||||
{
|
||||
// install the crash handler as soon as possible. note that the log path
|
||||
// does not depend on config being read.
|
||||
crashCatcherInstall(argc, argv, (mCfgMgr.getLogPath() / "openmw-cs-crash.log").string());
|
||||
|
||||
std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
|
||||
|
||||
setupDataFiles (config.first);
|
||||
|
|
|
@ -66,7 +66,7 @@ namespace CS
|
|||
|
||||
public:
|
||||
|
||||
Editor (int argc, char **argv);
|
||||
Editor ();
|
||||
~Editor ();
|
||||
|
||||
bool makeIPCServer();
|
||||
|
|
|
@ -8,9 +8,8 @@
|
|||
#include <QIcon>
|
||||
#include <QMetaType>
|
||||
|
||||
#include <components/misc/debugging.hpp>
|
||||
|
||||
#include "model/doc/messages.hpp"
|
||||
|
||||
#include "model/world/universalid.hpp"
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
|
@ -42,43 +41,45 @@ class Application : public QApplication
|
|||
Application (int& argc, char *argv[]) : QApplication (argc, argv) {}
|
||||
};
|
||||
|
||||
int runApplication(int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
||||
#endif
|
||||
#ifdef Q_OS_MAC
|
||||
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
|
||||
#endif
|
||||
|
||||
// To allow background thread drawing in OSG
|
||||
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
|
||||
|
||||
Q_INIT_RESOURCE (resources);
|
||||
|
||||
qRegisterMetaType<std::string> ("std::string");
|
||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||
|
||||
Application application (argc, argv);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
#endif
|
||||
|
||||
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
||||
|
||||
CS::Editor editor(argc, argv);
|
||||
|
||||
if(!editor.makeIPCServer())
|
||||
try
|
||||
{
|
||||
editor.connectToIPCServer();
|
||||
// To allow background thread drawing in OSG
|
||||
QApplication::setAttribute(Qt::AA_X11InitThreads, true);
|
||||
|
||||
Q_INIT_RESOURCE (resources);
|
||||
|
||||
qRegisterMetaType<std::string> ("std::string");
|
||||
qRegisterMetaType<CSMWorld::UniversalId> ("CSMWorld::UniversalId");
|
||||
qRegisterMetaType<CSMDoc::Message> ("CSMDoc::Message");
|
||||
|
||||
Application application (argc, argv);
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QDir dir(QCoreApplication::applicationDirPath());
|
||||
QDir::setCurrent(dir.absolutePath());
|
||||
#endif
|
||||
|
||||
application.setWindowIcon (QIcon (":./openmw-cs.png"));
|
||||
|
||||
CS::Editor editor;
|
||||
|
||||
if(!editor.makeIPCServer())
|
||||
{
|
||||
editor.connectToIPCServer();
|
||||
return 0;
|
||||
}
|
||||
return editor.run();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "ERROR: " << e.what() << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return editor.run();
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return wrapApplication(&runApplication, argc, argv, "/openmw-cs.log");
|
||||
}
|
||||
|
|
|
@ -320,13 +320,12 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
|
|||
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool)));
|
||||
|
||||
connect (&mTools, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mTools, SIGNAL (done (int, bool)), this, SIGNAL (operationDone (int, bool)));
|
||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone2 (int, bool)));
|
||||
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
|
||||
this, SIGNAL (mergeDone (CSMDoc::Document*)));
|
||||
|
||||
connect (&mSaving, SIGNAL (progress (int, int, int)), this, SLOT (progress (int, int, int)));
|
||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone2 (int, bool)));
|
||||
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool)));
|
||||
|
||||
connect (
|
||||
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
|
||||
|
@ -438,7 +437,7 @@ void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
|
|||
std::cout << message.mMessage << std::endl;
|
||||
}
|
||||
|
||||
void CSMDoc::Document::operationDone2 (int type, bool failed)
|
||||
void CSMDoc::Document::operationDone (int type, bool failed)
|
||||
{
|
||||
if (type==CSMDoc::State_Saving && !failed)
|
||||
mDirty = false;
|
||||
|
|
|
@ -168,15 +168,13 @@ namespace CSMDoc
|
|||
/// document. This signal must be handled to avoid a leak.
|
||||
void mergeDone (CSMDoc::Document *document);
|
||||
|
||||
void operationDone (int type, bool failed);
|
||||
|
||||
private slots:
|
||||
|
||||
void modificationStateChanged (bool clean);
|
||||
|
||||
void reportMessage (const CSMDoc::Message& message, int type);
|
||||
|
||||
void operationDone2 (int type, bool failed);
|
||||
void operationDone (int type, bool failed);
|
||||
|
||||
void runStateChanged();
|
||||
|
||||
|
|
|
@ -579,7 +579,7 @@ bool CSMFilter::Parser::parse (const std::string& filter, bool allowPredefined)
|
|||
}
|
||||
// We do not use isString() here, because there could be a pre-defined filter with an ID that is
|
||||
// equal a filter keyword.
|
||||
else if (token.mType==Token::Type_String)
|
||||
else if (token.mType==Token::Type_String && allowPredefined)
|
||||
{
|
||||
if (getNextToken()!=Token (Token::Type_EOS))
|
||||
{
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace CSMPrefs
|
|||
ShortcutMap::iterator shortcutListIt = mWidgetShortcuts.find(widget);
|
||||
if (shortcutListIt != mWidgetShortcuts.end())
|
||||
{
|
||||
shortcutListIt->second.erase(std::remove(shortcutListIt->second.begin(), shortcutListIt->second.end(), shortcut), shortcutListIt->second.end());
|
||||
std::remove(shortcutListIt->second.begin(), shortcutListIt->second.end(), shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -123,7 +123,6 @@ void CSMPrefs::State::declare()
|
|||
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
|
||||
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
|
||||
declareEnum ("double-sc", "Shift Control Double Click", actionNone).addValues (reportValues);
|
||||
declareBool("ignore-base-records", "Ignore base records in verifier", false);
|
||||
|
||||
declareCategory ("Search & Replace");
|
||||
declareInt ("char-before", "Characters before search string", 10).
|
||||
|
@ -201,9 +200,6 @@ void CSMPrefs::State::declare()
|
|||
declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1);
|
||||
|
||||
declareCategory ("Rendering");
|
||||
declareInt ("framerate-limit", "FPS limit", 60).
|
||||
setTooltip("Framerate limit in 3D preview windows. Zero value means \"unlimited\".").
|
||||
setRange(0, 10000);
|
||||
declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170);
|
||||
declareBool ("camera-ortho", "Orthographic projection for camera", false);
|
||||
declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).
|
||||
|
@ -226,15 +222,7 @@ void CSMPrefs::State::declare()
|
|||
EnumValues insertOutsideVisibleCell;
|
||||
insertOutsideVisibleCell.add (showAndInsert).add (dontInsert).add (insertAnyway);
|
||||
|
||||
EnumValue createAndLandEdit ("Create cell and land, then edit");
|
||||
EnumValue showAndLandEdit ("Show cell and edit");
|
||||
EnumValue dontLandEdit ("Discard");
|
||||
EnumValues landeditOutsideCell;
|
||||
landeditOutsideCell.add (createAndLandEdit).add (dontLandEdit);
|
||||
EnumValues landeditOutsideVisibleCell;
|
||||
landeditOutsideVisibleCell.add (showAndLandEdit).add (dontLandEdit);
|
||||
|
||||
declareCategory ("3D Scene Editing");
|
||||
declareCategory ("Scene Drops");
|
||||
declareInt ("distance", "Drop Distance", 50).
|
||||
setTooltip ("If an instance drop can not be placed against another object at the "
|
||||
"insert point, it will be placed by this distance from the insert point instead");
|
||||
|
@ -242,12 +230,6 @@ void CSMPrefs::State::declare()
|
|||
addValues (insertOutsideCell);
|
||||
declareEnum ("outside-visible-drop", "Handling drops outside of visible cells", showAndInsert).
|
||||
addValues (insertOutsideVisibleCell);
|
||||
declareEnum ("outside-landedit", "Handling land edit outside of cells", createAndLandEdit).
|
||||
addValues (landeditOutsideCell);
|
||||
declareEnum ("outside-visible-landedit", "Handling land edit outside of visible cells", showAndLandEdit).
|
||||
addValues (landeditOutsideVisibleCell);
|
||||
declareInt ("texturebrush-maximumsize", "Maximum texture brush size", 50).
|
||||
setMin (1);
|
||||
|
||||
declareCategory ("Key Bindings");
|
||||
|
||||
|
|
|
@ -5,20 +5,14 @@
|
|||
|
||||
#include <components/esm/loadbsgn.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
|
||||
: mBirthsigns (birthsigns)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::BirthsignCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mBirthsigns.getSize();
|
||||
}
|
||||
|
||||
|
@ -26,8 +20,7 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
|
|||
{
|
||||
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::BirthSign& birthsign = record.get();
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class BirthsignCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "bodypartcheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
||||
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
|
||||
const CSMWorld::Resources &meshes,
|
||||
|
@ -9,14 +7,10 @@ CSMTools::BodyPartCheckStage::BodyPartCheckStage(
|
|||
mBodyParts(bodyParts),
|
||||
mMeshes(meshes),
|
||||
mRaces(races)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{ }
|
||||
|
||||
int CSMTools::BodyPartCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mBodyParts.getSize();
|
||||
}
|
||||
|
||||
|
@ -24,8 +18,7 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
|
|||
{
|
||||
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if ( record.isDeleted() )
|
||||
return;
|
||||
|
||||
const ESM::BodyPart &bodyPart = record.get();
|
||||
|
|
|
@ -17,7 +17,6 @@ namespace CSMTools
|
|||
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
|
||||
const CSMWorld::Resources &mMeshes;
|
||||
const CSMWorld::IdCollection<ESM::Race> &mRaces;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
BodyPartCheckStage(
|
||||
|
|
|
@ -6,20 +6,14 @@
|
|||
#include <components/esm/loadclas.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
|
||||
: mClasses (classes)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::ClassCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mClasses.getSize();
|
||||
}
|
||||
|
||||
|
@ -27,21 +21,19 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Class& class_ = record.get();
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Class, class_.mId);
|
||||
|
||||
// A class should have a name
|
||||
// test for empty name and description
|
||||
if (class_.mName.empty())
|
||||
messages.push_back (std::make_pair (id, class_.mId + " doesn't have a name"));
|
||||
messages.push_back (std::make_pair (id, class_.mId + " has an empty name"));
|
||||
|
||||
// A playable class should have a description
|
||||
if (class_.mData.mIsPlayable != 0 && class_.mDescription.empty())
|
||||
messages.push_back (std::make_pair (id, class_.mId + " doesn't have a description and it's playable"));
|
||||
if (class_.mDescription.empty())
|
||||
messages.push_back (std::make_pair (id, class_.mId + " has an empty description"));
|
||||
|
||||
// test for invalid attributes
|
||||
for (int i=0; i<2; ++i)
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class ClassCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Class>& mClasses;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -6,20 +6,14 @@
|
|||
#include <components/esm/loadfact.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
|
||||
: mFactions (factions)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::FactionCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mFactions.getSize();
|
||||
}
|
||||
|
||||
|
@ -27,8 +21,7 @@ void CSMTools::FactionCheckStage::perform (int stage, CSMDoc::Messages& messages
|
|||
{
|
||||
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Faction& faction = record.get();
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class FactionCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,20 +2,14 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/defaultgmsts.hpp"
|
||||
|
||||
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
|
||||
: mGameSettings(gameSettings)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::GmstCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mGameSettings.getSize();
|
||||
}
|
||||
|
||||
|
@ -23,8 +17,7 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::GameSetting& gmst = record.get();
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace CSMTools
|
|||
private:
|
||||
|
||||
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
std::string varTypeToString(ESM::VarType);
|
||||
|
||||
|
|
|
@ -3,19 +3,13 @@
|
|||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
|
||||
const CSMWorld::InfoCollection& journalInfos)
|
||||
: mJournals(journals), mJournalInfos(journalInfos)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::JournalCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mJournals.getSize();
|
||||
}
|
||||
|
||||
|
@ -23,8 +17,7 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && journalRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || journalRecord.isDeleted())
|
||||
if (journalRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Dialogue &journal = journalRecord.get();
|
||||
|
@ -50,10 +43,6 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
|||
statusNamedCount += 1;
|
||||
}
|
||||
|
||||
// Skip "Base" records (setting!)
|
||||
if (mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||
continue;
|
||||
|
||||
if (journalInfo.mResponse.empty())
|
||||
{
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);
|
||||
|
|
|
@ -28,7 +28,6 @@ namespace CSMTools
|
|||
|
||||
const CSMWorld::IdCollection<ESM::Dialogue>& mJournals;
|
||||
const CSMWorld::InfoCollection& mJournalInfos;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/resources.hpp"
|
||||
#include "../world/data.hpp"
|
||||
|
||||
|
@ -79,26 +77,16 @@ CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollect
|
|||
mReferenceables(referenceables),
|
||||
mIcons(icons),
|
||||
mTextures(textures)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::MagicEffectCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mMagicEffects.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::MagicEffect> &record = mMagicEffects.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
ESM::MagicEffect effect = record.get();
|
||||
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
|
||||
|
||||
if (effect.mData.mBaseCost < 0.0f)
|
||||
|
|
|
@ -24,7 +24,6 @@ namespace CSMTools
|
|||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
const CSMWorld::Resources &mIcons;
|
||||
const CSMWorld::Resources &mTextures;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
private:
|
||||
bool isTextureExists(const std::string &texture, bool isIcon) const;
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
#include "../world/idcollection.hpp"
|
||||
#include "../world/subcellcollection.hpp"
|
||||
|
@ -12,14 +10,10 @@
|
|||
|
||||
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
|
||||
: mPathgrids (pathgrids)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::PathgridCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mPathgrids.getSize();
|
||||
}
|
||||
|
||||
|
@ -27,8 +21,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
{
|
||||
const CSMWorld::Record<CSMWorld::Pathgrid>& record = mPathgrids.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const CSMWorld::Pathgrid& pathgrid = record.get();
|
||||
|
@ -36,7 +29,7 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
|
|||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Pathgrid, pathgrid.mId);
|
||||
|
||||
// check the number of pathgrid points
|
||||
if (pathgrid.mData.mS2 < static_cast<int>(pathgrid.mPoints.size()))
|
||||
if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||
messages.add (id, pathgrid.mId + " has less points than expected", "", CSMDoc::Message::Severity_Error);
|
||||
else if (pathgrid.mData.mS2 > static_cast<int>(pathgrid.mPoints.size()))
|
||||
messages.add (id, pathgrid.mId + " has more points than expected", "", CSMDoc::Message::Severity_Error);
|
||||
|
|
|
@ -25,7 +25,6 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
|
||||
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
#include <components/esm/loadrace.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& messages)
|
||||
|
@ -17,14 +15,6 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
|
|||
|
||||
const ESM::Race& race = record.get();
|
||||
|
||||
// Consider mPlayable flag even when "Base" records are ignored
|
||||
if (race.mData.mFlags & 0x1)
|
||||
mPlayable = true;
|
||||
|
||||
// Skip "Base" records (setting!)
|
||||
if (mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||
return;
|
||||
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);
|
||||
|
||||
// test for empty name and description
|
||||
|
@ -48,6 +38,10 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
|
|||
if (race.mData.mWeight.mFemale<0)
|
||||
messages.push_back (std::make_pair (id, "female " + race.mId + " has negative weight"));
|
||||
|
||||
// remember playable flag
|
||||
if (race.mData.mFlags & 0x1)
|
||||
mPlayable = true;
|
||||
|
||||
/// \todo check data members that can't be edited in the table view
|
||||
}
|
||||
|
||||
|
@ -61,15 +55,11 @@ void CSMTools::RaceCheckStage::performFinal (CSMDoc::Messages& messages)
|
|||
|
||||
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
|
||||
: mRaces (races), mPlayable (false)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::RaceCheckStage::setup()
|
||||
{
|
||||
mPlayable = false;
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mRaces.getSize()+1;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::IdCollection<ESM::Race>& mRaces;
|
||||
bool mPlayable;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
void performPerRecord (int stage, CSMDoc::Messages& messages);
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/record.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
|
@ -20,7 +18,6 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
|
|||
mScripts(scripts),
|
||||
mPlayerPresent(false)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
|
@ -231,8 +228,6 @@ void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& me
|
|||
int CSMTools::ReferenceableCheckStage::setup()
|
||||
{
|
||||
mPlayerPresent = false;
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mReferencables.getSize() + 1;
|
||||
}
|
||||
|
||||
|
@ -243,9 +238,10 @@ void CSMTools::ReferenceableCheckStage::bookCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Book& book = (dynamic_cast<const CSMWorld::Record<ESM::Book>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Book, book.mId);
|
||||
|
@ -263,9 +259,10 @@ void CSMTools::ReferenceableCheckStage::activatorCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Activator& activator = (dynamic_cast<const CSMWorld::Record<ESM::Activator>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Activator, activator.mId);
|
||||
|
@ -285,9 +282,10 @@ void CSMTools::ReferenceableCheckStage::potionCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Potion& potion = (dynamic_cast<const CSMWorld::Record<ESM::Potion>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Potion, potion.mId);
|
||||
|
@ -307,9 +305,10 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Apparatus& apparatus = (dynamic_cast<const CSMWorld::Record<ESM::Apparatus>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Apparatus, apparatus.mId);
|
||||
|
@ -329,9 +328,10 @@ void CSMTools::ReferenceableCheckStage::armorCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Armor& armor = (dynamic_cast<const CSMWorld::Record<ESM::Armor>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Armor, armor.mId);
|
||||
|
@ -357,9 +357,10 @@ void CSMTools::ReferenceableCheckStage::clothingCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Clothing& clothing = (dynamic_cast<const CSMWorld::Record<ESM::Clothing>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Clothing, clothing.mId);
|
||||
|
@ -376,9 +377,10 @@ void CSMTools::ReferenceableCheckStage::containerCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Container& container = (dynamic_cast<const CSMWorld::Record<ESM::Container>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Container, container.mId);
|
||||
|
@ -409,8 +411,7 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
|
||||
|
@ -486,8 +487,7 @@ void CSMTools::ReferenceableCheckStage::doorCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Door& door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
|
||||
|
@ -511,9 +511,10 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Ingredient& ingredient = (dynamic_cast<const CSMWorld::Record<ESM::Ingredient>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Ingredient, ingredient.mId);
|
||||
|
@ -531,9 +532,10 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::CreatureLevList& CreatureLevList = (dynamic_cast<const CSMWorld::Record<ESM::CreatureLevList>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_CreatureLevelledList, CreatureLevList.mId); //CreatureLevList but Type_CreatureLevelledList :/
|
||||
|
@ -548,9 +550,10 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId);
|
||||
|
@ -564,8 +567,7 @@ void CSMTools::ReferenceableCheckStage::lightCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
|
||||
|
@ -575,8 +577,13 @@ void CSMTools::ReferenceableCheckStage::lightCheck(
|
|||
messages.push_back (std::make_pair (id, light.mId + " has negative light radius"));
|
||||
|
||||
if (light.mData.mFlags & ESM::Light::Carry)
|
||||
{
|
||||
inventoryItemCheck<ESM::Light>(light, messages, id.toString());
|
||||
|
||||
if (light.mData.mTime == 0)
|
||||
messages.push_back (std::make_pair (id, light.mId + " has zero duration"));
|
||||
}
|
||||
|
||||
// Check that mentioned scripts exist
|
||||
scriptCheck<ESM::Light>(light, messages, id.toString());
|
||||
}
|
||||
|
@ -588,9 +595,10 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Lockpick& lockpick = (dynamic_cast<const CSMWorld::Record<ESM::Lockpick>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Lockpick, lockpick.mId);
|
||||
|
@ -610,9 +618,10 @@ void CSMTools::ReferenceableCheckStage::miscCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Miscellaneous& miscellaneous = (dynamic_cast<const CSMWorld::Record<ESM::Miscellaneous>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Miscellaneous, miscellaneous.mId);
|
||||
|
@ -635,21 +644,17 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId);
|
||||
|
||||
short level(npc.mNpdt52.mLevel);
|
||||
char disposition(npc.mNpdt52.mDisposition);
|
||||
char reputation(npc.mNpdt52.mReputation);
|
||||
char rank(npc.mNpdt52.mRank);
|
||||
//Don't know what unknown is for
|
||||
int gold(npc.mNpdt52.mGold);
|
||||
|
||||
//Detect if player is present
|
||||
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
|
||||
mPlayerPresent = true;
|
||||
|
||||
// Skip "Base" records (setting!)
|
||||
if (mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
|
||||
return;
|
||||
|
||||
short level(npc.mNpdt.mLevel);
|
||||
char disposition(npc.mNpdt.mDisposition);
|
||||
char reputation(npc.mNpdt.mReputation);
|
||||
char rank(npc.mNpdt.mRank);
|
||||
//Don't know what unknown is for
|
||||
int gold(npc.mNpdt.mGold);
|
||||
|
||||
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
|
||||
{
|
||||
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
|
||||
|
@ -658,36 +663,36 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
return;
|
||||
}
|
||||
|
||||
level = npc.mNpdt.mLevel;
|
||||
disposition = npc.mNpdt.mDisposition;
|
||||
reputation = npc.mNpdt.mReputation;
|
||||
rank = npc.mNpdt.mRank;
|
||||
gold = npc.mNpdt.mGold;
|
||||
level = npc.mNpdt12.mLevel;
|
||||
disposition = npc.mNpdt12.mDisposition;
|
||||
reputation = npc.mNpdt12.mReputation;
|
||||
rank = npc.mNpdt12.mRank;
|
||||
gold = npc.mNpdt12.mGold;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (npc.mNpdt.mAgility == 0)
|
||||
if (npc.mNpdt52.mAgility == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " agility has zero value"));
|
||||
|
||||
if (npc.mNpdt.mEndurance == 0)
|
||||
if (npc.mNpdt52.mEndurance == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " endurance has zero value"));
|
||||
|
||||
if (npc.mNpdt.mIntelligence == 0)
|
||||
if (npc.mNpdt52.mIntelligence == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " intelligence has zero value"));
|
||||
|
||||
if (npc.mNpdt.mLuck == 0)
|
||||
if (npc.mNpdt52.mLuck == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " luck has zero value"));
|
||||
|
||||
if (npc.mNpdt.mPersonality == 0)
|
||||
if (npc.mNpdt52.mPersonality == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " personality has zero value"));
|
||||
|
||||
if (npc.mNpdt.mStrength == 0)
|
||||
if (npc.mNpdt52.mStrength == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " strength has zero value"));
|
||||
|
||||
if (npc.mNpdt.mSpeed == 0)
|
||||
if (npc.mNpdt52.mSpeed == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " speed has zero value"));
|
||||
|
||||
if (npc.mNpdt.mWillpower == 0)
|
||||
if (npc.mNpdt52.mWillpower == 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " willpower has zero value"));
|
||||
}
|
||||
|
||||
|
@ -701,14 +706,22 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
|
|||
messages.push_back (std::make_pair (id, npc.mId + " has any empty name"));
|
||||
|
||||
if (npc.mClass.empty())
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has an empty class"));
|
||||
{
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has any empty class"));
|
||||
}
|
||||
else if (mClasses.searchId (npc.mClass) == -1)
|
||||
{
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has invalid class"));
|
||||
}
|
||||
|
||||
if (npc.mRace.empty())
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has an empty race"));
|
||||
{
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has any empty race"));
|
||||
}
|
||||
else if (mRaces.searchId (npc.mRace) == -1)
|
||||
{
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has invalid race"));
|
||||
}
|
||||
|
||||
if (disposition < 0)
|
||||
messages.push_back (std::make_pair (id, npc.mId + " has negative disposition"));
|
||||
|
@ -748,8 +761,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
|
||||
|
@ -811,7 +823,7 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
|
|||
{
|
||||
//checking of health
|
||||
if (weapon.mData.mHealth <= 0)
|
||||
messages.push_back (std::make_pair (id, weapon.mId + " has non-positive health"));
|
||||
messages.push_back (std::make_pair (id, weapon.mId + " has non-positivie health"));
|
||||
|
||||
if (weapon.mData.mReach < 0)
|
||||
messages.push_back (std::make_pair (id, weapon.mId + " has negative reach"));
|
||||
|
@ -829,9 +841,10 @@ void CSMTools::ReferenceableCheckStage::probeCheck(
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::Probe& probe = (dynamic_cast<const CSMWorld::Record<ESM::Probe>& >(baseRecord)).get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_Probe, probe.mId);
|
||||
|
@ -849,8 +862,7 @@ void CSMTools::ReferenceableCheckStage::repairCheck (
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
|
||||
|
@ -869,8 +881,7 @@ void CSMTools::ReferenceableCheckStage::staticCheck (
|
|||
{
|
||||
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
|
||||
if (baseRecord.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();
|
||||
|
|
|
@ -82,7 +82,6 @@ namespace CSMTools
|
|||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
||||
bool mPlayerPresent;
|
||||
bool mIgnoreBaseRecords;
|
||||
};
|
||||
}
|
||||
#endif // REFERENCEABLECHECKSTAGE_H
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
#include "referencecheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
||||
const CSMWorld::RefCollection& references,
|
||||
const CSMWorld::RefIdCollection& referencables,
|
||||
|
@ -14,15 +12,13 @@ CSMTools::ReferenceCheckStage::ReferenceCheckStage(
|
|||
mCells(cells),
|
||||
mFactions(factions)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const CSMWorld::CellRef& cellRef = record.get();
|
||||
|
@ -104,7 +100,5 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
|
|||
|
||||
int CSMTools::ReferenceCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mReferences.getSize();
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@ namespace CSMTools
|
|||
const CSMWorld::RefIdData& mDataSet;
|
||||
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
|
||||
const CSMWorld::IdCollection<ESM::Faction>& mFactions;
|
||||
bool mIgnoreBaseRecords;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -5,20 +5,14 @@
|
|||
|
||||
#include <components/esm/loadregn.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
|
||||
: mRegions (regions)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::RegionCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mRegions.getSize();
|
||||
}
|
||||
|
||||
|
@ -26,8 +20,7 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Region& region = record.get();
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class RegionCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Region>& mRegions;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -60,8 +60,6 @@ CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
|
|||
|
||||
Compiler::registerExtensions (mExtensions);
|
||||
mContext.setExtensions (&mExtensions);
|
||||
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
|
||||
int CSMTools::ScriptCheckStage::setup()
|
||||
|
@ -80,25 +78,17 @@ int CSMTools::ScriptCheckStage::setup()
|
|||
mId.clear();
|
||||
Compiler::ErrorHandler::reset();
|
||||
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mDocument.getData().getScripts().getSize();
|
||||
}
|
||||
|
||||
void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::Script> &record = mDocument.getData().getScripts().getRecord(stage);
|
||||
|
||||
mId = mDocument.getData().getScripts().getId (stage);
|
||||
|
||||
if (mDocument.isBlacklisted (
|
||||
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
|
||||
return;
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
return;
|
||||
|
||||
mMessages = &messages;
|
||||
|
||||
switch (mWarningMode)
|
||||
|
@ -110,8 +100,10 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
|
||||
try
|
||||
{
|
||||
mFile = record.get().mId;
|
||||
std::istringstream input (record.get().mScriptText);
|
||||
const CSMWorld::Data& data = mDocument.getData();
|
||||
|
||||
mFile = data.getScripts().getRecord (stage).get().mId;
|
||||
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
|
||||
|
||||
Compiler::Scanner scanner (*this, input, mContext.getExtensions());
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ namespace CSMTools
|
|||
std::string mFile;
|
||||
CSMDoc::Messages *mMessages;
|
||||
WarningMode mWarningMode;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
CSMDoc::Message::Severity getSeverity (Type type);
|
||||
|
||||
|
|
|
@ -22,8 +22,7 @@ void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model,
|
|||
|
||||
int pos = 0;
|
||||
|
||||
Qt::CaseSensitivity caseSensitivity = mCase ? Qt::CaseSensitive : Qt::CaseInsensitive;
|
||||
while ((pos = text.indexOf (search, pos, caseSensitivity))!=-1)
|
||||
while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1)
|
||||
{
|
||||
std::ostringstream hint;
|
||||
hint
|
||||
|
@ -121,26 +120,25 @@ QString CSMTools::Search::flatten (const QString& text) const
|
|||
return flat;
|
||||
}
|
||||
|
||||
CSMTools::Search::Search() : mType (Type_None), mValue (0), mCase (false), mIdColumn (0), mTypeColumn (0),
|
||||
CSMTools::Search::Search() : mType (Type_None), mValue (0), mIdColumn (0), mTypeColumn (0),
|
||||
mPaddingBefore (10), mPaddingAfter (10) {}
|
||||
|
||||
CSMTools::Search::Search (Type type, bool caseSensitive, const std::string& value)
|
||||
: mType (type), mText (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
CSMTools::Search::Search (Type type, const std::string& value)
|
||||
: mType (type), mText (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
if (type!=Type_Text && type!=Type_Id)
|
||||
throw std::logic_error ("Invalid search parameter (string)");
|
||||
}
|
||||
|
||||
CSMTools::Search::Search (Type type, bool caseSensitive, const QRegExp& value)
|
||||
: mType (type), mRegExp (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
CSMTools::Search::Search (Type type, const QRegExp& value)
|
||||
: mType (type), mRegExp (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
mRegExp.setCaseSensitivity(mCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
|
||||
if (type!=Type_TextRegEx && type!=Type_IdRegEx)
|
||||
throw std::logic_error ("Invalid search parameter (RegExp)");
|
||||
}
|
||||
|
||||
CSMTools::Search::Search (Type type, bool caseSensitive, int value)
|
||||
: mType (type), mValue (value), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
CSMTools::Search::Search (Type type, int value)
|
||||
: mType (type), mValue (value), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
|
||||
{
|
||||
if (type!=Type_RecordState)
|
||||
throw std::logic_error ("invalid search parameter (int)");
|
||||
|
|
|
@ -43,7 +43,6 @@ namespace CSMTools
|
|||
std::string mText;
|
||||
QRegExp mRegExp;
|
||||
int mValue;
|
||||
bool mCase;
|
||||
std::set<int> mColumns;
|
||||
int mIdColumn;
|
||||
int mTypeColumn;
|
||||
|
@ -68,11 +67,11 @@ namespace CSMTools
|
|||
|
||||
Search();
|
||||
|
||||
Search (Type type, bool caseSensitive, const std::string& value);
|
||||
Search (Type type, const std::string& value);
|
||||
|
||||
Search (Type type, bool caseSensitive, const QRegExp& value);
|
||||
Search (Type type, const QRegExp& value);
|
||||
|
||||
Search (Type type, bool caseSensitive, int value);
|
||||
Search (Type type, int value);
|
||||
|
||||
// Configure search for the specified model.
|
||||
void configure (const CSMWorld::IdTableBase *model);
|
||||
|
|
|
@ -4,20 +4,14 @@
|
|||
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
|
||||
: mSkills (skills)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::SkillCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mSkills.getSize();
|
||||
}
|
||||
|
||||
|
@ -25,8 +19,7 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Skill& skill = record.get();
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class SkillCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Skill>& mSkills;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -4,20 +4,14 @@
|
|||
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
|
||||
: mSounds (sounds)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::SoundCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mSounds.getSize();
|
||||
}
|
||||
|
||||
|
@ -25,8 +19,7 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Sound& sound = record.get();
|
||||
|
@ -34,7 +27,7 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Sound, sound.mId);
|
||||
|
||||
if (sound.mData.mMinRange>sound.mData.mMaxRange)
|
||||
messages.push_back (std::make_pair (id, "Minimum range larger than maximum range"));
|
||||
messages.push_back (std::make_pair (id, "Maximum range larger than minimum range"));
|
||||
|
||||
/// \todo check, if the sound file exists
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class SoundCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Sound>& mSounds;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -2,8 +2,6 @@
|
|||
|
||||
#include <sstream>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/refiddata.hpp"
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
|
@ -13,24 +11,20 @@ CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ES
|
|||
: mSoundGens(soundGens),
|
||||
mSounds(sounds),
|
||||
mReferenceables(referenceables)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::SoundGenCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mSoundGens.getSize();
|
||||
}
|
||||
|
||||
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const ESM::SoundGenerator& soundGen = record.get();
|
||||
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
|
||||
const CSMWorld::IdCollection<ESM::Sound> &mSounds;
|
||||
const CSMWorld::RefIdCollection &mReferenceables;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,
|
||||
|
|
|
@ -5,20 +5,14 @@
|
|||
|
||||
#include <components/esm/loadspel.hpp>
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include "../world/universalid.hpp"
|
||||
|
||||
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
|
||||
: mSpells (spells)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
int CSMTools::SpellCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mSpells.getSize();
|
||||
}
|
||||
|
||||
|
@ -26,8 +20,7 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages)
|
|||
{
|
||||
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
const ESM::Spell& spell = record.get();
|
||||
|
|
|
@ -13,7 +13,6 @@ namespace CSMTools
|
|||
class SpellCheckStage : public CSMDoc::Stage
|
||||
{
|
||||
const CSMWorld::IdCollection<ESM::Spell>& mSpells;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -1,23 +1,18 @@
|
|||
#include "startscriptcheck.hpp"
|
||||
|
||||
#include "../prefs/state.hpp"
|
||||
|
||||
#include <components/misc/stringops.hpp>
|
||||
|
||||
CSMTools::StartScriptCheckStage::StartScriptCheckStage (
|
||||
const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
|
||||
const CSMWorld::IdCollection<ESM::Script>& scripts)
|
||||
: mStartScripts (startScripts), mScripts (scripts)
|
||||
{
|
||||
mIgnoreBaseRecords = false;
|
||||
}
|
||||
{}
|
||||
|
||||
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
|
||||
{
|
||||
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
|
||||
|
||||
// Skip "Base" records (setting!) and "Deleted" records
|
||||
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
|
||||
if (record.isDeleted())
|
||||
return;
|
||||
|
||||
std::string scriptId = record.get().mId;
|
||||
|
@ -31,7 +26,5 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
|
|||
|
||||
int CSMTools::StartScriptCheckStage::setup()
|
||||
{
|
||||
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
|
||||
|
||||
return mStartScripts.getSize();
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@ namespace CSMTools
|
|||
{
|
||||
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
|
||||
const CSMWorld::IdCollection<ESM::Script>& mScripts;
|
||||
bool mIgnoreBaseRecords;
|
||||
|
||||
public:
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue