Compare commits

...

1021 Commits

Author SHA1 Message Date
David Cernat 8aad93b904
Merge pull request #519 from TES3MP/0.7.0-alpha
[General] Update positions for dead players on other clients
6 years ago
David Cernat 3effd5f1ff [General] Update positions for dead players on other clients
Dead players will now show up at the correct cell and position for living players, making server scripts that allow players to revive each other much more functional.
6 years ago
David Cernat 4692f29b9d
Merge pull request #517 from uramer/0.7.0markers
update player map markers when client changes cell
6 years ago
David Cernat 03d377ec54
Merge pull request #518 from TES3MP/0.7.0-alpha
[General] Rename CellReplace packet into CellReset
6 years ago
David Cernat 8ff2d1b829 [General] Rename CellReplace packet into CellReset 6 years ago
David Cernat cb82318c36 [General] Fix problems with Utils::getArchitectureType() 6 years ago
uramer 3b2098382b update player map markers when client changes cell 6 years ago
David Cernat cb5e24e6c5
Merge pull request #516 from TES3MP/0.7.0-alpha
[Server] Add GetMillisecondsSinceServerStart() server function
6 years ago
David Cernat 91f82d845c [Server] Add GetMillisecondsSinceServerStart() server function 6 years ago
David Cernat d35026bbf5
Merge pull request #515 from TES3MP/0.7.0-alpha
0.7.0 alpha
6 years ago
David Cernat bd677726bf [Server] Add StatsFunctions that get/set damage to attributes/skills 6 years ago
David Cernat 9fc4c83858 [Client] Send skill/attribute packets when skills/attributes are damaged 6 years ago
David Cernat ece39748de [Server] Fix typo causing recursion in deprecated actor list function 6 years ago
David Cernat 5c4d3df551 [Server] Deprecate DoesFileExist(), add DoesFilePathExist() 6 years ago
David Cernat 2cdabddc0e [Server] Move most MiscellaneousFunctions to ServerFunctions 6 years ago
David Cernat b46767de6e [Server] Clean up recent additions to ServerFunctions 6 years ago
David Cernat 911079e0bc
Merge pull request #512 from TES3MP/0.7.0-alpha
0.7.0 alpha
6 years ago
David Cernat 331fa86844 [Server] Call OnServerPostInit after OnRequestDataFileList
This allows different actions to be taken in OnServerPostInit based on what the data files being used are.
6 years ago
David Cernat a0ec9dfd2e [Server] Rename OnRequestPluginList into OnRequestDataFileList 6 years ago
David Cernat 986528c67d [Server] Add error message as argument to OnServerScriptCrash 6 years ago
David Cernat 552a94a0ca [Server] Add OnServerScriptCrash script event 6 years ago
David Cernat a508a0faf8 [Server] Turn GetArguments() from ScriptFunctions into Utils function 6 years ago
David Cernat dcbc9d1831 [Client] Print cells for actor deaths 6 years ago
David Cernat 828c52138f [Documentation] Update readme and credits
According to some legal advice I've received, the "TES3MP Team" is too ambiguous of a legal entity, so – with Koncord's agreement – the copyright is now assigned specifically to us, the project's developers.
6 years ago
David Cernat 69e7d3f2a7 [Documentation] Update credits 6 years ago
David Cernat f3b8a5b909 [General] Check integrity of credits only on Windows clients
This avoids the problems that were encountered in Linux and macOS builds regarding this check while also still addressing the scenario where official Windows builds had their credits modified by people unrelated to the project.
6 years ago
David Cernat a0ad0b29bc Merge branch '0.7.0' of https://github.com/TES3MP/openmw-tes3mp into 0.7.0 6 years ago
David Cernat 222837976c [Server] Fix type name warning for Player
The warning in Visual Studio was: "'Player': type name first seen using 'class' now seen using 'struct'"
6 years ago
Koncord 77386525f2 [General] Update Travis CI 6 years ago
David Cernat c058dce346 [General] Clarify meaning of commit hash displayed on start 6 years ago
David Cernat 1df1515c7e [Client] Add logging for invalid enchantmentIds in RecordHelper 6 years ago
David Cernat 999ce857c7 [Client] Add logging for records ignored due to their invalid baseIds 6 years ago
David Cernat db7e09f441 [Client] Use more consistent logging when reading dynamic record packets 6 years ago
David Cernat 0fa116b47d [Client] Remove useless lines in RecordHelper 6 years ago
Koncord 0df32accca [Server] Fix ARM build 6 years ago
David Cernat fd40e8c971 [Client] Prevent ObjectState spam by not resending an already sent state 6 years ago
David Cernat 6e47b65205 [Client] Set attribute increases & level progress after correct packets
Originally, the PlayerSkill packet contained skills, attribute increases and level progress. In 78441c769a, the attribute increases were moved to the PlayerAttribute packet and the level progress was moved to the PlayerLevel packet, but – due to an oversight – attribute increases and level progress were still being applied to the local player only when a PlayerSkill packet was received, based on whatever values were stored from the last PlayerAttribute and PlayerLevel packets.
6 years ago
David Cernat f481c85e07 [Client] Use ADD before REMOVE for PlayerInventory in repair/recharge
Previously, when recharging or repairing an item, the client sent a PlayerInventory packet to the server with the old version of the item that was supposed to be removed and then it sent a PlayerInventory packet with the new version of the item that was supposed to be added.

Unfortunately, the current CoreScripts make it so custom items using generated IDs have their records deleted when they are completely removed from the world, however briefly, even if they are added back immediately afterwards. In practice, this meant that – before this commit – recharging or repairing a custom item led to its removal from the player inventory stored on the server, followed by the deletion of its record, followed by its readdition to the inventory (but with the record staying deleted). Logging out and logging back in immediately prevented the player from receiving the item anymore because of its now non-existent record.
6 years ago
David Cernat 8a99f215f6 [Client] Add LocalPlayer::sendItemChange() variant with mwmp::Item arg 6 years ago
David Cernat db9c1b9882 [Client] Add MechanicsHelper::getItem() for getting mwmp::Item from Ptr 6 years ago
David Cernat 799241e8c6 [Client] Use informative error message for RefData::setCount() issue 6 years ago
David Cernat 43f195f0c7 [Client] Use clearer debug for actor initializations 6 years ago
David Cernat 2e1d4a9449 [Server] Fix non-Windows builds 6 years ago
David Cernat 81e2e48561 [Client] Fix item magic casting synchronization for spell scrolls
Previously, spell scrolls were used up before their IDs could be included in attacks packets supposed to be sent for them.
6 years ago
David Cernat d83160523f [Client] Add items required for item magic casting when they are missing 6 years ago
David Cernat 433a69a588 [Client] Send all data for newly initialized LocalActors at least once 6 years ago
David Cernat e70fd2cf3a [Server] Accept clients with wrong password on servers with no password 6 years ago
David Cernat eb52babf29 [Server] Print IP instead of name or PID for players unable to connect
The player name was always blank in such situations, providing no useful information. The PID was not useful in any way either.
6 years ago
David Cernat e96091fd6b [General] Use more consistent variable names for password, address, etc. 6 years ago
David Cernat 906d2a837d [Client] Send PlayerInventory packets when recharging items w/ soulgems 6 years ago
David Cernat 71679934a1 [Client] Send PlayerInventory packets when repairing items 6 years ago
David Cernat 5d9893ee92 [Client] Set actor killer correctly for spells that do damage over time
Additionally, clean up comments related to other code that sets actor killers.
6 years ago
David Cernat 6e1504f0a1 [Server] Use clearer variable & function names in TimerAPI 6 years ago
David Cernat 42b5a8054f [Server] Remove unusable position functions for players 6 years ago
Koncord 4ce0331f1b [Server] Fix GCC build 6 years ago
Koncord 9343b8af2f [Server] Remove unused function 6 years ago
Koncord c2230a8a21 [Server] Add MP flag to the server if enabled 6 years ago
Koncord a0e89208a0 [General] Fix standalone server build 6 years ago
Koncord 55cea491ca [Server] Introduce MS VC++ 2017 support 6 years ago
Koncord 6af2400752 [Server] Remove usages of get/set env. Add GetModDir function 6 years ago
Koncord b3456a8841 [Server] Fix invalidation of iterators 6 years ago
David Cernat 343dd8b5ea [Client] Fix addition of items to player inventories
Previously, multiple stacks of the same item ID could overwrite data in each other because of how the logic in ContainerStore::add() works. For example, a stack of 5 grand soul gems with no souls would get added to the player, then the attempt to add a grand soul gem with a particular soul would retrieve the previous stack first before setting all of it to that soul, resulting in 6 grand soul gems with that soul.
6 years ago
David Cernat 76ac905efc [Client] Send PlayerInventory packets when trapping souls in soulgems 6 years ago
David Cernat f853368641 [Client] Fix loss of player items in ContainerStore::unstack()
Previously, unstacking items for a player led to a PlayerInventory packet being sent about the items' removal.

This change makes it so both a packet about their re-addition and their removal are sent instead, cancelling each other out, which is inelegant, but arguably preferable to complicating the sending of PlayerInventory packets again.
6 years ago
David Cernat 5e38e8abdb [Server] Add GetArchitectureType() script function
Additionally, bring GetOperatingSystem() up-to-date by making it use the renamed function in Utils.
6 years ago
David Cernat 9fe54aa8c6 [General] Add getArchitectureType() to multiplayer Utils
Additionally, rename getOperatingSystem() into getOperatingSystemType() for clarity.
6 years ago
David Cernat fa1700e2ab [Server] Add GetOperatingSystemType() script function 6 years ago
David Cernat da6b89c185 [General] Add getOperatingSystem() to multiplayer Utils 6 years ago
David Cernat 50714599d9 [Client] Spawn at exterior 0, -7 by default 6 years ago
David Cernat afd17e5a48 [Client] Don't finish drag & drop that is supposed to be unsuccessful
This prevents items from vanishing when your attempt to drop them in a full container is denied.
6 years ago
David Cernat a6c6db89fc [Client] Send object packets when scripts use PlaceItem/PlaceItemCell 6 years ago
David Cernat d05a82a734 [Client] Avoid repetitive code when unequipping items in resurrection 6 years ago
David Cernat b5b26c6685
Merge pull request #492 from terabyte25/patch-7
[Client] Disallow opening inventory menu when not logged in
6 years ago
terrabyte25 35755eb1f1
[Client] Disallow opening inventory menu when not logged in 6 years ago
David Cernat b7090b2550 [Server] Add experimental option for not crashing from Lua script errors
Additionally, fix return type of GetPluginEnforcementState()
6 years ago
David Cernat b39e3f518b [Client] Use correct log levels for inventory and dynamic record packets 6 years ago
David Cernat d8ca268067 [Server] Move plugin enforcement functions to ServerFunctions 6 years ago
David Cernat 2933526995 [Server] Include errors related to Lua calls in server logs 6 years ago
David Cernat ef80894c5c
Merge pull request #486 from testman42/patch-2
Use more descriptive terminology for chat modes
6 years ago
Testman 6b3f598837
Use more descriptive terminology for chat modes
Changed "Chat disabled" to "Chat hidden", "Chat enabled" to "Chat visible" and "Chat in hidden mode" to "Chat appearing when needed".
6 years ago
David Cernat eb3ae95f0e [Documentation] Display build status for correct branch 6 years ago
David Cernat d3eb106c3b [Documentation] Update readme for current situation 6 years ago
David Cernat e834a4ec74 [Client] Find closest enchantmentCharge in getItemPtrFromStore()
Enchanted inventory items continuously recharge their enchantment charges, which getItemPtrFromStore() should account for.

Additionally, prevent framelistener errors caused by PlayerItemUse packets about non-existent items.
6 years ago
David Cernat bc7bcae190
Merge pull request #484 from GrimKriegor/0.7.0
[General] Change the default plugins home location
6 years ago
Grim Kriegor 8f90f8a3b8 [General] Change the default plugins home location 6 years ago
Koncord e162af0003 [Server] Disallow non void callbacks 6 years ago
Koncord 07a5f5296c [Server] Rework OnRequestPluginList callback. Add AddPluginHash function 6 years ago
Koncord 20a7619a4a [Server] Remove result from the OnPlayerConnect callback
Now it's recommended to use tes3mp.Kick() function
6 years ago
Koncord f1e8569291 [Server] Remove result from the OnPlayerSendMessage callback 6 years ago
Koncord efa362031e [Server] Remove unused Main callback 6 years ago
Koncord b83e4056a8 [Server] Remove CallFF dependency as it not fully supported by Windows and MacOS 6 years ago
Koncord 585557ad8a [Server] Remove argument cast in the Call with va_args 6 years ago
Koncord 3101de5f02 [Server] Add kicked load status 6 years ago
Koncord e5e13b21ae [Client] Fix crash on drag&drop 6 years ago
David Cernat c65d6c1328 [Client] Disable mListener methods in mwworld/containerstore
This should put an end to frequent crashes until I can fix the problem properly.
6 years ago
David Cernat 1baf82db32 [Client] Avoid PlayerSpellbook packet spam in some mods 6 years ago
David Cernat d9bc1abf48 [Client] Don't send ObjectScale packets if not logged in 6 years ago
David Cernat a8cf1e02c4 [Client] Allow unilateral scripted container changes not from console
This prevents infinite loops in certain client scripts from mods that use while loops to determine that all items of a certain type have been removed from a container, such as in the script BCSwap2Arg from  Better_Clothes.
6 years ago
David Cernat 99f8ef88a5 [Server] Add SetObjectActivatingPid() script function 6 years ago
David Cernat 17f13872aa [Client] Use forceUpdate correctly in LocalPlayer::updateStatsDynamic()
Previously, the forceUpdate argument was useless, preventing dynamic stats from being sent by certain newly created characters.
6 years ago
David Cernat bfd7c83c4d [Client] Fix backwards logic when setting type for AI attacks 6 years ago
David Cernat d9dd7073cf [General] Send certain packets only when logged in
Previously, client mods adding packet-sending scripts to the spawn area made clients send the associated packets as soon as they inputted their character name when joining a server using those mods. This made the clients either get disconnected for not replying to a handshake first, or it made them get kicked for sending object packets that are disallowed for players who are not logged in.

To fix this, LocalPlayer's hasFinishedCharGen() has been replaced with isLoggedIn(), because the former was already returning true when players inputted their names.
6 years ago
David Cernat 66d666d60c [Client] Use less confusing terminology when displaying plugin mismatch 6 years ago
David Cernat bb834748c5 [Server] Log player kicks 6 years ago
David Cernat a3111fbcc1 [Server] Use clearer error message when failing to bind port 6 years ago
David Cernat 3d40a162bc
Merge pull request #476 from SamHellawell/0.7.0-fix-equipcrash-linux-cleanup
Cleanup fix for equip item crash on Linux
6 years ago
Sam Hellawell df1667b6e4 Cleanup fix for equip item crash on Linux
Signed-off-by: Sam Hellawell <sshellawell@gmail.com>
6 years ago
David Cernat db2b3e95b8
Merge pull request #475 from SamHellawell/0.7.0-fix-equipcrash-linux
Fix crash when equipping item on linux
6 years ago
Sam Hellawell 1e171ad9fd Fix crash when equipping item on linux
Signed-off-by: Sam Hellawell <sshellawell@gmail.com>
6 years ago
David Cernat e402a17757 [Client] Don't cast non-weapons to weapons in isUsingRangedWeapon()
This makes lockpicks and probes work again.
6 years ago
David Cernat 292536439e [Server] Rename script functions for clearing packet vectors for players 6 years ago
David Cernat c79660f721 [Server] Make inventory script functions consistent with others
Functions that add elements to a vector should not change the action. This fixes the last remaining oddity in Koncord's original implementation of inventory sync.
6 years ago
David Cernat 8c7e06293f [Documentation] Update changelog with attack synchronization details 6 years ago
David Cernat b76e00c66e [Server] Call OnPlayerCellChange script event near start of cell change
This makes it possible to send custom records used by players for their equipment before the hardcoded exchange of equipment packets takes place.

Additionally, remove the check for dead players because it has no real use and can potentially cause problems.
6 years ago
David Cernat f100a660d4 [General] Fix ranged attack sync when using last throwing weapon or ammo 6 years ago
David Cernat 3f304866fd [Client] Use clearer variable names in DedicatedPlayer::setEquipment() 6 years ago
David Cernat 995d20348f [General] Always use correct ranged weapon & ammo for ranged attack sync
Previously, the player's currently selected weapon was being used in ranged attacks as in the original melee-oriented attack sync, which meant that shooting one type of projectile and then equipping another while the old projectile was still in the air turned the old projectile into the new projectile upon impact.

Additionally, avoid running most of the code in MechanicsHelper::assignAttackTarget() for non-hitting melee and ranged attacks.
6 years ago
David Cernat db39c62e89 [Documentation] Update credits 6 years ago
David Cernat b04ca28ece
Merge pull request #471 from testman42/patch-1
Update credits
6 years ago
David Cernat b5f46ada73 [General] Synchronize projectile speed for ranged attacks
This is done by including the final attackStrength used for ranged attacks in packets and then applying it in WeaponAnimation::releaseArrow() on other clients.
6 years ago
David Cernat 7281f9fc42 [Client] Prevent unilateral paralysis of dedicated players & actors
This is a temporary workaround until active effect synchronization is implemented.
6 years ago
Testman 770d36ef67
Update credits
Reflect recent role changes
6 years ago
David Cernat 33a0886790 [Client] Fix synchronization of knockdown states 6 years ago
David Cernat 490303dc0b [Client] Clean up MechanicsHelper::processAttack() slightly
The debug is now more descriptive and some code is now skipped for non-ranged attacks.
6 years ago
David Cernat 9d2dc96a2e [Client] Use RANGED type for ranged attacks that haven't hit a target 6 years ago
David Cernat af49f711ca [Client] Add isUsingRangedWeapon() method to MechanicsHelper 6 years ago
David Cernat 3f6ca6f22b [Client] Bring drawState fallback for actors up-to-date w/ attack types 6 years ago
David Cernat 9d2cf6629b [Client] Fix logic for hand-to-hand attack sync 6 years ago
David Cernat fcd31bf4a6 [General] Fix problems with the synchronization of ranged attacks
Projectile hits now send Attack packets with RANGED attacks, and their success or failure is now synchronized.

Strike enchantments no longer require a valid victim to be synchronized.

Additional debug messages have been added for attacks.
6 years ago
David Cernat 31a9b77f34 [Client] Reset hitPosition in MechanicsHelper::resetAttack() 6 years ago
David Cernat 7d221509cd [Client] Move item magic hook to correct location
Previously, synchronization for strike enchantments was partially broken because it triggered the sending of ITEM_MAGIC attack packets, which are only supposed to be sent when a spell is cast from a magical inventory item.
6 years ago
David Cernat c9ad411dd3 [Client] Fix logic for setting applyProjectileEnchantment in attack sync 6 years ago
David Cernat 8012d0d7b7 [General] Include hit position in PlayerAttack and ActorAttack packets 6 years ago
David Cernat dcd4478028 [Client] Always stop sending weather updates when moving to an interior 6 years ago
David Cernat 113002ca19 [Client] Return early when processing actors that can't be initialized 6 years ago
Koncord 48f4792bc1 [Server] Add GetMaxPlayers, GetPort and HasPassword functions to API 6 years ago
David Cernat 3bd8aa82fe [General] Reduce inventory-sending hooks to just 2 in ContainerStore
Whenever an item is added to or removed from the player's ContainerStore, that player sends a PlayerInventory packet with just that addition or removal.

This eliminates all the unnecessary packet spam related to oversized PlayerInventory packets that had existed in one form or another since the initial implementation of inventory sync in 1b259e2d33

Additionally, move booleans from BasePlayer to LocalPlayer when they are only needed on the client, and make the usage of the isReceivingQuickKeys boolean consistent with the new isReceivingInventory boolean by having them both in the processors of their associated packets.
6 years ago
David Cernat ee3fc4a303 [Documentation] Update changelog for 0.7.0 6 years ago
David Cernat 9e58cc82bd [Server] Set minimum updateRate when communicating with master server 6 years ago
David Cernat be448e5b8e [General] Use more appropriate update rate in server config 6 years ago
David Cernat d1fa57ac14 [General] Switch to new official master server port when using old one 6 years ago
David Cernat 0658d39eaa [General] Update ports used for master server in client & server config 6 years ago
David Cernat 03832f933b [Client] Send only individual items in PlayerInventory packets
For a long time, whenever a PlayerInventory packet was sent, it contained all the items in the player's inventory, because that's how Koncord originally implemented it and I always had too many other priorities to go back and rework it.

From now on, clients only send PlayerInventory packet with the one item added or removed, with the single exception being trading with merchants, where the entire inventory is still sent for the time being.
6 years ago
David Cernat 75a64a69c7 [Server] Add GetInventoryChangesAction() script function
Additionally, fix a typo in the description of GetSpellBookChangesAction()
6 years ago
David Cernat 45b011452e [Client] Combine methods for sending spell packets into a single one 6 years ago
David Cernat 140e0ed52c [Client] Also clear aiActors when clearing ActorList 6 years ago
David Cernat aed4ca2fd2 [Client] Allow use of baseId for more record types
Additionally, don't allow new enchantment records to be created if they have no effects, to avoid a crash.
6 years ago
David Cernat a083439139 Merge pull request #469 from davidcernat/master while resolving conflicts
# Conflicts:
#	apps/openmw/main.cpp
#	apps/openmw/mwbase/world.hpp
#	apps/openmw/mwdialogue/dialoguemanagerimp.cpp
#	apps/openmw/mwmechanics/actors.cpp
#	apps/openmw/mwscript/dialogueextensions.cpp
#	apps/openmw/mwworld/worldimp.hpp
6 years ago
David Cernat 7efee0e968 [Client] Fix GCC build 6 years ago
David Cernat 5bd2244898 [Client] Uninitialize DedicatedActors instantly in some situations
When LocalActors briefly become DedicatedActors as the result of a server script, the DedicatedActors are immediately uninitialized to avoid bugs like them jumping in place or rotating slightly.

Additionally, the playing of animations and sounds received in packets for DedicatedActors is no longer done during their next update, but is instead done instantly when the packets are received.
6 years ago
David Cernat 5fd4113978 [General] Implement sending of ActorSpeech packets from server scripts 6 years ago
David Cernat 338efdb705 [General] Fix issues with MechanicsHelper::getItemPtrFromStore() 6 years ago
David Cernat aec0c5bd49 [Server] Make capitalization consistent for AI-related script functions 6 years ago
David Cernat 9598212aad [Client] Don't add bound items to inventory as a result of item packets
Additionally, don't include bound items when sending PlayerInventory packets.
6 years ago
David Cernat a3b9274365 [Client] Make it possible to check if an item ID belongs to a bound item 6 years ago
David Cernat a1933e7bc2 [Client] Don't declare variable twice in LocalPlayer's setEquipment()
The variable equipmentItem is identical to currentItem, so it should not have been added in commit 58a6a8c3bc

Addditionally, use a more descriptive variable name than "a" for item Ptrs.
6 years ago
Marc Zinnschlag 1cfc1f9bdb Merged pull request #1666 6 years ago
Marc Zinnschlag 0aedb3aada Merged puil request #1808 6 years ago
Marc Zinnschlag b67b17010d Merged pull request #1826 6 years ago
Marc Zinnschlag 24212d58e8 Merged pull request #1861 6 years ago
Andrei Kortunov ec9a1b0d05 Handle RootCollisionNode, attached to non-root node (bug #4311) 6 years ago
Andrei Kortunov cde95979d0 Fix combat engagement for creatures 6 years ago
David Cernat 5d66a9bb66 [Client] Fix path to MechanicsHelper in ProcessorPlayerItemUse 6 years ago
David Cernat 8df08c7d10 [General] Implement PlayerItemUse packet
Players can no longer unilaterally use items on themselves in their inventory. When they try to use an item, they send a PlayerItemUse packet to the server with the item's details. A serverside script can then check the item and either send the packet back to make the item use go through or drop it.
6 years ago
Andrei Kortunov 780648b584 Do not reset idle animations if we do not have ammo 6 years ago
Andrei Kortunov df577babe9 Increase priority of 1st-person weapon animations to avoid issues with animation blending 6 years ago
Andrei Kortunov 71bcc11ba5 Apply only crossbow reload animation to upper body 6 years ago
Andrei Kortunov a0d0e5d2db Give jumping animations higher priority than movement ones 6 years ago
Andrei Kortunov 6a03aa6fdb Reduce jittering during turning animations for player 6 years ago
Andrei Kortunov cd92014533 Do not touch GUI modes when taking screenshots (bug #4528) 6 years ago
Marc Zinnschlag fe19d8ff35 Merged pull request #1857 6 years ago
Marc Zinnschlag a2a57cf694 Merged pull request #1858 6 years ago
Marc Zinnschlag 0f510011b3 Merged pull request #1852 6 years ago
Marc Zinnschlag cb62936949 Merged pull request #1853 6 years ago
Bret Curtis 03bf599426
Merge pull request #1856 from Capostrophic/hidden
Revert untextured shapes rendering changes
6 years ago
Bret Curtis 144f37f9b3
Merge pull request #1860 from akortunov/warningfix
Do not use fall-through to avoid GCC warnings
6 years ago
Andrei Kortunov 126b2fdd42 Use the isPlayer variable to do not check if the current actor is player every time 6 years ago
Bret Curtis 0d976f2c5e
Merge pull request #1859 from Capostrophic/debug
Fix a bunch of MSVC warnings
6 years ago
Andrei Kortunov 57e1462417 Do not use fall-through 6 years ago
Capostrophic 348c6f848e
Fix a bunch of MSVC warnings 6 years ago
Andrei Kortunov 51af729305 Do not use headtracking in the 1st-person view (bug #4573) 6 years ago
Andrei Kortunov 6202b4eca9 Do not touch GUI modes when taking screenshots (bug #4528) 6 years ago
Capostrophic 85208eff7f Revert untextured shapes rendering changes 6 years ago
Bret Curtis 0c0379c1ef
Merge pull request #1855 from OpenMW/allow_msvc2015_failure
Update appveyor.yml
6 years ago
Bret Curtis 97bc9954d0
Update appveyor.yml
allow msvc2015 to fail
6 years ago
Capostrophic e9e9c0dd6b Fix guild guide fast travelling to exteriors time 6 years ago
Andrei Kortunov b7859b3fa9 Cap underwater view distance (bug #4565) 6 years ago
Capostrophic bcd9cc4baa Check the actor cell instead of the destination cell in fast travel price logic 6 years ago
Bret Curtis a19d55e035
Merge pull request #1850 from Capostrophic/nodemask
Fix untextured shapes nodemask
6 years ago
Capostrophic bda23c6ad6 Fix nodemask 6 years ago
Bret Curtis a9729878d7
Merge pull request #1848 from Capostrophic/texturing
Don't render NiTriShapes without NiTexturingProperty (bug #4483)
6 years ago
Capostrophic a1e3b2e586 Don't render NiTriShapes without NiTexturingProperty (bug #4483) 6 years ago
Marc Zinnschlag b75b5d139a Merged pull request #1845 6 years ago
Marc Zinnschlag 7a93d118d2 Merged pull request #1846 6 years ago
Marc Zinnschlag 31491fdbde Merged pull request #1844 6 years ago
Capostrophic 7087bad580 Use special behavior for all topics with reserved names (bug #4557) 6 years ago
Andrei Kortunov 1f4dd3b393 Make partial binary search case insensitive, as it supposed to be (bug #4558) 6 years ago
David Cernat 888e1dfff8 [General] Allow setting of AI fight & dynamic stats in record packets
Additionally, allow the setting of the Autocalc flag for an NPC record based on an existing record.
6 years ago
Andrei Kortunov b0f2e00e7f Make forcegreeting a non-op for non-actor objects (bug #4553) 6 years ago
Koncord d03722b3f4 [Browser] Rework browser for improved stability & clarity
(cherry picked from commits 5c79e7106f, 57353cdfff, 15723adb9a, 01a5196a92, ed75563a94, 3839a2dcfd, 1fd16ba69c, 66283943c5, ba8613a179, 5b8f4f3e92, 35b771b19e, 043eb224e2, 05fac2f67d)
6 years ago
Marc Zinnschlag 452a706047 Merged pull request #1837 6 years ago
Marc Zinnschlag b6a919a2d1 Merged pull request #1838 6 years ago
Marc Zinnschlag 99c03d55f0 Merged pull request #1841 6 years ago
Marc Zinnschlag 2a621fedd1 Merged pull request #1842 6 years ago
Capostrophic d15dcaff68
Don't adjust weapon rating according to weapon condition twice 6 years ago
Andrei Kortunov dd6cb85783 Remove redundant changelog entry 7 years ago
David Cernat 6498bcb22b [Server] Add script functions for getting player draw & sneak states 7 years ago
Andrei Kortunov e2519226aa Move boost include 7 years ago
Andrei Kortunov eeffe2e557 Check if item model exists inside drag and drop functions 7 years ago
Andrei Kortunov e4f862c0b9 Check if next char exists 7 years ago
Andrei Kortunov c2a175c2e0 Move crash catcher wrapper to separate file 7 years ago
Capostrophic 725a9323c4
Merge branch 'master' into sound 7 years ago
Capostrophic 1d1eedc001
Update changelog 7 years ago
Capostrophic 2f44acafe2
Fix changelog 7 years ago
Capostrophic 4c7f3cf626
Merge branch 'master' into weaponpriority 7 years ago
Capostrophic 433c24562e
Update changelog 7 years ago
Andrei Kortunov ac98797999 Add missing file 7 years ago
Marc Zinnschlag 4d280add81 Merged pull request #1843 7 years ago
Marc Zinnschlag d7718aae9b Merged pull request #1840 7 years ago
Marc Zinnschlag eb5f558f6f Merged pull request #1839 7 years ago
Marc Zinnschlag 79aaf0163a Merged pull request #1833 7 years ago
Andrei Kortunov 712c9995db Rename mIsScripted variable because its name is ambiguous 7 years ago
Andrei Kortunov c454f1bdad Use log file for editor (feature #4012) 7 years ago
Capostrophic 9d85b7c2d3
Use the actual damage for deducting weapon rating 7 years ago
Capostrophic 73d5496711
Revert addition change 7 years ago
Capostrophic 16af1a6c1c Replace 0 sound range values separately 7 years ago
Capostrophic 3ac030d75a
Handle explicit calls before handling quotes 7 years ago
Capostrophic 80f3bd9f86 Don't apply iWereWolfFleeMod to creatures 7 years ago
Capostrophic fa6c205e5d Make tab autocompletion work with explicit reference calls 7 years ago
Capostrophic bec47dfb7c Make ranged weapon bonus a distance-dependent multiplier 7 years ago
Andrei Kortunov 369ea7e177 Check if a temporary file was successfully closed 7 years ago
Capostrophic 382b68a081
Combat AI: take the actual hit chance in account when rating weapon 7 years ago
Andrei Kortunov 12144de8ed Initialize missing variables 7 years ago
Andrei Kortunov c0bed0fde2 Handle case when index < 0 7 years ago
Andrei Kortunov 770d86f9bd Initialize cubeSize variable for 360 degrees screenshots correctly 7 years ago
Andrei Kortunov a08048da4e Avoid dereference after null check 7 years ago
Capostrophic ab29f9e13f Add permanent barter disposition change option (feature #3103) 7 years ago
Marc Zinnschlag 1c13256456 Merged pull request #1829 7 years ago
Marc Zinnschlag 0e75e3816a Merged pull request #1830 7 years ago
Marc Zinnschlag 8812f9ddfa Merged pull request #1831 7 years ago
Marc Zinnschlag 0c507b74bc Merge pull request #1832 7 years ago
Marc Zinnschlag 7c7af1da61 Merged pull request #1834 7 years ago
Marc Zinnschlag e8139a5cc7 Merged pull request #1835 7 years ago
AnyOldName3 66c241337d
Merge pull request #1836 from OpenMW/water-shader-tabs
Sort out some tabs which snuck into the water shader
7 years ago
AnyOldName3 f717c9e56d
Sort out some tabs which snuck into the water shader 7 years ago
Capostrophic 4d48ede6f1 Add two missing gameplay settings to Advanced tab 7 years ago
Capostrophic be2e7e9e09 Make casting caster-linked on-self effects no-op (bug #4378) 7 years ago
Andrei Kortunov 5b92910829 Limit difficulty scaling, as mentioned in docs 7 years ago
Marc Zinnschlag aac580da6b Merged pull request #1828 7 years ago
Marc Zinnschlag 20d4e27f82 Merged pull request #1821 7 years ago
Andrei Kortunov c07cc0dc40 Reset animation state after weapon unequipping 7 years ago
Andrei Kortunov 469bb29621 Do not try to handle shape controllers as node controllers 7 years ago
Andrei Kortunov 0f2c3ecb17 Rescale player avatar (bug #4539) 7 years ago
David Cernat 8c40010c87 [General] Add missing inventoryBaseId to creatures in RecordDynamic 7 years ago
David Cernat b57807407a [General] Implement RecordDynamic packet, part 1
Spell, potion, enchantment, creature, NPC, armor, book, clothing, miscellaneous and weapon record data can now be sent in a RecordDynamic packet. Additionally, the packets include data related to associated magical effects (for spells, potions and enchantments), data related to default inventory contents (for creatures and NPCs) and data related to body parts affected (for armor and clothing).

The server now has associated script functions for setting most of the details of the above, with the main exception being individual creature and NPC stats.

Records can either be created entirely from scratch or can use an existing record (set via the baseId variable) as a starting point for their values. In the latter case, only the values that are specifically set override the starting values. Creature and NPC records also have an inventoryBaseId that can be used on top of the baseId to base their inventories on another existing record.

The client's RecordHelper class has been heavily expanded to allow for the above mentioned functionality.

When players create spells, potions and enchantments as part of regular gameplay, they send RecordDynamic packets that provide the server with the complete details of the records that should be created. When they create enchantments, they also provide the server with armor, book, clothing and weapon records corresponding to the items they've enchanted.

This functionality added by this packet was originally supposed to be exclusive to the rewrite, but I've gone ahead and tried to provide it for the pre-rewrite in a way that can mostly be reused for the rewrite.
7 years ago
Capostrophic c79f96d0d2 Implement ranged crits (feature #3703) 7 years ago
Andrei Kortunov 1d463d129d Finish AiTarget package, if destination is blocked by other actor 7 years ago
Andrei Kortunov 75835c8326 Prevent NPC from chosing farther pathgrid node 7 years ago
Marc Zinnschlag 9e6cba09a6 Merged pull request #1827 7 years ago
Marc Zinnschlag 84de55fb46 Merged puil request #1824 7 years ago
Marc Zinnschlag 78121c1774 Merged pull request #1823 7 years ago
Marc Zinnschlag 3ba9229f47 Merged pull request #1815 7 years ago
Capostrophic 9c8e284ead Fix quick key activation delay code (regression #4536) 7 years ago
Capostrophic 84a871cac7 Actually enable is_pod test 7 years ago
Andrei Kortunov 6d5d0039ec Make sure we apply OT_Murder only once 7 years ago
Andrei Kortunov bc82dbbd1b Do not try to find missing animated collision shape again and again 7 years ago
Andrei Kortunov 7e0df01c83 Do not optimize animated shapes (bug #3950) 7 years ago
Andrei Kortunov 2d4ec86b8d Provide launcher icons 7 years ago
Marc Zinnschlag 29a1899045 Merged pull request #1819 7 years ago
David Cernat 2dbf3893c0 [General] Compress item refIds in PlayerEquipment packets 7 years ago
David Cernat 2332423527 [Client] Fix extra qualification error in CellRef when compiling w/ GCC 7 years ago
David Cernat 7136329a94 [Client] Add World::updatePtrsWithRefId() method
This makes it possible to "reload" the Ptrs in active cells when changes happen to the ESM record that they are based on. In practice, the old Ptrs are deleted, their RefNums and MpNums are blanked out, and new Ptrs are created that use the same RefNum and MpNum as before.

The above has required me to also add a method called setRefNum() to CellRef to allow setting a RefNum on the fly.

There may be a more elegant implementation available for updatePtrsWithRefIds(), but it requires additional research.
7 years ago
Andrei Kortunov 28a02ac93b Use file selection dialogue result (bug #4524) 7 years ago
Marc Zinnschlag b7c159e5b6 Merged pull request #1816 7 years ago
Marc Zinnschlag c508938674 Merged pull request #1817 7 years ago
Marc Zinnschlag bbb22643e8 Merge remote-tracking branch 'capostrophic/warning' 7 years ago
David Cernat 9497c7f6f2 [Client] Add back mistakenly removed setting of mpNums for spawns 7 years ago
David Cernat 25fcd09780 [Client] Add doesNpcExist() method to RecordHelper 7 years ago
David Cernat 7995466e3c [Client] Check validity of refIds in ObjectSpawn packets
This reverts c7bcf70c32 because it provides a better solution to the problem solved there, while solving another related problem as well.
7 years ago
David Cernat 8d286657d4 [Client] Update messages when unilaterally creating custom objects 7 years ago
Capostrophic f7887ab05f
Fix MSVC C4456 warning: declaration of 'stats' hides previous local declaration 7 years ago
David Cernat c7bcf70c32 [Client] Ignore ObjectSpawn packets trying to spawn non-actors 7 years ago
David Cernat d93b67ef21 [General] Sync soul refIds for items and add related script functions 7 years ago
David Cernat f52364e05c [Client] Always create new references for new creature disguises
Previously, attempts to reuse the same reference for multiple creature disguises led to movement animation issues, as well as a dynamic_cast error in Creature::getInventoryStore() that made a DedicatedPlayer vanish completely when they first lost their creature disguise, then disguised themselves as a creature that could not hold weapons and then disguised themselves as a creature that could hold weapons.
7 years ago
David Cernat 60bc7447d9 [Client] Rework RecordHelper and add methods for other record types
The usage of const_cast has been replaced with usage of MWWorld::getModifiableStore() and ESMStore::overrideRecord()

Methods whose names started with "update" now start with "override", for consistency with ESMStore's overrideRecord()

New methods have been added for "overriding" enchantment, potion and spell records, which actually leads to them being created with their already set refIds if they haven't been created yet, as per the description of ESMStore::overrideRecord(): "Insert a record with set ID, and allow it to override a pre-existing static record."

Usage of RecordHelper methods has been updated in DedicatedPlayer.
7 years ago
Capostrophic 51d369d4da Add resumeGame method 7 years ago
David Cernat 4e78642273 [Client] Add getModifiableStore() to MWWorld 7 years ago
David Cernat d778bc3b8a [Server] Turn readWorldstate and writeWorldstate into static variables 7 years ago
David Cernat c3ff273a22 [General] Add getVectorSize() and resetVector() to Utils 7 years ago
David Cernat b4802e4201 [General] Use Time struct for time in BaseWorldstate 7 years ago
Andrei Kortunov 23d917df9c Do not use magic numbers in capacity calculations 7 years ago
David Cernat a4b588d1b5 [General] Add optional timestamps to journal entries in PlayerJournal 7 years ago
Capostrophic e55f49be45
Fix issue 4494 number 7 years ago
Capostrophic cac2bc768e
Fix NPC "can't teach more" message (bug #4494) 7 years ago
David Cernat ea8a41160c [General] Make ActorAttack packet consistent with PlayerAttack
Additionally, fix a typo in PlayerAttack where a boolean argument was outside of the parentheses it should have been in.
7 years ago
David Cernat b79221efcc [Server] Rename variable i into index in ActorFunctions 7 years ago
David Cernat 8fbed1f808 [General] Remove custom data from PlayerSpellbook packet
It has never made sense to have custom spell data in PlayerSpellbook packets, so it has been removed.
7 years ago
David Cernat 2e0b6e4e3e [Server] Rename variable i into index in script function arguments
Additionally, rename i into index in LangLua.
7 years ago
David Cernat 65de028e0d
Merge pull request #462 from OpenMW/master
Add OpenMW commits up to 23 Jul 2018
7 years ago
David Cernat 74fa1d0f01 [Client] Fix manual setting of inertial force
Actors who are on the ground have their inertial force ignored, so they are now made to not be regarded as being on the ground in World::setInertialForce()
7 years ago
David Cernat b69e6b96e6 [Client] Use verbose logging level for LocalActor debug 7 years ago
Bret Curtis 84b80ae405 no spaces in assignment 7 years ago
David Cernat 36ac2d9de4 [Client] Set packetOrigin for all ObjectList packets sent 7 years ago
David Cernat 692ee01340 [Client] Add ScriptController w/ contextType-to-packetOrigin method 7 years ago
David Cernat 63a86f145d [Client] Record type of each InterpreterContext for later checking 7 years ago
David Cernat d4a84ac34a [Server] Update script function descriptions for ObjectList origin 7 years ago
David Cernat 3165c84db4 [General] Rework PACKET_ORIGIN enum
Additionally, comment out reading of originClientScript in ObjectPacket for now.
7 years ago
David Cernat 9e6459043b [General] Fix typo related to originClientScript in ObjectPacket 7 years ago
David Cernat 3dc2d1b214 [General] Add packetOrigin and originClientScript to ObjectList packets
Additionally, add script functions for getting the packetOrigin and originClientScript of received ObjectList packets.
7 years ago
David Cernat b891acd46e [Client] Send Container packets when items are added/removed via scripts
Additionally, disable unilateral addition and removal of items on clients, and expect the server to reply back with an approved addition or removal.
7 years ago
David Cernat 2189ea1a63 [Client] Clean up sending of Container packets 7 years ago
David Cernat 8c0b75d9f4 [Client] Limit PlayerEquipment packets sent by recharging enchantments 7 years ago
David Cernat 715cac807d [General] Add compareFloats to Utils 7 years ago
David Cernat cb6c37a26d [General] Replace doubles with floats in BaseStructs and BaseWorldstate 7 years ago
David Cernat 18f8725d33 [Client] Remove tab character that somehow made its way into a comment 7 years ago
Bret Curtis b910106713 Catch an unbound variable before it happens. 7 years ago
Bret Curtis c959bdcf32
Merge pull request #1813 from rhtucker/master
Added CSS to drop shadow of figure images
7 years ago
Ryan Tucker 9f2ef1e68a Added CSS to drop shadow of figure images 7 years ago
David Cernat 038757b91a [General] Temporarily revert to original rotation animation sync
I originally added rotation animation sync as part of commit 068a45be87. Unfortunately, it meant the PlayerPosition packets were now twice as large as they had been before, which was less than ideal for such a frequently sent packet, which is why Koncord switched to a more optimized approach in commits 5f30dfd5db and d67db1a9bd.

Recently, there have since been some rotation animation problems in OpenMW, which have broken the way Koncord's approach looks. My original approach still looks somewhat okay, so I'm switching back to it until we can figure out how to reuse it under the current circumstances.
7 years ago
Marc Zinnschlag 8b2b37c270 Merged merge request !28 7 years ago
Marc Zinnschlag ddd5cbd17c Initialise lock state of newly opened subviews (fixes issue #4520) 7 years ago
David Cernat 3944c8aec6 [Client] Ignore WorldRegionAuthority packets that have an empty region 7 years ago
David Cernat 99e64bdcd7 [Client] Remove unused localWeather variable from Worldstate 7 years ago
David Cernat cd1fc590a7 [Client] Differentiate itemPtr from actor Ptr in DedicatedPlayer method
This fixes a mistake from 8f7da49152
7 years ago
David Cernat 5466092582 [Client] Reduce log level for actor cell changes 7 years ago
David Cernat 20e0100706 [General] Rework Attack packets and add synchronization for item magic 7 years ago
David Cernat 0f0e8b7c08 [Client] Adjust log levels used for weather and global map 7 years ago
David Cernat f1315ef30d [Cllient] Differentiate itemPtr from actor Ptr in DedicatedActor methods
2427a4f877 mistakenly used the variable name "ptr" for both the actor and the items in that actor's inventory.
7 years ago
David Cernat b6324e3532 [Client] Clean up debug for spell usage 7 years ago
David Cernat 826e64b40e [Server] Rename isPlayerExists() into doesPlayerExist() 7 years ago
David Cernat 21d5bb4d4e
Merge pull request #460 from OpenMW/master
Add 0.7.0 commits up to 20 Jul 2018
7 years ago
David Cernat 6c50d4199b Merge branch '0.7.0' of https://github.com/TES3MP/openmw-tes3mp into 0.7.0 7 years ago
David Cernat 421d0e7a99 [Client] Make forceWeather false by default for client-sent weather 7 years ago
David Cernat 892d71ce71 [General] Reimplement weather synchronization to allow soft transitions
Although weather sync was added by Koncord to the rewrite in fd721143e2 in a way that used surprisingly few lines of code, it relied on the server requesting weather states every second from authority players and sending them to non-authority players, while also allowing only very sudden weather transitions across regions, i.e. if there was one player in the Ascadian Isles who had stormy weather, and another player with clear weather in the Bitter Coast Region walked across to the Ascadian Isles, that player was instantly made to have stormy weather with no kind of transition at all.

My approach solves both of those problems. It solves the packet spam by only sending weather updates to the server when weather changes happen or when there are new arrivals to a weather authority's region, and it allows for both sudden weather transitions when players teleport to a region and for soft, gradual transitions when players walk across to a region. It is inspired by my previous actor sync, and uses a WorldRegionAuthority packet to set players as region authorities in a similar way to how ActorAuthority sets players as cell AI authorities. Weather changes are created only by the region authority for a given region, and weather packets are also only sent by that authority.

However, it should be noted that gradual weather transitions are used by default in this implementation. To use sudden weather transitions, the serverside Lua scripts need to forward WorldWeather packets with the forceWeather boolean set to true. That is, however, already handled by our default Lua scripts in situations where it makes sense.
7 years ago
Bret Curtis 4c9e1295e8
Merge pull request #1811 from akortunov/fallfix
Set movement speed to 0 when unconscious
7 years ago
Bret Curtis a54b779672 Revert "Revert "remove breath/doxygen autodoc""
This reverts commit 038d5a5566.
7 years ago
Andrei Kortunov 8281fd903f Set movement speed to 0 when unconscious (bug #4519) 7 years ago
Bret Curtis ee3aba149d Force RTD to not build any other types of docs. 7 years ago
Bret Curtis 038d5a5566 Revert "remove breath/doxygen autodoc"
This reverts commit f2fc8351bb.

small fixes
7 years ago
David Cernat b6db570d9c [Client] Display uniqueIndexes in a less confusing way in console 7 years ago
Bret Curtis 105b172fb5
Merge pull request #1809 from akortunov/enumfix
Sort icons in the DataDisplayDelegate
7 years ago
Andrei Kortunov 5c16ce1d36 Sort icons in the DataDisplayDelegate 7 years ago
Marc Zinnschlag 78a2725169 Merged pull request #1806 7 years ago
Marc Zinnschlag 326a3e61f4 Merged pull request #1807 7 years ago
Marc Zinnschlag 0142525ea2 Merged merge request !26 7 years ago
Marc Zinnschlag 111407c282 Merged merge request !24 7 years ago
Andrei Kortunov 38fa4e0a8a Do not play un-equipping animation when we switch to hand-to-hand 7 years ago
David Cernat 9823a77bf2 [General] Turn PlayerRegionAuthority into WorldRegionAuthority
WorldRegionAuthority is a Worldstate packet.
7 years ago
Miloslav Číž 3ff2740e59 Update CHANGELOG 7 years ago
Koncord 2e227c7af5 [Server] Do not allow to connect with an empty plugin list 7 years ago
Koncord b5c957c473 [Server] Move PreInit code to preInit method 7 years ago
Koncord 1a9bf253f6 [Server] Simplify getPlayer methods, add isPlayerExists method 7 years ago
Koncord 193034f09c [Documentation] Add copyrigts 7 years ago
Bret Curtis e7e3dab130
Merge pull request #1804 from akortunov/guifixes
Show magic items count in spells window (feature #4509)
7 years ago
Andrei Kortunov edd5769022 Show magic items count in spells window (feature #4509) 7 years ago
Bret Curtis 1430b64aaa
Merge pull request #1805 from akortunov/editor_markers
Use editor markers for lights and creatures levelled lists
7 years ago
Andrei Kortunov 30716344f2 Fix possible division by zero in the fatigue calculation (bug #4510) 7 years ago
David Cernat d5d3c0937f [Client] Adjust log level for actor transfers in CellStore 7 years ago
David Cernat 35fdb833df [Client] Verify integrity of credits file 7 years ago
David Cernat 72d286473b [General] Move credits integrity error message to new ErrorMessages file
Additionally, use correct log level for credit integrity message on server.
7 years ago
David Cernat 0b5cb15f71 [General] Turn GameWeather into WorldWeather, now a WorldstatePacket 7 years ago
David Cernat 646111d998 [General] Use correct credits checksum and move it to Version.hpp 7 years ago
David Cernat 0f36c3ea24 [Server] Verify integrity of credits file 7 years ago
David Cernat 22b2b7a9c6 [General] Add Utils methods for checksums 7 years ago
David Cernat 9445db61b4 [Documentation] Update credits 7 years ago
Andrei Kortunov 6ddf6eb885 Use editor markers for lights and creatures levelled lists 7 years ago
Nikolay Kasyanov 21f198af7a Fix debugger detection on macOS (#4511) 7 years ago
David Cernat 4ac371d292 [Server] Delete duplicate WorldKillCount processor with old filename 7 years ago
David Cernat 3649cf553f [General] Rename PlayerKillCount into WorldKillCount
This should clarify the real meaning of the packet and its associated event.

The event itself has been renamed from OnPlayerKillCount to OnWorldKillCount.
7 years ago
David Cernat 18a2d238ab [Client] Don't pop up dialogue screen when an NPC activates another NPC 7 years ago
David Cernat 4ef2aff11e [Client] Remove "Not implemented" message when activating other player
Serverside scripts can now make lots of different things happen as the result of such activation, which is why the message was no longer current.
7 years ago
David Cernat f13705e8be [Client] Improve debug for ObjectActivate and ConsoleCommand 7 years ago
David Cernat 6ebe09375f [General] Implement ObjectActivate packet & associated script functions 7 years ago
David Cernat 81b160cae8 [General] Add placeholder for ObjectActivate packet 7 years ago
David Cernat 61da0d2475 [General] Turn PlayerInteraction into PlayerInput 7 years ago
David Cernat 32b6134fad [General] Add placeholder for CellReplace packet 7 years ago
David Cernat a471f5e452 [General] Turn CellCreate into a Worldstate packet 7 years ago
David Cernat ae55ee7f0b [General] Add getNumberOfDigits to Utils in components 7 years ago
David Cernat f410cb90d8
Merge pull request #459 from GrimKriegor/bug/missing-luajit-on-pipeline
[Pipeline] Add missing LuaJIT dependency
7 years ago
David Cernat 98ff44172a
Merge pull request #458 from GrimKriegor/hotfix/crashcatcher-sdl-build-issue
[General] Temporarily disable the new OpenMW crash catcher
7 years ago
Grim Kriegor 2fcde5e8ba [General] Temporarily disable the new OpenMW crash catcher
This new crash catcher is preventing TES3MP from building on GNU/Linux
`components/crashcatcher/crashcatcher.cpp:23:28: fatal error: SDL_messagebox.h: No such file or directory`
Disable it until the developers isolate the issue and patch it
7 years ago
Grim Kriegor 88e4927146 [Pipeline] Add missing LuaJIT dependency 7 years ago
David Cernat 6cb5ac6e63 Merge pull request #457 from OpenMW/master while resolving conflicts
Conflicts:
	CMakeLists.txt
	apps/openmw/engine.cpp
	apps/openmw/main.cpp
	apps/openmw/mwgui/windowmanagerimp.cpp
	apps/openmw/mwmechanics/character.cpp
	components/CMakeLists.txt
7 years ago
David Cernat 6d43c8d63d [Client] Send ActorAI with combat when an NPC's fight is set to 100 7 years ago
David Cernat 743933134d [Client] Simplify sending of ActorAI packets for uninitialized actors 7 years ago
David Cernat 5f4ec1331f [Client] Send ActorAI packet when combat is started via a client script 7 years ago
David Cernat cc9e294cc0 [Client] Send ActorAI packet for new cell after being followed to it 7 years ago
David Cernat 528bd26a3b [General] Allow followers to follow non-authority players through cells 7 years ago
David Cernat ab5fd0aef8 [Server] Clean up descriptions for Object script functions 7 years ago
David Cernat 6c1173d598 [Client] Rename searchPtrViaRefIndex into searchPtrViaUniqueIndex 7 years ago
David Cernat 09da24f1ea [General] Rename all instances of refNumIndex into refNum
This creates symmetry with mpNum and should cause less confusion in the future.
7 years ago
David Cernat 20296859ee [Server] Clarify functions used for getting data in Networking 7 years ago
David Cernat 04dd59e638 [Server] Use clearer names for functions used to get last received data
Additionally, rename GetObjectChangesSize() into the less confusing GetObjectListSize()
7 years ago
David Cernat aeb2e57444 [Server] Bring Actor functions in line with Object functions, part 2
The ActorPacket-sending functions now have sendToOtherVisitors and skipAttachedPlayer arguments, except for the ones for ActorList and ActorAuthority (because such arguments don't make sense for those).
7 years ago
David Cernat 837c5369c0 [Server] Add OnActorAI event and remove autosync for ActorAI packets 7 years ago
David Cernat 8f745df055 [Server] Bring Actor functions in line with Object functions, part 1
The last received ActorList can now be copied into the write-only ActorList that can be sent in packets. Changing the pid of the write-only ActorList can now be done separately from clearing its contents.
7 years ago
David Cernat f0d4f1bbe5 [Client] Send ActorAI packets when followed by an NPC
The packet is sent regardless of whether we are the cell authority or not, so the server can decide what it wants to do with it.
7 years ago
David Cernat 6316f1e590 [Client] Add ActorList methods for sending ActorAI packets
Additionally, use consistent capitalization for AI-related methods.
7 years ago
David Cernat 0fd8f7660b [Client] Replace LocalActor arg with BaseActor in ActorList functions 7 years ago
Marc Zinnschlag 0bd6078826 Merged pull request #1789 7 years ago
Andrei Kortunov 32bd294a8a Add missing changelog entries 7 years ago
Andrei Kortunov 3d1daaebab Rework manual spellcasting (e.g. via scripts) 7 years ago
David Cernat bdf2f03c4f [General] Remove unnecessary MapChanges struct from BaseWorldstate 7 years ago
David Cernat 59a56ca35e [Client] Disallow clients from scaling their associated players
Additionally, display messages when trying to scale players.
7 years ago
David Cernat 8ca29dbaac [Client] Fix remaining mistakes in debug for received ActorAI packets 7 years ago
David Cernat 5bb442bbd3 [Server] Add sendToOtherVisitors boolean to SendActorAI()
Additionally, avoid repetition in functions that send Actor packets.
7 years ago
David Cernat 25f7a55495 [Client] Improve debug for received ActorAI packets 7 years ago
David Cernat ceea65f666 [General] Change pre-rewrite's version to 0.7.0-alpha 7 years ago
Miloslav Číž 4e3bc3e403 Change wave parameters based on weather 7 years ago
Bret Curtis 99e4d49e7c
Merge pull request #1787 from akortunov/profilierfont
Use the DejaVuLGCSansMono.ttf for profiler output
7 years ago
Andrei Kortunov 70b6d4983d Use the DejaVuLGCSansMono.ttf in profilier output 7 years ago
Marc Zinnschlag 2d919ba215 changelog cleanup 7 years ago
Marc Zinnschlag 232be000a2 Updated credits file 7 years ago
Marc Zinnschlag 5080a65910 Merged pull request #1796 7 years ago
Marc Zinnschlag ee759effce Merged pull request #1798 7 years ago
Marc Zinnschlag fa96154edd Merged pull request #1803 7 years ago
David Cernat 7a646494ee [General] Point to serverCore.lua instead of server.lua in server config 7 years ago
elsid 686830a6e3
Update changelog 7 years ago
elsid 3f21c49479
Put check for nif file name into separate function 7 years ago
elsid 2599aba196
Fix check whether file name starts with x or X
If path doens't contains / or \, then slashpos will be 0.
Therefore slashpos + 1 = 1 doesn't point to first symbol.

xmesh.nif
 ^
 slashpos + 1
7 years ago
David Cernat bff6e9e235 [General] Implement ActorAI packet, part 5
Allow repetition for AiWander package to be turned on and off.
7 years ago
Andrei Kortunov c77c50e92b Make Equip console command to bypass most of restrictions (bug #4460) 7 years ago
Capostrophic 3186edc630
Update changelog 7 years ago
Capostrophic 5cb9dc9d12 Use SpellTurnLeft/TurnRight animation groups 7 years ago
Bret Curtis b390ce3002
Merge pull request #1776 from akortunov/crossbowfix
Apply weapon reload animations only for upper body
7 years ago
Bret Curtis df1576fcf5
Merge branch 'master' into crossbowfix 7 years ago
Bret Curtis fde46f03b3
Merge pull request #1801 from terabyte25/terabyte25-trainingskill
Update trainer skill cap based off modified skill instead of based skill
7 years ago
terrabyte25 76fa8a163d
Update CHANGELOG.md 7 years ago
Andrei Kortunov 1c35e20fcc Use 1h animations as fallback for crossbows 7 years ago
Andrei Kortunov 75dcbea365 Apply weapon reload animations only for upper body 7 years ago
Bret Curtis 3f63e625cf
Merge pull request #1802 from Capostrophic/cmake
Update CMake lists for Windows (task #2490)
7 years ago
Capostrophic d000f2756e Update disabled warnings 7 years ago
Capostrophic 21403f8920 Update changelog 7 years ago
Capostrophic 7fd66c77e6 Update CMake lists for Windows
Don't use the debug console on Release-mode builds
Disable spammy 4297 and 5032 warnings that are not specific to OpenMW
7 years ago
Bret Curtis 5a1dba6a09
Merge pull request #1800 from akortunov/buildfix
Fix build with MSVC
7 years ago
Andrei Kortunov c921d1c7e9 Refactor NifStream class (eliminate LNK4221 MSVC warning) 7 years ago
David Cernat 2e31c212c0 [Client] Make any ActorAI packet override an actor's desire to fight 7 years ago
David Cernat 79ee976c95 [Client] Implement ACTIVATE action in DedicatedActor::setAI()
Additionally, clean up usage of CreatureStats in DedicatedActor.
7 years ago
David Cernat 0f30e21312 [Client] Add searchPtrViaRefIndex method to World to easily find objects 7 years ago
Andrei Kortunov 27a5da59ba Fix MSVC warnings C4456 7 years ago
Andrei Kortunov 16a4df25d6 Make void function to do not return value 7 years ago
David Cernat c984fc0881 [Client] Allow AiActivate to be used with specific Ptrs, not just refIds 7 years ago
David Cernat 00c13ae96c [General] Implement ActorAI packet, part 4
The server can now make actors activate players and objects, at least in theory. In practice, OpenMW''s AiActivate package needs to be worked so it allows specific objects as targets instead of just refIds.
7 years ago
David Cernat 0e13207afe [General] Implement ActorAI packet, part 3
The server can now cancel actor AI, make actors travel to a location, make actors wander, and make actors get escorted by a player or another actor.
7 years ago
David Cernat 5baef09f79 [General] Implement ActorAI packet, part 2
The server can now make actors start combat with players or other actors.
7 years ago
David Cernat 5628f3b977 [Client] Fix debug for DedicatedActor::setAI() 7 years ago
David Cernat b86155dc11 [Client] Allow AiFollow package to have infinite distance when desired 7 years ago
David Cernat 864c66d1d4 [Client] Make sure hasAiTarget is set correctly for DedicatedActors 7 years ago
David Cernat 26ac29e8b1 [Client] Add disclaimer to save dialog about singleplayer-only saves 7 years ago
David Cernat 4d4bced929 [Client] Allow singleplayer-only saves in main menu during multiplayer 7 years ago
terrabyte25 48296a7452
Update trainingwindow.cpp 7 years ago
Marc Zinnschlag 0bdd8f7d03 Merged merge request !19 7 years ago
Marc Zinnschlag 34c7181afc Merged merge request !21 7 years ago
Alexander Stillich 5abc3bd320 Merge branch 'opencs-crash-handler' of gitlab.com:docwest/openmw into opencs-crash-handler 7 years ago
Alexander Stillich 725cc94210 Renamed cc_install to something less cryptic (crashCatcherInstall) 7 years ago
Alex S d4d2077174 Fixed changelog entry 7 years ago
Doc West a6f962156c Updated change log 7 years ago
Doc West 467989cdd5 Moved crashcatcher to a component and also use it in CS
Reworked debugger detection (failed on gdb 7.11), it now uses /proc to detect the debugger
7 years ago
Alexander Stillich 1786211b83 Merge branch 'revert-update-fix' of gitlab.com:docwest/openmw into revert-update-fix 7 years ago
Alexander Stillich 1177e5ac79 Issue a single dataChanged() when the modified column changes 7 years ago
Doc West d26b5a13ef Fixed comment 7 years ago
Doc West 01b8ce5f70 Notify views of changes in all columns when updating the ColumnId_Modification column 7 years ago
Doc West 4a6457c346 Changed the way the revert command works: it now clones the changed record and uses the new RecordBase::revert() method to restore the previous value
Added Flag_Dialogue_Refresh to var type and var value columns so that sub views update properly
7 years ago
Doc West 4222b44dbb Updated change log 7 years ago
Doc West 143eadb58e Use setData() instead of emtitting dataChanged() which does not work on CI. Also Fixes the remaining issue with subviews not updating due to only the modified flag emitting a change, which prevented the widget mapper from working for updates. 7 years ago
Doc West 4780f1b2bd Notify views of changes of all cells in a row to properly update the row after revert 7 years ago
Alexander Stillich 78a5799911 Issue a single dataChanged() when the modified column changes 7 years ago
Bret Curtis 8834396cdd Merge branch 'patch-1' into 'master'
Update documentationHowTo.rst

See merge request OpenMW/openmw!22
7 years ago
Bret Curtis 13d8fba223
Merge pull request #1797 from Capostrophic/moveobject
Fix double call of addContainerScripts on player in moveObject (bug #4490)
7 years ago
Bret Curtis 7f4320feb0
Merge pull request #1799 from lysol90/patch-1
Updates to the texture modding page
7 years ago
Joakim Berg ba15d0a848
Fixed spelling error 7 years ago
Capostrophic d09c327b20 Update changelog 7 years ago
Joakim Berg efcad5e751
Updates to the texture modding page
There were some errors in the texture modding page about normal maps, so I did a quick change. Please do review if I made some errors, spelling or factual.
7 years ago
Capostrophic 14d3b213a1
Fix double call of addContainerScripts on player in moveObject (fixes #4490) 7 years ago
David Cernat 6ff7fa525e [Client] Disable autosaving when waiting 7 years ago
Bret Curtis a3a002e008
Merge pull request #1790 from rhtucker/master
Migrating necessary parts of Wiki over to RTD.
7 years ago
Marc Zinnschlag caad14093e Merged pull request #1795 7 years ago
David Cernat 04ba324290 [Client] Disable clientside disabling and enabling of objects 7 years ago
David Cernat 5043fb4246 [Client] Disable clientside disarming of traps 7 years ago
David Cernat cbb9817913 [Server] Add missing descriptions for PlayAnimation() and PlaySpeech() 7 years ago
David Cernat 6ba9b1742b [Server] Remove unused default parameters for script functions 7 years ago
David Cernat acdaf1a282 [Client] Disable clientside deletion of objects through console/scripts
Unfortunately, disabling clientside deletion of summons and items that can be picked up requires extra work on actors and inventories respectively, to avoid buggy situations.
7 years ago
David Cernat 8d9fde810e [Client] Disable clientside scaling of objects 7 years ago
David Cernat f3892d697b [Client] Disable clientside locking and unlocking of objects 7 years ago
David Cernat 563269d359 [Server] Bring comments up-to-date for packet-sending script functions 7 years ago
David Cernat 2f1ef049d2 [Server] Turn sendToAttachedPlayer into skipAttachedPlayer
Unfortunately, default values set in the C++ code for our script function parameters don't actually seem to work, and they always default to false because they receive a nil value from Lua. As a result, to not break compatibility with previous scripts, I've decided to use a skipAttachedPlayer argument instead so it can default to false while still providing the same benefits that sendToAttachedPlayer provided.
7 years ago
Ryan Tucker 380384ff39 Migrated textures section of wiki. 7 years ago
David Cernat 141e404ed9 [Server] Move server administration functions to ServerFunctions class 7 years ago
David Cernat c0fde5ae97 [General] Add explanation about 0.0.0.0 to server config file 7 years ago
David Cernat 6041425122 [Server] Move Chat functions to new ChatFunctions class 7 years ago
David Cernat 6a3fbf4e98 [Server] Use consistent arguments for script functions that send packets
Previously, there was a confusing separation between script functions that had a "broadcast" argument and script functions that had a "toOthers" argument.

Those with broadcast sent the packet to all players on the server when broadcast was true. Those with toOthers sent the packet to all players other than the packet's attached player.

The former was based on the pattern of the original SendMessage() script function. The latter more closely resembled RakNet's own broadcast argument as seen here:

https://github.com/TES3MP/CrabNet/blob/master/include/raknet/RakPeer.h#L219

This commit makes it so all sending functions have a sendToOtherPlayers argument that is false by default and a sendToAttachedPlayer that is true by default. This should simultaneously allow sending to be more intuitive, while not breaking previous existing scripts to a significant degree.

Additionally, this commit also reduces some code repetition for all instances of packet-fetching in script functions.
7 years ago
David Cernat 14e4f64296 [Server] Add GetVideoFilename() and SendVideoPlay() script functions 7 years ago
David Cernat 3ed9d89280 [General] Use separate variables for video & music filenames in packets 7 years ago
David Cernat 509882b5f6 [Client] Rework MechanicsHelper::getTarget() to avoid crashes 7 years ago
David Cernat 7f0549fc4f [Server] Remove hardcoded sync for VideoPlay and add OnVideoPlay event 7 years ago
David Cernat ae8b5a0709 [Server] Remove hardcoded sync for Place, Spawn & other Object packets 7 years ago
David Walley b5abe6a230 Update documentationHowTo.rst
Add a section, under the provisional name "Baby Steps" to describe a minimal process for editing/contributing. Basically just create an account on GitLab, fork openmw there, then edit the relevant document to create Merge Request
7 years ago
David Cernat e3e1cfc549 [Client] Add forgotten comparison in crimeTime and deathTime check 7 years ago
Capostrophic bded697f07
Make Goodbye block using hyperlinks 7 years ago
David Cernat 4eb72eecb1 [Client] Fix crash for invalid CellRefs in MechanicsHelper::getTarget() 7 years ago
Bret Curtis f4146d0079 Merge branch 'patch-1' into 'master'
Update documentationHowTo.rst - extend to integrate GitLab into PyCharm

See merge request OpenMW/openmw!20
7 years ago
David Cernat 4b30a44816 [Client] Compare crimeTime and deathTime when NPCs forgive player crimes
Previously, all crime witnesses stopped being hostile to a respawning player for as long as the player's diedSinceArrestAttempt was true. That meant that, in an area with no guards to arrest the player, crime witnesses did not enage in combat with the player at all ever again until diedSinceArrestAttempt became false.

This commit makes it so the time of the last crime is recorded for each witness, and that is then compared with the time of the LocalPlayer's last death for a one-time crime forgiveness during that player's current life.

This is essentially a gameplay adjustment for "singleplayer with respawns," and will have to be reworked to make sense for every player in multiplayer, though that requires reworking the crime system as a whole and is thus on hold.
7 years ago
Marc Zinnschlag d9de8ccb5b Merged pull request #1781 7 years ago
Marc Zinnschlag dd08194c75 Merged merge request !18 7 years ago
Marc Zinnschlag 7ba512b389 Merged merge request !17 7 years ago
Bret Curtis 94ea9e7dd0
Merge pull request #1793 from Capostrophic/death
Ensure forward-compatibility of death animations of pre-0.43.0 saves (bug #4274)
7 years ago
Alex S 6a2b8f7e85 Fixed changelog entry 7 years ago
David Cernat c23fc3446f [Client] Avoid sending map tiles for Wilderness cells 7 years ago
David Cernat 17c234d9ca [Client] Use initial values for LocalPlayer and LocalActor killers 7 years ago
David Cernat 3e52857e2b [General] Fix build for client and construction set 7 years ago
David Cernat 97cd3effa7 [Client] Make actor debug consistent with object debug 7 years ago
Doc West 6a78379757 Updated change log 7 years ago
Doc West 03c75794c1 Moved crashcatcher to a component and also use it in CS
Reworked debugger detection (failed on gdb 7.11), it now uses /proc to detect the debugger
7 years ago
Capostrophic 33c462c3c2
Update changelog 7 years ago
Capostrophic 9abfabb065
Ensure forward-compatibility of death animations in old saves (fixes #4274) 7 years ago
David Cernat b0bd12f9dd Merge branch '0.6.3' of https://github.com/TES3MP/openmw-tes3mp into 0.6.3 7 years ago
David Cernat c075496748 [General] Replace deathReason in death packets with a killer variable
Add serverside script functions for determining the killers of both players and actors.

Use unsigned ints for script functions returning an object or actor's refNumIndex or mpNum.

Remove updateDeadState() from LocalPlayer and make its code part of updateStatsDynamic() for simplicity.
7 years ago
David Cernat 934e592bdb [Server] Make spacing in CharClass consistent with other categories 7 years ago
David Cernat e8ce009521 [Server] Use regular int as return value for GetObjectSummonerPid()
Additionally, clarify descriptions of script functions for getting information about summoners.
7 years ago
David Cernat f02492a593 [General] Temporarily include target names in mwmp::Target
These will be removed once the server can get the names matching refIds by reading content files.
7 years ago
Doc West b8e53b5b81 Fixed comment 7 years ago
Doc West e187733811 Notify views of changes in all columns when updating the ColumnId_Modification column 7 years ago
Doc West f9b565a46e Removed QDebug include, moved updateUndoRedoAction to an anonymous namespace 7 years ago
Doc West 61109d70b1 Removed invalid / unused signal / slot connection 7 years ago
David Cernat 691b332d03 [Client] Use MechanicsHelper::getTarget() for summoners in ObjectList 7 years ago
David Cernat 130a32ebb0 [Client] Add new methods for handling mwmp::Target in MechanicsHelper 7 years ago
Koncord 7a032baaa3 [General] Move OSG hack to ELSE branch 7 years ago
Koncord 533cd9cdec [General] Fix FindRakNet 7 years ago
Koncord 470ea50b54 [General] Use LuaJit instead default Lua 7 years ago
David Walley 9ebcd65634 Update docs/source/reference/documentationHowTo.rst 7 years ago
Bret Curtis b36bd75b59
Merge pull request #1792 from Capostrophic/character
Make spellcasting stance transition more smooth (bug #4358)
7 years ago
David Walley d03f9125e3 Update documentationHowTo.rst - extend to integrate GitLab into PyCharm
A subsequent MR will suggest moving most of this to a separate document for intermediate-level contributors, and replacing it with much simpler instructions for beginners - basically edit directly on GitLab as suggested by Psi29a on the forum here - https://forum.openmw.org/viewtopic.php?f=43&p=56458#p56457
7 years ago
David Cernat 32ad8ef2f0 [General] Fix incorrect capitalization in ObjectMove directives 7 years ago
David Cernat bbb461a5e5 [General] Make sure data in guiMessageBox is compressed 7 years ago
David Cernat 7010575075 [Server] Return -1 in GetObjectSummonerPid() when the player is invalid 7 years ago
Capostrophic 5bc073603e
Update changelog 7 years ago
Capostrophic faf3e9ba5a Make spellcasting stance transition more smooth (fixes #4358)
If a movement animation was identical to the previous one that was played, restart it from the point the previous animation ended
7 years ago
Doc West 9bfa01c579 Changed the way the revert command works: it now clones the changed record and uses the new RecordBase::revert() method to restore the previous value
Added Flag_Dialogue_Refresh to var type and var value columns so that sub views update properly
7 years ago
David Cernat 76731f5def [Client] Don't remove SummonKeys with actorIds of -1
This prevents summon duplication caused by a SummonKey sometimes being deleted immediately after being created, before the server can send back an ObjectSpawn packet spawning a creature that can be attached to the SummonKey.
7 years ago
Doc West 3cbbbeceb4 Updated change log 7 years ago
Doc West bf49a3e760 Use setData() instead of emtitting dataChanged() which does not work on CI. Also Fixes the remaining issue with subviews not updating due to only the modified flag emitting a change, which prevented the widget mapper from working for updates. 7 years ago
Doc West 96cf2cbd05 Notify views of changes of all cells in a row to properly update the row after revert 7 years ago
Doc West 1c1b5986e9 Updated change log 7 years ago
Doc West 5d38160239 Updated change log 7 years ago
Doc West 2c39dba83b Updated change log 7 years ago
Doc West baf21362e1 Fixed undo / redo actions losing their shortcuts 7 years ago
Doc West 414f626309 Implemented search case sensitivity 7 years ago
David Cernat c2411982d2 [Client] Log object refNumIndexes and mpNums in a consistent way 7 years ago
Bret Curtis 2ff9dc34a4 Merge branch 'win10_ci' into 'master'
see if we can get win10 going

See merge request OpenMW/openmw!8
7 years ago
Bret Curtis d4d46fc602 Build everything but branches until we can allow VM/CIs to run on forked projects. 7 years ago
Bret Curtis 739c49d59b Merge branch 'master' into 'win10_ci'
# Conflicts:
#   CI/before_script.msvc.sh
7 years ago
AnyOldName3 8c153d116b
Merge pull request #1786 from OpenMW/CI_before_script_msvc_fixes
Update before_script.msvc.sh to add GitLab CI support and update dependency links
7 years ago
David Cernat 7775780ad7 [Cllient] Update multiplayer code for handling quick keys 7 years ago
David Cernat 3438061b55 [Server] Add script function for getting a summoner's pid
Additionally, fix typos in the comments for other script functions relating to summoners.
7 years ago
David Cernat 8a23a96da4 [Client] Update initialization of AiFollow packages in multiplayer code 7 years ago
David Cernat a236ffc4be Merge pull request #456 from OpenMW/master while resolving conflicts
# Conflicts:
#	.travis.yml
#	README.md
#	apps/openmw/mwgui/quickkeysmenu.cpp
#	apps/openmw/mwmechanics/actors.cpp
#	apps/openmw/mwmechanics/combat.cpp
7 years ago
Koncord 79903c455c [General] Allow different types for vectorContains 7 years ago
Bret Curtis 57e2573593
Update before_script.msvc.sh
check if temp directory exists, error out and warn user about it.
7 years ago
Bret Curtis 70e9d5c0a0 ; it? 7 years ago
Bret Curtis 11030e56c4 detect existing dir 7 years ago
Bret Curtis 4f07ca28a6 Try passing the _real_ windows dir to innoinstaller, then using the linux-like directory for mv. 7 years ago
Bret Curtis d4c9586bd0 try just converting the \ to a / 7 years ago
Koncord 1f4e6e9114 [General] Add integrity checks to Handshake packet 7 years ago
Koncord f9ff5f10df [General] Reduce packets size and add integrity checks 7 years ago
Koncord fa2bf0663e [General] Simplify vectorContains 7 years ago
Marc Zinnschlag 908af3720f Merged pull request #1791 7 years ago
Marc Zinnschlag 47d0321366 updated credits file 7 years ago
Marc Zinnschlag 2a367a0c35 updated changelog 7 years ago
Marc Zinnschlag e50c3657b3 Merged merge request !16 7 years ago
Marc Zinnschlag 9a88f9147e Merged merge request !15 7 years ago
Doc West e9cc697b60 Sort EnumDelegate values by name 7 years ago
David Cernat 3aa125ceda [Server] Add script functions for getting a summoner's refId and indexes 7 years ago
Koncord 53346e2663 [Client] Return 0 if effect not found 7 years ago
Koncord c5c1a160b2 [Client] Comment out an unused variable 7 years ago
Koncord c69819e0db [General] Change type of refNumIndex & mpNum to unsigned 7 years ago
Koncord 99158beb2e [General] Change effectCount type to unsigned 7 years ago
Koncord 895634cd16 [General] Change type of MpNum to "unsigned int" 7 years ago
Koncord 779f2a564d [General] Change "unsigned long" to uint32_t for cross platform compatibility 7 years ago
Koncord 23684489da [General] Fix clang-tidy warning
Converting integer literal to bool, use bool literal instead
7 years ago
Koncord 7639db02f3 [General] RW functions return true on success 7 years ago
Koncord 45c7c3a0b6 [General] Add integrity checks to PacketPreInit 7 years ago
Koncord d999cc0d55 [General] Add packetValid flag to packets 7 years ago
Koncord 695fb7d4a7 [General] Reorder RW(string) arguments
Change limit of default max string size to 64 KiB
7 years ago
David Cernat f9ebe400f7 [Server] Add script function for checking if object's summoner is player 7 years ago
Koncord d162f6fd3a [General] Explicitly use limitations of the master server 7 years ago
Koncord a48d5b48ef [General] Add maxSize parameter to RW(std::string)
Minor type changes
7 years ago
Koncord 62877f38b7 [General] Remove Terra support
Use LuaJIT instead.
7 years ago
Koncord 685a80887b Remove Pawn support 7 years ago
Andrei Kortunov f4330cf057 Editor: limit FPS in 3D preview windows (feature #3641) 7 years ago
Thunderforge 7cbc4eeb49 Adding missing override keywords
Prevents compiler warnings such as this:

```
/Users/Will/CLionProjects/OpenMW/apps/openmw/mwgui/windowbase.hpp:65:22: warning: 'onOpen' overrides a member function but is not marked 'override' [-Winconsistent-missing-override]
        virtual void onOpen();
                     ^
/Users/Will/CLionProjects/OpenMW/apps/openmw/mwgui/windowbase.hpp:38:22: note: overridden virtual function is here
        virtual void onOpen() {}
                     ^
```
7 years ago
David Cernat bef53749ed [General] Replace BaseObject's hasMaster variable with isSummon
Additionally, add a GetObjectSummonState() script function to the server.
7 years ago
David Cernat 8ce225b1cc [Client] Use the casters of damage-dealing spells as death reasons 7 years ago
Marc Zinnschlag aa5ddd6b28 Merged merge request livestreamer https://www.twitch.tv/vanguardlx best 7 years ago
Finbar Crago 5d9035c6b2 [Fixes #4482] Missing HandToHand on key quick key 0 (introduced in MR !11 for issue #4480)
because apparently i can't count to ten...
7 years ago
David Cernat 958b220835 [General] Send summon duration to server in ObjectSpawn packets 7 years ago
Marc Zinnschlag 3660d55adf updated credits file 7 years ago
Marc Zinnschlag 362798bd90 updated changelog 7 years ago
Marc Zinnschlag 2ea85d0bb6 Merge remote-tracking branch 'gl_finbar-crago/fix_quickkey_segfalt' 7 years ago
Bret Curtis af75c1e909
Update before_script.msvc.sh
reverting back to what works
7 years ago
Bret Curtis dcb2ab80f5
Merge pull request #1788 from Capostrophic/armorcond
Make unarmed creature attacks not affect armor condition (bug #2455)
7 years ago
Bret Curtis 4d60fe5a76 reverting back 7 years ago
Finbar Crago 09c9bd34c3 cleanup more unnecessary struct keywords... 7 years ago
Bret Curtis b8b07b52f0 try this... 7 years ago
Bret Curtis 4177fd04eb
Update before_script.msvc.sh
Does it blend?
7 years ago
Bret Curtis 209359bbc3 Try this on for size... 7 years ago
Bret Curtis 78a3f95ee4 Update before_script.msvc.sh 7 years ago
Bret Curtis 2bf0d598cf
Update before_script.msvc.sh
Wrap in quites
7 years ago
Capostrophic 6e9c08083d
Add missing empty attacker checks 7 years ago
Capostrophic bccba24c40 Make unarmed creature attacks not affect armor condition (fixes #2455) 7 years ago
Bret Curtis 9b6ea0e89f # because our CI VMs are not public, MRs can't use them and timeout 7 years ago
Bret Curtis d3dfe17441 try limiting scope 7 years ago
Finbar Crago 69cd7031e7 Merge branch 'master' into fix_quickkey_segfalt 7 years ago
Finbar Crago 596be205c1 cleanup unnecessary struct keywords... 7 years ago
Bret Curtis 06216aa124 Update .gitlab-ci.yml 7 years ago
Finbar Crago 2722ca50fb fix QuickKeysMenu crash on reopening window after item drop + pickup [see: !11#note_85086570] 7 years ago
Bret Curtis c474709127
Update before_script.msvc.sh 7 years ago
Bret Curtis ca0f6fff4a Update before_script.msvc.sh 7 years ago
Bret Curtis dc48a46e50 Update before_script.msvc.sh 7 years ago
Bret Curtis a6d6dd5995 updating for the nits 7 years ago
Bret Curtis 8811c7141a
Update before_script.msvc.sh
taking nits into account :)
7 years ago
Marc Zinnschlag a45d86bdf3 Merge remote-tracking branch 'gl_thunderforge/4479/separate-game-advanced-settings-in-launcher-take-2' 7 years ago
Marc Zinnschlag f06dd39892 Merge remote-tracking branch 'upstream/master' 7 years ago
Bret Curtis c2ff30c4d7 correcting from GH/AV feedback, testing on GL. 7 years ago
Bret Curtis a532aef935
Update before_script.msvc.sh
updating version check and correct indentation, wrap BOOST_SDK in "" to support dirs with spaces.
7 years ago
Bret Curtis 4c0e475092
Update before_script.msvc.sh
Use powershell trick with boost_temp so there is little chance of collision.
7 years ago
Bret Curtis bccd83c656 Use 1.67 7 years ago
Bret Curtis bc830a9c45 use boost_temp 7 years ago
Bret Curtis 63bbc77ee7 try using the powershell trick from AnyOldName3 7 years ago
Finbar Crago 7ae388086b Merge branch 'master' into fix_quickkey_segfalt 7 years ago
Thunderforge 72f6b1a693 Separating "Game" Advanced Settings into "Game Mechanics" and "User Interface" 7 years ago
Bret Curtis 3379eafd33 Update before_script.msvc.sh 7 years ago
Bret Curtis 3ceb9116de Give pwd -W a try 7 years ago
Finbar Crago ed71656ea6 fix updateActivatedQuickKey() crash
keyboard numbers don't start at zero...
7 years ago
Bret Curtis c4a4111b2e Update before_script.msvc.sh 7 years ago
Bret Curtis fb6ad9faec try %TMP% ? 7 years ago
Bret Curtis 4ad3d66629 try using just ${TMP} 7 years ago
Bret Curtis 8be52d228e
Update before_script.msvc.sh
small fixes
7 years ago
Finbar Crago 24d5fb09da fix crash on simultaneous key presses 7 years ago
Bret Curtis 60ec340fa3 remove toolset_real, use just toolset, do proper comparison 7 years ago
Bret Curtis 71314f0c3a Use boost 1.67 instead of 1.61 7 years ago
Bret Curtis 46575d8de7
Update before_script.msvc.sh
1.61 -> 1.67
7 years ago
Bret Curtis 660193ae1b
Update before_script.msvc.sh
This has working GL Win10 MSVC updates, should be cross-compatible with appveyor.
7 years ago
Bret Curtis 1c4363eaa6 Using SYSTEMDRIVE because TEMP apparently means something different in bash then to windows cmd. 7 years ago
Bret Curtis 7bf502dd02 Bash it out! 7 years ago
Bret Curtis 1061270ac0 Try using @TEMP@ instead of hard coding it. 7 years ago
Bret Curtis 45d77372a0 with 260 char path fixed, this should work. 7 years ago
Bret Curtis 2d70c94733 gather up everything with 7zip 7 years ago
Bret Curtis f07d50e5bf
Merge pull request #1785 from akortunov/warnfix
Fix some GCC warnings
7 years ago
Bret Curtis 102266d08d
Merge pull request #1784 from nikolaykasyanov/revert-sdl-get-attribute
Revert "Retrieve SDL window settings instead of using magic numbers"
7 years ago
Bret Curtis a8adb9374b use quotes 7 years ago
Finbar Crago d790a27060 Merge branch 'master' into fix_quickkey_segfalt 7 years ago
Bret Curtis 7cd0235fed Try creating a zip and archiving it. 7 years ago
Andrei Kortunov d9a1de0ec7 Do not use deprecated function 7 years ago
Andrei Kortunov 5455490ad2 Avoid fall-through in spell selection 7 years ago
Finbar Crago 80a3f0a0d4 switch mSelectedIndex/mActivatedIndex int to mSelected/mActivated keyData pointers 7 years ago
Finbar Crago 335e2c5897 add keyData struct + general cleanup 7 years ago
David Cernat 9102df7fde [General] Make WorldCollisionOverride also work with specific refIds
For now, this only makes it possible to enforce collision for specific refIds for placed objects.
7 years ago
David Cernat c7f10892a9 [General] Add vectorContains util for checking strings in vectors 7 years ago
David Cernat 84af9d9999 [Server] Reorder world map script functions 7 years ago
David Cernat b81ca18316 [Client] Don't clear container Ptrs when disposing of corpses
The reason for this is that only the server should be determine whether a corpse can be disposed of or not.
7 years ago
Bret Curtis 83e23ee6fd gather up artifacts and use all processors available 7 years ago
Nikolay Kasyanov 5fcb091127 Replace FIXME with a detailed explanation of the issue 7 years ago
Bret Curtis f17426cbcd give boost 1.67 a spin with msvc 14.1 7 years ago
Nikolay Kasyanov 9c78364c45 Revert "Merge pull request #1771 from Xenkhan/master"
This reverts commit 9667dd051c, reversing
changes made to f52e06fc19.
7 years ago
David Cernat 7ffdb18bf9 [General] Implement ActorDeath packet, part 1
ActorDeath packets are sent for dead actors before their StatsDynamic packets. They contain the actor's deathReason in a manner similar to that of PlayerDeath packets.

A future commit will replace the deathReason with a variable named killer which will be an mwmp::Target.
7 years ago
Bret Curtis 8511f2398a try a set and call? 7 years ago
Bret Curtis df23e0f857 Try calling it directly 7 years ago
Bret Curtis bd602847b5 fix broken QT 5.7.0 link 7 years ago
Bret Curtis 59a4251a6a try to extract boost higher up in dir, then move. 7 years ago
Bret Curtis 609d6a1b29 bad syntax 7 years ago
Bret Curtis b6fc204dd3 be more aggressive about suppressing message boxes 7 years ago
Bret Curtis f7e1083ba4 get more output from boost 7 years ago
Bret Curtis da5d7afe22 Update .gitlab-ci.yml 7 years ago
Bret Curtis 6751a7991d Update .gitlab-ci.yml 7 years ago
Bret Curtis 2d5f71e5be Update .gitlab-ci.yml 7 years ago
Bret Curtis edd22342f2 Update .gitlab-ci.yml 7 years ago
Bret Curtis 218353e452 Update .gitlab-ci.yml 7 years ago
Bret Curtis 0105a48a4f give %% a try 7 years ago
Bret Curtis 6d1a83e667 Update .gitlab-ci.yml 7 years ago
Bret Curtis 51179a2c38 try a wildcard? 7 years ago
Bret Curtis 1fdffd6ef9 see if we can get win10 going 7 years ago
Bret Curtis 87d9a4ff0b Merge branch 'zini_updates' into 'master'
last minute updates from zini

See merge request OpenMW/openmw!7
7 years ago
Marc Zinnschlag 520e65f822 last minute updates from zini 7 years ago
Marc Zinnschlag 5ee731d86f updated roadmap section 7 years ago
Marc Zinnschlag 8bc6c85396 last minute changes (this time for real; forgot to merge in the last update from the private repo) 7 years ago
Bret Curtis f64d949169
Merge pull request #1780 from akortunov/persistanims
Ignore movement from scripted animations
7 years ago
Marc Zinnschlag 8cda355af6 last minute changes to design doc 7 years ago
Marc Zinnschlag 2afcea3870 added post-1.0 design document 7 years ago
Andrei Kortunov ec73011617 Clean temporary storage if we assign new AI package (bug #4464) 7 years ago
Andrei Kortunov ee45f54b53 Refactor AiTemporaryStorage usage 7 years ago
Andrei Kortunov 3c7ab976c3 Ignore movement from scripted animations (bug #4475) 7 years ago
Finbar Crago cac6d59140 Merge branch 'master' into fix_quickkey_segfalt 7 years ago
Bret Curtis 26615d588e Merge branch 'multi_build' into 'master'
Multi build

See merge request OpenMW/openmw!4
7 years ago
Bret Curtis 4d6ca2c387 preserve dmg artifact 7 years ago
Bret Curtis 9e7731259d what if we try make -j2 package ? 7 years ago
Bret Curtis cfcd9c3fc6 What happens when we don't make install? 7 years ago
Bret Curtis dd60b8f179 only delete files inside OpenMW.app dir 7 years ago
Bret Curtis c1aee49b76 clean up after our previous build. 7 years ago
Bret Curtis 06eb9539bd Let make install do it's thing, it's more reasonable on macos and let's only archive that. 7 years ago
Bret Curtis e068ee3533 tell unzip to overwrite all files 7 years ago
Bret Curtis 9e2c6d9fe1 actually step into the build directory and build! 7 years ago
Bret Curtis 308d78e3da only download via curl if file on server is different than what is currently cached on VM. 7 years ago
Bret Curtis ae4cb0c3ee no need for macos_qt_formula since on osx there is no more qt4, just qt5 7 years ago
Finbar Crago 43c9fd4cec check MWWorld::Ptr != NULL for MWGui ItemPtr tooltips 7 years ago
Finbar Crago 186ec8c50f rm ContainerStore/refItem 7 years ago
Marc Zinnschlag 705b2dca0e Merged pull request #1777 7 years ago
Marc Zinnschlag baeaff2309 Merged pull request #1778 7 years ago
Bret Curtis a0cae78cb2
Merge pull request #1779 from akortunov/coverity
Fix some code coverity issues
7 years ago
Andrei Kortunov 97d8cc0efe Check if the local was not found, just for sure 7 years ago
Andrei Kortunov 7dff8d8fe2 Check cell for null 7 years ago
Finbar Crago 46c6abcf54 add string vectors for name/id in QuickKeysMenu for item lookups 7 years ago
Andrei Kortunov 441463327c Validate map size 7 years ago
Andrei Kortunov 359e748c28 Initialize some missing fields in constructors 7 years ago
Bret Curtis d008cd0c46 Update .gitlab-ci.yml 7 years ago
Bret Curtis 87f367ec11 Update .gitlab-ci.yml 7 years ago
Capostrophic d6a170f848
Update changelog 7 years ago
Capostrophic ecafcefae9
Fall back to regular head when getVampireHead fails 7 years ago
Bret Curtis f1158e8129 Update .gitlab-ci.yml 7 years ago
Bret Curtis 55de1c1a72 Update .gitlab-ci.yml 7 years ago
Capostrophic afbe8f2161
Update changelog 7 years ago
Capostrophic 35b0546737 Consider <p> tag when discarding post-EOL tag text (regression #4473) 7 years ago
Finbar Crago da4c55d5ad prevent segfalt in QuickKeysMenu when item has been removed from player inventory
added a MWWorld::ContainerStore to hold item copies which are then used to find
real items with findReplacement().

(storing the RefId could be a better solution but would probably leave tooltips broken...)
7 years ago
Bret Curtis 40a9d8ac06 Update .gitlab-ci.yml 7 years ago
Bret Curtis c2826ca878 Update .gitlab-ci.yml 7 years ago
Bret Curtis 393ec99944 Update .gitlab-ci.yml 7 years ago
Bret Curtis 88555c0463 Update .gitlab-ci.yml 7 years ago
Bret Curtis 601b69b36c Update .gitlab-ci.yml 7 years ago
Bret Curtis dcba3a1058 Update .gitlab-ci.yml 7 years ago
Bret Curtis 516fc0283b Update .gitlab-ci.yml 7 years ago
Bret Curtis 64cc3b3a6a
Merge pull request #1774 from nikolaykasyanov/ci-macos-1013
[macOS, CI] Build using macOS 10.13 SDK
7 years ago
Bret Curtis 9667dd051c
Merge pull request #1771 from Xenkhan/master
Retrieve SDL window settings instead of using magic numbers
7 years ago
Bret Curtis a55583a395
Merge branch 'master' into master 7 years ago
Xenkhan f0acc64544
Update changelog 7 years ago
Marc Zinnschlag f52e06fc19 Merge branch 'glsl-editorconfig' into 'master'
Update .editorconfig to include GLSL

See merge request OpenMW/openmw!3
7 years ago
AnyOldName3 d1736ad0c8 Update .editorconfig to include GLSL 7 years ago
Xenkhan 405a0caf29
Remove unneeded whitespace 7 years ago
Xenkhan 5a4817c147
Get rid of reinterpret_cast<> 7 years ago
Nikolay Kasyanov 90ccf5b42b [macOS, CI] Build using macOS 10.13 SDK 7 years ago
Marc Zinnschlag 22eb037c18 Merged pull request #1773 7 years ago
Bret Curtis 6655b7e512
Merge pull request #1740 from nikolaykasyanov/software-cursor-decompression
Decompress cursors using SDL software renderer on Mac or if OSG >= 3.5.8 or if OPENMW_DECOMPRESS_TEXTURES is set
7 years ago
Bret Curtis 9cf815505b
formatting 7 years ago
Marc Zinnschlag 4e121a7434 updated credits file 7 years ago
Marc Zinnschlag c90996f991 Merged merge request !1 7 years ago
Marc Zinnschlag 6315848620 Merged merge request !2 7 years ago
Nikolay Kasyanov 65ec58a669 Move the changelog entry to 0.44.0 7 years ago
Bret Curtis b619c0de2d
Merge pull request #1772 from akortunov/deathanim
Fast-forward death animation to end if death animation was finished earlier
7 years ago
Andrei Kortunov c195144b17 Take transformation from first node with given name in file (bug #4469) 7 years ago
Atahualpa c0fc615cd6 Adds the option to ignore "Base" records when running the verifier. (fixes #4466)
Improves previous commit:
1. Initialise mIgnoreBase boolean member with FALSE.
2. Remove isBaseOnly() function and replace with direct use of Record member.
7 years ago
Bret Curtis 664edc5a39
Merge pull request #1757 from akortunov/musicfix
Handle exception when try to load non-music file
7 years ago
Andrei Kortunov c9756cee4c Fast-forward death animation to end if death animation was finished earlier (regression #4468) 7 years ago
Bret Curtis 3ebebdf3c1
Merge pull request #1751 from wareya/terrainbleeding
Fix #4452
7 years ago
Bret Curtis f3923a41c0
Merge pull request #1770 from Capostrophic/open
Make Open spells casted by anything trigger player crime event (bug #4461)
7 years ago
Atahualpa 9d61d76e92 Adds the option to ignore "Base" records when running the verifier. (fixes #4466)
Adds a boolean setting to the user preferences. This setting is locally saved to all OpenMW-CS check stages. When a verification is done, the setting is updated on setup for each check stage. If set to true, the boolean value is then used to skip the verification process for every base record - minus some special cases where, e.g., counters are to be set first.

Related issue:
- Fixes #4466: Editor: Add option to ignore base records when running verifier (https://gitlab.com/OpenMW/openmw/issues/4466)

Tests:
The changes were successfully tested in OpenMW-CS by creating faulty "Base" and "Modified" records for every record type (if possible) and, then, running the verifier with and without the option respectively.
7 years ago
Xenkhan 24ddb66af9
Retrieve SDL window settings instead of using magic numbers 7 years ago
Capostrophic 6c23caadd7 Fix crash when a target in a different cell is (un)locked 7 years ago
Adam Bowen 0d70cb9473 Re-link bugtracker links to Gitlab
* Link "1.0" issues to the "1.0" tag
* Link "report a bug" to the issues page
* Link "known issues" to the "Bug" tag
7 years ago
Capostrophic 0731d79c09
Update changelog 7 years ago
Capostrophic 0c4fa55f16 Make Open spells casted by anything trigger player crime event (fixes #4461) 7 years ago
Marc Zinnschlag 101f0b1579 Merge remote-tracking branch 'upstream/master' 7 years ago
Bret Curtis 975597bac9
Merge pull request #1766 from rhtucker/master
Started migrating installation guide from the wiki.
7 years ago
Bret Curtis c1eb9042b3
Merge branch 'master' into terrainbleeding 7 years ago
Marc Zinnschlag 7cfb7063c2 Merged pull request #1767 7 years ago
Marc Zinnschlag 7be069fcd2 Merged pull request #1743 7 years ago
Marc Zinnschlag f275e657f6 Merged pull request #1761 7 years ago
Andrei Kortunov 5fd3ec1035 Implement unlockable locks with 'lock 0' console command 7 years ago
Marc Zinnschlag a8ad530db9 Merged pull request #1749 7 years ago
Marc Zinnschlag 2a52ade219 Merged pull request #1760 7 years ago
rhtucker fe86e7ffc7
Fixed inconsistent use of "since" 7 years ago
Bret Curtis 1c7d5c68c5 Update CHANGELOG.md, technically solved by moving from redmine over to gitlab. 7 years ago
Capostrophic 0cf2f6452b Update changelog 7 years ago
Capostrophic 8376c8c68e Allow partial matches in NotCell condition (fixes #4459) 7 years ago
Bret Curtis e93104a6b3
Merge pull request #1758 from Capostrophic/screenshot
Remove screenshot taken message again
7 years ago
Bret Curtis 70dec71c00
Merge pull request #1763 from akortunov/activatedoor
Forbid actors to use teleporting doors
7 years ago
Bret Curtis 3cc6da1db2
Update door.cpp
typo fix
7 years ago
Bret Curtis 88bf74b2a3
Merge pull request #1765 from akortunov/wanderfix
Fix arguments parsing for AiWander console command
7 years ago
Bret Curtis 3f2dbdc8a8
Merge branch 'master' into wanderfix 7 years ago
Bret Curtis ecfc5fcd63
Merge pull request #1764 from akortunov/lightfix
Ignore lights without CanCarry flags when NPC selects torch
7 years ago
Ryan Tucker 7e23e6586b Put together most of the informal guide on contributing to documentation. 7 years ago
Ryan Tucker c5f5984c09 Started migrating installation guide from the wiki.
Fixed a bunch of errors that popped up on my local build.
7 years ago
Andrei Kortunov f3f7487664 Fix arguments parsing for AiWander console command (bug #4458) 7 years ago
Andrei Kortunov e08b0d3070 Ignore lights without CanCarry flags when NPC selects torch (bug #4457) 7 years ago
Nikolay Kasyanov 75d79e98b9 Force software decompression if OPENMW_DECOMPRESS_TEXTURES is set 7 years ago
Andrei Kortunov 2a65aaf5ab Forbid actors to use teleporting doors (bug #2562) 7 years ago
Nikolay Kasyanov 359f87ab9f Change imageToSurface to return a unique_ptr to avoid manual surface cleanup 7 years ago
Bret Curtis 3f88aa46d0
Merge pull request #1759 from Thunderforge/refactor-launcher-sdl
Refactor SDL loading in Launcher to fix macOS errors
7 years ago
Andrei Kortunov 9c3da41130 Add murder bounty when a player follower commits murder (bug #2852) 7 years ago
Marc Zinnschlag 5a9e382efe Merged pull request #1421 7 years ago
Thunderforge 506d615acc Moving csignal import from main to graphicspage 7 years ago
Thunderforge e51bfb46c6 Adding Changelog records 7 years ago
Thunderforge 7615e78e52 Move SDL initialization from main.cpp to graphicspage.cpp 7 years ago
Capostrophic 1abf749f03
Remove screenshot taken message 7 years ago
Andrei Kortunov 2854f6ca83 Handle exception if we try to play non-music file (bug #4416) 7 years ago
Miloslav Číž 2a23b53515 Merge branch 'drummyfish/openmw-toggleborders' 7 years ago
Miloslav Číž 477e1437d2 Resolve conflicts 7 years ago
Andrei Kortunov 49ba00a3ec Add NPC validation to esmstore (bug #2772) 7 years ago
Miloslav Číž 34f8eca7bd Fix indent 7 years ago
Miloslav Číž 31c68c534c Merge branch 'drummyfish/openmw-toggleborders' 7 years ago
Miloslav Číž 24078d4a72 Update CHANGELOG 7 years ago
Miloslav Číž ab8de9fa14 Set node mask to cell borders 7 years ago
Miloslav Číž 414e6caafe Make tb work with distant terrain 7 years ago
Miloslav Číž f18d57429e Move cell border management to World 7 years ago
Miloslav Číž 1b8d500c07 Make tb command work again 7 years ago
Miloslav Číž 1fd5ad3e56 Use REAL_SIZE constant 7 years ago
Bret Curtis ccfc07e7e3
Merge pull request #1548 from drummyfish/screenshot360
360° screenshots
7 years ago
Miloslav Číž dd00e438fe Merge branch 'screenshot360' of https://github.com/drummyfish/openmw into screenshot360 7 years ago
Miloslav Číž 7178ee3a6e Add FIXME comment 7 years ago
Miloslav Číž d629c30fdb
Merge branch 'master' into screenshot360 7 years ago
Miloslav Číž 5387e3ba8f Update CHANGELOG 7 years ago
Bret Curtis 60d2678cff
Merge pull request #1755 from akortunov/master
Add missing changelog entries
7 years ago
Andrei Kortunov e814843cdb Add missing changelog entries 7 years ago
Marc Zinnschlag 2b35c5efd7 Merge remote-tracking branch 'upstream/master' 7 years ago
Marc Zinnschlag aea481eacb Merged pull request #1753 7 years ago
Marc Zinnschlag f62df90960 Merged pull request #1572 7 years ago
Marc Zinnschlag 17db4b4db3 Merged pull request 1754 7 years ago
Bret Curtis 48d74a8781 Disable testing for now, not yet necessary. 7 years ago
Bret Curtis a275972361 Merge branch 'add_pipeline_badge' into 'master'
Update README.md to indicate that our gitlab pipeline is building

See merge request OpenMW/openmw!1734
7 years ago
Andrei Kortunov 61c968d550 Ignore broken items when search for replacement (bug #4453) 7 years ago
Bret Curtis 45957dd707
Merge pull request #1647 from Capostrophic/fatigue
Improve the logic of trading formulae (bug #2222)
7 years ago
Marc Zinnschlag 7ca56ccd29 set search status bar to 'no results' message when search yields no results 7 years ago
Andrei Kortunov 81b78a82e8 AI: try to open doors every AI_REACTION_TIME seconds (bug #4454) 7 years ago
Bret Curtis 9bd940e153 Update README.md to indicate that our gitlab pipeline is building 7 years ago
Marc Zinnschlag 7d2394273e added statusbar to search window (Fixes #3276) 7 years ago
Bret Curtis 032768a505 try to use as many cores as possible 7 years ago
Bret Curtis 3f4d5598a5 Update README.md to be more generic about OpenMW 7 years ago
Bret Curtis da37585a8e Update .gitlab-ci.yml so that we only build with -j2 7 years ago
Bret Curtis 559754fa76 try this dance again 7 years ago
Bret Curtis a49649c313 Try to get it to run and build on my docker instance. 7 years ago
Bret Curtis 674925dfb5 Merge branch 'psi29a-master-patch-17094' into 'master'
what does this give us from a CI perspective?

See merge request OpenMW/openmw!1732
7 years ago
Miloslav Číž dcfbd554bb Remove try catch block 7 years ago
Bret Curtis 2e2be76e3f Update .gitlab-ci.yml 7 years ago
Bret Curtis 3e4dc31e39
Merge branch 'master' into fatigue 7 years ago
Bret Curtis a747318c90
Merge branch 'master' into terrainbleeding 7 years ago
Marc Zinnschlag 4c4d4672d4 Merged pull request #1752 7 years ago
Marc Zinnschlag 1ba0317905 Merged pull request #1670 7 years ago
Marc Zinnschlag 48711bbdde Merged pull request #1592 7 years ago
Miloslav Číž c3d7ee5a9e Resolve merge conflicts 7 years ago
Thunderforge b37f325126 #4324/Updating Changelog.md 7 years ago
Thunderforge 058cfb553c Adding CFBundleIdentifier to OpenMW's Info.plist file for Macs 7 years ago
wareya bd4badc153 update changelog 7 years ago
wareya 94f695cffc Fix #4452 and remove dead code 7 years ago
Miloslav Číž db8aaa74d6 Start cell border debug drawing 7 years ago
Bret Curtis 3c933ebaad Update .gitlab-ci.yml 7 years ago
Bret Curtis cc396f4dfd Update .gitlab-ci.yml 7 years ago
Nikolay Kasyanov 224b94c0ce Decompress cursors using SDL software renderer on Mac or if OSG >= 3.5.8 7 years ago
Andrei Kortunov 9c45cc7e48 Use player reference instead of pointer 7 years ago
Marc Zinnschlag a3911f52a0 Merged pull request #1750 7 years ago
Marc Zinnschlag 6114cff842 updated credits file 7 years ago
Marc Zinnschlag 97773697a9 Merge remote-tracking branch 'florianjw/precise-rotations' 7 years ago
Capostrophic 1c8a20a54a Set ok button focus in settings window by default (fixes #4368) 7 years ago
Marc Zinnschlag 565922f9ad naked expressions beginning with the member operator were allowed erroneously outside of the console (Fixes issue #2971) 7 years ago
Marc Zinnschlag 296ad8424e updated changelog 7 years ago
Marc Zinnschlag 8d0f717e72 Merged pull request #1739 7 years ago
Marc Zinnschlag 90febde783 Merged pull request #1742 7 years ago
Marc Zinnschlag 816a1733dc Allow comma after Begin and End script instruction (Fixes #4451) 7 years ago
Bret Curtis 1c736ea064 Update .gitlab-ci.yml 7 years ago
Andrei Kortunov bce6d79ad3 Add changelog entries, related to animations 7 years ago
Andrei Kortunov f299be8158 Play scripted animations even if SkipAnim is used 7 years ago
Bret Curtis a166534226 Update .gitlab-ci.yml 7 years ago
Bret Curtis dddceba8f2 Update .gitlab-ci.yml 7 years ago
Bret Curtis e3832cd2e2 Update .gitlab-ci.yml 7 years ago
Bret Curtis bc0eb3349b Update .gitlab-ci.yml 7 years ago
Andrei Kortunov 25bb7c1826 Make 'PlayGroup idle' to cancel scripted animations 7 years ago
Bret Curtis e5dff83e38 Update .gitlab-ci.yml 7 years ago
Bret Curtis a89441e879 Update .gitlab-ci.yml 7 years ago
Bret Curtis 20d8a424d6 Update .gitlab-ci.yml 7 years ago
Andrei Kortunov 0e441d48ac Give scripted animations highest priority (bug #4286) 7 years ago
Bret Curtis 8c4731728c Update .gitlab-ci.yml 7 years ago
Bret Curtis de1cad86ab Update .gitlab-ci.yml 7 years ago
Bret Curtis d986354d53 Update .gitlab-ci.yml 7 years ago
Bret Curtis 8714f48ce7 Update .gitlab-ci.yml 7 years ago
Bret Curtis 04dc74a1d6 Update .gitlab-ci.yml 7 years ago
Marc Zinnschlag 3af003d36b Merge branch 'test_update_workflow' into 'master'
Update README.md with an important distinction.

See merge request OpenMW/openmw!1731
7 years ago
Bret Curtis 7502a7dc4d what does this give us from a CI perspective? 7 years ago
Andrei Kortunov 0c92655250 Avoid code duplication in character manager 7 years ago
Andrei Kortunov e3812f4075 Check creature stats only for actors 7 years ago
Andrei Kortunov b0a140e714 Disable actor collision only after end of death animation 7 years ago
Andrei Kortunov ebaa6fb5a2 Play death scream only once 7 years ago
Bret Curtis 5fba1c599b Update README.md with an important distinction. 7 years ago
Andrei Kortunov 0d3f535590 Warn about mod conflicts 7 years ago
Andrei Kortunov 427be928d0 Do not update animation state for dead actors 7 years ago
Andrei Kortunov 977a27ecb7 Do not clear corpses until end of death animation (bug #4307) 7 years ago
Bret Curtis 7310e3c8c2
Merge pull request #1748 from akortunov/bookfix
Do not show any book text after last <BR> tag
7 years ago
Andrei Kortunov a42c663fd7 Do not interrupt scripted animations by death animation (bug #4286) 7 years ago
Andrei Kortunov d0619cfb35 Play death animation for non-persisting actors with 0 health (bug #4291) 7 years ago
Andrei Kortunov 6099735c60 Early out only when scripted animation is playing 7 years ago
Bret Curtis e53fb953bc
Merge pull request #1746 from Capostrophic/interrupt
Make WakeUpPC interrupt waiting if it was supposed to be (bug #3629)
7 years ago
Andrei Kortunov e234dd2a36 Do not interrupt scripted animations 7 years ago
Bret Curtis 23d16dc870
Merge pull request #1745 from Thunderforge/patch-1
Adding Feature #4345 to Changelog.md
7 years ago
Andrei Kortunov 66a46ff03c Do not show any book text after last <BR> tag. 7 years ago
Capostrophic d43766d3c9 Make WakeUpPC interrupt waiting if it was supposed to be (fixes #3629) 7 years ago
Thunderforge ab03d238bb
Adding Feature #4345
Implemented as part of #1623, but not added.
7 years ago
Andrei Kortunov acd3cba5fa Store previous items in the savegame 7 years ago
Andrei Kortunov 9fd2d57b86 Move previous items to player 7 years ago
Andrei Kortunov f977c6876f Bound items: store item ID instead of pointer 7 years ago
Andrei Kortunov 4de9d9fa77 Split adjustBoundItem() 7 years ago
Andrei Kortunov d1b1cb748d Reequip previous item only if the expired bound item was equipped 7 years ago
Andrei Kortunov 9b72a6ac69 Use the MWWorld::Ptr() instead of string ID 7 years ago
Andrei Kortunov 0375bedab2 Equip previous item after a bound item expires (bug #2326) 7 years ago
Bret Curtis 926ddcd47e
Merge pull request #1741 from akortunov/master
Do not reset mUpperBodyState for weapon->weapon switch
7 years ago
Marc Zinnschlag dbc87e7c7d updated changelog 7 years ago
Marc Zinnschlag 25e4c52adf Merged pull request #1744 7 years ago
Thunderforge a9ca528fb8 Adding version number of macOS build of OpenMW 7 years ago
wareya 7344323b9e remove indentation from blank lines 7 years ago
wareya 8f45b0d53a remove unnecessary conditions 7 years ago
Andrei Kortunov fba0c155df Fix assertion fail related to NiLookAtController 7 years ago
Andrei Kortunov ae87e0d3fc Do not reset mUpperBodyState for weapon->weapon switch (regression #4446) 7 years ago
Andrei Kortunov 5ead6353ac Add missing changelog entry 7 years ago
Andrei Kortunov 4ba361fea6 Unhardcode sunset and sunrise settings (bug #1990) 7 years ago
Marc Zinnschlag 7d9de93fd3 Merged pull request #1477 7 years ago
Marc Zinnschlag 551a69f1b1 Merged pull request #1559 7 years ago
Marc Zinnschlag efb4abbb7f Merged pull request #1623 7 years ago
Marc Zinnschlag 619110ca4c Merged pull request #1737 7 years ago
Marc Zinnschlag 76972bb2f6 Merged pull request #1709 7 years ago
Marc Zinnschlag 6a4cd975b6 Merge remote-tracking branch 'capostrophic/goodbye' 7 years ago
Thunderforge dfa9968565 Renaming Launcher::DataFilesPage::signalSelectedFilesChanged to signalLoadedCellsChanged 7 years ago
Thunderforge 62c4eb8d6a Explicitly flagging loaded cells changed as queued 7 years ago
wareya 6277f5511c fix #3876 and #3993 7 years ago
Andrei Kortunov 2e6cf2a414 Add changelog entries 7 years ago
Andrei Kortunov 6ed2773299 Do not stack return packages 7 years ago
Andrei Kortunov 74a2cbe696 AI: return back after pursuit 7 years ago
Andrei Kortunov 3d0631cfcc Store last AI package in savegame 7 years ago
Andrei Kortunov 3a0ee78d2b AiTravel: store mHidden flag in savegame 7 years ago
Andrei Kortunov 2f5beb8853 Remove unnecessary hack 7 years ago
Andrei Kortunov 57d686131e Remove redundant condition 7 years ago
Andrei Kortunov 5105c67642 Add mHidden field to AiTravel 7 years ago
Andrei Kortunov 81f29d8dcd AiWander: resume moving to destination after combat 7 years ago
Andrei Kortunov 18ff097e4a Add the parameter to AiSequence::stack() to control ability to cancel other AI packages 7 years ago
Andrei Kortunov 9d27eb197f AiWander: return to initial position only after combat 7 years ago
Bret Curtis 3c2c0960d1
Merge pull request #1734 from MocquillonCedric/windows-cmake-pre3.9-support
Add support for msvc with cmake version pre 3.9 (fixes #4429)
7 years ago
Bret Curtis 61c969e970
Merge branch 'master' into hitboxfix 7 years ago
Capostrophic b274931165
Revert erroneous changes 7 years ago
Capostrophic dd2a11b243
Merge branch 'master' into goodbye 7 years ago
Capostrophic 99781ab70c
Fix changelog 7 years ago
Capostrophic 01f12a6bd5
Update changelog 7 years ago
Capostrophic 24c1ee7744 Use relative stat difference for haggling 7 years ago
Capostrophic b7026df551 Improve the offered price formula (Fixes #2222) 7 years ago
Andrei Kortunov fed10e87aa Store integer actor ID in AI packages (bug #4036) 7 years ago
Marc Zinnschlag 9d0ce25052 Merged pull request #1738 7 years ago
Cédric de5a3eaae9 Fix indentation issue: replace tab by spaces 7 years ago
Marc Zinnschlag 7899f44173 Merged pull request #1619 7 years ago
Bret Curtis 6c04cecab1
Merge pull request #1704 from akortunov/per_group_animation
[Feedback needed] Support for per-group KF-animation files
7 years ago
Andrei Kortunov fea34bd73f Added support for per-group animation files 7 years ago
Capostrophic 0db702dfa7
Update changelog 7 years ago
Capostrophic 11103211c5 Make Goodbye and Choice choices mutually exclusive 7 years ago
Andrei Kortunov 2fada94879 Improve MRK NiStringExtraData handling (bug #4419) 7 years ago
Marc Zinnschlag 53e8882366 updated changelog 7 years ago
Marc Zinnschlag 21ea49fe83 Merge remote-tracking branch 'capostrophic/physics' 7 years ago
Cédric b784c7873d Update authors 7 years ago
Cédric 4a9b790dbe Update changelog 7 years ago
Cédric 7cafec9861 Add support for msvc with cmake version pre 3.9 (fixes #4429) 7 years ago
Capostrophic 1a354f88ac Make choices trigger goodbye if Goodbye is used (fixes #3897) 7 years ago
Andrei Kortunov 05026b891e Add changelog entries 7 years ago
Andrei Kortunov 6eb531c6ac Add missing changelog entries 7 years ago
Andrei Kortunov 1b9edbe119 Add unequip animation during stance switching (bug #4327) 7 years ago
Andrei Kortunov bde1d07d4e Use hitboxes and focused object for touch spells (bug #3374) 7 years ago
Andrei Kortunov 4666a6a0ab Use default hit formula as fallback 7 years ago
Andrei Kortunov 9e5d577a71 Aim from center of attacker to center of target 7 years ago
Andrei Kortunov f5dc9f0162 Use hitbox cone only as fallback 7 years ago
Andrei Kortunov ab433102a4 Increase hit distance for player by halfExtents 7 years ago
Thunderforge d46590934a Importing mutex 7 years ago
Thunderforge e282ece3d1 Fixing bug with autocomplete not loading correctly during startup 7 years ago
Thunderforge 103a7ac628 Using a mutex lock to prevent race conditions 7 years ago
Thunderforge e26c675829 Changing join to detach so that the thread will not block the UI 7 years ago
Thunderforge 26dfef7970 Changing where we are loading cells to prevent Qt access issue 7 years ago
Thunderforge 78234e9468 Moving autocomplete code to thread 7 years ago
Thunderforge c2fff61ccd Changing so that data changes happen only after the addon is checked 7 years ago
Thunderforge d58cce9c72 Adding WIP code to dynamically change the autocomplete fields 7 years ago
Capostrophic e32f38b939 Allow jumping when you're stuck on a slope (fixes #4221) 7 years ago
Thunderforge fb27f34a32 Add autocomplete to the "Start default character at" field 7 years ago
Thunderforge d42791e260 Moving testing options to Advanced page 7 years ago
Thunderforge f07a12af73 Changing label "and may cause issues" to "and will cause issues" 7 years ago
Thunderforge 6931f6cadc Adding message indicating the purpose of the "Testing" block 7 years ago
Thunderforge dcc262ed91 Fixing Skip Menu checkbox not working correctly 7 years ago
Thunderforge 082e166fae Making "start default character at" field enabled or disabled by the previous checkbox 7 years ago
Thunderforge da74ca5ce0 Add testing options to the Settings page 7 years ago
Florian Weber 10fe334247
add more precise float-spinbox and use it for rotations 7 years ago
Miloslav Číž db6107f12f
Merge branch 'master' into screenshot360 7 years ago
Miloslav Číž a142a67972 Add default settings for 360 screenshots 7 years ago
Miloslav Číž 37aa761283 Change spherical screenshot filtering to nearest 7 years ago
Miloslav Číž 390838e084 Replace switch with ifs in shader 7 years ago
Miloslav Číž ea5e078526 Update shaders in CMakeLists 7 years ago
Miloslav Číž df61a30259 preincrement 7 years ago
Miloslav Číž ddbf6c162f use linear filtering for the cubemap 7 years ago
Miloslav Číž fc507c66f7 remove no longer needed stuff 7 years ago
Miloslav Číž 3ae5310567 use loading screen to freeze the screen 7 years ago
Miloslav Číž 2b5f147545 allow non-power-of-2 sized cubemaps 7 years ago
Miloslav Číž 902862aa8b display confirming message for all screenshots 7 years ago
Miloslav Číž bccff768ff select closest power of 2 resolution for the cubemap 7 years ago
Miloslav Číž 56c74fb96f add scene switch node 7 years ago
Miloslav Číž 1a4f351e3d move camera freeze code 7 years ago
Miloslav Číž af38d3a47d get rid of sphericalscreenshot class 7 years ago
Miloslav Číž 226fb9c26b render cubemaps in OGL coordinates 7 years ago
Miloslav Číž 1c3d45f641 dirty 360 screenshot GPU setup 7 years ago
Miloslav Číž 823218bb61 freeze screen during screenshot taking 7 years ago
Miloslav Číž 1ab854446c remove unused include 7 years ago
Miloslav Číž 511a5686da planet mapping adjustment 7 years ago
Miloslav Číž 4fc532d873 reference screenshot settings only from one place 7 years ago
Miloslav Číž d71d984cfa more unused stuff cleanup 7 years ago
Miloslav Číž e804c4a011 remove no longer used method 7 years ago
Miloslav Číž 525f8b4d8e get rid of special key for 360 screenshot 7 years ago
Miloslav Číž 1f49612ca3 enable water effects for 360 screenshots 7 years ago
Miloslav Číž 319ed2f9b8 disable 360 screenshots in vanity/preview mode 7 years ago
Miloslav Číž 497b33e403 small corrections 7 years ago
Miloslav Číž 9ab3a0c44b set cubemap width differently 7 years ago
Miloslav Číž 5baff05bac add cubemap mapping 7 years ago
Miloslav Číž 5a07d135ae add settings for cubemap size 7 years ago
Miloslav Číž 43c49e2f31 delete accidentally commited files 7 years ago
Miloslav Číž 1b184d8716 correct player mask 7 years ago
Miloslav Číž e54c0a90fa fix mirrored spherical screenshots 7 years ago
Miloslav Číž d763e9fe46 add settings for spherical screenshots 7 years ago
Miloslav Číž 8f32114025 segfault fix 7 years ago
Miloslav Číž d4fd08a63f save 360 screenshots in the configured directory 7 years ago
Miloslav Číž 1b97a541f4 make a new action for 360 screenshot 7 years ago
Miloslav Číž f60840754f disable water effects for spherical screenshots 7 years ago
Miloslav Číž 5698d70806 small planet mapping 7 years ago
Miloslav Číž 5f36518181 spherical mapping 7 years ago
Miloslav Číž 4761a3d98b dirty cylindrical projection 7 years ago
Miloslav Číž 3be9e2ee95 make spherical screenshot class 7 years ago
Miloslav Číž 5afe02505b hide player in first person 360 screenshot 7 years ago
Miloslav Číž ce55d7c2f5 basic cubemap rendering 7 years ago
Miloslav Číž 7feba7e498 basic setup for 360 screenshots 7 years ago

@ -9,3 +9,8 @@ insert_final_newline = true
indent_style = space indent_style = space
indent_size = 4 indent_size = 4
insert_final_newline = true insert_final_newline = true
[*.glsl]
indent_style = space
indent_size = 4
insert_final_newline = false

@ -0,0 +1,69 @@
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"

@ -1,6 +1,10 @@
os:
- linux
# - osx
osx_image: xcode9.4
language: cpp language: cpp
sudo: required sudo: required
dist: trusty dist: xenial
branches: branches:
only: only:
- master - master
@ -11,19 +15,18 @@ env:
global: global:
# The next declaration is the encrypted COVERITY_SCAN_TOKEN, created # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created
# via the "travis encrypt" command using the project repo's public key # via the "travis encrypt" command using the project repo's public key
- secure: NZmvVuA0O9NJXVQ12tXQZHDJC2mbFgYNFcsicw0DgW1It2Nk5hxIkF0pfu4/Z59mhQuOPgRVjl5b0FKy2Axh0gkWc1DJEXGwNaiW5lpTMNWR1LJG5rxa8LrDUpFkycpbzfAFuTUZu5z3iYVv64XzELvBuqNGhPMu1LeBnrlech0jFNjkR9p5qtJGWb8zYcPMCC57rig8a9g1ABoVYS6UXjrKpx0946ZLRsE5ukc9pXsypGwPmOMyfzZkxxzIqFaxoE5JIEdaJTWba/6Za315ozYYIi/N35ROI1YAv5GHRe/Iw9XAa4vQpbDzjM7ZSsZdTvvQsSU598gD2xC6jFUKSrpW6GZKwM2x236fZLGnOk5Uw7DUbG+AwpcEmxBwoy9PjBl9ZF3tJykI0gROewCy8MODhdsVMKr1HGIMVBIJySm/RnNqtoDbYV8mYnSl5b8rwJiCajoiR8Zuv4CIfGneeH1a3DOQDPH/qkDsU6ilzF4ANsBlMUUpgY653KBMBmTlNuVZSH527tnD7Fg6JgHVuSQkTbRa1vSkR7Zcre604RZcAoaEdbX3bhVDasPPghU/I742L0RH3oQNlR09pPBDZ8kG7ydl4aPHwpCWnvXNM1vgxtGvnYLztwrse7IoaRXRYiMFmrso78WhMWUDKgvY4wV9aeUu0DtnMezZVIQwCKg= - secure: 1QK0yVyoOB+gf2I7XzvhXu9w/5lq4stBXIwJbVCTjz4Q4XVHCosURaW1MAgKzMrPnbFEwjyn5uQ8BwsvvfkuN1AZD0YXITgc7gyI+J1wQ/p/ljxRxglakU6WEgsTs2J5z9UmGac4YTXg+quK7YP3rv+zuGim2I2rhzImejyzp0Ym3kRCnNcy+SGBsiRaevRJMe00Ch8zGAbEhduQGeSoS6W0rcu02DNlQKiq5NktWsXR+TWWWVfIeIlQR/lbPsCd0pdxMaMv2QCY0rVbwrYxWJwr/Qe45dAdWp+8/C3PbXpeMSGxlLa33nJNX4Lf/djxbjm8KWk6edaXPajrjR/0iwcpwq0jg2Jt6XfEdnJt35F1gpXlc04sxStjG45uloOKCFYT0wdhIO1Lq+hDP54wypQl+JInd5qC001O7pwhVxO36EgKWqo8HD+BqGDBwsNj2engy9Qcp3wO6G0rLBPB3CrZsk9wrHVv5cSiQSLMhId3Xviu3ZI2qEDA+kgTvxrKrsnMj4bILVCyG5Ka2Mj22wIDW9e8oIab9oTdujax3DTN1GkD6QuOAGzwDsNwGASsgfoeZ+FUhgM75RlBWGMilgkmnF7EJ0oAXLEpjtABnEr2d4qHv+y08kOuTDBLB9ExzCIj024dYYYNLZrqPKx0ncHuCMG2QNj2aJAJEZtj1rQ=
- macos_qt_formula=qt
addons: addons:
apt: apt:
sources: sources:
- sourceline: 'ppa:openmw/openmw' - sourceline: 'ppa:openmw/openmw'
- sourceline: 'ppa:rakhimov/boost' - sourceline: 'ppa:rakhimov/boost'
- ubuntu-toolchain-r-test - ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.8
packages: [ packages: [
# Dev # Dev
cmake, clang-3.8, libunshield-dev, libtinyxml-dev, cmake, clang-6.0, libunshield-dev, libtinyxml-dev,
g++-6, g++-8,
# Tests # Tests
libgtest-dev, google-mock, libgtest-dev, google-mock,
# Boost # Boost
@ -35,14 +38,14 @@ addons:
# The other ones from OpenMW ppa # The other ones from OpenMW ppa
libbullet-dev, libswresample-dev, libopenscenegraph-3.4-dev, libmygui-dev, libbullet-dev, libswresample-dev, libopenscenegraph-3.4-dev, libmygui-dev,
# tes3mp stuff # tes3mp stuff
libboost1.61-dev, libqt5opengl5-dev libboost1.61-dev, libqt5opengl5-dev, libluajit-5.1-dev
] ]
coverity_scan: coverity_scan:
project: project:
name: "TES3MP/openmw-tes3mp" name: "TES3MP/openmw-tes3mp"
description: "<Your project description here>" description: "<Your project description here>"
notification_email: stas5978@gmail.com notification_email: koncord@tes3mp.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_prepend: "cmake . -DBUILD_UNITTESTS=FALSE -DBUILD_OPENCS=FALSE -DBUILD_BSATOOL=FALSE -DBUILD_ESMTOOL=FALSE -DBUILD_MWINIIMPORTER=FALSE -DBUILD_LAUNCHER=FALSE"
build_command: "make -j3" build_command: "make -j3"
branch_pattern: coverity_scan branch_pattern: coverity_scan
@ -50,21 +53,21 @@ matrix:
include: include:
- os: linux - os: linux
env: env:
- ANALYZE="scan-build-3.8 --use-cc clang-3.8 --use-c++ clang++-3.8 " - ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
compiler: clang compiler: clang
- os: linux - os: linux
env: env:
- MATRIX_CC="CC=gcc-6 && CXX=g++-6" - MATRIX_CC="CC=gcc-8 && CXX=g++-8"
- os: linux - os: linux
env: env:
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
allow_failures: allow_failures:
- env: - env:
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
- env: - env:
- ANALYZE="scan-build-3.8 --use-cc clang-3.8 --use-c++ clang++-3.8 " - ANALYZE="scan-build-6.0 --use-cc clang-6.0 --use-c++ clang++-6.0 "
- MATRIX_CC="CC=clang-3.8 && CXX=clang++-3.8" - MATRIX_CC="CC=clang-6.0 && CXX=clang++-6.0"
before_install: before_install:
- ./CI/before_install.${TRAVIS_OS_NAME}.sh - ./CI/before_install.${TRAVIS_OS_NAME}.sh

@ -22,6 +22,7 @@ Programmers
alexanderkjall alexanderkjall
Alexander Nadeau (wareya) Alexander Nadeau (wareya)
Alexander Olofsson (Ace) Alexander Olofsson (Ace)
Alex S (docwest)
Allofich Allofich
Andrei Kortunov (akortunov) Andrei Kortunov (akortunov)
AnyOldName3 AnyOldName3
@ -37,6 +38,7 @@ Programmers
Britt Mathis (galdor557) Britt Mathis (galdor557)
Capostrophic Capostrophic
cc9cii cc9cii
Cédric Mocquillon
Chris Boyce (slothlife) Chris Boyce (slothlife)
Chris Robinson (KittyCat) Chris Robinson (KittyCat)
Cory F. Cohen (cfcohen) Cory F. Cohen (cfcohen)
@ -62,6 +64,8 @@ Programmers
Evgeniy Mineev (sandstranger) Evgeniy Mineev (sandstranger)
Federico Guerra (FedeWar) Federico Guerra (FedeWar)
Fil Krynicki (filkry) Fil Krynicki (filkry)
Finbar Crago(finbar-crago)
Florian Weber (Florianjw)
Gašper Sedej Gašper Sedej
gugus/gus gugus/gus
Hallfaer Tuilinn Hallfaer Tuilinn
@ -139,6 +143,7 @@ Programmers
Rohit Nirmal Rohit Nirmal
Roman Melnik (Kromgart) Roman Melnik (Kromgart)
Roman Proskuryakov (kpp) Roman Proskuryakov (kpp)
Roman Siromakha (elsid)
Sandy Carter (bwrsandman) Sandy Carter (bwrsandman)
Scott Howard Scott Howard
scrawl scrawl
@ -171,6 +176,7 @@ Programmers
Documentation Documentation
------------- -------------
Adam Bowen (adamnbowen)
Alejandro Sanchez (HiPhish) Alejandro Sanchez (HiPhish)
Bodillium Bodillium
Bret Curtis (psi29a) Bret Curtis (psi29a)

@ -1,8 +1,114 @@
0.45.0 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 #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 #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 #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 0.44.0
------ ------
@ -88,6 +194,7 @@
Bug #4412: openmw-iniimporter ignores data paths from config Bug #4412: openmw-iniimporter ignores data paths from config
Bug #4413: Moving with 0 strength uses all of your fatigue 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 #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 #4435: Item health is considered a signed integer
Bug #4441: Adding items to currently disabled weapon-wielding creatures crashes the game Bug #4441: Adding items to currently disabled weapon-wielding creatures crashes the game
Feature #1786: Round up encumbrance value in the encumbrance bar Feature #1786: Round up encumbrance value in the encumbrance bar

@ -15,19 +15,8 @@ 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 sudo ln -s /usr/src/gtest/build/libgtest_main.so /usr/lib/libgtest_main.so
cd ~/ cd ~/
git clone https://github.com/TES3MP/RakNet git clone https://github.com/TES3MP/CrabNet
cd RakNet cd CrabNet
cmake . -DRAKNET_ENABLE_DLL=OFF -DRAKNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release cmake . -DCRABNET_ENABLE_DLL=OFF -DCRABNET_ENABLE_SAMPLES=OFF -DCMAKE_BUILD_TYPE=Release
make -j3 make -j3
cd ~/
git clone https://github.com/Koncord/CallFF
cd CallFF
mkdir build
cd build
cmake ../
make -j3
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 cmake || brew upgrade cmake
brew outdated pkgconfig || brew upgrade pkgconfig brew outdated pkgconfig || brew upgrade pkgconfig
brew install $macos_qt_formula brew install qt
curl https://downloads.openmw.org/osx/dependencies/openmw-deps-c40905f.zip -o ~/openmw-deps.zip curl -fSL -R -J https://downloads.openmw.org/osx/dependencies/openmw-deps-100d2e0.zip -o ~/openmw-deps.zip
unzip ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null unzip -o ~/openmw-deps.zip -d /private/tmp/openmw-deps > /dev/null

@ -9,8 +9,7 @@ if [ ! -z "${MATRIX_CC}" ]; then
eval "${MATRIX_CC}" eval "${MATRIX_CC}"
fi fi
export RAKNET_ROOT=~/RakNet export RAKNET_ROOT=~/CrabNet
export Terra_ROOT=~/terra-Linux-x86_64-332a506
export CODE_COVERAGE=0 export CODE_COVERAGE=0
if [ ! -z "${ANALYZE}" ]; then if [ ! -z "${ANALYZE}" ]; then
@ -36,7 +35,5 @@ ${ANALYZE}cmake .. \
-DBINDIR=/usr/games \ -DBINDIR=/usr/games \
-DCMAKE_BUILD_TYPE="None" \ -DCMAKE_BUILD_TYPE="None" \
-DUSE_SYSTEM_TINYXML=TRUE \ -DUSE_SYSTEM_TINYXML=TRUE \
-DRakNet_LIBRARY_RELEASE=~/RakNet/lib/libRakNetLibStatic.a \ -DRakNet_LIBRARY_RELEASE=~/CrabNet/lib/libRakNetLibStatic.a \
-DRakNet_LIBRARY_DEBUG=~/RakNet/lib/libRakNetLibStatic.a \ -DRakNet_LIBRARY_DEBUG=~/CrabNet/lib/libRakNetLibStatic.a
-DCallFF_INCLUDES=~/CallFF/include \
-DCallFF_LIBRARY=~/CallFF/build/src/libcallff.a

@ -1,4 +1,5 @@
#!/bin/bash #!/bin/bash
# set -x # turn-on for debugging
MISSINGTOOLS=0 MISSINGTOOLS=0
@ -76,7 +77,6 @@ while [ $# -gt 0 ]; do
h ) h )
cat <<EOF cat <<EOF
Usage: $0 [-cdehkpuvV] Usage: $0 [-cdehkpuvV]
Options: Options:
-c <Release/Debug> -c <Release/Debug>
Set the configuration, can also be set with environment variable CONFIGURATION. Set the configuration, can also be set with environment variable CONFIGURATION.
@ -232,10 +232,9 @@ fi
case $VS_VERSION in case $VS_VERSION in
15|15.0|2017 ) 15|15.0|2017 )
GENERATOR="Visual Studio 15 2017" GENERATOR="Visual Studio 15 2017"
TOOLSET="vc140" TOOLSET="vc141"
TOOLSET_REAL="vc141"
MSVC_REAL_VER="15" MSVC_REAL_VER="15"
MSVC_VER="14" MSVC_VER="14.1"
MSVC_YEAR="2015" MSVC_YEAR="2015"
MSVC_DISPLAY_YEAR="2017" MSVC_DISPLAY_YEAR="2017"
;; ;;
@ -243,9 +242,8 @@ case $VS_VERSION in
14|14.0|2015 ) 14|14.0|2015 )
GENERATOR="Visual Studio 14 2015" GENERATOR="Visual Studio 14 2015"
TOOLSET="vc140" TOOLSET="vc140"
TOOLSET_REAL="vc140"
MSVC_REAL_VER="14" MSVC_REAL_VER="14"
MSVC_VER="14" MSVC_VER="14.0"
MSVC_YEAR="2015" MSVC_YEAR="2015"
MSVC_DISPLAY_YEAR="2015" MSVC_DISPLAY_YEAR="2015"
;; ;;
@ -253,9 +251,8 @@ case $VS_VERSION in
12|12.0|2013 ) 12|12.0|2013 )
GENERATOR="Visual Studio 12 2013" GENERATOR="Visual Studio 12 2013"
TOOLSET="vc120" TOOLSET="vc120"
TOOLSET_REAL="vc120"
MSVC_REAL_VER="12" MSVC_REAL_VER="12"
MSVC_VER="12" MSVC_VER="12.0"
MSVC_YEAR="2013" MSVC_YEAR="2013"
MSVC_DISPLAY_YEAR="2013" MSVC_DISPLAY_YEAR="2013"
;; ;;
@ -325,9 +322,9 @@ if [ -z $SKIP_DOWNLOAD ]; then
# Boost # Boost
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
download "Boost 1.61.0" \ download "Boost 1.67.0" \
"https://sourceforge.net/projects/boost/files/boost-binaries/1.61.0/boost_1_61_0-msvc-${MSVC_VER}.0-${BITS}.exe" \ "https://sourceforge.net/projects/boost/files/boost-binaries/1.67.0/boost_1_67_0-msvc-${MSVC_VER}-${BITS}.exe" \
"boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" "boost-1.67.0-msvc${MSVC_YEAR}-win${BITS}.exe"
fi fi
# Bullet # Bullet
@ -365,8 +362,8 @@ if [ -z $SKIP_DOWNLOAD ]; then
QT_SUFFIX="" QT_SUFFIX=""
fi fi
download "Qt 5.7.2" \ download "Qt 5.7.0" \
"https://download.qt.io/official_releases/qt/5.7/5.7.0/qt-opensource-windows-x86-msvc${MSVC_YEAR}${QT_SUFFIX}-5.7.0.exe" \ "https://download.qt.io/archive/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" \ "qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" \
"https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \ "https://www.lysator.liu.se/~ace/OpenMW/deps/qt-5-install.qs" \
"qt-5-install.qs" "qt-5-install.qs"
@ -403,9 +400,9 @@ echo
# Boost # Boost
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
printf "Boost 1.61.0... " printf "Boost 1.67.0... "
else else
if [ $MSVC_VER -eq 12 ]; then if [ $MSVC_VER -eq 12.0 ]; then
printf "Boost 1.58.0 AppVeyor... " printf "Boost 1.58.0 AppVeyor... "
else else
printf "Boost 1.67.0 AppVeyor... " printf "Boost 1.67.0 AppVeyor... "
@ -417,17 +414,28 @@ fi
BOOST_SDK="$(real_pwd)/Boost" BOOST_SDK="$(real_pwd)/Boost"
if [ -d Boost ] && grep "BOOST_VERSION 106100" Boost/boost/version.hpp > /dev/null; then # 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
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf Boost rm -rf Boost
"${DEPS}/boost-1.61.0-msvc${MSVC_YEAR}-win${BITS}.exe" //dir="$(echo $BOOST_SDK | sed s,/,\\\\,g)" //verysilent 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 fi
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \
-DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}.0" -DBOOST_LIBRARYDIR="${BOOST_SDK}/lib${BITS}-msvc-${MSVC_VER}"
add_cmake_opts -DBoost_COMPILER="-${TOOLSET}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
echo Done. echo Done.
else else
# Appveyor unstable has all the boost we need already # Appveyor unstable has all the boost we need already
@ -444,19 +452,17 @@ fi
add_cmake_opts -DBOOST_ROOT="$BOOST_SDK" \ 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}.${LIB_SUFFIX}"
add_cmake_opts -DBoost_COMPILER="-${TOOLSET_REAL}" add_cmake_opts -DBoost_COMPILER="-${TOOLSET}"
echo Done. echo Done.
fi fi
} }
cd $DEPS cd $DEPS
echo echo
# Bullet # Bullet
printf "Bullet 2.86... " printf "Bullet 2.86... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d Bullet ]; then if [ -d Bullet ]; then
printf -- "Exists. (No version checking) " printf -- "Exists. (No version checking) "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
@ -464,49 +470,38 @@ printf "Bullet 2.86... "
eval 7z x -y "${DEPS}/Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP 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 mv "Bullet-2.86-msvc${MSVC_YEAR}-win${BITS}" Bullet
fi fi
export BULLET_ROOT="$(real_pwd)/Bullet" export BULLET_ROOT="$(real_pwd)/Bullet"
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# FFmpeg # FFmpeg
printf "FFmpeg 3.2.4... " printf "FFmpeg 3.2.4... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then if [ -d FFmpeg ] && grep "FFmpeg version: 3.2.4" FFmpeg/README.txt > /dev/null; then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf FFmpeg 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-win${BITS}.zip" $STRIP
eval 7z x -y "${DEPS}/ffmpeg-3.2.4-dev-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 mv "ffmpeg-3.2.4-win${BITS}-shared" FFmpeg
cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/ cp -r "ffmpeg-3.2.4-win${BITS}-dev/"* FFmpeg/
rm -rf "ffmpeg-3.2.4-win${BITS}-dev" rm -rf "ffmpeg-3.2.4-win${BITS}-dev"
fi fi
export FFMPEG_HOME="$(real_pwd)/FFmpeg" export FFMPEG_HOME="$(real_pwd)/FFmpeg"
add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll add_runtime_dlls "$(pwd)/FFmpeg/bin/"{avcodec-57,avformat-57,avutil-55,swresample-2,swscale-4}.dll
if [ $BITS -eq 32 ]; then if [ $BITS -eq 32 ]; then
add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\"" add_cmake_opts "-DCMAKE_EXE_LINKER_FLAGS=\"/machine:X86 /safeseh:no\""
fi fi
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# MyGUI # MyGUI
printf "MyGUI 3.2.2... " printf "MyGUI 3.2.2... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d MyGUI ] && \ if [ -d MyGUI ] && \
grep "MYGUI_VERSION_MAJOR 3" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \ 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 && \ grep "MYGUI_VERSION_MINOR 2" MyGUI/include/MYGUI/MyGUI_Prerequest.h > /dev/null && \
@ -518,21 +513,17 @@ printf "MyGUI 3.2.2... "
eval 7z x -y "${DEPS}/MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP 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 mv "MyGUI-3.2.2-msvc${MSVC_YEAR}-win${BITS}" MyGUI
fi fi
export MYGUI_HOME="$(real_pwd)/MyGUI" export MYGUI_HOME="$(real_pwd)/MyGUI"
if [ $CONFIGURATION == "Debug" ]; then if [ $CONFIGURATION == "Debug" ]; then
SUFFIX="_d" SUFFIX="_d"
else else
SUFFIX="" SUFFIX=""
fi fi
add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll" add_runtime_dlls "$(pwd)/MyGUI/bin/${CONFIGURATION}/MyGUIEngine${SUFFIX}.dll"
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# OpenAL # OpenAL
printf "OpenAL-Soft 1.17.2... " printf "OpenAL-Soft 1.17.2... "
{ {
@ -542,24 +533,18 @@ printf "OpenAL-Soft 1.17.2... "
rm -rf openal-soft-1.17.2-bin rm -rf openal-soft-1.17.2-bin
eval 7z x -y OpenAL-Soft-1.17.2.zip $STRIP eval 7z x -y OpenAL-Soft-1.17.2.zip $STRIP
fi fi
OPENAL_SDK="$(real_pwd)/openal-soft-1.17.2-bin" OPENAL_SDK="$(real_pwd)/openal-soft-1.17.2-bin"
add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \ add_cmake_opts -DOPENAL_INCLUDE_DIR="${OPENAL_SDK}/include/AL" \
-DOPENAL_LIBRARY="${OPENAL_SDK}/libs/Win${BITS}/OpenAL32.lib" -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" add_runtime_dlls "$(pwd)/openal-soft-1.17.2-bin/bin/WIN${BITS}/soft_oal.dll:OpenAL32.dll"
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# OSG # OSG
printf "OSG 3.4.1-scrawl... " printf "OSG 3.4.1-scrawl... "
{ {
cd $DEPS_INSTALL cd $DEPS_INSTALL
if [ -d OSG ] && \ if [ -d OSG ] && \
grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \ grep "OPENSCENEGRAPH_MAJOR_VERSION 3" OSG/include/osg/Version > /dev/null && \
grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \ grep "OPENSCENEGRAPH_MINOR_VERSION 4" OSG/include/osg/Version > /dev/null && \
@ -571,28 +556,21 @@ printf "OSG 3.4.1-scrawl... "
eval 7z x -y "${DEPS}/OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}.7z" $STRIP 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 mv "OSG-3.4.1-scrawl-msvc${MSVC_YEAR}-win${BITS}" OSG
fi fi
OSG_SDK="$(real_pwd)/OSG" OSG_SDK="$(real_pwd)/OSG"
add_cmake_opts -DOSG_DIR="$OSG_SDK" add_cmake_opts -DOSG_DIR="$OSG_SDK"
if [ $CONFIGURATION == "Debug" ]; then if [ $CONFIGURATION == "Debug" ]; then
SUFFIX="d" SUFFIX="d"
else else
SUFFIX="" SUFFIX=""
fi fi
add_runtime_dlls "$(pwd)/OSG/bin/"{OpenThreads,zlib,libpng*}${SUFFIX}.dll \ 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 "$(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_"{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 add_osg_dlls "$(pwd)/OSG/bin/osgPlugins-3.4.1/osgdb_serializers_osg"{,animation,fx,ga,particle,text,util,viewer}${SUFFIX}.dll
echo Done. echo Done.
} }
cd $DEPS cd $DEPS
echo echo
# Qt # Qt
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
printf "Qt 5.7.0... " printf "Qt 5.7.0... "
@ -605,71 +583,53 @@ fi
else else
SUFFIX="" SUFFIX=""
fi fi
if [ -z $APPVEYOR ]; then if [ -z $APPVEYOR ]; then
cd $DEPS_INSTALL cd $DEPS_INSTALL
QT_SDK="$(real_pwd)/Qt/5.7/msvc${MSVC_YEAR}${SUFFIX}" 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 if [ -d Qt ] && head -n2 Qt/InstallationLog.txt | grep "5.7.0" > /dev/null; then
printf "Exists. " printf "Exists. "
elif [ -z $SKIP_EXTRACT ]; then elif [ -z $SKIP_EXTRACT ]; then
rm -rf Qt rm -rf Qt
cp "${DEPS}/qt-5-install.qs" qt-install.qs cp "${DEPS}/qt-5-install.qs" qt-install.qs
sed -i "s|INSTALL_DIR|$(real_pwd)/Qt|" 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 sed -i "s/qt.VERSION.winBITS_msvcYEAR/qt.57.win${BITS}_msvc${MSVC_YEAR}${SUFFIX}/" qt-install.qs
printf -- "(Installation might take a while) " printf -- "(Installation might take a while) "
"${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent "${DEPS}/qt-5.7.0-msvc${MSVC_YEAR}-win${BITS}.exe" --script qt-install.qs --silent
mv qt-install.qs Qt/ mv qt-install.qs Qt/
echo Done. echo Done.
printf " Cleaning up extraneous data... " 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} rm -r "$(real_pwd)/Qt/"{dist,Docs,Examples,Tools,vcredist,components.xml,MaintenanceTool.dat,MaintenanceTool.exe,MaintenanceTool.ini,network.xml,qt-install.qs}
fi fi
cd $QT_SDK cd $QT_SDK
add_cmake_opts -DDESIRED_QT_VERSION=5 \ add_cmake_opts -DDESIRED_QT_VERSION=5 \
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
-DCMAKE_PREFIX_PATH="$QT_SDK" -DCMAKE_PREFIX_PATH="$QT_SDK"
if [ $CONFIGURATION == "Debug" ]; then if [ $CONFIGURATION == "Debug" ]; then
SUFFIX="d" SUFFIX="d"
else else
SUFFIX="" SUFFIX=""
fi fi
add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll add_runtime_dlls "$(pwd)/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll" add_qt_platform_dlls "$(pwd)/plugins/platforms/qwindows${SUFFIX}.dll"
echo Done. echo Done.
else else
QT_SDK="C:/Qt/5.10/msvc${MSVC_DISPLAY_YEAR}${SUFFIX}" QT_SDK="C:/Qt/5.10/msvc${MSVC_DISPLAY_YEAR}${SUFFIX}"
add_cmake_opts -DDESIRED_QT_VERSION=5 \ add_cmake_opts -DDESIRED_QT_VERSION=5 \
-DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \ -DQT_QMAKE_EXECUTABLE="${QT_SDK}/bin/qmake.exe" \
-DCMAKE_PREFIX_PATH="$QT_SDK" -DCMAKE_PREFIX_PATH="$QT_SDK"
if [ $CONFIGURATION == "Debug" ]; then if [ $CONFIGURATION == "Debug" ]; then
SUFFIX="d" SUFFIX="d"
else else
SUFFIX="" SUFFIX=""
fi fi
DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,") DIR=$(echo "${QT_SDK}" | sed "s,\\\\,/,g" | sed "s,\(.\):,/\\1,")
add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll add_runtime_dlls "${DIR}/bin/Qt5"{Core,Gui,Network,OpenGL,Widgets}${SUFFIX}.dll
add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll" add_qt_platform_dlls "${DIR}/plugins/platforms/qwindows${SUFFIX}.dll"
echo Done. echo Done.
fi fi
} }
cd $DEPS cd $DEPS
echo echo
# SDL2 # SDL2
printf "SDL 2.0.7... " printf "SDL 2.0.7... "
{ {
@ -679,26 +639,18 @@ printf "SDL 2.0.7... "
rm -rf SDL2-2.0.7 rm -rf SDL2-2.0.7
eval 7z x -y SDL2-2.0.7.zip $STRIP eval 7z x -y SDL2-2.0.7.zip $STRIP
fi fi
export SDL2DIR="$(real_pwd)/SDL2-2.0.7" export SDL2DIR="$(real_pwd)/SDL2-2.0.7"
add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll" add_runtime_dlls "$(pwd)/SDL2-2.0.7/lib/x${ARCHSUFFIX}/SDL2.dll"
echo Done. echo Done.
} }
echo echo
cd $DEPS_INSTALL/.. cd $DEPS_INSTALL/..
echo echo
echo "Setting up OpenMW build..." echo "Setting up OpenMW build..."
add_cmake_opts -DBUILD_BSATOOL=no \ add_cmake_opts -DBUILD_BSATOOL=no \
-DBUILD_ESMTOOL=no \ -DBUILD_ESMTOOL=no \
-DBUILD_MYGUI_PLUGIN=no \ -DBUILD_MYGUI_PLUGIN=no \
-DOPENMW_MP_BUILD=on -DOPENMW_MP_BUILD=on
if [ ! -z $CI ]; then if [ ! -z $CI ]; then
case $STEP in case $STEP in
components ) components )
@ -710,7 +662,6 @@ if [ ! -z $CI ]; then
-DBUILD_OPENMW=no \ -DBUILD_OPENMW=no \
-DBUILD_WIZARD=no -DBUILD_WIZARD=no
;; ;;
openmw ) openmw )
echo " Building subproject: OpenMW." echo " Building subproject: OpenMW."
add_cmake_opts -DBUILD_ESSIMPORTER=no \ add_cmake_opts -DBUILD_ESSIMPORTER=no \
@ -719,7 +670,6 @@ if [ ! -z $CI ]; then
-DBUILD_OPENCS=no \ -DBUILD_OPENCS=no \
-DBUILD_WIZARD=no -DBUILD_WIZARD=no
;; ;;
opencs ) opencs )
echo " Building subproject: OpenCS." echo " Building subproject: OpenCS."
add_cmake_opts -DBUILD_ESSIMPORTER=no \ add_cmake_opts -DBUILD_ESSIMPORTER=no \
@ -728,7 +678,6 @@ if [ ! -z $CI ]; then
-DBUILD_OPENMW=no \ -DBUILD_OPENMW=no \
-DBUILD_WIZARD=no -DBUILD_WIZARD=no
;; ;;
misc ) misc )
echo " Building subprojects: Misc." echo " Building subprojects: Misc."
add_cmake_opts -DBUILD_OPENCS=no \ add_cmake_opts -DBUILD_OPENCS=no \
@ -736,7 +685,6 @@ if [ ! -z $CI ]; then
;; ;;
esac esac
fi fi
# NOTE: Disable this when/if we want to run test cases # NOTE: Disable this when/if we want to run test cases
#if [ -z $CI ]; then #if [ -z $CI ]; then
echo "- Copying Runtime DLLs..." echo "- Copying Runtime DLLs..."
@ -745,16 +693,13 @@ fi
TARGET="$(basename "$DLL")" TARGET="$(basename "$DLL")"
if [[ "$DLL" == *":"* ]]; then if [[ "$DLL" == *":"* ]]; then
IFS=':'; SPLIT=( ${DLL} ); unset IFS IFS=':'; SPLIT=( ${DLL} ); unset IFS
DLL=${SPLIT[0]} DLL=${SPLIT[0]}
TARGET=${SPLIT[1]} TARGET=${SPLIT[1]}
fi fi
echo " ${TARGET}." echo " ${TARGET}."
cp "$DLL" "$BUILD_CONFIG/$TARGET" cp "$DLL" "$BUILD_CONFIG/$TARGET"
done done
echo echo
echo "- OSG Plugin DLLs..." echo "- OSG Plugin DLLs..."
mkdir -p $BUILD_CONFIG/osgPlugins-3.4.1 mkdir -p $BUILD_CONFIG/osgPlugins-3.4.1
for DLL in $OSG_PLUGINS; do for DLL in $OSG_PLUGINS; do
@ -762,7 +707,6 @@ fi
cp "$DLL" $BUILD_CONFIG/osgPlugins-3.4.1 cp "$DLL" $BUILD_CONFIG/osgPlugins-3.4.1
done done
echo echo
echo "- Qt Platform DLLs..." echo "- Qt Platform DLLs..."
mkdir -p ${BUILD_CONFIG}/platforms mkdir -p ${BUILD_CONFIG}/platforms
for DLL in $QT_PLATFORMS; do for DLL in $QT_PLATFORMS; do
@ -771,16 +715,13 @@ fi
done done
echo echo
#fi #fi
if [ -z $VERBOSE ]; then if [ -z $VERBOSE ]; then
printf -- "- Configuring... " printf -- "- Configuring... "
else else
echo "- cmake .. $CMAKE_OPTS" echo "- cmake .. $CMAKE_OPTS"
fi fi
run_cmd cmake .. $CMAKE_OPTS run_cmd cmake .. $CMAKE_OPTS
RET=$? RET=$?
if [ -z $VERBOSE ]; then if [ -z $VERBOSE ]; then
if [ $RET -eq 0 ]; then if [ $RET -eq 0 ]; then
echo Done. echo Done.
@ -788,5 +729,4 @@ if [ -z $VERBOSE ]; then
echo Failed. echo Failed.
fi fi
fi fi
exit $RET exit $RET

@ -4,14 +4,14 @@ export CXX=clang++
export CC=clang export CC=clang
DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps" DEPENDENCIES_ROOT="/private/tmp/openmw-deps/openmw-deps"
QT_PATH=`brew --prefix $macos_qt_formula` QT_PATH=`brew --prefix qt`
mkdir build mkdir build
cd build cd build
cmake \ cmake \
-D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \ -D CMAKE_PREFIX_PATH="$DEPENDENCIES_ROOT;$QT_PATH" \
-D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \ -D CMAKE_OSX_DEPLOYMENT_TARGET="10.9" \
-D CMAKE_OSX_SYSROOT="macosx10.12" \ -D CMAKE_OSX_SYSROOT="macosx10.13" \
-D CMAKE_BUILD_TYPE=Release \ -D CMAKE_BUILD_TYPE=Release \
-D OPENMW_OSX_DEPLOYMENT=TRUE \ -D OPENMW_OSX_DEPLOYMENT=TRUE \
-D DESIRED_QT_VERSION=5 \ -D DESIRED_QT_VERSION=5 \

@ -250,7 +250,8 @@ IF(BUILD_OPENMW OR BUILD_OPENCS)
find_package(SDL2 REQUIRED) find_package(SDL2 REQUIRED)
find_package(OpenAL REQUIRED) find_package(OpenAL REQUIRED)
find_package(Bullet ${REQUIRED_BULLET_VERSION} REQUIRED COMPONENTS BulletCollision LinearMath) 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) ENDIF(BUILD_OPENMW OR BUILD_OPENCS)
@ -665,10 +666,10 @@ if (WIN32)
endif() endif()
if (BUILD_OPENMW) if (BUILD_OPENMW)
# Release builds use the debug console # Release builds don't use the debug console
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:CONSOLE") set_target_properties(tes3mp PROPERTIES LINK_FLAGS_RELEASE "/SUBSYSTEM:WINDOWS")
set_target_properties(tes3mp PROPERTIES COMPILE_DEFINITIONS_RELEASE "_CONSOLE") set_target_properties(tes3mp PROPERTIES COMPILE_DEFINITIONS_RELEASE "_WINDOWS")
set_target_properties(tes3mp PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:CONSOLE") set_target_properties(tes3mp PROPERTIES LINK_FLAGS_MINSIZEREL "/SUBSYSTEM:WINDOWS")
endif() endif()
# Play a bit with the warning levels # Play a bit with the warning levels
@ -679,7 +680,8 @@ if (WIN32)
# Warnings that aren't enabled normally and don't need to be enabled # Warnings that aren't enabled normally and don't need to be enabled
# They're unneeded and sometimes completely retarded warnings that /Wall enables # 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 # 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 4820 4826 4917 4946 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
# Warnings that are thrown on standard libraries and not OpenMW # Warnings that are thrown on standard libraries and not OpenMW
4347 # Non-template function with same name and parameter count as template function 4347 # Non-template function with same name and parameter count as template function
@ -700,6 +702,7 @@ if (WIN32)
# caused by MyGUI # caused by MyGUI
4275 # non dll-interface class 'std::exception' used as base for dll-interface class 'MyGUI::Exception' 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 # OpenMW specific warnings
4099 # Type mismatch, declared class or struct is defined with other type 4099 # Type mismatch, declared class or struct is defined with other type
@ -733,7 +736,10 @@ if (WIN32)
endforeach(d) endforeach(d)
set_target_properties(components PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") 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}") set_target_properties(osg-ffmpeg-videoplayer PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")
endif()
if (BUILD_BSATOOL) if (BUILD_BSATOOL)
set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}") set_target_properties(bsatool PROPERTIES COMPILE_FLAGS "${WARNINGS} ${MT_BUILD}")

@ -3,7 +3,7 @@ How to contribute to OpenMW
Not sure what to do with all your free time? Pick out a task from here: Not sure what to do with all your free time? Pick out a task from here:
https://bugs.openmw.org/ https://gitlab.com/OpenMW/openmw/issues
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. 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.

@ -1,45 +1,49 @@
TES3MP TES3MP
====== ======
[![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=master)](https://travis-ci.org/TES3MP/openmw-tes3mp) Copyright (c) 2008-2015, OpenMW Team
Copyright (c) 2016-2019, Stanislav Zhukov & David Cernat
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". [![Build Status](https://travis-ci.org/TES3MP/openmw-tes3mp.svg?branch=0.7.0)](https://travis-ci.org/TES3MP/openmw-tes3mp)
* TES3MP version: 0.6.3 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 * OpenMW version: 0.44.0
* License: GPLv3 (see [LICENSE](https://github.com/TES3MP/openmw-tes3mp/blob/master/LICENSE) for more information) * License: GPLv3 (see [LICENSE](https://github.com/TES3MP/openmw-tes3mp/blob/master/LICENSE) for more information)
Font Licenses: 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) * 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) [Version changelog](https://github.com/TES3MP/openmw-tes3mp/blob/master/tes3mp-changelog.md)
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. 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).
Remaining gameplay problems mostly relate to AI and the synchronization of clientside script variables.
Donations
---------------
[Serverside Lua scripts](https://github.com/TES3MP/CoreScripts) are used to save and load the state of most of the aforementioned. 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 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. Helping us with documentation, bug hunting and video showcases is always 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). 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. 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 Getting started
--------------- ---------------
* [Quickstart guide](https://github.com/TES3MP/openmw-tes3mp/wiki/Quickstart-guide) * [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/) * [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=44) * [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) * [Subreddit](https://www.reddit.com/r/tes3mp)
* [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues) * [Known issues and bug reports](https://github.com/TES3MP/openmw-tes3mp/issues)
Donations
---------------
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,6 +54,7 @@ MainWindow::MainWindow(QWidget *parent)
connect(tblServerBrowser, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(play())); connect(tblServerBrowser, SIGNAL(doubleClicked(QModelIndex)), this, SLOT(play()));
connect(cBoxNotFull, SIGNAL(toggled(bool)), this, SLOT(notFullSwitch(bool))); connect(cBoxNotFull, SIGNAL(toggled(bool)), this, SLOT(notFullSwitch(bool)));
connect(cBoxWithPlayers, SIGNAL(toggled(bool)), this, SLOT(havePlayersSwitch(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(comboLatency, SIGNAL(currentIndexChanged(int)), this, SLOT(maxLatencyChanged(int)));
connect(leGamemode, SIGNAL(textChanged(const QString &)), this, SLOT(gamemodeChanged(const QString &))); connect(leGamemode, SIGNAL(textChanged(const QString &)), this, SLOT(gamemodeChanged(const QString &)));
loadFavorites(); loadFavorites();
@ -65,7 +66,7 @@ MainWindow::~MainWindow()
delete mGameInvoker; delete mGameInvoker;
} }
void MainWindow::addServerAndUpdate(QString addr) void MainWindow::addServerAndUpdate(const QString &addr)
{ {
favorites->insertRow(0); favorites->insertRow(0);
QModelIndex mi = favorites->index(0, ServerData::ADDR); QModelIndex mi = favorites->index(0, ServerData::ADDR);
@ -121,19 +122,16 @@ void MainWindow::play()
if (id < 0) if (id < 0)
return; return;
ServerInfoDialog infoDialog(this);
ServerModel *sm = ((ServerModel*)proxyModel->sourceModel()); ServerModel *sm = ((ServerModel*)proxyModel->sourceModel());
int sourceId = proxyModel->mapToSource(proxyModel->index(id, ServerData::ADDR)).row(); int sourceId = proxyModel->mapToSource(proxyModel->index(id, ServerData::ADDR)).row();
infoDialog.Server(sm->myData[sourceId].addr); ServerInfoDialog infoDialog(sm->myData[sourceId].addr, this);
if (!infoDialog.refresh()) if (!infoDialog.exec())
{
queryHelper->refresh();
return; return;
}
if (!infoDialog.exec()) if (!infoDialog.isUpdated())
return; return;
QStringList arguments; QStringList arguments;
@ -142,7 +140,8 @@ void MainWindow::play()
if (sm->myData[sourceId].GetPassword() == 1) if (sm->myData[sourceId].GetPassword() == 1)
{ {
bool ok; bool ok;
QString passw = QInputDialog::getText(this, "Connecting to: " + sm->myData[sourceId].addr, "Password: ", QLineEdit::Password, "", &ok); QString passw = QInputDialog::getText(this, tr("Connecting to: ") + sm->myData[sourceId].addr, tr("Password: "),
QLineEdit::Password, "", &ok);
if (!ok) if (!ok)
return; return;
arguments.append(QLatin1String("--password=") + passw.toLatin1()); arguments.append(QLatin1String("--password=") + passw.toLatin1());
@ -228,6 +227,11 @@ void MainWindow::havePlayersSwitch(bool state)
proxyModel->filterEmptyServers(state); proxyModel->filterEmptyServers(state);
} }
void MainWindow::noPasswordSwitch(bool state)
{
proxyModel->filterPassworded(state);
}
void MainWindow::maxLatencyChanged(int index) void MainWindow::maxLatencyChanged(int index)
{ {
int maxLatency = index * 50; int maxLatency = index * 50;

@ -17,11 +17,11 @@ class MainWindow : public QMainWindow, private Ui::MainWindow
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit MainWindow(QWidget *parent = 0); explicit MainWindow(QWidget *parent = nullptr);
virtual ~MainWindow(); ~MainWindow() override;
protected: protected:
void closeEvent(QCloseEvent * event) Q_DECL_OVERRIDE; void closeEvent(QCloseEvent * event) Q_DECL_OVERRIDE;
void addServerAndUpdate(QString addr); void addServerAndUpdate(const QString &addr);
protected slots: protected slots:
void tabSwitched(int index); void tabSwitched(int index);
void addServer(); void addServer();
@ -31,6 +31,7 @@ protected slots:
void serverSelected(); void serverSelected();
void notFullSwitch(bool state); void notFullSwitch(bool state);
void havePlayersSwitch(bool state); void havePlayersSwitch(bool state);
void noPasswordSwitch(bool state);
void maxLatencyChanged(int index); void maxLatencyChanged(int index);
void gamemodeChanged(const QString &text); void gamemodeChanged(const QString &text);
private: private:

@ -6,6 +6,7 @@
#include "ServerModel.hpp" #include "ServerModel.hpp"
#include <qdebug.h> #include <qdebug.h>
#include <apps/browser/netutils/Utils.hpp>
bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{ {
@ -13,26 +14,49 @@ bool MySortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &
QModelIndex pingIndex = sourceModel()->index(sourceRow, ServerData::PING, sourceParent); QModelIndex pingIndex = sourceModel()->index(sourceRow, ServerData::PING, sourceParent);
QModelIndex plIndex = sourceModel()->index(sourceRow, ServerData::PLAYERS, sourceParent); QModelIndex plIndex = sourceModel()->index(sourceRow, ServerData::PLAYERS, sourceParent);
QModelIndex maxPlIndex = sourceModel()->index(sourceRow, ServerData::MAX_PLAYERS, sourceParent); QModelIndex maxPlIndex = sourceModel()->index(sourceRow, ServerData::MAX_PLAYERS, sourceParent);
QModelIndex passwordIndex = sourceModel()->index(sourceRow, ServerData::PASSW, sourceParent);
int ping = sourceModel()->data(pingIndex).toInt(); bool pingOk;
int ping = sourceModel()->data(pingIndex).toInt(&pingOk);
int players = sourceModel()->data(plIndex).toInt(); int players = sourceModel()->data(plIndex).toInt();
int maxPlayers = sourceModel()->data(maxPlIndex).toInt(); int maxPlayers = sourceModel()->data(maxPlIndex).toInt();
if (maxPing > 0 && (ping == -1 || ping > maxPing)) if (maxPing > 0 && (ping == -1 || ping > maxPing || !pingOk))
return false; return false;
if (filterEmpty && players == 0) if (filterEmpty && players == 0)
return false; return false;
if (filterFull && players >= maxPlayers) if (filterFull && players >= maxPlayers)
return false; return false;
if(filterPasswEnabled && sourceModel()->data(passwordIndex).toString() == "Yes")
return false;
return QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent); 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) MySortFilterProxyModel::MySortFilterProxyModel(QObject *parent) : QSortFilterProxyModel(parent)
{ {
filterEmpty = false; filterEmpty = false;
filterFull = false; filterFull = false;
filterPasswEnabled = false;
maxPing = 0; maxPing = 0;
setSortCaseSensitivity(Qt::CaseSensitivity::CaseInsensitive);
} }
void MySortFilterProxyModel::filterEmptyServers(bool state) void MySortFilterProxyModel::filterEmptyServers(bool state)
@ -52,3 +76,9 @@ void MySortFilterProxyModel::pingLessThan(int maxPing)
this->maxPing = maxPing; this->maxPing = maxPing;
invalidateFilter(); invalidateFilter();
} }
void MySortFilterProxyModel::filterPassworded(bool state)
{
filterPasswEnabled = state;
invalidateFilter();
}

@ -13,13 +13,15 @@ class MySortFilterProxyModel : public QSortFilterProxyModel
Q_OBJECT Q_OBJECT
protected: protected:
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const Q_DECL_FINAL; 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: public:
MySortFilterProxyModel(QObject *parent); explicit MySortFilterProxyModel(QObject *parent);
void filterFullServer(bool state); void filterFullServer(bool state);
void filterEmptyServers(bool state); void filterEmptyServers(bool state);
void filterPassworded(bool state);
void pingLessThan(int maxPing); void pingLessThan(int maxPing);
private: private:
bool filterEmpty, filterFull; bool filterEmpty, filterFull, filterPasswEnabled;
int maxPing; int maxPing;
}; };

@ -7,13 +7,19 @@
#include <QDebug> #include <QDebug>
#include "PingUpdater.hpp" #include "PingUpdater.hpp"
void PingHelper::Add(int row, AddrPair addrPair) void PingHelper::Add(int row, const AddrPair &addrPair)
{ {
pingUpdater->addServer(row, addrPair); pingUpdater->addServer(row, addrPair);
if (!pingThread->isRunning()) if (!pingThread->isRunning())
pingThread->start(); pingThread->start();
} }
void PingHelper::Reset()
{
//if (pingThread->isRunning())
Stop();
}
void PingHelper::Stop() void PingHelper::Stop()
{ {
emit pingUpdater->stop(); emit pingUpdater->stop();
@ -35,9 +41,8 @@ PingHelper &PingHelper::Get()
return helper; return helper;
} }
PingHelper::PingHelper() PingHelper::PingHelper() : QObject()
{ {
QObject();
pingThread = new QThread; pingThread = new QThread;
pingUpdater = new PingUpdater; pingUpdater = new PingUpdater;
pingUpdater->moveToThread(pingThread); pingUpdater->moveToThread(pingThread);
@ -48,11 +53,4 @@ PingHelper::PingHelper()
connect(this, SIGNAL(stop()), pingUpdater, SLOT(stop())); connect(this, SIGNAL(stop()), pingUpdater, SLOT(stop()));
//connect(pingUpdater, SIGNAL(finished()), pingUpdater, SLOT(deleteLater())); //connect(pingUpdater, SIGNAL(finished()), pingUpdater, SLOT(deleteLater()));
connect(pingUpdater, SIGNAL(updateModel(int, unsigned)), this, SLOT(update(int, unsigned))); connect(pingUpdater, SIGNAL(updateModel(int, unsigned)), this, SLOT(update(int, unsigned)));
}
PingHelper::~PingHelper()
{
} }

@ -17,17 +17,17 @@ class PingHelper : public QObject
Q_OBJECT Q_OBJECT
public: public:
void Add(int row, AddrPair addrPair); void Reset();
void Add(int row, const AddrPair &addrPair);
void Stop(); void Stop();
void SetModel(QAbstractTableModel *model); void SetModel(QAbstractTableModel *model);
//void UpdateImmedialy(PingUpdater::AddrPair addrPair); //void UpdateImmedialy(PingUpdater::AddrPair addrPair);
static PingHelper &Get(); static PingHelper &Get();
private:
PingHelper();
~PingHelper();
PingHelper(const PingHelper&) = delete; PingHelper(const PingHelper&) = delete;
PingHelper& operator=(const PingHelper&) = delete; PingHelper& operator=(const PingHelper&) = delete;
private:
PingHelper();
signals: signals:
void stop(); void stop();
public slots: public slots:

@ -14,7 +14,7 @@ void PingUpdater::stop()
run = false; run = false;
} }
void PingUpdater::addServer(int row, AddrPair addr) void PingUpdater::addServer(int row, const AddrPair &addr)
{ {
servers.push_back({row, addr}); servers.push_back({row, addr});
run = true; run = true;
@ -42,7 +42,7 @@ void PingUpdater::process()
unsigned ping = PingRakNetServer(server.second.first.toLatin1(), server.second.second); unsigned ping = PingRakNetServer(server.second.first.toLatin1(), server.second.second);
qDebug() << "Pong from" << server.second.first + "|" + QString::number(server.second.second) qDebug() << "Pong from" << server.second.first + "|" + QString::number(server.second.second)
<< ":" << ping << "ms"; << ":" << ping << "ms" << "Sizeof servers: " << servers.size();
emit updateModel(server.first, ping); emit updateModel(server.first, ping);
} }

@ -14,7 +14,7 @@ class PingUpdater : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
void addServer(int row, AddrPair addrPair); void addServer(int row, const AddrPair &addrPair);
public slots: public slots:
void stop(); void stop();
void process(); void process();

@ -19,8 +19,8 @@ QueryHelper::QueryHelper(QAbstractItemModel *model)
connect(queryThread, SIGNAL(started()), queryUpdate, SLOT(process())); connect(queryThread, SIGNAL(started()), queryUpdate, SLOT(process()));
connect(queryUpdate, SIGNAL(finished()), queryThread, SLOT(quit())); connect(queryUpdate, SIGNAL(finished()), queryThread, SLOT(quit()));
connect(queryUpdate, &QueryUpdate::finished, [this](){emit finished();}); connect(queryUpdate, &QueryUpdate::finished, [this](){emit finished();});
connect(queryUpdate, SIGNAL(updateModel(QString, unsigned short, QueryData)), connect(queryUpdate, SIGNAL(updateModel(const QString&, unsigned short, const QueryData&)),
this, SLOT(update(QString, unsigned short, QueryData))); this, SLOT(update(const QString&, unsigned short, const QueryData&)));
queryUpdate->moveToThread(queryThread); queryUpdate->moveToThread(queryThread);
} }
@ -29,6 +29,7 @@ void QueryHelper::refresh()
if (!queryThread->isRunning()) if (!queryThread->isRunning())
{ {
_model->removeRows(0, _model->rowCount()); _model->removeRows(0, _model->rowCount());
PingHelper::Get().Stop();
queryThread->start(); queryThread->start();
emit started(); emit started();
} }
@ -39,7 +40,7 @@ void QueryHelper::terminate()
queryThread->terminate(); queryThread->terminate();
} }
void QueryHelper::update(QString addr, unsigned short port, QueryData data) void QueryHelper::update(const QString &addr, unsigned short port, const QueryData& data)
{ {
ServerModel *model = ((ServerModel*)_model); ServerModel *model = ((ServerModel*)_model);
model->insertRow(model->rowCount()); model->insertRow(model->rowCount());
@ -80,7 +81,7 @@ void QueryUpdate::process()
return; return;
} }
for (auto server : data) for (const auto &server : data)
emit updateModel(server.first.ToString(false), server.first.GetPort(), server.second); emit updateModel(server.first.ToString(false), server.first.GetPort(), server.second);
emit finished(); emit finished();
} }

@ -23,7 +23,7 @@ public slots:
void refresh(); void refresh();
void terminate(); void terminate();
private slots: private slots:
void update(QString addr, unsigned short port, QueryData data); void update(const QString &addr, unsigned short port, const QueryData& data);
signals: signals:
void finished(); void finished();
void started(); void started();
@ -38,7 +38,7 @@ class QueryUpdate : public QObject
Q_OBJECT Q_OBJECT
signals: signals:
void finished(); void finished();
void updateModel(QString addr, unsigned short port, QueryData data); void updateModel(const QString &addr, unsigned short port, const QueryData& data);
public slots: public slots:
void process(); void process();
}; };

@ -6,32 +6,65 @@
#include "qdebug.h" #include "qdebug.h"
#include "ServerInfoDialog.hpp" #include "ServerInfoDialog.hpp"
#include <apps/browser/netutils/Utils.hpp>
#include <algorithm> #include <algorithm>
#include <utility>
#include <QThread>
using namespace std; using namespace std;
using namespace RakNet; using namespace RakNet;
ServerInfoDialog::ServerInfoDialog(QWidget *parent): QDialog(parent) 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)
{ {
setupUi(this); setupUi(this);
connect(btnRefresh, SIGNAL(clicked()), this, SLOT(refresh())); 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();
});
} }
ServerInfoDialog::~ServerInfoDialog() ServerInfoDialog::~ServerInfoDialog()
{ {
worker->dialog = nullptr;
if (!refreshThread->isRunning())
refreshThread->terminate();
}
bool ServerInfoDialog::isUpdated()
{
return sd.first != UNASSIGNED_SYSTEM_ADDRESS;
} }
void ServerInfoDialog::Server(QString addr) void ServerInfoDialog::setData(std::pair<RakNet::SystemAddress, QueryData> &newSD)
{ {
this->addr = addr; sd = newSD;
} }
bool ServerInfoDialog::refresh() void ServerInfoDialog::refresh()
{ {
QStringList list = addr.split(':');
auto sd = QueryClient::Get().Update(SystemAddress(list[0].toLatin1(), list[1].toUShort()));
if (sd.first != UNASSIGNED_SYSTEM_ADDRESS) if (sd.first != UNASSIGNED_SYSTEM_ADDRESS)
{ {
leAddr->setText(sd.first.ToString(true, ':')); leAddr->setText(sd.first.ToString(true, ':'));
@ -41,17 +74,16 @@ bool ServerInfoDialog::refresh()
btnConnect->setDisabled(ping == PING_UNREACHABLE); btnConnect->setDisabled(ping == PING_UNREACHABLE);
listPlayers->clear(); listPlayers->clear();
for (const auto &player : sd.second.players)
for (auto player : sd.second.players)
listPlayers->addItem(QString::fromStdString(player)); listPlayers->addItem(QString::fromStdString(player));
listPlugins->clear(); listPlugins->clear();
for (auto plugin : sd.second.plugins) for (const auto &plugin : sd.second.plugins)
listPlugins->addItem(QString::fromStdString(plugin.name)); listPlugins->addItem(QString::fromStdString(plugin.name));
listRules->clear(); listRules->clear();
const static vector<std::string> defaultRules {"gamemode", "maxPlayers", "name", "passw", "players", "version"}; 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()) if (::find(defaultRules.begin(), defaultRules.end(), rule.first) != defaultRules.end())
continue; continue;
@ -64,7 +96,12 @@ bool ServerInfoDialog::refresh()
} }
lblPlayers->setText(QString::number(sd.second.players.size()) + " / " + QString::number(sd.second.GetMaxPlayers())); lblPlayers->setText(QString::number(sd.second.players.size()) + " / " + QString::number(sd.second.GetMaxPlayers()));
return true;
} }
return false; }
int ServerInfoDialog::exec()
{
if (!refreshThread->isRunning())
refreshThread->start();
return QDialog::exec();
} }

@ -6,18 +6,45 @@
#define NEWLAUNCHER_SERVERINFODIALOG_HPP #define NEWLAUNCHER_SERVERINFODIALOG_HPP
#include "ui_ServerInfo.h" #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 class ServerInfoDialog : public QDialog, public Ui::Dialog
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ServerInfoDialog(QWidget *parent = 0); explicit ServerInfoDialog(const QString &addr, QWidget *parent = nullptr);
virtual ~ServerInfoDialog(); ~ServerInfoDialog() override;
void Server(QString addr); bool isUpdated();
void setData(std::pair<RakNet::SystemAddress, QueryData> &newSD);
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: public slots:
bool refresh(); void process();
signals:
void finished();
private: private:
QString addr; QString addr;
unsigned short port;
bool stopped;
ServerInfoDialog *dialog;
}; };

@ -1,16 +1,11 @@
#include <qmessagebox.h> #include <qmessagebox.h>
#include "ServerModel.hpp" #include "ServerModel.hpp"
#include <qdebug.h> #include <qdebug.h>
#include <apps/browser/netutils/Utils.hpp>
ServerModel::ServerModel(QObject *parent) : QAbstractTableModel(parent) ServerModel::ServerModel(QObject *parent) : QAbstractTableModel(parent)
{ {
} }
ServerModel::~ServerModel()
{
}
/*QHash<int, QByteArray> ServerModel::roleNames() const /*QHash<int, QByteArray> ServerModel::roleNames() const
{ {
return roles; return roles;
@ -49,7 +44,7 @@ QVariant ServerModel::data(const QModelIndex &index, int role) const
var = QString(sd.rules.at("name").str.c_str()); var = QString(sd.rules.at("name").str.c_str());
break; break;
case ServerData::PING: case ServerData::PING:
var = sd.ping; var = sd.ping == PING_UNREACHABLE ? QVariant("Unreachable") : sd.ping;
break; break;
case ServerData::MODNAME: case ServerData::MODNAME:
if (sd.rules.at("gamemode").str == "") if (sd.rules.at("gamemode").str == "")
@ -136,7 +131,7 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
sd.SetPassword(value.toBool()); sd.SetPassword(value.toBool());
break; break;
case ServerData::VERSION: case ServerData::VERSION:
sd.SetVersion(value.toString().toLatin1()); sd.SetVersion(value.toString().toUtf8());
ok = !sd.addr.isEmpty(); ok = !sd.addr.isEmpty();
break; break;
case ServerData::PLAYERS: case ServerData::PLAYERS:
@ -146,14 +141,14 @@ bool ServerModel::setData(const QModelIndex &index, const QVariant &value, int r
sd.SetMaxPlayers(value.toInt(&ok)); sd.SetMaxPlayers(value.toInt(&ok));
break; break;
case ServerData::HOSTNAME: case ServerData::HOSTNAME:
sd.SetName(value.toString().toLatin1()); sd.SetName(value.toString().toUtf8());
ok = !sd.addr.isEmpty(); ok = !sd.addr.isEmpty();
break; break;
case ServerData::PING: case ServerData::PING:
sd.ping = value.toInt(&ok); sd.ping = value.toInt(&ok);
break; break;
case ServerData::MODNAME: case ServerData::MODNAME:
sd.SetGameMode(value.toString().toLatin1()); sd.SetGameMode(value.toString().toUtf8());
break; break;
default: default:
return false; return false;
@ -170,9 +165,7 @@ bool ServerModel::insertRows(int position, int count, const QModelIndex &index)
Q_UNUSED(index); Q_UNUSED(index);
beginInsertRows(QModelIndex(), position, position + count - 1); beginInsertRows(QModelIndex(), position, position + count - 1);
for (int row = 0; row < count; ++row) { myData.insert(position, count, {});
myData.insert(position, {});
}
endInsertRows(); endInsertRows();
return true; return true;

@ -29,8 +29,7 @@ class ServerModel: public QAbstractTableModel
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit ServerModel(QObject *parent = 0); explicit ServerModel(QObject *parent = nullptr);
~ServerModel();
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_FINAL; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const Q_DECL_FINAL;
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_FINAL; int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_FINAL;
int columnCount(const QModelIndex &parent) const Q_DECL_FINAL; int columnCount(const QModelIndex &parent) const Q_DECL_FINAL;

@ -36,6 +36,11 @@ int main(int argc, char *argv[])
std::string addr = mgr.getString("address", "Master"); std::string addr = mgr.getString("address", "Master");
int port = mgr.getInt("port", "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 // initialize resources, if needed
// Q_INIT_RESOURCE(resfile); // Q_INIT_RESOURCE(resfile);

@ -30,7 +30,7 @@ QueryClient::~QueryClient()
RakPeerInterface::DestroyInstance(peer); RakPeerInterface::DestroyInstance(peer);
} }
void QueryClient::SetServer(std::string addr, unsigned short port) void QueryClient::SetServer(const string &addr, unsigned short port)
{ {
masterAddr = SystemAddress(addr.c_str(), port); masterAddr = SystemAddress(addr.c_str(), port);
} }
@ -83,7 +83,7 @@ map<SystemAddress, QueryData> QueryClient::Query()
return query; return query;
} }
pair<SystemAddress, QueryData> QueryClient::Update(RakNet::SystemAddress addr) pair<SystemAddress, QueryData> QueryClient::Update(const RakNet::SystemAddress &addr)
{ {
qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)"; qDebug() << "Locking mutex in QueryClient::Update(RakNet::SystemAddress addr)";
pair<SystemAddress, QueryData> server; pair<SystemAddress, QueryData> server;
@ -179,7 +179,7 @@ ConnectionState QueryClient::Connect()
{ {
ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW, ConnectionAttemptResult car = peer->Connect(masterAddr.ToString(false), masterAddr.GetPort(), TES3MP_MASTERSERVER_PASSW,
strlen(TES3MP_MASTERSERVER_PASSW), 0, 0, 5, 500); strlen(TES3MP_MASTERSERVER_PASSW), nullptr, 0, 5, 500);
while (true) while (true)
{ {

@ -14,16 +14,16 @@
class QueryClient class QueryClient
{ {
private: public:
QueryClient(QueryClient const &) = delete; QueryClient(QueryClient const &) = delete;
QueryClient(QueryClient &&) = delete; QueryClient(QueryClient &&) = delete;
QueryClient &operator=(QueryClient const &) = delete; QueryClient &operator=(QueryClient const &) = delete;
QueryClient &operator=(QueryClient &&) = delete; QueryClient &operator=(QueryClient &&) = delete;
public:
static QueryClient &Get(); static QueryClient &Get();
void SetServer(std::string addr, unsigned short port); void SetServer(const std::string &addr, unsigned short port);
std::map<RakNet::SystemAddress, QueryData> Query(); std::map<RakNet::SystemAddress, QueryData> Query();
std::pair<RakNet::SystemAddress, QueryData> Update(RakNet::SystemAddress addr); std::pair<RakNet::SystemAddress, QueryData> Update(const RakNet::SystemAddress &addr);
int Status(); int Status();
private: private:
RakNet::ConnectionState Connect(); RakNet::ConnectionState Connect();

@ -44,12 +44,16 @@ unsigned int PingRakNetServer(const char *addr, unsigned short port)
break; break;
case ID_CONNECTED_PING: case ID_CONNECTED_PING:
case ID_UNCONNECTED_PONG: case ID_UNCONNECTED_PONG:
{
RakNet::BitStream bsIn(&packet->data[1], packet->length, false); RakNet::BitStream bsIn(&packet->data[1], packet->length, false);
bsIn.Read(time); bsIn.Read(time);
time = now - time; time = now - time;
done = true; done = true;
break; break;
} }
default:
break;
}
peer->DeallocatePacket(packet); peer->DeallocatePacket(packet);
} }
@ -69,9 +73,9 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
sstr << TES3MP_VERSION; sstr << TES3MP_VERSION;
sstr << TES3MP_PROTO_VERSION; sstr << TES3MP_PROTO_VERSION;
std::string msg = ""; std::string msg;
if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), 0, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED) if (peer->Connect(addr, port, sstr.str().c_str(), (int)(sstr.str().size()), nullptr, 0, 3, 500, 0) != RakNet::CONNECTION_ATTEMPT_STARTED)
msg = "Connection attempt failed.\n"; msg = "Connection attempt failed.\n";
@ -142,14 +146,14 @@ ServerExtendedData getExtendedData(const char *addr, unsigned short port)
{ {
RakNet::RakString str; RakNet::RakString str;
bs.Read(str); bs.Read(str);
data.players.push_back(str.C_String()); data.players.emplace_back(str.C_String());
} }
bs.Read(length); bs.Read(length);
for (size_t i = 0; i < length; i++) for (size_t i = 0; i < length; i++)
{ {
RakNet::RakString str; RakNet::RakString str;
bs.Read(str); bs.Read(str);
data.plugins.push_back(str.C_String()); data.plugins.emplace_back(str.C_String());
} }
done = true; done = true;
} }

@ -20,6 +20,7 @@ namespace ESSImport
item.mId = contItem.mItem.toString(); item.mId = contItem.mItem.toString();
item.mCount = contItem.mCount; item.mCount = contItem.mCount;
item.mRelativeEquipmentSlot = -1; item.mRelativeEquipmentSlot = -1;
item.mLockLevel = 0;
unsigned int itemCount = std::abs(item.mCount); unsigned int itemCount = std::abs(item.mCount);
bool separateStacks = false; bool separateStacks = false;

@ -8,6 +8,7 @@ set(LAUNCHER
settingspage.cpp settingspage.cpp
advancedpage.cpp advancedpage.cpp
utils/cellnameloader.cpp
utils/profilescombobox.cpp utils/profilescombobox.cpp
utils/textinputdialog.cpp utils/textinputdialog.cpp
utils/lineedit.cpp utils/lineedit.cpp
@ -24,6 +25,7 @@ set(LAUNCHER_HEADER
settingspage.hpp settingspage.hpp
advancedpage.hpp advancedpage.hpp
utils/cellnameloader.hpp
utils/profilescombobox.hpp utils/profilescombobox.hpp
utils/textinputdialog.hpp utils/textinputdialog.hpp
utils/lineedit.hpp utils/lineedit.hpp
@ -39,6 +41,7 @@ set(LAUNCHER_HEADER_MOC
settingspage.hpp settingspage.hpp
advancedpage.hpp advancedpage.hpp
utils/cellnameloader.hpp
utils/textinputdialog.hpp utils/textinputdialog.hpp
utils/profilescombobox.hpp utils/profilescombobox.hpp
utils/lineedit.hpp utils/lineedit.hpp

@ -1,10 +1,18 @@
#include "advancedpage.hpp" #include "advancedpage.hpp"
#include <components/files/configurationmanager.hpp> #include <components/config/gamesettings.hpp>
#include <components/config/launchersettings.hpp>
Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent) #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) : QWidget(parent)
, mCfgMgr(cfg) , mCfgMgr(cfg)
, mGameSettings(gameSettings)
, mEngineSettings(engineSettings) , mEngineSettings(engineSettings)
{ {
setObjectName ("AdvancedPage"); setObjectName ("AdvancedPage");
@ -13,23 +21,61 @@ Launcher::AdvancedPage::AdvancedPage(Files::ConfigurationManager &cfg, Settings:
loadSettings(); 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() 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 // Game Settings
loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); loadSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); loadSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); loadSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
loadSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
loadSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
loadSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
loadSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); loadSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
loadSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
// Expected values are (0, 1, 2, 3) loadSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
int showOwnedIndex = mEngineSettings.getInt("show owned", "Game"); loadSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
// Match the index with the option. Will default to 0 if invalid.
if (showOwnedIndex >= 0 && showOwnedIndex <= 3)
showOwnedComboBox->setCurrentIndex(showOwnedIndex);
// Input Settings // Input Settings
loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); loadSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
@ -40,6 +86,16 @@ bool Launcher::AdvancedPage::loadSettings()
loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves"); loadSettingBool(timePlayedCheckbox, "timeplayed", "Saves");
maximumQuicksavesComboBox->setValue(mEngineSettings.getInt("max quicksaves", "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 // Other Settings
QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper(); QString screenshotFormatString = QString::fromStdString(mEngineSettings.getString("screenshot format", "General")).toUpper();
if (screenshotFormatComboBox->findText(screenshotFormatString) == -1) if (screenshotFormatComboBox->findText(screenshotFormatString) == -1)
@ -54,19 +110,27 @@ void Launcher::AdvancedPage::saveSettings()
// Ensure we only set the new settings if they changed. This is to avoid cluttering the // 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) // 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 // Game Settings
saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game"); saveSettingBool(canLootDuringDeathAnimationCheckBox, "can loot during death animation", "Game");
saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game"); saveSettingBool(followersAttackOnSightCheckBox, "followers attack on sight", "Game");
saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game"); saveSettingBool(preventMerchantEquippingCheckBox, "prevent merchant equipping", "Game");
saveSettingBool(showEffectDurationCheckBox, "show effect duration", "Game");
saveSettingBool(showEnchantChanceCheckBox, "show enchant chance", "Game");
saveSettingBool(showMeleeInfoCheckBox, "show melee info", "Game");
saveSettingBool(showProjectileDamageCheckBox, "show projectile damage", "Game");
saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game"); saveSettingBool(rebalanceSoulGemValuesCheckBox, "rebalance soul gem values", "Game");
saveSettingBool(chargeForEveryFollowerCheckBox, "charge for every follower travelling", "Game");
int showOwnedCurrentIndex = showOwnedComboBox->currentIndex(); saveSettingBool(enchantedWeaponsMagicalCheckBox, "enchanted weapons are magical", "Game");
if (showOwnedCurrentIndex != mEngineSettings.getInt("show owned", "Game")) saveSettingBool(permanentBarterDispositionChangeCheckBox, "barter disposition change is permanent", "Game");
mEngineSettings.setInt("show owned", "Game", showOwnedCurrentIndex);
// Input Settings // Input Settings
saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input"); saveSettingBool(allowThirdPersonZoomCheckBox, "allow third person zoom", "Input");
@ -80,6 +144,15 @@ void Launcher::AdvancedPage::saveSettings()
mEngineSettings.setInt("max quicksaves", "Saves", maximumQuicksaves); 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 // Other Settings
std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString(); std::string screenshotFormatString = screenshotFormatComboBox->currentText().toLower().toStdString();
if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General")) if (screenshotFormatString != mEngineSettings.getString("screenshot format", "General"))
@ -96,3 +169,8 @@ void Launcher::AdvancedPage::saveSettingBool(QCheckBox *checkbox, const std::str
if (cValue != mEngineSettings.getBool(setting, group)) if (cValue != mEngineSettings.getBool(setting, group))
mEngineSettings.setBool(setting, group, cValue); mEngineSettings.setBool(setting, group, cValue);
} }
void Launcher::AdvancedPage::slotLoadedCellsChanged(QStringList cellNames)
{
loadCellsForAutocomplete(cellNames);
}

@ -8,6 +8,7 @@
#include <components/settings/settings.hpp> #include <components/settings/settings.hpp>
namespace Files { struct ConfigurationManager; } namespace Files { struct ConfigurationManager; }
namespace Config { class GameSettings; }
namespace Launcher namespace Launcher
{ {
@ -16,15 +17,29 @@ namespace Launcher
Q_OBJECT Q_OBJECT
public: public:
AdvancedPage(Files::ConfigurationManager &cfg, Settings::Manager &engineSettings, QWidget *parent = 0); AdvancedPage(Files::ConfigurationManager &cfg, Config::GameSettings &gameSettings,
Settings::Manager &engineSettings, QWidget *parent = 0);
bool loadSettings(); bool loadSettings();
void saveSettings(); void saveSettings();
public slots:
void slotLoadedCellsChanged(QStringList cellNames);
private slots:
void on_skipMenuCheckBox_stateChanged(int state);
void on_runScriptAfterStartupBrowseButton_clicked();
private: private:
Files::ConfigurationManager &mCfgMgr; Files::ConfigurationManager &mCfgMgr;
Config::GameSettings &mGameSettings;
Settings::Manager &mEngineSettings; 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 loadSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group); void saveSettingBool(QCheckBox *checkbox, const std::string& setting, const std::string& group);
}; };

@ -7,7 +7,10 @@
#include <QCheckBox> #include <QCheckBox>
#include <QMenu> #include <QMenu>
#include <QSortFilterProxyModel> #include <QSortFilterProxyModel>
#include <thread>
#include <mutex>
#include <apps/launcher/utils/cellnameloader.hpp>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
#include <components/contentselector/model/esmfile.hpp> #include <components/contentselector/model/esmfile.hpp>
@ -16,6 +19,7 @@
#include <components/config/gamesettings.hpp> #include <components/config/gamesettings.hpp>
#include <components/config/launchersettings.hpp> #include <components/config/launchersettings.hpp>
#include <iostream>
#include "utils/textinputdialog.hpp" #include "utils/textinputdialog.hpp"
#include "utils/profilescombobox.hpp" #include "utils/profilescombobox.hpp"
@ -40,6 +44,13 @@ Launcher::DataFilesPage::DataFilesPage(Files::ConfigurationManager &cfg, Config:
buildView(); buildView();
loadSettings(); 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() void Launcher::DataFilesPage::buildView()
@ -142,6 +153,17 @@ void Launcher::DataFilesPage::saveSettings(const QString &profile)
mGameSettings.setContentList(fileNames); 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) void Launcher::DataFilesPage::removeProfile(const QString &profile)
{ {
mLauncherSettings.removeContentList(profile); mLauncherSettings.removeContentList(profile);
@ -308,3 +330,31 @@ bool Launcher::DataFilesPage::showDeleteMessageBox (const QString &text)
return (msgBox.clickedButton() == deleteButton); 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,6 +7,7 @@
#include <QDir> #include <QDir>
#include <QFile> #include <QFile>
#include <QStringList>
class QSortFilterProxyModel; class QSortFilterProxyModel;
class QAbstractItemModel; class QAbstractItemModel;
@ -41,8 +42,15 @@ namespace Launcher
void saveSettings(const QString &profile = ""); void saveSettings(const QString &profile = "");
bool loadSettings(); bool loadSettings();
/**
* Returns the file paths of all selected content files
* @return the file paths of all selected content files
*/
QStringList selectedFilePaths();
signals: signals:
void signalProfileChanged (int index); void signalProfileChanged (int index);
void signalLoadedCellsChanged(QStringList selectedFiles);
public slots: public slots:
void slotProfileChanged (int index); void slotProfileChanged (int index);
@ -52,6 +60,7 @@ namespace Launcher
void slotProfileChangedByUser(const QString &previous, const QString &current); void slotProfileChangedByUser(const QString &previous, const QString &current);
void slotProfileRenamed(const QString &previous, const QString &current); void slotProfileRenamed(const QString &previous, const QString &current);
void slotProfileDeleted(const QString &item); void slotProfileDeleted(const QString &item);
void slotAddonDataChanged ();
void updateOkButton(const QString &text); void updateOkButton(const QString &text);
@ -72,7 +81,7 @@ namespace Launcher
Config::LauncherSettings &mLauncherSettings; Config::LauncherSettings &mLauncherSettings;
QString mPreviousProfile; QString mPreviousProfile;
QStringList previousSelectedFiles;
QString mDataLocal; QString mDataLocal;
void setPluginsCheckstates(Qt::CheckState state); void setPluginsCheckstates(Qt::CheckState state);
@ -87,6 +96,7 @@ namespace Launcher
void addProfile (const QString &profile, bool setAsCurrent); void addProfile (const QString &profile, bool setAsCurrent);
void checkForDefaultProfile(); void checkForDefaultProfile();
void populateFileViews(const QString& contentModelName); void populateFileViews(const QString& contentModelName);
void reloadCells(QStringList selectedFiles);
class PathIterator class PathIterator
{ {

@ -1,6 +1,7 @@
#include "graphicspage.hpp" #include "graphicspage.hpp"
#include <boost/math/common_factor.hpp> #include <boost/math/common_factor.hpp>
#include <csignal>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QMessageBox> #include <QMessageBox>
#include <QDir> #include <QDir>
@ -11,6 +12,7 @@
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif // MAC_OS_X_VERSION_MIN_REQUIRED #endif // MAC_OS_X_VERSION_MIN_REQUIRED
#include <SDL.h>
#include <SDL_video.h> #include <SDL_video.h>
#include <components/files/configurationmanager.hpp> #include <components/files/configurationmanager.hpp>
@ -46,8 +48,28 @@ 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 Launcher::GraphicsPage::setupSDL()
{ {
bool sdlConnectSuccessful = connectToSdl();
if (!sdlConnectSuccessful)
{
return false;
}
int displays = SDL_GetNumVideoDisplays(); int displays = SDL_GetNumVideoDisplays();
if (displays < 0) if (displays < 0)
@ -67,6 +89,9 @@ bool Launcher::GraphicsPage::setupSDL()
screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1)); screenComboBox->addItem(QString(tr("Screen ")) + QString::number(i + 1));
} }
// Disconnect from SDL processes
SDL_Quit();
return true; return true;
} }

@ -37,6 +37,11 @@ namespace Launcher
QStringList getAvailableResolutions(int screen); QStringList getAvailableResolutions(int screen);
QRect getMaximumResolution(); 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(); bool setupSDL();
}; };
} }

@ -1,5 +1,4 @@
#include <iostream> #include <iostream>
#include <csignal>
#include <QApplication> #include <QApplication>
#include <QTextCodec> #include <QTextCodec>
@ -12,24 +11,12 @@
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ #define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
#endif // MAC_OS_X_VERSION_MIN_REQUIRED #endif // MAC_OS_X_VERSION_MIN_REQUIRED
#include <SDL.h>
#include "maindialog.hpp" #include "maindialog.hpp"
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
try 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); QApplication app(argc, argv);
// Now we make sure the current dir is set to application path // Now we make sure the current dir is set to application path
@ -46,9 +33,7 @@ int main(int argc, char *argv[])
if (result == Launcher::FirstRunDialogResultContinue) if (result == Launcher::FirstRunDialogResultContinue)
mainWin.show(); mainWin.show();
int returnValue = app.exec(); return app.exec();
SDL_Quit();
return returnValue;
} }
catch (std::exception& e) catch (std::exception& e)
{ {

@ -90,19 +90,19 @@ void Launcher::MainDialog::createIcons()
dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); dataFilesButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget); QListWidgetItem *graphicsButton = new QListWidgetItem(iconWidget);
graphicsButton->setIcon(QIcon::fromTheme("video-display")); graphicsButton->setIcon(QIcon(":/images/preferences-video.png"));
graphicsButton->setText(tr("Graphics")); graphicsButton->setText(tr("Graphics"));
graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute); graphicsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom | Qt::AlignAbsolute);
graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); graphicsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QListWidgetItem *settingsButton = new QListWidgetItem(iconWidget); QListWidgetItem *settingsButton = new QListWidgetItem(iconWidget);
settingsButton->setIcon(QIcon::fromTheme("preferences-system")); settingsButton->setIcon(QIcon(":/images/preferences.png"));
settingsButton->setText(tr("Settings")); settingsButton->setText(tr("Settings"));
settingsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); settingsButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
settingsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); settingsButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
QListWidgetItem *advancedButton = new QListWidgetItem(iconWidget); QListWidgetItem *advancedButton = new QListWidgetItem(iconWidget);
advancedButton->setIcon(QIcon::fromTheme("emblem-system")); advancedButton->setIcon(QIcon(":/images/preferences-advanced.png"));
advancedButton->setText(tr("Advanced")); advancedButton->setText(tr("Advanced"));
advancedButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom); advancedButton->setTextAlignment(Qt::AlignHCenter | Qt::AlignBottom);
advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled); advancedButton->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEnabled);
@ -119,7 +119,7 @@ void Launcher::MainDialog::createPages()
mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this); mDataFilesPage = new DataFilesPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this); mGraphicsPage = new GraphicsPage(mCfgMgr, mEngineSettings, this);
mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this); mSettingsPage = new SettingsPage(mCfgMgr, mGameSettings, mLauncherSettings, this);
mAdvancedPage = new AdvancedPage(mCfgMgr, mEngineSettings, this); mAdvancedPage = new AdvancedPage(mCfgMgr, mGameSettings, mEngineSettings, this);
// Set the combobox of the play page to imitate the combobox on the datafilespage // Set the combobox of the play page to imitate the combobox on the datafilespage
mPlayPage->setProfilesModel(mDataFilesPage->profilesModel()); mPlayPage->setProfilesModel(mDataFilesPage->profilesModel());
@ -139,6 +139,8 @@ void Launcher::MainDialog::createPages()
connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int))); connect(mPlayPage, SIGNAL(signalProfileChanged(int)), mDataFilesPage, SLOT(slotProfileChanged(int)));
connect(mDataFilesPage, SIGNAL(signalProfileChanged(int)), mPlayPage, SLOT(setProfilesIndex(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);
} }

@ -0,0 +1,48 @@
#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);
}

@ -0,0 +1,41 @@
#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

@ -874,7 +874,6 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co
{ {
std::vector<std::pair<std::time_t, boost::filesystem::path>> contentFiles; std::vector<std::pair<std::time_t, boost::filesystem::path>> contentFiles;
std::string baseGameFile("Game Files:GameFile"); std::string baseGameFile("Game Files:GameFile");
std::string gameFile("");
std::time_t defaultTime = 0; std::time_t defaultTime = 0;
ToUTF8::Utf8Encoder encoder(mEncoding); ToUTF8::Utf8Encoder encoder(mEncoding);
@ -890,7 +889,7 @@ void MwIniImporter::importGameFiles(multistrmap &cfg, const multistrmap &ini, co
multistrmap::const_iterator it = ini.begin(); multistrmap::const_iterator it = ini.begin();
for (int i=0; it != ini.end(); i++) for (int i=0; it != ini.end(); i++)
{ {
gameFile = baseGameFile; std::string gameFile = baseGameFile;
gameFile.append(std::to_string(i)); gameFile.append(std::to_string(i));
it = ini.find(gameFile); it = ini.find(gameFile);

@ -5,6 +5,9 @@
#include <QLocalSocket> #include <QLocalSocket>
#include <QMessageBox> #include <QMessageBox>
#include <components/crashcatcher/crashcatcher.hpp>
#include <components/fallback/validate.hpp> #include <components/fallback/validate.hpp>
#include <components/nifosg/nifloader.hpp> #include <components/nifosg/nifloader.hpp>
@ -18,12 +21,16 @@
using namespace Fallback; using namespace Fallback;
CS::Editor::Editor () CS::Editor::Editor (int argc, char **argv)
: mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr), : mSettingsState (mCfgMgr), mDocumentManager (mCfgMgr),
mViewManager (mDocumentManager), mPid(""), mViewManager (mDocumentManager), mPid(""),
mLock(), mMerge (mDocumentManager), mLock(), mMerge (mDocumentManager),
mIpcServerName ("org.openmw.OpenCS"), mServer(NULL), mClientSocket(NULL) 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(); std::pair<Files::PathContainer, std::vector<std::string> > config = readConfig();
setupDataFiles (config.first); setupDataFiles (config.first);

@ -66,7 +66,7 @@ namespace CS
public: public:
Editor (); Editor (int argc, char **argv);
~Editor (); ~Editor ();
bool makeIPCServer(); bool makeIPCServer();

@ -8,8 +8,9 @@
#include <QIcon> #include <QIcon>
#include <QMetaType> #include <QMetaType>
#include "model/doc/messages.hpp" #include <components/misc/debugging.hpp>
#include "model/doc/messages.hpp"
#include "model/world/universalid.hpp" #include "model/world/universalid.hpp"
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
@ -41,14 +42,12 @@ class Application : public QApplication
Application (int& argc, char *argv[]) : QApplication (argc, argv) {} Application (int& argc, char *argv[]) : QApplication (argc, argv) {}
}; };
int main(int argc, char *argv[]) int runApplication(int argc, char *argv[])
{ {
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0); setenv("OSG_GL_TEXTURE_STORAGE", "OFF", 0);
#endif #endif
try
{
// To allow background thread drawing in OSG // To allow background thread drawing in OSG
QApplication::setAttribute(Qt::AA_X11InitThreads, true); QApplication::setAttribute(Qt::AA_X11InitThreads, true);
@ -60,26 +59,26 @@ int main(int argc, char *argv[])
Application application (argc, argv); Application application (argc, argv);
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
QDir dir(QCoreApplication::applicationDirPath()); QDir dir(QCoreApplication::applicationDirPath());
QDir::setCurrent(dir.absolutePath()); QDir::setCurrent(dir.absolutePath());
#endif #endif
application.setWindowIcon (QIcon (":./openmw-cs.png")); application.setWindowIcon (QIcon (":./openmw-cs.png"));
CS::Editor editor; CS::Editor editor(argc, argv);
if(!editor.makeIPCServer()) if(!editor.makeIPCServer())
{ {
editor.connectToIPCServer(); editor.connectToIPCServer();
return 0; return 0;
} }
return editor.run(); return editor.run();
} }
catch (std::exception& e)
{
std::cerr << "ERROR: " << e.what() << std::endl;
return 0;
}
int main(int argc, char *argv[])
{
return wrapApplication(&runApplication, argc, argv, "/openmw-cs.log");
} }

@ -320,12 +320,13 @@ CSMDoc::Document::Document (const Files::ConfigurationManager& configuration,
connect (&mUndoStack, SIGNAL (cleanChanged (bool)), this, SLOT (modificationStateChanged (bool))); 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 (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mTools, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); 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 (mergeDone (CSMDoc::Document*)), connect (&mTools, SIGNAL (mergeDone (CSMDoc::Document*)),
this, 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 (progress (int, int, int)), this, SLOT (progress (int, int, int)));
connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone (int, bool))); connect (&mSaving, SIGNAL (done (int, bool)), this, SLOT (operationDone2 (int, bool)));
connect ( connect (
&mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)), &mSaving, SIGNAL (reportMessage (const CSMDoc::Message&, int)),
@ -437,7 +438,7 @@ void CSMDoc::Document::reportMessage (const CSMDoc::Message& message, int type)
std::cout << message.mMessage << std::endl; std::cout << message.mMessage << std::endl;
} }
void CSMDoc::Document::operationDone (int type, bool failed) void CSMDoc::Document::operationDone2 (int type, bool failed)
{ {
if (type==CSMDoc::State_Saving && !failed) if (type==CSMDoc::State_Saving && !failed)
mDirty = false; mDirty = false;

@ -168,13 +168,15 @@ namespace CSMDoc
/// document. This signal must be handled to avoid a leak. /// document. This signal must be handled to avoid a leak.
void mergeDone (CSMDoc::Document *document); void mergeDone (CSMDoc::Document *document);
void operationDone (int type, bool failed);
private slots: private slots:
void modificationStateChanged (bool clean); void modificationStateChanged (bool clean);
void reportMessage (const CSMDoc::Message& message, int type); void reportMessage (const CSMDoc::Message& message, int type);
void operationDone (int type, bool failed); void operationDone2 (int type, bool failed);
void runStateChanged(); void runStateChanged();

@ -123,6 +123,7 @@ void CSMPrefs::State::declare()
declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues); declareEnum ("double-s", "Shift Double Click", actionRemove).addValues (reportValues);
declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues); declareEnum ("double-c", "Control Double Click", actionEditAndRemove).addValues (reportValues);
declareEnum ("double-sc", "Shift Control Double Click", actionNone).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"); declareCategory ("Search & Replace");
declareInt ("char-before", "Characters before search string", 10). declareInt ("char-before", "Characters before search string", 10).
@ -200,6 +201,9 @@ void CSMPrefs::State::declare()
declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1); declareDouble ("rotate-factor", "Free rotation factor", 0.007).setPrecision(4).setRange(0.0001, 0.1);
declareCategory ("Rendering"); 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); declareInt ("camera-fov", "Camera FOV", 90).setRange(10, 170);
declareBool ("camera-ortho", "Orthographic projection for camera", false); declareBool ("camera-ortho", "Orthographic projection for camera", false);
declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100). declareInt ("camera-ortho-size", "Orthographic projection size parameter", 100).

@ -5,14 +5,20 @@
#include <components/esm/loadbsgn.hpp> #include <components/esm/loadbsgn.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns) CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
: mBirthsigns (birthsigns) : mBirthsigns (birthsigns)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::BirthsignCheckStage::setup() int CSMTools::BirthsignCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mBirthsigns.getSize(); return mBirthsigns.getSize();
} }
@ -20,7 +26,8 @@ void CSMTools::BirthsignCheckStage::perform (int stage, CSMDoc::Messages& messag
{ {
const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage); const CSMWorld::Record<ESM::BirthSign>& record = mBirthsigns.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::BirthSign& birthsign = record.get(); const ESM::BirthSign& birthsign = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class BirthsignCheckStage : public CSMDoc::Stage class BirthsignCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns; const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
bool mIgnoreBaseRecords;
public: public:

@ -1,5 +1,7 @@
#include "bodypartcheck.hpp" #include "bodypartcheck.hpp"
#include "../prefs/state.hpp"
CSMTools::BodyPartCheckStage::BodyPartCheckStage( CSMTools::BodyPartCheckStage::BodyPartCheckStage(
const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts, const CSMWorld::IdCollection<ESM::BodyPart> &bodyParts,
const CSMWorld::Resources &meshes, const CSMWorld::Resources &meshes,
@ -7,10 +9,14 @@ CSMTools::BodyPartCheckStage::BodyPartCheckStage(
mBodyParts(bodyParts), mBodyParts(bodyParts),
mMeshes(meshes), mMeshes(meshes),
mRaces(races) mRaces(races)
{ } {
mIgnoreBaseRecords = false;
}
int CSMTools::BodyPartCheckStage::setup() int CSMTools::BodyPartCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mBodyParts.getSize(); return mBodyParts.getSize();
} }
@ -18,7 +24,8 @@ void CSMTools::BodyPartCheckStage::perform (int stage, CSMDoc::Messages &message
{ {
const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage); const CSMWorld::Record<ESM::BodyPart> &record = mBodyParts.getRecord(stage);
if ( record.isDeleted() ) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::BodyPart &bodyPart = record.get(); const ESM::BodyPart &bodyPart = record.get();

@ -17,6 +17,7 @@ namespace CSMTools
const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts; const CSMWorld::IdCollection<ESM::BodyPart> &mBodyParts;
const CSMWorld::Resources &mMeshes; const CSMWorld::Resources &mMeshes;
const CSMWorld::IdCollection<ESM::Race> &mRaces; const CSMWorld::IdCollection<ESM::Race> &mRaces;
bool mIgnoreBaseRecords;
public: public:
BodyPartCheckStage( BodyPartCheckStage(

@ -6,14 +6,20 @@
#include <components/esm/loadclas.hpp> #include <components/esm/loadclas.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes) CSMTools::ClassCheckStage::ClassCheckStage (const CSMWorld::IdCollection<ESM::Class>& classes)
: mClasses (classes) : mClasses (classes)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::ClassCheckStage::setup() int CSMTools::ClassCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mClasses.getSize(); return mClasses.getSize();
} }
@ -21,7 +27,8 @@ void CSMTools::ClassCheckStage::perform (int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage); const CSMWorld::Record<ESM::Class>& record = mClasses.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Class& class_ = record.get(); const ESM::Class& class_ = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class ClassCheckStage : public CSMDoc::Stage class ClassCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Class>& mClasses; const CSMWorld::IdCollection<ESM::Class>& mClasses;
bool mIgnoreBaseRecords;
public: public:

@ -6,14 +6,20 @@
#include <components/esm/loadfact.hpp> #include <components/esm/loadfact.hpp>
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions) CSMTools::FactionCheckStage::FactionCheckStage (const CSMWorld::IdCollection<ESM::Faction>& factions)
: mFactions (factions) : mFactions (factions)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::FactionCheckStage::setup() int CSMTools::FactionCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mFactions.getSize(); return mFactions.getSize();
} }
@ -21,7 +27,8 @@ void CSMTools::FactionCheckStage::perform (int stage, CSMDoc::Messages& messages
{ {
const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage); const CSMWorld::Record<ESM::Faction>& record = mFactions.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Faction& faction = record.get(); const ESM::Faction& faction = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class FactionCheckStage : public CSMDoc::Stage class FactionCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Faction>& mFactions; const CSMWorld::IdCollection<ESM::Faction>& mFactions;
bool mIgnoreBaseRecords;
public: public:

@ -2,14 +2,20 @@
#include <sstream> #include <sstream>
#include "../prefs/state.hpp"
#include "../world/defaultgmsts.hpp" #include "../world/defaultgmsts.hpp"
CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings) CSMTools::GmstCheckStage::GmstCheckStage(const CSMWorld::IdCollection<ESM::GameSetting>& gameSettings)
: mGameSettings(gameSettings) : mGameSettings(gameSettings)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::GmstCheckStage::setup() int CSMTools::GmstCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mGameSettings.getSize(); return mGameSettings.getSize();
} }
@ -17,7 +23,8 @@ void CSMTools::GmstCheckStage::perform(int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage); const CSMWorld::Record<ESM::GameSetting>& record = mGameSettings.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::GameSetting& gmst = record.get(); const ESM::GameSetting& gmst = record.get();

@ -25,6 +25,7 @@ namespace CSMTools
private: private:
const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings; const CSMWorld::IdCollection<ESM::GameSetting>& mGameSettings;
bool mIgnoreBaseRecords;
std::string varTypeToString(ESM::VarType); std::string varTypeToString(ESM::VarType);

@ -3,13 +3,19 @@
#include <set> #include <set>
#include <sstream> #include <sstream>
#include "../prefs/state.hpp"
CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals, CSMTools::JournalCheckStage::JournalCheckStage(const CSMWorld::IdCollection<ESM::Dialogue> &journals,
const CSMWorld::InfoCollection& journalInfos) const CSMWorld::InfoCollection& journalInfos)
: mJournals(journals), mJournalInfos(journalInfos) : mJournals(journals), mJournalInfos(journalInfos)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::JournalCheckStage::setup() int CSMTools::JournalCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mJournals.getSize(); return mJournals.getSize();
} }
@ -17,7 +23,8 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage); const CSMWorld::Record<ESM::Dialogue> &journalRecord = mJournals.getRecord(stage);
if (journalRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && journalRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || journalRecord.isDeleted())
return; return;
const ESM::Dialogue &journal = journalRecord.get(); const ESM::Dialogue &journal = journalRecord.get();
@ -43,6 +50,10 @@ void CSMTools::JournalCheckStage::perform(int stage, CSMDoc::Messages& messages)
statusNamedCount += 1; statusNamedCount += 1;
} }
// Skip "Base" records (setting!)
if (mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly)
continue;
if (journalInfo.mResponse.empty()) if (journalInfo.mResponse.empty())
{ {
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_JournalInfo, journalInfo.mId);

@ -28,6 +28,7 @@ namespace CSMTools
const CSMWorld::IdCollection<ESM::Dialogue>& mJournals; const CSMWorld::IdCollection<ESM::Dialogue>& mJournals;
const CSMWorld::InfoCollection& mJournalInfos; const CSMWorld::InfoCollection& mJournalInfos;
bool mIgnoreBaseRecords;
}; };
} }

@ -2,6 +2,8 @@
#include <components/misc/resourcehelpers.hpp> #include <components/misc/resourcehelpers.hpp>
#include "../prefs/state.hpp"
#include "../world/resources.hpp" #include "../world/resources.hpp"
#include "../world/data.hpp" #include "../world/data.hpp"
@ -77,16 +79,26 @@ CSMTools::MagicEffectCheckStage::MagicEffectCheckStage(const CSMWorld::IdCollect
mReferenceables(referenceables), mReferenceables(referenceables),
mIcons(icons), mIcons(icons),
mTextures(textures) mTextures(textures)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::MagicEffectCheckStage::setup() int CSMTools::MagicEffectCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mMagicEffects.getSize(); return mMagicEffects.getSize();
} }
void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages) void CSMTools::MagicEffectCheckStage::perform(int stage, CSMDoc::Messages &messages)
{ {
ESM::MagicEffect effect = mMagicEffects.getRecord(stage).get(); 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();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_MagicEffect, effect.mId);
if (effect.mData.mBaseCost < 0.0f) if (effect.mData.mBaseCost < 0.0f)

@ -24,6 +24,7 @@ namespace CSMTools
const CSMWorld::RefIdCollection &mReferenceables; const CSMWorld::RefIdCollection &mReferenceables;
const CSMWorld::Resources &mIcons; const CSMWorld::Resources &mIcons;
const CSMWorld::Resources &mTextures; const CSMWorld::Resources &mTextures;
bool mIgnoreBaseRecords;
private: private:
bool isTextureExists(const std::string &texture, bool isIcon) const; bool isTextureExists(const std::string &texture, bool isIcon) const;

@ -3,6 +3,8 @@
#include <sstream> #include <sstream>
#include <algorithm> #include <algorithm>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
#include "../world/idcollection.hpp" #include "../world/idcollection.hpp"
#include "../world/subcellcollection.hpp" #include "../world/subcellcollection.hpp"
@ -10,10 +12,14 @@
CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids) CSMTools::PathgridCheckStage::PathgridCheckStage (const CSMWorld::SubCellCollection<CSMWorld::Pathgrid>& pathgrids)
: mPathgrids (pathgrids) : mPathgrids (pathgrids)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::PathgridCheckStage::setup() int CSMTools::PathgridCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mPathgrids.getSize(); return mPathgrids.getSize();
} }
@ -21,7 +27,8 @@ void CSMTools::PathgridCheckStage::perform (int stage, CSMDoc::Messages& message
{ {
const CSMWorld::Record<CSMWorld::Pathgrid>& record = mPathgrids.getRecord (stage); const CSMWorld::Record<CSMWorld::Pathgrid>& record = mPathgrids.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const CSMWorld::Pathgrid& pathgrid = record.get(); const CSMWorld::Pathgrid& pathgrid = record.get();

@ -25,6 +25,7 @@ namespace CSMTools
{ {
const CSMWorld::SubCellCollection<CSMWorld::Pathgrid, const CSMWorld::SubCellCollection<CSMWorld::Pathgrid,
CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids; CSMWorld::IdAccessor<CSMWorld::Pathgrid> >& mPathgrids;
bool mIgnoreBaseRecords;
public: public:

@ -4,6 +4,8 @@
#include <components/esm/loadrace.hpp> #include <components/esm/loadrace.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& messages) void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& messages)
@ -15,6 +17,14 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
const ESM::Race& race = record.get(); 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); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Race, race.mId);
// test for empty name and description // test for empty name and description
@ -38,10 +48,6 @@ void CSMTools::RaceCheckStage::performPerRecord (int stage, CSMDoc::Messages& me
if (race.mData.mWeight.mFemale<0) if (race.mData.mWeight.mFemale<0)
messages.push_back (std::make_pair (id, "female " + race.mId + " has negative weight")); 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 /// \todo check data members that can't be edited in the table view
} }
@ -55,11 +61,15 @@ void CSMTools::RaceCheckStage::performFinal (CSMDoc::Messages& messages)
CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races) CSMTools::RaceCheckStage::RaceCheckStage (const CSMWorld::IdCollection<ESM::Race>& races)
: mRaces (races), mPlayable (false) : mRaces (races), mPlayable (false)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::RaceCheckStage::setup() int CSMTools::RaceCheckStage::setup()
{ {
mPlayable = false; mPlayable = false;
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mRaces.getSize()+1; return mRaces.getSize()+1;
} }

@ -14,6 +14,7 @@ namespace CSMTools
{ {
const CSMWorld::IdCollection<ESM::Race>& mRaces; const CSMWorld::IdCollection<ESM::Race>& mRaces;
bool mPlayable; bool mPlayable;
bool mIgnoreBaseRecords;
void performPerRecord (int stage, CSMDoc::Messages& messages); void performPerRecord (int stage, CSMDoc::Messages& messages);

@ -2,6 +2,8 @@
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
#include "../prefs/state.hpp"
#include "../world/record.hpp" #include "../world/record.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
@ -18,6 +20,7 @@ CSMTools::ReferenceableCheckStage::ReferenceableCheckStage(
mScripts(scripts), mScripts(scripts),
mPlayerPresent(false) mPlayerPresent(false)
{ {
mIgnoreBaseRecords = false;
} }
void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& messages) void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& messages)
@ -228,6 +231,8 @@ void CSMTools::ReferenceableCheckStage::perform (int stage, CSMDoc::Messages& me
int CSMTools::ReferenceableCheckStage::setup() int CSMTools::ReferenceableCheckStage::setup()
{ {
mPlayerPresent = false; mPlayerPresent = false;
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mReferencables.getSize() + 1; return mReferencables.getSize() + 1;
} }
@ -238,7 +243,8 @@ void CSMTools::ReferenceableCheckStage::bookCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Book& book = (dynamic_cast<const CSMWorld::Record<ESM::Book>& >(baseRecord)).get(); const ESM::Book& book = (dynamic_cast<const CSMWorld::Record<ESM::Book>& >(baseRecord)).get();
@ -257,7 +263,8 @@ void CSMTools::ReferenceableCheckStage::activatorCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Activator& activator = (dynamic_cast<const CSMWorld::Record<ESM::Activator>& >(baseRecord)).get(); const ESM::Activator& activator = (dynamic_cast<const CSMWorld::Record<ESM::Activator>& >(baseRecord)).get();
@ -278,7 +285,8 @@ void CSMTools::ReferenceableCheckStage::potionCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Potion& potion = (dynamic_cast<const CSMWorld::Record<ESM::Potion>& >(baseRecord)).get(); const ESM::Potion& potion = (dynamic_cast<const CSMWorld::Record<ESM::Potion>& >(baseRecord)).get();
@ -299,7 +307,8 @@ void CSMTools::ReferenceableCheckStage::apparatusCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Apparatus& apparatus = (dynamic_cast<const CSMWorld::Record<ESM::Apparatus>& >(baseRecord)).get(); const ESM::Apparatus& apparatus = (dynamic_cast<const CSMWorld::Record<ESM::Apparatus>& >(baseRecord)).get();
@ -320,7 +329,8 @@ void CSMTools::ReferenceableCheckStage::armorCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Armor& armor = (dynamic_cast<const CSMWorld::Record<ESM::Armor>& >(baseRecord)).get(); const ESM::Armor& armor = (dynamic_cast<const CSMWorld::Record<ESM::Armor>& >(baseRecord)).get();
@ -347,7 +357,8 @@ void CSMTools::ReferenceableCheckStage::clothingCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Clothing& clothing = (dynamic_cast<const CSMWorld::Record<ESM::Clothing>& >(baseRecord)).get(); const ESM::Clothing& clothing = (dynamic_cast<const CSMWorld::Record<ESM::Clothing>& >(baseRecord)).get();
@ -365,7 +376,8 @@ void CSMTools::ReferenceableCheckStage::containerCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Container& container = (dynamic_cast<const CSMWorld::Record<ESM::Container>& >(baseRecord)).get(); const ESM::Container& container = (dynamic_cast<const CSMWorld::Record<ESM::Container>& >(baseRecord)).get();
@ -397,7 +409,8 @@ void CSMTools::ReferenceableCheckStage::creatureCheck (
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get(); const ESM::Creature& creature = (dynamic_cast<const CSMWorld::Record<ESM::Creature>&>(baseRecord)).get();
@ -473,7 +486,8 @@ void CSMTools::ReferenceableCheckStage::doorCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Door& door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get(); const ESM::Door& door = (dynamic_cast<const CSMWorld::Record<ESM::Door>&>(baseRecord)).get();
@ -497,7 +511,8 @@ void CSMTools::ReferenceableCheckStage::ingredientCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Ingredient& ingredient = (dynamic_cast<const CSMWorld::Record<ESM::Ingredient>& >(baseRecord)).get(); const ESM::Ingredient& ingredient = (dynamic_cast<const CSMWorld::Record<ESM::Ingredient>& >(baseRecord)).get();
@ -516,10 +531,9 @@ void CSMTools::ReferenceableCheckStage::creaturesLevListCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
{ if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
}
const ESM::CreatureLevList& CreatureLevList = (dynamic_cast<const CSMWorld::Record<ESM::CreatureLevList>& >(baseRecord)).get(); 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 :/ CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_CreatureLevelledList, CreatureLevList.mId); //CreatureLevList but Type_CreatureLevelledList :/
@ -534,10 +548,9 @@ void CSMTools::ReferenceableCheckStage::itemLevelledListCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
{ if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
}
const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get(); const ESM::ItemLevList& ItemLevList = (dynamic_cast<const CSMWorld::Record<ESM::ItemLevList>& >(baseRecord)).get();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_ItemLevelledList, ItemLevList.mId);
@ -551,7 +564,8 @@ void CSMTools::ReferenceableCheckStage::lightCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get(); const ESM::Light& light = (dynamic_cast<const CSMWorld::Record<ESM::Light>& >(baseRecord)).get();
@ -574,7 +588,8 @@ void CSMTools::ReferenceableCheckStage::lockpickCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Lockpick& lockpick = (dynamic_cast<const CSMWorld::Record<ESM::Lockpick>& >(baseRecord)).get(); const ESM::Lockpick& lockpick = (dynamic_cast<const CSMWorld::Record<ESM::Lockpick>& >(baseRecord)).get();
@ -595,7 +610,8 @@ void CSMTools::ReferenceableCheckStage::miscCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Miscellaneous& miscellaneous = (dynamic_cast<const CSMWorld::Record<ESM::Miscellaneous>& >(baseRecord)).get(); const ESM::Miscellaneous& miscellaneous = (dynamic_cast<const CSMWorld::Record<ESM::Miscellaneous>& >(baseRecord)).get();
@ -619,6 +635,14 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get(); const ESM::NPC& npc = (dynamic_cast<const CSMWorld::Record<ESM::NPC>& >(baseRecord)).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId); CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Npc, npc.mId);
//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); short level(npc.mNpdt.mLevel);
char disposition(npc.mNpdt.mDisposition); char disposition(npc.mNpdt.mDisposition);
char reputation(npc.mNpdt.mReputation); char reputation(npc.mNpdt.mReputation);
@ -626,10 +650,6 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
//Don't know what unknown is for //Don't know what unknown is for
int gold(npc.mNpdt.mGold); int gold(npc.mNpdt.mGold);
//Detect if player is present
if (Misc::StringUtils::ciEqual(npc.mId, "player")) //Happy now, scrawl?
mPlayerPresent = true;
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
{ {
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
@ -728,7 +748,8 @@ void CSMTools::ReferenceableCheckStage::weaponCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get(); const ESM::Weapon& weapon = (dynamic_cast<const CSMWorld::Record<ESM::Weapon>& >(baseRecord)).get();
@ -808,7 +829,8 @@ void CSMTools::ReferenceableCheckStage::probeCheck(
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord(stage); const CSMWorld::RecordBase& baseRecord = records.getRecord(stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Probe& probe = (dynamic_cast<const CSMWorld::Record<ESM::Probe>& >(baseRecord)).get(); const ESM::Probe& probe = (dynamic_cast<const CSMWorld::Record<ESM::Probe>& >(baseRecord)).get();
@ -827,7 +849,8 @@ void CSMTools::ReferenceableCheckStage::repairCheck (
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get(); const ESM::Repair& repair = (dynamic_cast<const CSMWorld::Record<ESM::Repair>& >(baseRecord)).get();
@ -846,7 +869,8 @@ void CSMTools::ReferenceableCheckStage::staticCheck (
{ {
const CSMWorld::RecordBase& baseRecord = records.getRecord (stage); const CSMWorld::RecordBase& baseRecord = records.getRecord (stage);
if (baseRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && baseRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || baseRecord.isDeleted())
return; return;
const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get(); const ESM::Static& staticElement = (dynamic_cast<const CSMWorld::Record<ESM::Static>& >(baseRecord)).get();

@ -82,6 +82,7 @@ namespace CSMTools
const CSMWorld::IdCollection<ESM::Faction>& mFactions; const CSMWorld::IdCollection<ESM::Faction>& mFactions;
const CSMWorld::IdCollection<ESM::Script>& mScripts; const CSMWorld::IdCollection<ESM::Script>& mScripts;
bool mPlayerPresent; bool mPlayerPresent;
bool mIgnoreBaseRecords;
}; };
} }
#endif // REFERENCEABLECHECKSTAGE_H #endif // REFERENCEABLECHECKSTAGE_H

@ -1,5 +1,7 @@
#include "referencecheck.hpp" #include "referencecheck.hpp"
#include "../prefs/state.hpp"
CSMTools::ReferenceCheckStage::ReferenceCheckStage( CSMTools::ReferenceCheckStage::ReferenceCheckStage(
const CSMWorld::RefCollection& references, const CSMWorld::RefCollection& references,
const CSMWorld::RefIdCollection& referencables, const CSMWorld::RefIdCollection& referencables,
@ -12,13 +14,15 @@ CSMTools::ReferenceCheckStage::ReferenceCheckStage(
mCells(cells), mCells(cells),
mFactions(factions) mFactions(factions)
{ {
mIgnoreBaseRecords = false;
} }
void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages) void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &messages)
{ {
const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage); const CSMWorld::Record<CSMWorld::CellRef>& record = mReferences.getRecord(stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const CSMWorld::CellRef& cellRef = record.get(); const CSMWorld::CellRef& cellRef = record.get();
@ -100,5 +104,7 @@ void CSMTools::ReferenceCheckStage::perform(int stage, CSMDoc::Messages &message
int CSMTools::ReferenceCheckStage::setup() int CSMTools::ReferenceCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mReferences.getSize(); return mReferences.getSize();
} }

@ -23,6 +23,7 @@ namespace CSMTools
const CSMWorld::RefIdData& mDataSet; const CSMWorld::RefIdData& mDataSet;
const CSMWorld::IdCollection<CSMWorld::Cell>& mCells; const CSMWorld::IdCollection<CSMWorld::Cell>& mCells;
const CSMWorld::IdCollection<ESM::Faction>& mFactions; const CSMWorld::IdCollection<ESM::Faction>& mFactions;
bool mIgnoreBaseRecords;
}; };
} }

@ -5,14 +5,20 @@
#include <components/esm/loadregn.hpp> #include <components/esm/loadregn.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions) CSMTools::RegionCheckStage::RegionCheckStage (const CSMWorld::IdCollection<ESM::Region>& regions)
: mRegions (regions) : mRegions (regions)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::RegionCheckStage::setup() int CSMTools::RegionCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mRegions.getSize(); return mRegions.getSize();
} }
@ -20,7 +26,8 @@ void CSMTools::RegionCheckStage::perform (int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage); const CSMWorld::Record<ESM::Region>& record = mRegions.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Region& region = record.get(); const ESM::Region& region = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class RegionCheckStage : public CSMDoc::Stage class RegionCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Region>& mRegions; const CSMWorld::IdCollection<ESM::Region>& mRegions;
bool mIgnoreBaseRecords;
public: public:

@ -60,6 +60,8 @@ CSMTools::ScriptCheckStage::ScriptCheckStage (const CSMDoc::Document& document)
Compiler::registerExtensions (mExtensions); Compiler::registerExtensions (mExtensions);
mContext.setExtensions (&mExtensions); mContext.setExtensions (&mExtensions);
mIgnoreBaseRecords = false;
} }
int CSMTools::ScriptCheckStage::setup() int CSMTools::ScriptCheckStage::setup()
@ -78,17 +80,25 @@ int CSMTools::ScriptCheckStage::setup()
mId.clear(); mId.clear();
Compiler::ErrorHandler::reset(); Compiler::ErrorHandler::reset();
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mDocument.getData().getScripts().getSize(); return mDocument.getData().getScripts().getSize();
} }
void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages) 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); mId = mDocument.getData().getScripts().getId (stage);
if (mDocument.isBlacklisted ( if (mDocument.isBlacklisted (
CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId))) CSMWorld::UniversalId (CSMWorld::UniversalId::Type_Script, mId)))
return; return;
// Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return;
mMessages = &messages; mMessages = &messages;
switch (mWarningMode) switch (mWarningMode)
@ -100,10 +110,8 @@ void CSMTools::ScriptCheckStage::perform (int stage, CSMDoc::Messages& messages)
try try
{ {
const CSMWorld::Data& data = mDocument.getData(); mFile = record.get().mId;
std::istringstream input (record.get().mScriptText);
mFile = data.getScripts().getRecord (stage).get().mId;
std::istringstream input (data.getScripts().getRecord (stage).get().mScriptText);
Compiler::Scanner scanner (*this, input, mContext.getExtensions()); Compiler::Scanner scanner (*this, input, mContext.getExtensions());

@ -32,6 +32,7 @@ namespace CSMTools
std::string mFile; std::string mFile;
CSMDoc::Messages *mMessages; CSMDoc::Messages *mMessages;
WarningMode mWarningMode; WarningMode mWarningMode;
bool mIgnoreBaseRecords;
CSMDoc::Message::Severity getSeverity (Type type); CSMDoc::Message::Severity getSeverity (Type type);

@ -22,7 +22,8 @@ void CSMTools::Search::searchTextCell (const CSMWorld::IdTableBase *model,
int pos = 0; int pos = 0;
while ((pos = text.indexOf (search, pos, Qt::CaseInsensitive))!=-1) Qt::CaseSensitivity caseSensitivity = mCase ? Qt::CaseSensitive : Qt::CaseInsensitive;
while ((pos = text.indexOf (search, pos, caseSensitivity))!=-1)
{ {
std::ostringstream hint; std::ostringstream hint;
hint hint
@ -120,25 +121,26 @@ QString CSMTools::Search::flatten (const QString& text) const
return flat; return flat;
} }
CSMTools::Search::Search() : mType (Type_None), mValue (0), mIdColumn (0), mTypeColumn (0), CSMTools::Search::Search() : mType (Type_None), mValue (0), mCase (false), mIdColumn (0), mTypeColumn (0),
mPaddingBefore (10), mPaddingAfter (10) {} mPaddingBefore (10), mPaddingAfter (10) {}
CSMTools::Search::Search (Type type, const std::string& value) CSMTools::Search::Search (Type type, bool caseSensitive, const std::string& value)
: mType (type), mText (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) : mType (type), mText (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
{ {
if (type!=Type_Text && type!=Type_Id) if (type!=Type_Text && type!=Type_Id)
throw std::logic_error ("Invalid search parameter (string)"); throw std::logic_error ("Invalid search parameter (string)");
} }
CSMTools::Search::Search (Type type, const QRegExp& value) CSMTools::Search::Search (Type type, bool caseSensitive, const QRegExp& value)
: mType (type), mRegExp (value), mValue (0), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) : mType (type), mRegExp (value), mValue (0), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
{ {
mRegExp.setCaseSensitivity(mCase ? Qt::CaseSensitive : Qt::CaseInsensitive);
if (type!=Type_TextRegEx && type!=Type_IdRegEx) if (type!=Type_TextRegEx && type!=Type_IdRegEx)
throw std::logic_error ("Invalid search parameter (RegExp)"); throw std::logic_error ("Invalid search parameter (RegExp)");
} }
CSMTools::Search::Search (Type type, int value) CSMTools::Search::Search (Type type, bool caseSensitive, int value)
: mType (type), mValue (value), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10) : mType (type), mValue (value), mCase (caseSensitive), mIdColumn (0), mTypeColumn (0), mPaddingBefore (10), mPaddingAfter (10)
{ {
if (type!=Type_RecordState) if (type!=Type_RecordState)
throw std::logic_error ("invalid search parameter (int)"); throw std::logic_error ("invalid search parameter (int)");

@ -43,6 +43,7 @@ namespace CSMTools
std::string mText; std::string mText;
QRegExp mRegExp; QRegExp mRegExp;
int mValue; int mValue;
bool mCase;
std::set<int> mColumns; std::set<int> mColumns;
int mIdColumn; int mIdColumn;
int mTypeColumn; int mTypeColumn;
@ -67,11 +68,11 @@ namespace CSMTools
Search(); Search();
Search (Type type, const std::string& value); Search (Type type, bool caseSensitive, const std::string& value);
Search (Type type, const QRegExp& value); Search (Type type, bool caseSensitive, const QRegExp& value);
Search (Type type, int value); Search (Type type, bool caseSensitive, int value);
// Configure search for the specified model. // Configure search for the specified model.
void configure (const CSMWorld::IdTableBase *model); void configure (const CSMWorld::IdTableBase *model);

@ -4,14 +4,20 @@
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills) CSMTools::SkillCheckStage::SkillCheckStage (const CSMWorld::IdCollection<ESM::Skill>& skills)
: mSkills (skills) : mSkills (skills)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::SkillCheckStage::setup() int CSMTools::SkillCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mSkills.getSize(); return mSkills.getSize();
} }
@ -19,7 +25,8 @@ void CSMTools::SkillCheckStage::perform (int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage); const CSMWorld::Record<ESM::Skill>& record = mSkills.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Skill& skill = record.get(); const ESM::Skill& skill = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class SkillCheckStage : public CSMDoc::Stage class SkillCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Skill>& mSkills; const CSMWorld::IdCollection<ESM::Skill>& mSkills;
bool mIgnoreBaseRecords;
public: public:

@ -4,14 +4,20 @@
#include <components/esm/loadskil.hpp> #include <components/esm/loadskil.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds) CSMTools::SoundCheckStage::SoundCheckStage (const CSMWorld::IdCollection<ESM::Sound>& sounds)
: mSounds (sounds) : mSounds (sounds)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::SoundCheckStage::setup() int CSMTools::SoundCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mSounds.getSize(); return mSounds.getSize();
} }
@ -19,7 +25,8 @@ void CSMTools::SoundCheckStage::perform (int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage); const CSMWorld::Record<ESM::Sound>& record = mSounds.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Sound& sound = record.get(); const ESM::Sound& sound = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class SoundCheckStage : public CSMDoc::Stage class SoundCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Sound>& mSounds; const CSMWorld::IdCollection<ESM::Sound>& mSounds;
bool mIgnoreBaseRecords;
public: public:

@ -2,6 +2,8 @@
#include <sstream> #include <sstream>
#include "../prefs/state.hpp"
#include "../world/refiddata.hpp" #include "../world/refiddata.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
@ -11,20 +13,24 @@ CSMTools::SoundGenCheckStage::SoundGenCheckStage(const CSMWorld::IdCollection<ES
: mSoundGens(soundGens), : mSoundGens(soundGens),
mSounds(sounds), mSounds(sounds),
mReferenceables(referenceables) mReferenceables(referenceables)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::SoundGenCheckStage::setup() int CSMTools::SoundGenCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mSoundGens.getSize(); return mSoundGens.getSize();
} }
void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages) void CSMTools::SoundGenCheckStage::perform(int stage, CSMDoc::Messages &messages)
{ {
const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage); const CSMWorld::Record<ESM::SoundGenerator> &record = mSoundGens.getRecord(stage);
if (record.isDeleted())
{ // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
}
const ESM::SoundGenerator& soundGen = record.get(); const ESM::SoundGenerator& soundGen = record.get();
CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId); CSMWorld::UniversalId id(CSMWorld::UniversalId::Type_SoundGen, soundGen.mId);

@ -13,6 +13,7 @@ namespace CSMTools
const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens; const CSMWorld::IdCollection<ESM::SoundGenerator> &mSoundGens;
const CSMWorld::IdCollection<ESM::Sound> &mSounds; const CSMWorld::IdCollection<ESM::Sound> &mSounds;
const CSMWorld::RefIdCollection &mReferenceables; const CSMWorld::RefIdCollection &mReferenceables;
bool mIgnoreBaseRecords;
public: public:
SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens, SoundGenCheckStage(const CSMWorld::IdCollection<ESM::SoundGenerator> &soundGens,

@ -5,14 +5,20 @@
#include <components/esm/loadspel.hpp> #include <components/esm/loadspel.hpp>
#include "../prefs/state.hpp"
#include "../world/universalid.hpp" #include "../world/universalid.hpp"
CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells) CSMTools::SpellCheckStage::SpellCheckStage (const CSMWorld::IdCollection<ESM::Spell>& spells)
: mSpells (spells) : mSpells (spells)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::SpellCheckStage::setup() int CSMTools::SpellCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mSpells.getSize(); return mSpells.getSize();
} }
@ -20,7 +26,8 @@ void CSMTools::SpellCheckStage::perform (int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage); const CSMWorld::Record<ESM::Spell>& record = mSpells.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
const ESM::Spell& spell = record.get(); const ESM::Spell& spell = record.get();

@ -13,6 +13,7 @@ namespace CSMTools
class SpellCheckStage : public CSMDoc::Stage class SpellCheckStage : public CSMDoc::Stage
{ {
const CSMWorld::IdCollection<ESM::Spell>& mSpells; const CSMWorld::IdCollection<ESM::Spell>& mSpells;
bool mIgnoreBaseRecords;
public: public:

@ -1,18 +1,23 @@
#include "startscriptcheck.hpp" #include "startscriptcheck.hpp"
#include "../prefs/state.hpp"
#include <components/misc/stringops.hpp> #include <components/misc/stringops.hpp>
CSMTools::StartScriptCheckStage::StartScriptCheckStage ( CSMTools::StartScriptCheckStage::StartScriptCheckStage (
const CSMWorld::IdCollection<ESM::StartScript>& startScripts, const CSMWorld::IdCollection<ESM::StartScript>& startScripts,
const CSMWorld::IdCollection<ESM::Script>& scripts) const CSMWorld::IdCollection<ESM::Script>& scripts)
: mStartScripts (startScripts), mScripts (scripts) : mStartScripts (startScripts), mScripts (scripts)
{} {
mIgnoreBaseRecords = false;
}
void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages) void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messages)
{ {
const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage); const CSMWorld::Record<ESM::StartScript>& record = mStartScripts.getRecord (stage);
if (record.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && record.mState == CSMWorld::RecordBase::State_BaseOnly) || record.isDeleted())
return; return;
std::string scriptId = record.get().mId; std::string scriptId = record.get().mId;
@ -26,5 +31,7 @@ void CSMTools::StartScriptCheckStage::perform(int stage, CSMDoc::Messages& messa
int CSMTools::StartScriptCheckStage::setup() int CSMTools::StartScriptCheckStage::setup()
{ {
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mStartScripts.getSize(); return mStartScripts.getSize();
} }

@ -14,6 +14,7 @@ namespace CSMTools
{ {
const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts; const CSMWorld::IdCollection<ESM::StartScript>& mStartScripts;
const CSMWorld::IdCollection<ESM::Script>& mScripts; const CSMWorld::IdCollection<ESM::Script>& mScripts;
bool mIgnoreBaseRecords;
public: public:

@ -2,6 +2,8 @@
#include <sstream> #include <sstream>
#include "../prefs/state.hpp"
#include "../world/infoselectwrapper.hpp" #include "../world/infoselectwrapper.hpp"
CSMTools::TopicInfoCheckStage::TopicInfoCheckStage( CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
@ -29,7 +31,9 @@ CSMTools::TopicInfoCheckStage::TopicInfoCheckStage(
mTopics(topics), mTopics(topics),
mReferencables(referencables), mReferencables(referencables),
mSoundFiles(soundFiles) mSoundFiles(soundFiles)
{} {
mIgnoreBaseRecords = false;
}
int CSMTools::TopicInfoCheckStage::setup() int CSMTools::TopicInfoCheckStage::setup()
{ {
@ -67,6 +71,8 @@ int CSMTools::TopicInfoCheckStage::setup()
} }
} }
mIgnoreBaseRecords = CSMPrefs::get()["Reports"]["ignore-base-records"].isTrue();
return mTopicInfos.getSize(); return mTopicInfos.getSize();
} }
@ -74,7 +80,8 @@ void CSMTools::TopicInfoCheckStage::perform(int stage, CSMDoc::Messages& message
{ {
const CSMWorld::Record<CSMWorld::Info>& infoRecord = mTopicInfos.getRecord(stage); const CSMWorld::Record<CSMWorld::Info>& infoRecord = mTopicInfos.getRecord(stage);
if (infoRecord.isDeleted()) // Skip "Base" records (setting!) and "Deleted" records
if ((mIgnoreBaseRecords && infoRecord.mState == CSMWorld::RecordBase::State_BaseOnly) || infoRecord.isDeleted())
return; return;
const CSMWorld::Info& topicInfo = infoRecord.get(); const CSMWorld::Info& topicInfo = infoRecord.get();

@ -65,6 +65,8 @@ namespace CSMTools
std::set<std::string> mCellNames; std::set<std::string> mCellNames;
bool mIgnoreBaseRecords;
// These return false when not successful and write an error // These return false when not successful and write an error
bool verifyActor(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifyActor(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);
bool verifyCell(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages); bool verifyCell(const std::string& name, const CSMWorld::UniversalId& id, CSMDoc::Messages& messages);

@ -88,6 +88,7 @@ namespace CSMWorld
Display_UnsignedInteger8, Display_UnsignedInteger8,
Display_Integer, Display_Integer,
Display_Float, Display_Float,
Display_Double,
Display_Var, Display_Var,
Display_GmstVarType, Display_GmstVarType,
Display_GlobalVarType, Display_GlobalVarType,

@ -136,7 +136,7 @@ namespace CSMWorld
struct VarTypeColumn : public Column<ESXRecordT> struct VarTypeColumn : public Column<ESXRecordT>
{ {
VarTypeColumn (ColumnBase::Display display) VarTypeColumn (ColumnBase::Display display)
: Column<ESXRecordT> (Columns::ColumnId_ValueType, display) : Column<ESXRecordT> (Columns::ColumnId_ValueType, display, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh)
{} {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
@ -161,7 +161,7 @@ namespace CSMWorld
template<typename ESXRecordT> template<typename ESXRecordT>
struct VarValueColumn : public Column<ESXRecordT> struct VarValueColumn : public Column<ESXRecordT>
{ {
VarValueColumn() : Column<ESXRecordT> (Columns::ColumnId_Value, ColumnBase::Display_Var) {} VarValueColumn() : Column<ESXRecordT> (Columns::ColumnId_Value, ColumnBase::Display_Var, ColumnBase::Flag_Table | ColumnBase::Flag_Dialogue | ColumnBase::Flag_Dialogue_Refresh) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {
@ -1371,7 +1371,7 @@ namespace CSMWorld
RotColumn (ESM::Position ESXRecordT::* position, int index, bool door) RotColumn (ESM::Position ESXRecordT::* position, int index, bool door)
: Column<ESXRecordT> ( : Column<ESXRecordT> (
(door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index, (door ? Columns::ColumnId_DoorPositionXRot : Columns::ColumnId_PositionXRot)+index,
ColumnBase::Display_Float), mPosition (position), mIndex (index) {} ColumnBase::Display_Double), mPosition (position), mIndex (index) {}
virtual QVariant get (const Record<ESXRecordT>& record) const virtual QVariant get (const Record<ESXRecordT>& record) const
{ {

@ -84,15 +84,28 @@ bool CSMWorld::IdTable::setData (const QModelIndex &index, const QVariant &value
if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole) if (mIdCollection->getColumn (index.column()).isEditable() && role==Qt::EditRole)
{ {
mIdCollection->setData (index.row(), index.column(), value); mIdCollection->setData (index.row(), index.column(), value);
emit dataChanged(index, index);
// Modifying a value can also change the Modified status of a record.
int stateColumn = searchColumnIndex(Columns::ColumnId_Modification); int stateColumn = searchColumnIndex(Columns::ColumnId_Modification);
if (stateColumn != -1) if (stateColumn != -1)
{ {
if (index.column() == stateColumn)
{
// modifying the state column can modify other values. we need to tell
// views that the whole row has changed.
emit dataChanged(this->index(index.row(), 0),
this->index(index.row(), columnCount(index.parent())));
} else
{
emit dataChanged(index, index);
// Modifying a value can also change the Modified status of a record.
QModelIndex stateIndex = this->index(index.row(), stateColumn); QModelIndex stateIndex = this->index(index.row(), stateColumn);
emit dataChanged(stateIndex, stateIndex); emit dataChanged(stateIndex, stateIndex);
} }
} else
emit dataChanged(index, index);
return true; return true;
} }

@ -184,11 +184,11 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_PosZ, CSMWorld::ColumnBase::Display_Float));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_RotX, CSMWorld::ColumnBase::Display_Double));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_RotY, CSMWorld::ColumnBase::Display_Double));
mColumns.back().addColumn( mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Float)); new RefIdColumn (Columns::ColumnId_RotZ, CSMWorld::ColumnBase::Display_Double));
// Nested table // Nested table
mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList, mColumns.push_back(RefIdColumn (Columns::ColumnId_AiPackageList,

@ -101,15 +101,39 @@ void CSVDoc::View::setupFileMenu()
file->addAction(exit); file->addAction(exit);
} }
namespace
{
void updateUndoRedoAction(QAction *action, const std::string &settingsKey)
{
QKeySequence seq;
CSMPrefs::State::get().getShortcutManager().getSequence(settingsKey, seq);
action->setShortcut(seq);
}
}
void CSVDoc::View::undoActionChanged()
{
updateUndoRedoAction(mUndo, "document-edit-undo");
}
void CSVDoc::View::redoActionChanged()
{
updateUndoRedoAction(mRedo, "document-edit-redo");
}
void CSVDoc::View::setupEditMenu() void CSVDoc::View::setupEditMenu()
{ {
QMenu *edit = menuBar()->addMenu (tr ("Edit")); QMenu *edit = menuBar()->addMenu (tr ("Edit"));
mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo")); mUndo = mDocument->getUndoStack().createUndoAction (this, tr("Undo"));
setupShortcut("document-edit-undo", mUndo); setupShortcut("document-edit-undo", mUndo);
connect(mUndo, SIGNAL (changed ()), this, SLOT (undoActionChanged ()));
edit->addAction (mUndo); edit->addAction (mUndo);
mRedo= mDocument->getUndoStack().createRedoAction (this, tr("Redo")); mRedo = mDocument->getUndoStack().createRedoAction (this, tr("Redo"));
connect(mRedo, SIGNAL (changed ()), this, SLOT (redoActionChanged ()));
setupShortcut("document-edit-redo", mRedo); setupShortcut("document-edit-redo", mRedo);
edit->addAction (mRedo); edit->addAction (mRedo);
@ -622,6 +646,7 @@ void CSVDoc::View::addSubView (const CSMWorld::UniversalId& id, const std::strin
} }
assert(view); assert(view);
view->setParent(this); view->setParent(this);
view->setEditLock (mDocument->getState() & CSMDoc::State_Locked);
mSubViews.append(view); // only after assert mSubViews.append(view); // only after assert
int minWidth = windows["minimum-width"].toInt(); int minWidth = windows["minimum-width"].toInt();

@ -152,6 +152,10 @@ namespace CSVDoc
void settingChanged (const CSMPrefs::Setting *setting); void settingChanged (const CSMPrefs::Setting *setting);
void undoActionChanged();
void redoActionChanged();
void newView(); void newView();
void save(); void save();

@ -102,6 +102,14 @@ void CSVRender::Object::update()
if (recordType == CSMWorld::UniversalId::Type_Light) if (recordType == CSMWorld::UniversalId::Type_Light)
{ {
light = &dynamic_cast<const CSMWorld::Record<ESM::Light>& >(referenceables.getRecord(index)).get(); light = &dynamic_cast<const CSMWorld::Record<ESM::Light>& >(referenceables.getRecord(index)).get();
if (model.empty())
model = "marker_light.nif";
}
if (recordType == CSMWorld::UniversalId::Type_CreatureLevelledList)
{
if (model.empty())
model = "marker_creature.nif";
} }
if (model.empty()) if (model.empty())
@ -372,10 +380,10 @@ osg::ref_ptr<osg::Node> CSVRender::Object::makeRotateMarker (int axis)
indices[j] -= VertexCount; indices[j] -= VertexCount;
} }
size_t offset = i * IndicesPerSegment; size_t elementOffset = i * IndicesPerSegment;
for (size_t j = 0; j < IndicesPerSegment; ++j) for (size_t j = 0; j < IndicesPerSegment; ++j)
{ {
primitives->setElement(offset++, indices[IndexPattern[j]]); primitives->setElement(elementOffset++, indices[IndexPattern[j]]);
} }
} }

@ -151,6 +151,9 @@ CompositeViewer::CompositeViewer()
connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) ); connect( &mTimer, SIGNAL(timeout()), this, SLOT(update()) );
mTimer.start( 10 ); mTimer.start( 10 );
int frameRateLimit = CSMPrefs::get()["Rendering"]["framerate-limit"].toInt();
setRunMaxFrameRate(frameRateLimit);
} }
CompositeViewer &CompositeViewer::get() CompositeViewer &CompositeViewer::get()
@ -168,6 +171,12 @@ void CompositeViewer::update()
mSimulationTime += dt; mSimulationTime += dt;
frame(mSimulationTime); frame(mSimulationTime);
double minFrameTime = _runMaxFrameRate > 0.0 ? 1.0 / _runMaxFrameRate : 0.0;
if (dt < minFrameTime)
{
OpenThreads::Thread::microSleep(1000*1000*(minFrameTime-dt));
}
} }
// --------------------------------------------------- // ---------------------------------------------------
@ -376,6 +385,10 @@ void SceneWidget::settingChanged (const CSMPrefs::Setting *setting)
{ {
mOrbitCamControl->setConstRoll(setting->isTrue()); mOrbitCamControl->setConstRoll(setting->isTrue());
} }
else if (*setting=="Rendering/framerate-limit")
{
CompositeViewer::get().setRunMaxFrameRate(setting->toInt());
}
else if (*setting=="Rendering/camera-fov" || else if (*setting=="Rendering/camera-fov" ||
*setting=="Rendering/camera-ortho" || *setting=="Rendering/camera-ortho" ||
*setting=="Rendering/camera-ortho-size") *setting=="Rendering/camera-ortho-size")

@ -651,7 +651,6 @@ void CSVRender::WorldspaceWidget::mouseMoveEvent (QMouseEvent *event)
if (mDragMode == InteractionType_PrimaryEdit) if (mDragMode == InteractionType_PrimaryEdit)
{ {
EditMode& editMode = dynamic_cast<CSVRender::EditMode&> (*mEditMode->getCurrent());
editMode.drag (event->pos(), mDragX, mDragY, mDragFactor); // note: terraintexturemode only uses pos editMode.drag (event->pos(), mDragX, mDragY, mDragFactor); // note: terraintexturemode only uses pos
} }
} }

@ -35,7 +35,7 @@ void CSVTools::SearchBox::updateSearchButton()
} }
CSVTools::SearchBox::SearchBox (QWidget *parent) CSVTools::SearchBox::SearchBox (QWidget *parent)
: QWidget (parent), mSearch ("Search"), mSearchEnabled (false), mReplace ("Replace All") : QWidget (parent), mSearch (tr("Search")), mSearchEnabled (false), mReplace (tr("Replace All"))
{ {
mLayout = new QGridLayout (this); mLayout = new QGridLayout (this);
@ -48,29 +48,26 @@ CSVTools::SearchBox::SearchBox (QWidget *parent)
++iter) ++iter)
mRecordState.addItem (QString::fromUtf8 (iter->c_str())); mRecordState.addItem (QString::fromUtf8 (iter->c_str()));
mMode.addItem ("Text"); mMode.addItem (tr("Text"));
mMode.addItem ("Text (RegEx)"); mMode.addItem (tr("Text (RegEx)"));
mMode.addItem ("ID"); mMode.addItem (tr("ID"));
mMode.addItem ("ID (RegEx)"); mMode.addItem (tr("ID (RegEx)"));
mMode.addItem ("Record State"); mMode.addItem (tr("Record State"));
connect (&mMode, SIGNAL (activated (int)), this, SLOT (modeSelected (int)));
mLayout->addWidget (&mMode, 0, 0); mLayout->addWidget (&mMode, 0, 0);
mLayout->addWidget (&mSearch, 0, 3); connect (&mText, SIGNAL (textChanged (const QString&)), this, SLOT (textChanged (const QString&)));
connect (&mText, SIGNAL (returnPressed()), this, SLOT (startSearch()));
mInput.insertWidget (0, &mText); mInput.insertWidget (0, &mText);
mInput.insertWidget (1, &mRecordState);
mInput.insertWidget (1, &mRecordState);
mLayout->addWidget (&mInput, 0, 1); mLayout->addWidget (&mInput, 0, 1);
connect (&mMode, SIGNAL (activated (int)), this, SLOT (modeSelected (int))); mCaseSensitive.setText (tr ("Case"));
mLayout->addWidget (&mCaseSensitive, 0, 2);
connect (&mText, SIGNAL (textChanged (const QString&)),
this, SLOT (textChanged (const QString&)));
connect (&mSearch, SIGNAL (clicked (bool)), this, SLOT (startSearch (bool))); connect (&mSearch, SIGNAL (clicked (bool)), this, SLOT (startSearch (bool)));
mLayout->addWidget (&mSearch, 0, 3);
connect (&mText, SIGNAL (returnPressed()), this, SLOT (startSearch()));
// replace panel // replace panel
mReplaceInput.insertWidget (0, &mReplaceText); mReplaceInput.insertWidget (0, &mReplaceText);
@ -103,22 +100,23 @@ void CSVTools::SearchBox::setSearchMode (bool enabled)
CSMTools::Search CSVTools::SearchBox::getSearch() const CSMTools::Search CSVTools::SearchBox::getSearch() const
{ {
CSMTools::Search::Type type = static_cast<CSMTools::Search::Type> (mMode.currentIndex()); CSMTools::Search::Type type = static_cast<CSMTools::Search::Type> (mMode.currentIndex());
bool caseSensitive = mCaseSensitive.isChecked();
switch (type) switch (type)
{ {
case CSMTools::Search::Type_Text: case CSMTools::Search::Type_Text:
case CSMTools::Search::Type_Id: case CSMTools::Search::Type_Id:
return CSMTools::Search (type, std::string (mText.text().toUtf8().data())); return CSMTools::Search (type, caseSensitive, std::string (mText.text().toUtf8().data()));
case CSMTools::Search::Type_TextRegEx: case CSMTools::Search::Type_TextRegEx:
case CSMTools::Search::Type_IdRegEx: case CSMTools::Search::Type_IdRegEx:
return CSMTools::Search (type, QRegExp (mText.text().toUtf8().data(), Qt::CaseInsensitive)); return CSMTools::Search (type, caseSensitive, QRegExp (mText.text().toUtf8().data(), Qt::CaseInsensitive));
case CSMTools::Search::Type_RecordState: case CSMTools::Search::Type_RecordState:
return CSMTools::Search (type, mRecordState.currentIndex()); return CSMTools::Search (type, caseSensitive, mRecordState.currentIndex());
case CSMTools::Search::Type_None: case CSMTools::Search::Type_None:

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save