mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-03-03 21:19:40 +00:00
Merge pull request #413 from TES3MP/0.6.3 while resolving conflicts
Conflicts: apps/openmw-mp/processors/player/ProcessorPlayerCellChange.hpp components/openmw-mp/Base/BasePlayer.hpp components/openmw-mp/Packets/Player/PacketPlayerEquipment.hpp components/openmw-mp/Packets/Player/PacketPlayerSkill.cpp
This commit is contained in:
commit
502751cae0
18 changed files with 205 additions and 113 deletions
|
@ -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.
|
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
|
Other resources
|
||||||
===============
|
===============
|
||||||
|
|
|
@ -29,10 +29,14 @@ namespace mwmp
|
||||||
{
|
{
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Moved to %s", player->cell.getDescription().c_str());
|
LOG_APPEND(Log::LOG_INFO, "- Moved to %s", player->cell.getDescription().c_str());
|
||||||
|
|
||||||
|
player->exchangeFullInfo = true;
|
||||||
|
|
||||||
player->forEachLoaded([this](Player *pl, Player *other) {
|
player->forEachLoaded([this](Player *pl, Player *other) {
|
||||||
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Started information exchange with %s", other->npc.mName.c_str());
|
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_STATS_DYNAMIC)->setPlayer(other);
|
||||||
playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(other);
|
playerController->GetPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(other);
|
||||||
playerController->GetPacket(ID_PLAYER_POSITION)->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_ANIM_FLAGS)->Send(other->guid);
|
||||||
playerController->GetPacket(ID_PLAYER_SHAPESHIFT)->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());
|
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<CoreEvent::ON_PLAYER_CELLCHANGE>(player.get());
|
Networking::get().getState().getEventCtrl().Call<CoreEvent::ON_PLAYER_CELLCHANGE>(player.get());
|
||||||
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Finished processing ID_PLAYER_CELL_CHANGE");
|
LOG_APPEND(Log::LOG_INFO, "- Finished processing ID_PLAYER_CELL_CHANGE");
|
||||||
|
|
||||||
|
player->exchangeFullInfo = false;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Ignored because %s is dead", player->npc.mName.c_str());
|
LOG_APPEND(Log::LOG_INFO, "- Ignored because %s is dead", player->npc.mName.c_str());
|
||||||
|
|
|
@ -404,7 +404,12 @@ namespace MWGui
|
||||||
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
MWMechanics::CreatureStats& stats = player.getClass().getCreatureStats(player);
|
||||||
MWMechanics::Spells& spells = stats.getSpells();
|
MWMechanics::Spells& spells = stats.getSpells();
|
||||||
if (!spells.hasSpell(spellId))
|
if (!spells.hasSpell(spellId))
|
||||||
|
{
|
||||||
|
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().find(spellId);
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox (
|
||||||
|
"#{sQuickMenu5} " + spell->mName);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
store.setSelectedEnchantItem(store.end());
|
store.setSelectedEnchantItem(store.end());
|
||||||
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
MWBase::Environment::get().getWindowManager()->setSelectedSpell(spellId, int(MWMechanics::getSpellSuccessChance(spellId, player)));
|
||||||
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
MWBase::Environment::get().getWorld()->getPlayer().setDrawState(MWMechanics::DrawState_Spell);
|
||||||
|
|
|
@ -302,7 +302,7 @@ void CharacterController::refreshHitRecoilAnims()
|
||||||
}
|
}
|
||||||
else if (recovery)
|
else if (recovery)
|
||||||
{
|
{
|
||||||
std::string anim = isSwimming ? chooseRandomGroup("swimhit") : chooseRandomGroup("hit");
|
std::string anim = chooseRandomGroup("swimhit");
|
||||||
if (isSwimming && mAnimation->hasAnimation(anim))
|
if (isSwimming && mAnimation->hasAnimation(anim))
|
||||||
{
|
{
|
||||||
mHitState = CharState_SwimHit;
|
mHitState = CharState_SwimHit;
|
||||||
|
|
|
@ -194,6 +194,9 @@ bool LocalPlayer::hasFinishedCharGen()
|
||||||
|
|
||||||
void LocalPlayer::updateStatsDynamic(bool forceUpdate)
|
void LocalPlayer::updateStatsDynamic(bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
if (statsDynamicIndexChanges.size() > 0)
|
||||||
|
statsDynamicIndexChanges.clear();
|
||||||
|
|
||||||
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
||||||
|
|
||||||
MWMechanics::CreatureStats *ptrCreatureStats = &ptrPlayer.getClass().getCreatureStats(ptrPlayer);
|
MWMechanics::CreatureStats *ptrCreatureStats = &ptrPlayer.getClass().getCreatureStats(ptrPlayer);
|
||||||
|
@ -231,9 +234,9 @@ void LocalPlayer::updateStatsDynamic(bool forceUpdate)
|
||||||
magicka.writeState(creatureStats.mDynamic[1]);
|
magicka.writeState(creatureStats.mDynamic[1]);
|
||||||
fatigue.writeState(creatureStats.mDynamic[2]);
|
fatigue.writeState(creatureStats.mDynamic[2]);
|
||||||
|
|
||||||
|
exchangeFullInfo = false;
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(this);
|
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->setPlayer(this);
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->Send();
|
getNetworking()->getPlayerPacket(ID_PLAYER_STATS_DYNAMIC)->Send();
|
||||||
statsDynamicIndexChanges.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +246,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
|
||||||
// overwritten by the werewolf ones
|
// overwritten by the werewolf ones
|
||||||
if (isWerewolf) return;
|
if (isWerewolf) return;
|
||||||
|
|
||||||
|
if (attributeIndexChanges.size() > 0)
|
||||||
|
attributeIndexChanges.clear();
|
||||||
|
|
||||||
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
||||||
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
|
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
|
||||||
|
|
||||||
|
@ -261,9 +267,9 @@ void LocalPlayer::updateAttributes(bool forceUpdate)
|
||||||
|
|
||||||
if (attributeIndexChanges.size() > 0)
|
if (attributeIndexChanges.size() > 0)
|
||||||
{
|
{
|
||||||
|
exchangeFullInfo = false;
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(this);
|
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->setPlayer(this);
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->Send();
|
getNetworking()->getPlayerPacket(ID_PLAYER_ATTRIBUTE)->Send();
|
||||||
attributeIndexChanges.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,6 +279,9 @@ void LocalPlayer::updateSkills(bool forceUpdate)
|
||||||
// overwritten by the werewolf ones
|
// overwritten by the werewolf ones
|
||||||
if (isWerewolf) return;
|
if (isWerewolf) return;
|
||||||
|
|
||||||
|
if (skillIndexChanges.size() > 0)
|
||||||
|
skillIndexChanges.clear();
|
||||||
|
|
||||||
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
||||||
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
|
const MWMechanics::NpcStats &ptrNpcStats = ptrPlayer.getClass().getNpcStats(ptrPlayer);
|
||||||
|
|
||||||
|
@ -291,9 +300,9 @@ void LocalPlayer::updateSkills(bool forceUpdate)
|
||||||
|
|
||||||
if (skillIndexChanges.size() > 0)
|
if (skillIndexChanges.size() > 0)
|
||||||
{
|
{
|
||||||
|
exchangeFullInfo = false;
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->setPlayer(this);
|
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->setPlayer(this);
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->Send();
|
getNetworking()->getPlayerPacket(ID_PLAYER_SKILL)->Send();
|
||||||
skillIndexChanges.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,6 +441,9 @@ void LocalPlayer::updateCell(bool forceUpdate)
|
||||||
|
|
||||||
void LocalPlayer::updateEquipment(bool forceUpdate)
|
void LocalPlayer::updateEquipment(bool forceUpdate)
|
||||||
{
|
{
|
||||||
|
if (equipmentIndexChanges.size() > 0)
|
||||||
|
equipmentIndexChanges.clear();
|
||||||
|
|
||||||
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
||||||
|
|
||||||
MWWorld::InventoryStore &invStore = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
|
MWWorld::InventoryStore &invStore = ptrPlayer.getClass().getInventoryStore(ptrPlayer);
|
||||||
|
@ -442,7 +454,11 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
|
||||||
|
|
||||||
if (it != invStore.end())
|
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);
|
equipmentIndexChanges.push_back(slot);
|
||||||
item.refId = it->getCellRef().getRefId();
|
item.refId = it->getCellRef().getRefId();
|
||||||
|
@ -463,9 +479,9 @@ void LocalPlayer::updateEquipment(bool forceUpdate)
|
||||||
|
|
||||||
if (!equipmentIndexChanges.empty())
|
if (!equipmentIndexChanges.empty())
|
||||||
{
|
{
|
||||||
|
exchangeFullInfo = false;
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->setPlayer(this);
|
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->setPlayer(this);
|
||||||
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->Send();
|
getNetworking()->getPlayerPacket(ID_PLAYER_EQUIPMENT)->Send();
|
||||||
equipmentIndexChanges.clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -574,6 +574,7 @@ namespace MWScript
|
||||||
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
|
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);
|
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
|
Start of tes3mp addition
|
||||||
|
|
|
@ -393,32 +393,8 @@ namespace MWSound
|
||||||
|
|
||||||
void SoundManager::startRandomTitle()
|
void SoundManager::startRandomTitle()
|
||||||
{
|
{
|
||||||
std::vector<std::string> filelist;
|
const std::vector<std::string> &filelist = mMusicFiles[mCurrentPlaylist];
|
||||||
auto &tracklist = mMusicToPlay[mCurrentPlaylist];
|
auto &tracklist = mMusicToPlay[mCurrentPlaylist];
|
||||||
if (mMusicFiles.find(mCurrentPlaylist) == mMusicFiles.end())
|
|
||||||
{
|
|
||||||
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
|
||||||
|
|
||||||
std::string pattern = "Music/" + mCurrentPlaylist;
|
|
||||||
mVFS->normalizeFilename(pattern);
|
|
||||||
|
|
||||||
std::map<std::string, VFS::File*>::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
|
// Do a Fisher-Yates shuffle
|
||||||
|
|
||||||
|
@ -454,6 +430,33 @@ namespace MWSound
|
||||||
|
|
||||||
void SoundManager::playPlaylist(const std::string &playlist)
|
void SoundManager::playPlaylist(const std::string &playlist)
|
||||||
{
|
{
|
||||||
|
if (mCurrentPlaylist == playlist)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (mMusicFiles.find(playlist) == mMusicFiles.end())
|
||||||
|
{
|
||||||
|
std::vector<std::string> filelist;
|
||||||
|
const std::map<std::string, VFS::File*>& index = mVFS->getIndex();
|
||||||
|
|
||||||
|
std::string pattern = "Music/" + playlist;
|
||||||
|
mVFS->normalizeFilename(pattern);
|
||||||
|
|
||||||
|
std::map<std::string, VFS::File*>::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;
|
mCurrentPlaylist = playlist;
|
||||||
startRandomTitle();
|
startRandomTitle();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
#include "fallback.hpp"
|
#include "fallback.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +17,6 @@ namespace Fallback
|
||||||
std::map<std::string,std::string>::const_iterator it;
|
std::map<std::string,std::string>::const_iterator it;
|
||||||
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
|
if((it = mFallbackMap.find(fall)) == mFallbackMap.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Warning: fallback value " << fall << " not found." << std::endl;
|
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
return it->second;
|
return it->second;
|
||||||
|
|
|
@ -63,28 +63,16 @@ std::string Misc::ResourceHelpers::correctResourcePath(const std::string &topLev
|
||||||
|
|
||||||
std::string origExt = correctedPath;
|
std::string origExt = correctedPath;
|
||||||
|
|
||||||
// since we know all (GOTY edition or less) textures end
|
if (vfs->exists(origExt)
|
||||||
// in .dds, we change the extension
|
|| (changeExtensionToDds(correctedPath) && vfs->exists(correctedPath)))
|
||||||
bool changedToDds = changeExtensionToDds(correctedPath);
|
|
||||||
if (vfs->exists(correctedPath))
|
|
||||||
return 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
|
// fall back to a resource in the top level directory if it exists
|
||||||
std::string fallback = topLevelDirectory + "\\" + getBasename(correctedPath);
|
std::string fallback = topLevelDirectory + "\\" + getBasename(origExt);
|
||||||
if (vfs->exists(fallback))
|
if (vfs->exists(fallback)
|
||||||
|
|| (changeExtensionToDds(fallback) && vfs->exists(fallback)))
|
||||||
return fallback;
|
return fallback;
|
||||||
|
|
||||||
if (changedToDds)
|
|
||||||
{
|
|
||||||
fallback = topLevelDirectory + "\\" + getBasename(origExt);
|
|
||||||
if (vfs->exists(fallback))
|
|
||||||
return fallback;
|
|
||||||
}
|
|
||||||
|
|
||||||
return correctedPath;
|
return correctedPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,28 +1,31 @@
|
||||||
#include "rng.hpp"
|
#include "rng.hpp"
|
||||||
#include <cstdlib>
|
|
||||||
#include <ctime>
|
#include <chrono>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
|
||||||
|
std::mt19937 Rng::generator = std::mt19937();
|
||||||
|
|
||||||
void Rng::init()
|
void Rng::init()
|
||||||
{
|
{
|
||||||
std::srand(static_cast<unsigned int>(std::time(NULL)));
|
generator.seed(static_cast<unsigned int>(std::chrono::high_resolution_clock::now().time_since_epoch().count()));
|
||||||
}
|
}
|
||||||
|
|
||||||
float Rng::rollProbability()
|
float Rng::rollProbability()
|
||||||
{
|
{
|
||||||
return static_cast<float>(std::rand() / (static_cast<double>(RAND_MAX)+1.0));
|
return std::uniform_real_distribution<float>(0, 1 - std::numeric_limits<float>::epsilon())(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
float Rng::rollClosedProbability()
|
float Rng::rollClosedProbability()
|
||||||
{
|
{
|
||||||
return static_cast<float>(std::rand() / static_cast<double>(RAND_MAX));
|
return std::uniform_real_distribution<float>(0, 1)(generator);
|
||||||
}
|
}
|
||||||
|
|
||||||
int Rng::rollDice(int max)
|
int Rng::rollDice(int max)
|
||||||
{
|
{
|
||||||
return static_cast<int>((std::rand() / (static_cast<double>(RAND_MAX)+1.0)) * (max));
|
return max > 0 ? std::uniform_int_distribution<int>(0, max - 1)(generator) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define OPENMW_COMPONENTS_MISC_RNG_H
|
#define OPENMW_COMPONENTS_MISC_RNG_H
|
||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace Misc
|
namespace Misc
|
||||||
{
|
{
|
||||||
|
@ -13,6 +14,9 @@ class Rng
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/// create a RNG
|
||||||
|
static std::mt19937 generator;
|
||||||
|
|
||||||
/// seed the RNG
|
/// seed the RNG
|
||||||
static void init();
|
static void init();
|
||||||
|
|
||||||
|
|
|
@ -256,6 +256,7 @@ namespace mwmp
|
||||||
{
|
{
|
||||||
spellbookChanges.action = SpellbookChanges::Type::None;
|
spellbookChanges.action = SpellbookChanges::Type::None;
|
||||||
isWerewolf = false;
|
isWerewolf = false;
|
||||||
|
exchangeFullInfo = false;
|
||||||
displayCreatureName = false;
|
displayCreatureName = false;
|
||||||
resetStats = false;
|
resetStats = false;
|
||||||
enforcedLogLevel = -1;
|
enforcedLogLevel = -1;
|
||||||
|
@ -286,6 +287,8 @@ namespace mwmp
|
||||||
// with the skill values themselves being stored in npcStats.mSkills
|
// with the skill values themselves being stored in npcStats.mSkills
|
||||||
std::vector<int> skillIndexChanges;
|
std::vector<int> skillIndexChanges;
|
||||||
|
|
||||||
|
bool exchangeFullInfo;
|
||||||
|
|
||||||
SpellbookChanges spellbookChanges;
|
SpellbookChanges spellbookChanges;
|
||||||
QuickKeyChanges quickKeyChanges;
|
QuickKeyChanges quickKeyChanges;
|
||||||
JournalChanges journalChanges;
|
JournalChanges journalChanges;
|
||||||
|
|
|
@ -13,23 +13,34 @@ void PacketPlayerAttribute::Packet(RakNet::BitStream *bs, bool send)
|
||||||
{
|
{
|
||||||
PlayerPacket::Packet(bs, send);
|
PlayerPacket::Packet(bs, send);
|
||||||
|
|
||||||
uint32_t count;
|
RW(player->exchangeFullInfo, send);
|
||||||
if (send)
|
|
||||||
count = static_cast<uint32_t>(player->attributeIndexChanges.size());
|
|
||||||
|
|
||||||
RW(count, send);
|
if (player->exchangeFullInfo)
|
||||||
|
|
||||||
if (!send)
|
|
||||||
{
|
{
|
||||||
player->attributeIndexChanges.clear();
|
RW(player->creatureStats.mAttributes, send);
|
||||||
player->attributeIndexChanges.resize(count);
|
RW(player->npcStats.mSkillIncrease, send);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (auto &&attributeIndex : player->attributeIndexChanges)
|
|
||||||
{
|
{
|
||||||
RW(attributeIndex, send);
|
uint32_t count;
|
||||||
|
|
||||||
RW(player->creatureStats.mAttributes[attributeIndex], send);
|
if (send)
|
||||||
RW(player->npcStats.mSkillIncrease[attributeIndex], send);
|
count = static_cast<uint32_t>(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "PacketPlayerEquipment.hpp"
|
#include "PacketPlayerEquipment.hpp"
|
||||||
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
using namespace mwmp;
|
using namespace mwmp;
|
||||||
|
@ -12,25 +13,42 @@ void PacketPlayerEquipment::Packet(RakNet::BitStream *bs, bool send)
|
||||||
{
|
{
|
||||||
PlayerPacket::Packet(bs, send);
|
PlayerPacket::Packet(bs, send);
|
||||||
|
|
||||||
uint32_t count;
|
RW(player->exchangeFullInfo, send);
|
||||||
if (send)
|
|
||||||
count = static_cast<uint32_t>(player->equipmentIndexChanges.size());
|
|
||||||
|
|
||||||
RW(count, send);
|
if (player->exchangeFullInfo)
|
||||||
|
|
||||||
if (!send)
|
|
||||||
{
|
{
|
||||||
player->equipmentIndexChanges.clear();
|
for (auto &&equipmentItem : player->equipmentItems)
|
||||||
player->equipmentIndexChanges.resize(count);
|
{
|
||||||
|
ExchangeItemInformation(equipmentItem, send);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (auto &&equipmentIndex : player->equipmentIndexChanges)
|
|
||||||
{
|
{
|
||||||
RW(equipmentIndex, send);
|
uint32_t count;
|
||||||
|
if (send)
|
||||||
|
count = static_cast<uint32_t>(player->equipmentIndexChanges.size());
|
||||||
|
|
||||||
RW(player->equipmentItems[equipmentIndex].refId, send);
|
RW(count, send);
|
||||||
RW(player->equipmentItems[equipmentIndex].count, send);
|
|
||||||
RW(player->equipmentItems[equipmentIndex].charge, send);
|
if (!send)
|
||||||
RW(player->equipmentItems[equipmentIndex].enchantmentCharge, 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace mwmp
|
||||||
PacketPlayerEquipment(RakNet::RakPeerInterface *peer);
|
PacketPlayerEquipment(RakNet::RakPeerInterface *peer);
|
||||||
|
|
||||||
void Packet(RakNet::BitStream *bs, bool send) override;
|
void Packet(RakNet::BitStream *bs, bool send) override;
|
||||||
|
void ExchangeItemInformation(Item &item, bool send);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,23 +13,32 @@ PacketPlayerSkill::PacketPlayerSkill(RakNet::RakPeerInterface *peer) : PlayerPac
|
||||||
void PacketPlayerSkill::Packet(RakNet::BitStream *bs, bool send)
|
void PacketPlayerSkill::Packet(RakNet::BitStream *bs, bool send)
|
||||||
{
|
{
|
||||||
PlayerPacket::Packet(bs, send);
|
PlayerPacket::Packet(bs, send);
|
||||||
|
|
||||||
uint32_t count;
|
|
||||||
|
|
||||||
if (send)
|
RW(player->exchangeFullInfo, send);
|
||||||
count = static_cast<uint32_t>(player->skillIndexChanges.size());
|
|
||||||
|
|
||||||
RW(count, send);
|
if (player->exchangeFullInfo)
|
||||||
|
|
||||||
if (!send)
|
|
||||||
{
|
{
|
||||||
player->skillIndexChanges.clear();
|
RW(player->npcStats.mSkills, send);
|
||||||
player->skillIndexChanges.resize(count);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (auto &&skillId : player->skillIndexChanges)
|
|
||||||
{
|
{
|
||||||
RW(skillId, send);
|
uint32_t count;
|
||||||
RW(player->npcStats.mSkills[skillId], send);
|
|
||||||
|
if (send)
|
||||||
|
count = static_cast<uint32_t>(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include "PacketPlayerStatsDynamic.hpp"
|
#include "PacketPlayerStatsDynamic.hpp"
|
||||||
|
|
||||||
#include <components/openmw-mp/NetworkMessages.hpp>
|
#include <components/openmw-mp/NetworkMessages.hpp>
|
||||||
|
|
||||||
using namespace mwmp;
|
using namespace mwmp;
|
||||||
|
@ -12,22 +13,32 @@ void PacketPlayerStatsDynamic::Packet(RakNet::BitStream *bs, bool send)
|
||||||
{
|
{
|
||||||
PlayerPacket::Packet(bs, send);
|
PlayerPacket::Packet(bs, send);
|
||||||
|
|
||||||
uint32_t count;
|
RW(player->exchangeFullInfo, send);
|
||||||
if (send)
|
|
||||||
count = static_cast<uint32_t>(player->statsDynamicIndexChanges.size());
|
|
||||||
|
|
||||||
RW(count, send);
|
if (player->exchangeFullInfo)
|
||||||
|
|
||||||
if (!send)
|
|
||||||
{
|
{
|
||||||
player->statsDynamicIndexChanges.clear();
|
RW(player->creatureStats.mDynamic, send);
|
||||||
player->statsDynamicIndexChanges.resize(count);
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
for (auto &&statsDynamicIndex : player->statsDynamicIndexChanges)
|
|
||||||
{
|
{
|
||||||
RW(statsDynamicIndex, send);
|
uint32_t count;
|
||||||
|
|
||||||
RW(player->creatureStats.mDynamic[statsDynamicIndex], send);
|
if (send)
|
||||||
|
count = static_cast<uint32_t>(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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@
|
||||||
Copyright 2015 Alexandre Moine <nobrakal@gmail.com>
|
Copyright 2015 Alexandre Moine <nobrakal@gmail.com>
|
||||||
Copyright 2017 Bret Curtis <psi29a@gmail.com>
|
Copyright 2017 Bret Curtis <psi29a@gmail.com>
|
||||||
-->
|
-->
|
||||||
<component>
|
<component type="desktop">
|
||||||
<id>org.openmw.desktop</id>
|
<id>org.openmw.desktop</id>
|
||||||
<metadata_license>CC0-1.0</metadata_license>
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
<project_license> GPL-3.0 and MIT</project_license>
|
<project_license>GPL-3.0 and MIT</project_license>
|
||||||
<name>OpenMW</name>
|
<name>OpenMW</name>
|
||||||
<summary>Unofficial open source engine re-implementation of the game Morrowind</summary>
|
<summary>Unofficial open source engine re-implementation of the game Morrowind</summary>
|
||||||
<description>
|
<description>
|
||||||
|
@ -20,7 +20,6 @@ Copyright 2017 Bret Curtis <psi29a@gmail.com>
|
||||||
You will still need the original game data to play OpenMW.
|
You will still need the original game data to play OpenMW.
|
||||||
</p>
|
</p>
|
||||||
</description>
|
</description>
|
||||||
|
|
||||||
<screenshots>
|
<screenshots>
|
||||||
<screenshot type="default">
|
<screenshot type="default">
|
||||||
<image>https://wiki.openmw.org/images/b/b2/Openmw_0.11.1_launcher_1.png</image>
|
<image>https://wiki.openmw.org/images/b/b2/Openmw_0.11.1_launcher_1.png</image>
|
||||||
|
@ -34,7 +33,18 @@ Copyright 2017 Bret Curtis <psi29a@gmail.com>
|
||||||
<image>https://wiki.openmw.org/images/5/5b/Screenshot_Vivec_seen_from_Ebonheart_0.35.png</image>
|
<image>https://wiki.openmw.org/images/5/5b/Screenshot_Vivec_seen_from_Ebonheart_0.35.png</image>
|
||||||
<caption>Vivec seen from Ebonheart on OpenMW</caption>
|
<caption>Vivec seen from Ebonheart on OpenMW</caption>
|
||||||
</screenshot>
|
</screenshot>
|
||||||
|
<screenshot>
|
||||||
|
<image>http://wiki.openmw.org/images/a/a3/0.40_Screenshot-Balmora_3.png</image>
|
||||||
|
<caption>Balmora at morning on OpenMW</caption>
|
||||||
|
</screenshot>
|
||||||
</screenshots>
|
</screenshots>
|
||||||
|
<categories>
|
||||||
|
<category>Game</category>
|
||||||
|
<category>RolePlaying</category>
|
||||||
|
</categories>
|
||||||
|
<releases>
|
||||||
|
<release version="0.43.0" date="2017-12-05"/>
|
||||||
|
</releases>
|
||||||
<url type="homepage">https://openmw.org</url>
|
<url type="homepage">https://openmw.org</url>
|
||||||
<url type="bugtracker">https://bugs.openmw.org/</url>
|
<url type="bugtracker">https://bugs.openmw.org/</url>
|
||||||
<url type="faq">https://openmw.org/faq/</url>
|
<url type="faq">https://openmw.org/faq/</url>
|
||||||
|
|
Loading…
Reference in a new issue