forked from teamnwah/openmw-tes3coop
Merge pull request #508 from TES3MP/0.7.0
Add 0.7.0 commits up to 19 Feb 2019
This commit is contained in:
commit
43340fd033
11 changed files with 141 additions and 102 deletions
26
.travis.yml
26
.travis.yml
|
@ -4,7 +4,7 @@ os:
|
||||||
osx_image: xcode9.4
|
osx_image: xcode9.4
|
||||||
language: cpp
|
language: cpp
|
||||||
sudo: required
|
sudo: required
|
||||||
dist: trusty
|
dist: xenial
|
||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
|
@ -15,18 +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=
|
||||||
|
|
||||||
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
|
||||||
|
@ -45,7 +45,7 @@ addons:
|
||||||
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
|
||||||
|
@ -53,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
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
|
@ -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
|
|
||||||
|
|
23
README.md
23
README.md
|
@ -2,7 +2,7 @@ TES3MP
|
||||||
======
|
======
|
||||||
|
|
||||||
Copyright (c) 2008-2015, OpenMW Team
|
Copyright (c) 2008-2015, OpenMW Team
|
||||||
Copyright (c) 2016-2018, TES3MP Team
|
Copyright (c) 2016-2019, Stanislav Zhukov & David Cernat
|
||||||
|
|
||||||
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
[](https://travis-ci.org/TES3MP/openmw-tes3mp)
|
||||||
|
|
||||||
|
@ -15,7 +15,7 @@ TES3MP is a project adding multiplayer functionality to [OpenMW](https://github.
|
||||||
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)
|
||||||
|
@ -24,25 +24,26 @@ As of version 0.7.0, TES3MP is fully playable, providing very extensive player,
|
||||||
|
|
||||||
Remaining gameplay problems mostly relate to AI and the synchronization of clientside script variables.
|
Remaining gameplay problems mostly relate to AI and the synchronization of clientside script variables.
|
||||||
|
|
||||||
|
Donations
|
||||||
|
---------------
|
||||||
|
|
||||||
|
You can benefit the project by donating on Patreon to our two developers, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).
|
||||||
|
|
||||||
Contributing
|
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=45)
|
* [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, [David Cernat](https://www.patreon.com/davidcernat) and [Koncord](https://www.patreon.com/Koncord), as well as by supporting [OpenMW](https://openmw.org).
|
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include "Cell.hpp"
|
#include "Cell.hpp"
|
||||||
#include "CellController.hpp"
|
#include "CellController.hpp"
|
||||||
|
|
||||||
struct Player;
|
|
||||||
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
|
typedef std::map<RakNet::RakNetGUID, Player*> TPlayers;
|
||||||
typedef std::map<unsigned short, Player*> TSlots;
|
typedef std::map<unsigned short, Player*> TSlots;
|
||||||
|
|
||||||
|
|
|
@ -201,26 +201,6 @@ int main(int argc, char *argv[])
|
||||||
vector<string> plugins(Utils::split(mgr.getString("plugins", "Plugins"), ','));
|
vector<string> plugins(Utils::split(mgr.getString("plugins", "Plugins"), ','));
|
||||||
|
|
||||||
Utils::printVersion("TES3MP dedicated server", TES3MP_VERSION, version.mCommitHash, TES3MP_PROTO_VERSION);
|
Utils::printVersion("TES3MP dedicated server", TES3MP_VERSION, version.mCommitHash, TES3MP_PROTO_VERSION);
|
||||||
|
|
||||||
// Check for unmodified tes3mp-credits file; this makes it so people can't repackage official releases with
|
|
||||||
// their own made-up credits, though it obviously has no bearing on unofficial releases that change
|
|
||||||
// the checksum below
|
|
||||||
boost::filesystem::path folderPath(boost::filesystem::initial_path<boost::filesystem::path>());
|
|
||||||
folderPath = boost::filesystem::system_complete(boost::filesystem::path(argv[0])).remove_filename();
|
|
||||||
std::string creditsPath = folderPath.string() + "/tes3mp-credits";
|
|
||||||
|
|
||||||
unsigned int expectedChecksumInt = Utils::hexStrToInt(TES3MP_CREDITS_CHECKSUM);
|
|
||||||
bool hasValidCredits = Utils::doesFileHaveChecksum(creditsPath + ".md", expectedChecksumInt);
|
|
||||||
|
|
||||||
if (!hasValidCredits)
|
|
||||||
hasValidCredits = Utils::doesFileHaveChecksum(creditsPath + ".txt", expectedChecksumInt);
|
|
||||||
|
|
||||||
if (!hasValidCredits)
|
|
||||||
{
|
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_FATAL, "The server is shutting down");
|
|
||||||
LOG_APPEND(Log::LOG_FATAL, "- %s", TES3MP_CREDITS_ERROR);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Script::SetModDir(dataDirectory);
|
Script::SetModDir(dataDirectory);
|
||||||
|
|
||||||
|
|
|
@ -221,10 +221,11 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
/*
|
/*
|
||||||
Start of tes3mp addition
|
Start of tes3mp addition
|
||||||
|
|
||||||
Check for unmodified tes3mp-credits file; this makes it so people can't repackage official releases with
|
Check for unmodified tes3mp-credits file on Windows; this makes it so people can't repackage official
|
||||||
their own made-up credits, though it obviously has no bearing on unofficial releases that change
|
releases with their own made-up credits, though it obviously has no bearing on unofficial releases that
|
||||||
the checksum below
|
change the checksum below
|
||||||
*/
|
*/
|
||||||
|
#ifdef _WIN32
|
||||||
boost::filesystem::path folderPath(boost::filesystem::initial_path<boost::filesystem::path>());
|
boost::filesystem::path folderPath(boost::filesystem::initial_path<boost::filesystem::path>());
|
||||||
folderPath = boost::filesystem::system_complete(boost::filesystem::path(argv[0])).remove_filename();
|
folderPath = boost::filesystem::system_complete(boost::filesystem::path(argv[0])).remove_filename();
|
||||||
std::string creditsPath = folderPath.string() + "/tes3mp-credits";
|
std::string creditsPath = folderPath.string() + "/tes3mp-credits";
|
||||||
|
@ -242,6 +243,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
||||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "tes3mp", TES3MP_CREDITS_ERROR, 0);
|
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "tes3mp", TES3MP_CREDITS_ERROR, 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
/*
|
/*
|
||||||
End of tes3mp addition
|
End of tes3mp addition
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -110,7 +110,7 @@ void RecordHelper::overrideCreatureRecord(const mwmp::CreatureRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +164,11 @@ void RecordHelper::overrideCreatureRecord(const mwmp::CreatureRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -175,7 +180,7 @@ void RecordHelper::overrideNpcRecord(const mwmp::NpcRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -186,12 +191,12 @@ void RecordHelper::overrideNpcRecord(const mwmp::NpcRecord& record)
|
||||||
{
|
{
|
||||||
if (!doesRaceRecordExist(recordData.mRace))
|
if (!doesRaceRecordExist(recordData.mRace))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new NPC record with invalid race provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new NPC record with invalid race provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else if (!doesClassRecordExist(recordData.mClass))
|
else if (!doesClassRecordExist(recordData.mClass))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new NPC record with invalid class provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new NPC record with invalid class provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -272,6 +277,11 @@ void RecordHelper::overrideNpcRecord(const mwmp::NpcRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -283,18 +293,17 @@ void RecordHelper::overrideEnchantmentRecord(const mwmp::EnchantmentRecord& reco
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isExistingId = doesEnchantmentRecordExist(recordData.mId);
|
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
if (record.baseId.empty())
|
if (record.baseId.empty())
|
||||||
{
|
{
|
||||||
if (recordData.mEffects.mList.empty())
|
if (recordData.mEffects.mList.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new enchantment record with no effects");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new enchantment record with no effects");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -323,6 +332,11 @@ void RecordHelper::overrideEnchantmentRecord(const mwmp::EnchantmentRecord& reco
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordHelper::overridePotionRecord(const mwmp::PotionRecord& record)
|
void RecordHelper::overridePotionRecord(const mwmp::PotionRecord& record)
|
||||||
|
@ -331,7 +345,7 @@ void RecordHelper::overridePotionRecord(const mwmp::PotionRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -374,6 +388,11 @@ void RecordHelper::overridePotionRecord(const mwmp::PotionRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -385,7 +404,7 @@ void RecordHelper::overrideSpellRecord(const mwmp::SpellRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,9 +438,11 @@ void RecordHelper::overrideSpellRecord(const mwmp::SpellRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if (isExistingId)
|
{
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
||||||
|
@ -430,7 +451,7 @@ void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -441,7 +462,7 @@ void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
||||||
{
|
{
|
||||||
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new armor record with invalid enchantment provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new armor record with invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -479,8 +500,13 @@ void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
||||||
if (record.baseOverrides.hasArmorRating)
|
if (record.baseOverrides.hasArmorRating)
|
||||||
finalData.mData.mArmor = recordData.mData.mArmor;
|
finalData.mData.mArmor = recordData.mData.mArmor;
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentId && doesEnchantmentRecordExist(recordData.mEnchant))
|
if (record.baseOverrides.hasEnchantmentId)
|
||||||
finalData.mEnchant = recordData.mEnchant;
|
{
|
||||||
|
if (doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
|
finalData.mEnchant = recordData.mEnchant;
|
||||||
|
else
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentCharge)
|
if (record.baseOverrides.hasEnchantmentCharge)
|
||||||
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
||||||
|
@ -493,6 +519,11 @@ void RecordHelper::overrideArmorRecord(const mwmp::ArmorRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -504,7 +535,7 @@ void RecordHelper::overrideBookRecord(const mwmp::BookRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -515,7 +546,7 @@ void RecordHelper::overrideBookRecord(const mwmp::BookRecord& record)
|
||||||
{
|
{
|
||||||
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new book record with invalid enchantment provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new book record with invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -551,8 +582,13 @@ void RecordHelper::overrideBookRecord(const mwmp::BookRecord& record)
|
||||||
if (record.baseOverrides.hasSkillId)
|
if (record.baseOverrides.hasSkillId)
|
||||||
finalData.mData.mSkillId = recordData.mData.mSkillId;
|
finalData.mData.mSkillId = recordData.mData.mSkillId;
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentId && doesEnchantmentRecordExist(recordData.mEnchant))
|
if (record.baseOverrides.hasEnchantmentId)
|
||||||
finalData.mEnchant = recordData.mEnchant;
|
{
|
||||||
|
if (doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
|
finalData.mEnchant = recordData.mEnchant;
|
||||||
|
else
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentCharge)
|
if (record.baseOverrides.hasEnchantmentCharge)
|
||||||
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
||||||
|
@ -562,6 +598,11 @@ void RecordHelper::overrideBookRecord(const mwmp::BookRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -573,7 +614,7 @@ void RecordHelper::overrideClothingRecord(const mwmp::ClothingRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -584,7 +625,7 @@ void RecordHelper::overrideClothingRecord(const mwmp::ClothingRecord& record)
|
||||||
{
|
{
|
||||||
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new clothing record with invalid enchantment provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new clothing record with invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -614,8 +655,13 @@ void RecordHelper::overrideClothingRecord(const mwmp::ClothingRecord& record)
|
||||||
if (record.baseOverrides.hasValue)
|
if (record.baseOverrides.hasValue)
|
||||||
finalData.mData.mValue = recordData.mData.mValue;
|
finalData.mData.mValue = recordData.mData.mValue;
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentId && doesEnchantmentRecordExist(recordData.mEnchant))
|
if (record.baseOverrides.hasEnchantmentId)
|
||||||
finalData.mEnchant = recordData.mEnchant;
|
{
|
||||||
|
if (doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
|
finalData.mEnchant = recordData.mEnchant;
|
||||||
|
else
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentCharge)
|
if (record.baseOverrides.hasEnchantmentCharge)
|
||||||
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
||||||
|
@ -628,6 +674,11 @@ void RecordHelper::overrideClothingRecord(const mwmp::ClothingRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -639,7 +690,7 @@ void RecordHelper::overrideMiscellaneousRecord(const mwmp::MiscellaneousRecord&
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,6 +730,11 @@ void RecordHelper::overrideMiscellaneousRecord(const mwmp::MiscellaneousRecord&
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
@ -690,7 +746,7 @@ void RecordHelper::overrideWeaponRecord(const mwmp::WeaponRecord& record)
|
||||||
|
|
||||||
if (recordData.mId.empty())
|
if (recordData.mId.empty())
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring record override with no id provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with no id provided");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,7 +757,7 @@ void RecordHelper::overrideWeaponRecord(const mwmp::WeaponRecord& record)
|
||||||
{
|
{
|
||||||
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
if (!recordData.mEnchant.empty() && !doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_INFO, "Ignoring new weapon record with invalid enchantment provided");
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring new weapon record with invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -761,8 +817,13 @@ void RecordHelper::overrideWeaponRecord(const mwmp::WeaponRecord& record)
|
||||||
if (record.baseOverrides.hasFlags)
|
if (record.baseOverrides.hasFlags)
|
||||||
finalData.mData.mFlags = recordData.mData.mFlags;
|
finalData.mData.mFlags = recordData.mData.mFlags;
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentId && doesEnchantmentRecordExist(recordData.mEnchant))
|
if (record.baseOverrides.hasEnchantmentId)
|
||||||
finalData.mEnchant = recordData.mEnchant;
|
{
|
||||||
|
if (doesEnchantmentRecordExist(recordData.mEnchant))
|
||||||
|
finalData.mEnchant = recordData.mEnchant;
|
||||||
|
else
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring invalid enchantmentId %s", recordData.mEnchant.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
if (record.baseOverrides.hasEnchantmentCharge)
|
if (record.baseOverrides.hasEnchantmentCharge)
|
||||||
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
finalData.mData.mEnchant = recordData.mData.mEnchant;
|
||||||
|
@ -772,6 +833,11 @@ void RecordHelper::overrideWeaponRecord(const mwmp::WeaponRecord& record)
|
||||||
|
|
||||||
world->getModifiableStore().overrideRecord(finalData);
|
world->getModifiableStore().overrideRecord(finalData);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "-- Ignoring record override with invalid baseId %s", record.baseId.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (isExistingId)
|
if (isExistingId)
|
||||||
world->updatePtrsWithRefId(recordData.mId);
|
world->updatePtrsWithRefId(recordData.mId);
|
||||||
|
|
|
@ -211,7 +211,7 @@ void Utils::printVersion(std::string appName, std::string version, std::string c
|
||||||
cout << appName << " " << version;
|
cout << appName << " " << version;
|
||||||
cout << " (" << getOperatingSystemType() << " " << getArchitectureType() << ")" << endl;
|
cout << " (" << getOperatingSystemType() << " " << getArchitectureType() << ")" << endl;
|
||||||
cout << "Protocol version: " << protocol << endl;
|
cout << "Protocol version: " << protocol << endl;
|
||||||
cout << "Commit hash: " << commitHash.substr(0, 10) << endl;
|
cout << "Oldest compatible commit hash: " << commitHash.substr(0, 10) << endl;
|
||||||
|
|
||||||
cout << "------------------------------------------------------------" << endl;
|
cout << "------------------------------------------------------------" << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#define TES3MP_DEFAULT_PASSW "SuperPassword"
|
#define TES3MP_DEFAULT_PASSW "SuperPassword"
|
||||||
#define TES3MP_MASTERSERVER_PASSW "12345"
|
#define TES3MP_MASTERSERVER_PASSW "12345"
|
||||||
|
|
||||||
#define TES3MP_CREDITS_CHECKSUM "BC39D2E9"
|
#define TES3MP_CREDITS_CHECKSUM "BAEFF920"
|
||||||
|
|
||||||
|
|
||||||
#endif //OPENMW_VERSION_HPP
|
#endif //OPENMW_VERSION_HPP
|
||||||
|
|
|
@ -4,14 +4,14 @@ tes3mp Credits
|
||||||
Programmers
|
Programmers
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Stanislav Zhukov (Koncord) - Overall architecture, networking & scripting systems, player sync, server browser & master server
|
Stanislav Zhukov (Koncord) - Architecture, networking & scripting systems, player sync, server browser & master server
|
||||||
David Cernat - World, NPC & quest sync, player sync improvements, state saving & loading, extensive bug fixes
|
David Cernat - World, NPC & quest sync, player sync improvements, state saving & loading, extensive bug fixes
|
||||||
|
|
||||||
|
|
||||||
Additional programming
|
Additional programming
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
Grim Kriegor - Lua teleportation commands, early script fixes
|
Grim Kriegor - Linux deployment scripts, Lua teleportation commands, early script fixes
|
||||||
Battlerax - Various small fixes
|
Battlerax - Various small fixes
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ Community administrators
|
||||||
Community moderators
|
Community moderators
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
Lysol
|
||||||
Michael Fitzmayer (mupf)
|
Michael Fitzmayer (mupf)
|
||||||
Nac
|
Nac
|
||||||
NicholasAH
|
NicholasAH
|
||||||
|
@ -53,6 +54,7 @@ Translation
|
||||||
Super special thanks
|
Super special thanks
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
Alexander Ovsyannikov
|
||||||
Bret Curtis (psi29a)
|
Bret Curtis (psi29a)
|
||||||
Gabriel Pascu (iGrebla)
|
Gabriel Pascu (iGrebla)
|
||||||
greetasdf
|
greetasdf
|
||||||
|
@ -73,8 +75,9 @@ Special thanks
|
||||||
Gluka
|
Gluka
|
||||||
Goodevil
|
Goodevil
|
||||||
Ignatious
|
Ignatious
|
||||||
James Wards of Gore Corps LAN Club (www.gorecorps.co.nz)
|
James Wards of Gore Corps LAN Club (gorecorps.co.nz)
|
||||||
Jeremiah
|
Jeremiah
|
||||||
|
Kyle Willey of Loreshaper Games (steempeak.com/@loreshapergames)
|
||||||
Lewis Sadlier
|
Lewis Sadlier
|
||||||
Luc Keating
|
Luc Keating
|
||||||
Michael Zagar (Zoops)
|
Michael Zagar (Zoops)
|
||||||
|
@ -84,6 +87,7 @@ Special thanks
|
||||||
Scorcio
|
Scorcio
|
||||||
Simon Nemes
|
Simon Nemes
|
||||||
Texafornian
|
Texafornian
|
||||||
|
Thrud
|
||||||
Zaphida
|
Zaphida
|
||||||
All the developers of OpenMW for creating an amazing open source project
|
All the developers of OpenMW for creating an amazing open source project
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue