diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4b2b4dfdd..4805bff3b 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -103,6 +103,10 @@ To be able to merge PRs, commit priviledges are required. If you do not have the
The person to merge the PR may either use github's Merge button or if using the command line, use the ```--no-ff``` flag (so a merge commit is created, just like with Github's merge button) and include the pull request number in the commit description.
+Dealing with regressions
+========================
+
+The master branch should always be in a working state that is not worse than the previous release in any way. If a regression is found, the first and foremost priority should be to get the regression fixed quickly, either by reverting the change that caused it or finding a better solution. Please avoid leaving the project in the 'broken' state for an extensive period of time while proper solutions are found. If the solution takes more than a day or so then it is usually better to revert the offending change first and reapply it later when fixed.
Other resources
===============
diff --git a/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp b/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp
index b0ef4d951..7a568a705 100644
--- a/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp
+++ b/apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp
@@ -29,10 +29,14 @@ namespace mwmp
{
LOG_APPEND(Log::LOG_INFO, "- Moved to %s", player->cell.getDescription().c_str());
+ player->exchangeFullInfo = true;
+
player->forEachLoaded([this](Player *pl, Player *other) {
LOG_APPEND(Log::LOG_INFO, "- Started information exchange with %s", other->npc.mName.c_str());
+ other->exchangeFullInfo = true;
+
playerController->GetPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(other);
playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(other);
playerController->GetPacket(ID_PLAYER_POSITION)->setPlayer(other);
@@ -63,6 +67,8 @@ namespace mwmp
playerController->GetPacket(ID_PLAYER_ANIM_FLAGS)->Send(other->guid);
playerController->GetPacket(ID_PLAYER_SHAPESHIFT)->Send(other->guid);
+ other->exchangeFullInfo = false;
+
LOG_APPEND(Log::LOG_INFO, "- Finished information exchange with %s", other->npc.mName.c_str());
});
@@ -74,6 +80,8 @@ namespace mwmp
Networking::get().getState().getEventCtrl().Call(player.get());
LOG_APPEND(Log::LOG_INFO, "- Finished processing ID_PLAYER_CELL_CHANGE");
+
+ player->exchangeFullInfo = false;
}
else
LOG_APPEND(Log::LOG_INFO, "- Ignored because %s is dead", player->npc.mName.c_str());
diff --git a/apps/openmw/mwgui/quickkeysmenu.cpp b/apps/openmw/mwgui/quickkeysmenu.cpp
index 97c57ad65..82153da2b 100644
--- a/apps/openmw/mwgui/quickkeysmenu.cpp
+++ b/apps/openmw/mwgui/quickkeysmenu.cpp
@@ -404,7 +404,12 @@ namespace MWGui
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
MWMechanics::Spells& spells = stats.getSpells();
if (!spells.hasSpell(spellId))
+ {
+ const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get().find(spellId);
+ MWBase::Environment::get().getWindowManager()->messageBox (
+ "#{sQuickMenu5} " + spell->mName);
return;
+ }
store.setSelectedEnchantItem(store.end());
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp
index 901a158e1..730457205 100644
--- a/apps/openmw/mwmechanics/character.cpp
+++ b/apps/openmw/mwmechanics/character.cpp
@@ -302,7 +302,7 @@ void CharacterController::refreshHitRecoilAnims()
}
else if (recovery)
{
- std::string anim = isSwimming ? chooseRandomGroup("swimhit") : chooseRandomGroup("hit");
+ std::string anim = chooseRandomGroup("swimhit");
if (isSwimming && mAnimation->hasAnimation(anim))
{
mHitState = CharState_SwimHit;
diff --git a/apps/openmw/mwmp/LocalPlayer.cpp b/apps/openmw/mwmp/LocalPlayer.cpp
index 8d179c093..3afdac766 100644
--- a/apps/openmw/mwmp/LocalPlayer.cpp
+++ b/apps/openmw/mwmp/LocalPlayer.cpp
@@ -194,6 +194,9 @@ bool LocalPlayer::hasFinishedCharGen()
void LocalPlayer::updateStatsDynamic(bool forceUpdate)
{
+ if (statsDynamicIndexChanges.size() > 0)
+ statsDynamicIndexChanges.clear();
+
MWWorld::Ptr ptrPlayer = getPlayerPtr();
MWMechanics::CreatureStats *ptrCreatureStats = &ptrPlayer.getClass().getCreatureStats(ptrPlayer);
@@ -231,9 +234,9 @@ void LocalPlayer::updateStatsDynamic(bool forceUpdate)
magicka.writeState(creatureStats.mDynamic[1]);
fatigue.writeState(creatureStats.mDynamic[2]);
+ exchangeFullInfo = false;
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->Send();
- statsDynamicIndexChanges.clear();
}
}
@@ -243,6 +246,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
// overwritten by the werewolf ones
if (isWerewolf) return;
+ if (attributeIndexChanges.size() > 0)
+ attributeIndexChanges.clear();
+
MWWorld::Ptr ptrPlayer = getPlayerPtr();
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
@@ -261,9 +267,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
if (attributeIndexChanges.size() > 0)
{
+ exchangeFullInfo = false;
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->Send();
- attributeIndexChanges.clear();
}
}
@@ -273,6 +279,9 @@ void LocalPlayer::updateSkills(bool forceUpdate)
// overwritten by the werewolf ones
if (isWerewolf) return;
+ if (skillIndexChanges.size() > 0)
+ skillIndexChanges.clear();
+
MWWorld::Ptr ptrPlayer = getPlayerPtr();
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
@@ -291,9 +300,9 @@ void LocalPlayer::updateSkills(bool forceUpdate)
if (skillIndexChanges.size() > 0)
{
+ exchangeFullInfo = false;
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->Send();
- skillIndexChanges.clear();
}
}
@@ -432,6 +441,9 @@ void LocalPlayer::updateCell(bool forceUpdate)
void LocalPlayer::updateEquipment(bool forceUpdate)
{
+ if (equipmentIndexChanges.size() > 0)
+ equipmentIndexChanges.clear();
+
MWWorld::Ptr ptrPlayer = getPlayerPtr();
MWWorld::InventoryStore &invStore = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
@@ -442,7 +454,11 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
if (it != invStore.end())
{
- if (!::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipmentItems[slot].refId) || forceUpdate)
+ if (!::Misc::StringUtils::ciEqual(it->getCellRef().getRefId(), equipmentItems[slot].refId) ||
+ it->getCellRef().getCharge() != item.charge ||
+ it->getCellRef().getEnchantmentCharge() != item.enchantmentCharge ||
+ it->getRefData().getCount() != item.count ||
+ forceUpdate)
{
equipmentIndexChanges.push_back(slot);
item.refId = it->getCellRef().getRefId();
@@ -463,9 +479,9 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
if (!equipmentIndexChanges.empty())
{
+ exchangeFullInfo = false;
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->setPlayer(this);
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->Send();
- equipmentIndexChanges.clear();
}
}
diff --git a/apps/openmw/mwscript/transformationextensions.cpp b/apps/openmw/mwscript/transformationextensions.cpp
index 874cbe1b7..933331de6 100644
--- a/apps/openmw/mwscript/transformationextensions.cpp
+++ b/apps/openmw/mwscript/transformationextensions.cpp
@@ -574,6 +574,7 @@ namespace MWScript
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance);
+ MWBase::Environment::get().getWorld()->scaleObject(ptr, actor.getCellRef().getScale());
/*
Start of tes3mp addition
diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp
index a798d350c..db02bb482 100644
--- a/apps/openmw/mwsound/soundmanagerimp.cpp
+++ b/apps/openmw/mwsound/soundmanagerimp.cpp
@@ -393,32 +393,8 @@ namespace MWSound
void SoundManager::startRandomTitle()
{
- std::vector filelist;
+ const std::vector &filelist = mMusicFiles[mCurrentPlaylist];
auto &tracklist = mMusicToPlay[mCurrentPlaylist];
- if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end())
- {
- const std::map& index = mVFS->getIndex();
-
- std::string pattern = "Music/" + mCurrentPlaylist;
- mVFS->normalizeFilename(pattern);
-
- std::map::const_iterator found = index.lower_bound(pattern);
- while (found != index.end())
- {
- if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern)
- filelist.push_back(found->first);
- else
- break;
- ++found;
- }
-
- mMusicFiles[mCurrentPlaylist] = filelist;
- }
- else
- filelist = mMusicFiles[mCurrentPlaylist];
-
- if(filelist.empty())
- return;
// Do a Fisher-Yates shuffle
@@ -454,6 +430,33 @@ namespace MWSound
void SoundManager::playPlaylist(const std::string &playlist)
{
+ if (mCurrentPlaylist == playlist)
+ return;
+
+ if (mMusicFiles.find(playlist) == mMusicFiles.end())
+ {
+ std::vector filelist;
+ const std::map& index = mVFS->getIndex();
+
+ std::string pattern = "Music/" + playlist;
+ mVFS->normalizeFilename(pattern);
+
+ std::map::const_iterator found = index.lower_bound(pattern);
+ while (found != index.end())
+ {
+ if (found->first.size() >= pattern.size() && found->first.substr(0, pattern.size()) == pattern)
+ filelist.push_back(found->first);
+ else
+ break;
+ ++found;
+ }
+
+ mMusicFiles[playlist] = filelist;
+ }
+
+ if (mMusicFiles[playlist].empty())
+ return;
+
mCurrentPlaylist = playlist;
startRandomTitle();
}
diff --git a/components/fallback/fallback.cpp b/components/fallback/fallback.cpp
index ce6cba313..edc3f2678 100644
--- a/components/fallback/fallback.cpp
+++ b/components/fallback/fallback.cpp
@@ -1,7 +1,5 @@
#include "fallback.hpp"
-#include
-
#include
@@ -19,7 +17,6 @@ namespace Fallback
std::map::const_iterator it;
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
{
- std::cerr << "Warning: fallback value " << fall << " not found." << std::endl;
return "";
}
return it->second;
diff --git a/components/misc/resourcehelpers.cpp b/components/misc/resourcehelpers.cpp
index 5cf4378b8..f38387ff8 100644
--- a/components/misc/resourcehelpers.cpp
+++ b/components/misc/resourcehelpers.cpp
@@ -63,28 +63,16 @@ std::string Misc::ResourceHelpers::correctResourcePath(const std::string &topLev
std::string origExt = correctedPath;
- // since we know all (GOTY edition or less) textures end
- // in .dds, we change the extension
- bool changedToDds = changeExtensionToDds(correctedPath);
- if (vfs->exists(correctedPath))
+ if (vfs->exists(origExt)
+ || (changeExtensionToDds(correctedPath) && vfs->exists(correctedPath)))
return correctedPath;
- // if it turns out that the above wasn't true in all cases (not for vanilla, but maybe mods)
- // verify, and revert if false (this call succeeds quickly, but fails slowly)
- if (changedToDds && vfs->exists(origExt))
- return origExt;
// fall back to a resource in the top level directory if it exists
- std::string fallback = topLevelDirectory + "\\" + getBasename(correctedPath);
- if (vfs->exists(fallback))
+ std::string fallback = topLevelDirectory + "\\" + getBasename(origExt);
+ if (vfs->exists(fallback)
+ || (changeExtensionToDds(fallback) && vfs->exists(fallback)))
return fallback;
- if (changedToDds)
- {
- fallback = topLevelDirectory + "\\" + getBasename(origExt);
- if (vfs->exists(fallback))
- return fallback;
- }
-
return correctedPath;
}
diff --git a/components/misc/rng.cpp b/components/misc/rng.cpp
index df0fc687e..e402f0b79 100644
--- a/components/misc/rng.cpp
+++ b/components/misc/rng.cpp
@@ -1,28 +1,31 @@
#include "rng.hpp"
-#include
-#include
+
+#include
+#include
namespace Misc
{
+ std::mt19937 Rng::generator = std::mt19937();
+
void Rng::init()
{
- std::srand(static_cast(std::time(NULL)));
+ generator.seed(static_cast(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
}
float Rng::rollProbability()
{
- return static_cast(std::rand() / (static_cast(RAND_MAX)+1.0));
+ return std::uniform_real_distribution(0, 1 - std::numeric_limits::epsilon())(generator);
}
float Rng::rollClosedProbability()
{
- return static_cast(std::rand() / static_cast(RAND_MAX));
+ return std::uniform_real_distribution(0, 1)(generator);
}
int Rng::rollDice(int max)
{
- return static_cast((std::rand() / (static_cast(RAND_MAX)+1.0)) * (max));
+ return max > 0 ? std::uniform_int_distribution(0, max - 1)(generator) : 0;
}
}
diff --git a/components/misc/rng.hpp b/components/misc/rng.hpp
index 01fcdd763..ff56906d9 100644
--- a/components/misc/rng.hpp
+++ b/components/misc/rng.hpp
@@ -2,6 +2,7 @@
#define OPENMW_COMPONENTS_MISC_RNG_H
#include
+#include
namespace Misc
{
@@ -13,6 +14,9 @@ class Rng
{
public:
+ /// create a RNG
+ static std::mt19937 generator;
+
/// seed the RNG
static void init();
diff --git a/components/openmw-mp/Base/BasePlayer.hpp b/components/openmw-mp/Base/BasePlayer.hpp
index 159929e6d..03845791b 100644
--- a/components/openmw-mp/Base/BasePlayer.hpp
+++ b/components/openmw-mp/Base/BasePlayer.hpp
@@ -256,6 +256,7 @@ namespace mwmp
{
spellbookChanges.action = SpellbookChanges::Type::None;
isWerewolf = false;
+ exchangeFullInfo = false;
displayCreatureName = false;
resetStats = false;
enforcedLogLevel = -1;
@@ -286,6 +287,8 @@ namespace mwmp
// with the skill values themselves being stored in npcStats.mSkills
std::vector skillIndexChanges;
+ bool exchangeFullInfo;
+
SpellbookChanges spellbookChanges;
QuickKeyChanges quickKeyChanges;
JournalChanges journalChanges;
diff --git a/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp b/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp
index e99e69d03..391fcf10e 100644
--- a/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp
+++ b/components/openmw-mp/Packets/Player/PacketPlayerAttribute.cpp
@@ -13,23 +13,34 @@ void PacketPlayerAttribute::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
- uint32_t count;
- if (send)
- count = static_cast(player->attributeIndexChanges.size());
+ RW(player->exchangeFullInfo, send);
- RW(count, send);
-
- if (!send)
+ if (player->exchangeFullInfo)
{
- player->attributeIndexChanges.clear();
- player->attributeIndexChanges.resize(count);
+ RW(player->creatureStats.mAttributes, send);
+ RW(player->npcStats.mSkillIncrease, send);
}
-
- for (auto &&attributeIndex : player->attributeIndexChanges)
+ else
{
- RW(attributeIndex, send);
+ uint32_t count;
+
+ if (send)
+ count = static_cast(player->attributeIndexChanges.size());
+
+ RW(count, send);
+
+ if (!send)
+ {
+ player->attributeIndexChanges.clear();
+ player->attributeIndexChanges.resize(count);
+ }
+
+ for (auto &&attributeIndex : player->attributeIndexChanges)
+ {
+ RW(attributeIndex, send);
- RW(player->creatureStats.mAttributes[attributeIndex], send);
- RW(player->npcStats.mSkillIncrease[attributeIndex], send);
+ RW(player->creatureStats.mAttributes[attributeIndex], send);
+ RW(player->npcStats.mSkillIncrease[attributeIndex], send);
+ }
}
}
diff --git a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp
index 63d7a0b1f..c6f267935 100644
--- a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp
+++ b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.cpp
@@ -1,4 +1,5 @@
#include "PacketPlayerEquipment.hpp"
+
#include
using namespace mwmp;
@@ -12,25 +13,42 @@ void PacketPlayerEquipment::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
- uint32_t count;
- if (send)
- count = static_cast(player->equipmentIndexChanges.size());
-
- RW(count, send);
+ RW(player->exchangeFullInfo, send);
- if (!send)
+ if (player->exchangeFullInfo)
{
- player->equipmentIndexChanges.clear();
- player->equipmentIndexChanges.resize(count);
+ for (auto &&equipmentItem : player->equipmentItems)
+ {
+ ExchangeItemInformation(equipmentItem, send);
+ }
}
-
- for (auto &&equipmentIndex : player->equipmentIndexChanges)
+ else
{
- RW(equipmentIndex, send);
-
- RW(player->equipmentItems[equipmentIndex].refId, send);
- RW(player->equipmentItems[equipmentIndex].count, send);
- RW(player->equipmentItems[equipmentIndex].charge, send);
- RW(player->equipmentItems[equipmentIndex].enchantmentCharge, send);
+ uint32_t count;
+ if (send)
+ count = static_cast(player->equipmentIndexChanges.size());
+
+ RW(count, send);
+
+ if (!send)
+ {
+ player->equipmentIndexChanges.clear();
+ player->equipmentIndexChanges.resize(count);
+ }
+
+ for (auto &&equipmentIndex : player->equipmentIndexChanges)
+ {
+ RW(equipmentIndex, send);
+ ExchangeItemInformation(player->equipmentItems[equipmentIndex], send);
+ }
}
}
+
+void PacketPlayerEquipment::ExchangeItemInformation(Item &item, bool send)
+{
+ RW(item.refId, send);
+ RW(item.count, send);
+ RW(item.charge, send);
+ RW(item.enchantmentCharge, send);
+}
+
diff --git a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp
index 2d110e09d..04156f15d 100644
--- a/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp
+++ b/components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp
@@ -15,6 +15,7 @@ namespace mwmp
PacketPlayerEquipment(RakNet::RakPeerInterface *peer);
void Packet(RakNet::BitStream *bs, bool send) override;
+ void ExchangeItemInformation(Item &item, bool send);
};
}
diff --git a/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp b/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp
index 205098ef3..0978e1797 100644
--- a/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp
+++ b/components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp
@@ -13,23 +13,32 @@ PacketPlayerSkill::PacketPlayerSkill(RakNet::RakPeerInterface *peer) : PlayerPac
void PacketPlayerSkill::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
-
- uint32_t count;
- if (send)
- count = static_cast(player->skillIndexChanges.size());
+ RW(player->exchangeFullInfo, send);
- RW(count, send);
-
- if (!send)
+ if (player->exchangeFullInfo)
{
- player->skillIndexChanges.clear();
- player->skillIndexChanges.resize(count);
+ RW(player->npcStats.mSkills, send);
}
-
- for (auto &&skillId : player->skillIndexChanges)
+ else
{
- RW(skillId, send);
- RW(player->npcStats.mSkills[skillId], send);
+ uint32_t count;
+
+ if (send)
+ count = static_cast(player->skillIndexChanges.size());
+
+ RW(count, send);
+
+ if (!send)
+ {
+ player->skillIndexChanges.clear();
+ player->skillIndexChanges.resize(count);
+ }
+
+ for (auto &&skillId : player->skillIndexChanges)
+ {
+ RW(skillId, send);
+ RW(player->npcStats.mSkills[skillId], send);
+ }
}
}
diff --git a/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp b/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp
index 97b1fe589..b83a75e9c 100644
--- a/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp
+++ b/components/openmw-mp/Packets/Player/PacketPlayerStatsDynamic.cpp
@@ -1,4 +1,5 @@
#include "PacketPlayerStatsDynamic.hpp"
+
#include
using namespace mwmp;
@@ -12,22 +13,32 @@ void PacketPlayerStatsDynamic::Packet(RakNet::BitStream *bs, bool send)
{
PlayerPacket::Packet(bs, send);
- uint32_t count;
- if (send)
- count = static_cast(player->statsDynamicIndexChanges.size());
-
- RW(count, send);
+ RW(player->exchangeFullInfo, send);
- if (!send)
+ if (player->exchangeFullInfo)
{
- player->statsDynamicIndexChanges.clear();
- player->statsDynamicIndexChanges.resize(count);
+ RW(player->creatureStats.mDynamic, send);
}
-
- for (auto &&statsDynamicIndex : player->statsDynamicIndexChanges)
+ else
{
- RW(statsDynamicIndex, send);
+ uint32_t count;
+
+ if (send)
+ count = static_cast(player->statsDynamicIndexChanges.size());
+
+ RW(count, send);
+
+ if (!send)
+ {
+ player->statsDynamicIndexChanges.clear();
+ player->statsDynamicIndexChanges.resize(count);
+ }
+
+ for (auto &&statsDynamicIndex : player->statsDynamicIndexChanges)
+ {
+ RW(statsDynamicIndex, send);
- RW(player->creatureStats.mDynamic[statsDynamicIndex], send);
+ RW(player->creatureStats.mDynamic[statsDynamicIndex], send);
+ }
}
}
diff --git a/files/openmw.appdata.xml b/files/openmw.appdata.xml
index 1503c2fd8..e66fb2978 100644
--- a/files/openmw.appdata.xml
+++ b/files/openmw.appdata.xml
@@ -3,10 +3,10 @@
Copyright 2015 Alexandre Moine
Copyright 2017 Bret Curtis
-->
-
+
org.openmw.desktop
CC0-1.0
- GPL-3.0 and MIT
+ GPL-3.0 and MIT
OpenMW
Unofficial open source engine re-implementation of the game Morrowind
@@ -20,7 +20,6 @@ Copyright 2017 Bret Curtis
You will still need the original game data to play OpenMW.
-
https://wiki.openmw.org/images/b/b2/Openmw_0.11.1_launcher_1.png
@@ -34,7 +33,18 @@ Copyright 2017 Bret Curtis
https://wiki.openmw.org/images/5/5b/Screenshot_Vivec_seen_from_Ebonheart_0.35.png
Vivec seen from Ebonheart on OpenMW
+
+ http://wiki.openmw.org/images/a/a3/0.40_Screenshot-Balmora_3.png
+ Balmora at morning on OpenMW
+
+
+ Game
+ RolePlaying
+
+
+
+
https://openmw.org
https://bugs.openmw.org/
https://openmw.org/faq/