mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-04-01 12:36:42 +00:00
Merge pull request #404 from TES3MP/0.6.3 while resolving conflicts
Conflicts: apps/openmw-mp/Player.hpp apps/openmw-mp/Script/Functions/Mechanics.cpp apps/openmw-mp/Script/Functions/Mechanics.hpp apps/openmw-mp/Script/Functions/Settings.hpp apps/openmw-mp/Script/Functions/Stats.cpp apps/openmw-mp/Script/Functions/Stats.hpp components/openmw-mp/Base/BasePlayer.hpp
This commit is contained in:
commit
2390744b45
30 changed files with 489 additions and 348 deletions
|
@ -21,6 +21,7 @@ NetActor::NetActor() : inventory(this), cellAPI(this), isActorPlayer(false)
|
||||||
void NetActor::resetUpdateFlags()
|
void NetActor::resetUpdateFlags()
|
||||||
{
|
{
|
||||||
baseInfoChanged = false;
|
baseInfoChanged = false;
|
||||||
|
shapeshiftChanged = false;
|
||||||
levelChanged = false;
|
levelChanged = false;
|
||||||
statsChanged = false;
|
statsChanged = false;
|
||||||
positionChanged = false;
|
positionChanged = false;
|
||||||
|
|
|
@ -68,7 +68,7 @@ public:
|
||||||
bool isPlayer() const { return isActorPlayer; }
|
bool isPlayer() const { return isActorPlayer; }
|
||||||
Player *toPlayer();
|
Player *toPlayer();
|
||||||
protected:
|
protected:
|
||||||
bool baseInfoChanged, levelChanged, statsChanged, positionChanged, attributesChanged, skillsChanged;
|
bool baseInfoChanged, shapeshiftChanged, levelChanged, statsChanged, positionChanged, attributesChanged, skillsChanged;
|
||||||
|
|
||||||
mwmp::BasePlayer *basePlayer;
|
mwmp::BasePlayer *basePlayer;
|
||||||
mwmp::BaseNetCreature *netCreature;
|
mwmp::BaseNetCreature *netCreature;
|
||||||
|
|
|
@ -106,8 +106,12 @@ void Networking::processPlayerPacket(RakNet::Packet *packet)
|
||||||
|
|
||||||
if (!player->isHandshaked())
|
if (!player->isHandshaked())
|
||||||
{
|
{
|
||||||
|
player->incrementHandshakeAttempts();
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Have not completed handshake with player %d", player->getId());
|
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Have not completed handshake with player %d", player->getId());
|
||||||
if (player->handshakeAttempts() > 5)
|
|
||||||
|
LOG_MESSAGE_SIMPLE(Log::LOG_WARN, "Attempts so far: %i", player->getHandshakeAttempts());
|
||||||
|
|
||||||
|
if (player->getHandshakeAttempts() > 5)
|
||||||
kickPlayer(player->guid);
|
kickPlayer(player->guid);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,11 +60,13 @@ void Player::Init(LuaState &lua)
|
||||||
"head", sol::property(&Player::getHead, &Player::setHead),
|
"head", sol::property(&Player::getHead, &Player::setHead),
|
||||||
"hair", sol::property(&Player::getHair, &Player::setHair),
|
"hair", sol::property(&Player::getHair, &Player::setHair),
|
||||||
"birthsign", sol::property(&Player::getBirthsign, &Player::setBirthsign),
|
"birthsign", sol::property(&Player::getBirthsign, &Player::setBirthsign),
|
||||||
|
"setResetStats", &Player::setResetStats,
|
||||||
|
|
||||||
"bounty", sol::property(&Player::getBounty, &Player::setBounty),
|
"bounty", sol::property(&Player::getBounty, &Player::setBounty),
|
||||||
"reputation", sol::property(&Player::getReputation, &Player::setReputation),
|
"reputation", sol::property(&Player::getReputation, &Player::setReputation),
|
||||||
"levelProgress", sol::property(&Player::getLevelProgress, &Player::setLevelProgress),
|
"levelProgress", sol::property(&Player::getLevelProgress, &Player::setLevelProgress),
|
||||||
"creatureModel", sol::property(&Player::getCreatureModel, &Player::setCreatureModel),
|
"creatureRefId", sol::property(&Player::getCreatureRefId, &Player::setCreatureRefId),
|
||||||
"isCreatureName", sol::property(&Player::isCreatureName, &Player::creatureName),
|
"displayCreatureName", sol::property(&Player::getCreatureNameDisplayState, &Player::setCreatureNameDisplayState),
|
||||||
|
|
||||||
"resurrect", &Player::resurrect,
|
"resurrect", &Player::resurrect,
|
||||||
"jail", &Player::jail,
|
"jail", &Player::jail,
|
||||||
|
@ -182,6 +184,14 @@ void Player::update()
|
||||||
packet->Send(false);
|
packet->Send(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (shapeshiftChanged)
|
||||||
|
{
|
||||||
|
auto packet = plPCtrl->GetPacket(ID_PLAYER_SHAPESHIFT);
|
||||||
|
packet->setPlayer(basePlayer);
|
||||||
|
packet->Send(false);
|
||||||
|
packet->Send(true);
|
||||||
|
}
|
||||||
|
|
||||||
// The character class can override values from below on the client, so send it first
|
// The character class can override values from below on the client, so send it first
|
||||||
cClass.update();
|
cClass.update();
|
||||||
|
|
||||||
|
@ -300,9 +310,14 @@ void Player::setHandshake()
|
||||||
handshakeCounter = numeric_limits<int>::max();
|
handshakeCounter = numeric_limits<int>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
int Player::handshakeAttempts()
|
void Player::incrementHandshakeAttempts()
|
||||||
{
|
{
|
||||||
return handshakeCounter++;
|
handshakeCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Player::getHandshakeAttempts()
|
||||||
|
{
|
||||||
|
return handshakeCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Player::getLoadState()
|
int Player::getLoadState()
|
||||||
|
@ -627,6 +642,12 @@ void Player::setBirthsign(const std::string &sign)
|
||||||
baseInfoChanged = true;
|
baseInfoChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Player::setResetStats(bool state)
|
||||||
|
{
|
||||||
|
resetStats = state;
|
||||||
|
baseInfoChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
int Player::getBounty() const
|
int Player::getBounty() const
|
||||||
{
|
{
|
||||||
return npcStats.mBounty;
|
return npcStats.mBounty;
|
||||||
|
@ -668,26 +689,26 @@ void Player::setLevelProgress(int progress)
|
||||||
levelChanged = true;
|
levelChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Player::getCreatureModel() const
|
std::string Player::getCreatureRefId() const
|
||||||
{
|
{
|
||||||
return creatureModel;
|
return creatureRefId;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setCreatureModel(const std::string &model)
|
void Player::setCreatureRefId(const std::string &refId)
|
||||||
{
|
{
|
||||||
creatureModel = model;
|
creatureRefId = refId;
|
||||||
baseInfoChanged = true;
|
shapeshiftChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::creatureName(bool useName)
|
bool Player::getCreatureNameDisplayState() const
|
||||||
{
|
{
|
||||||
useCreatureName = useName;
|
return displayCreatureName;
|
||||||
baseInfoChanged = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Player::isCreatureName() const
|
void Player::setCreatureNameDisplayState(bool useName)
|
||||||
{
|
{
|
||||||
return useCreatureName;
|
displayCreatureName = useName;
|
||||||
|
shapeshiftChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<int, int> Player::getAttribute(unsigned short attributeId) const
|
std::tuple<int, int> Player::getAttribute(unsigned short attributeId) const
|
||||||
|
@ -846,11 +867,7 @@ bool Player::getWerewolfState() const
|
||||||
void Player::setWerewolfState(bool state)
|
void Player::setWerewolfState(bool state)
|
||||||
{
|
{
|
||||||
isWerewolf = state;
|
isWerewolf = state;
|
||||||
|
shapeshiftChanged = true;
|
||||||
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT);
|
|
||||||
packet->setPlayer(this);
|
|
||||||
packet->Send(false);
|
|
||||||
packet->Send(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
float Player::getScale() const
|
float Player::getScale() const
|
||||||
|
@ -861,11 +878,7 @@ float Player::getScale() const
|
||||||
void Player::setScale(float newScale)
|
void Player::setScale(float newScale)
|
||||||
{
|
{
|
||||||
scale = newScale;
|
scale = newScale;
|
||||||
|
shapeshiftChanged = true;
|
||||||
auto packet = mwmp::Networking::get().getPlayerPacketController()->GetPacket(ID_PLAYER_SHAPESHIFT);
|
|
||||||
packet->setPlayer(this);
|
|
||||||
packet->Send(false);
|
|
||||||
packet->Send(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Player::setMark(float x, float y, float z, float xRot, float zRot, const std::string &cellDescription)
|
void Player::setMark(float x, float y, float z, float xRot, float zRot, const std::string &cellDescription)
|
||||||
|
|
|
@ -58,7 +58,8 @@ public:
|
||||||
void setId(unsigned short id);
|
void setId(unsigned short id);
|
||||||
|
|
||||||
bool isHandshaked();
|
bool isHandshaked();
|
||||||
int handshakeAttempts();
|
int getHandshakeAttempts();
|
||||||
|
void incrementHandshakeAttempts();
|
||||||
void setHandshake();
|
void setHandshake();
|
||||||
|
|
||||||
void setLoadState(int state);
|
void setLoadState(int state);
|
||||||
|
@ -101,6 +102,7 @@ public:
|
||||||
void setHair(const std::string &hair);
|
void setHair(const std::string &hair);
|
||||||
std::string getBirthsign() const;
|
std::string getBirthsign() const;
|
||||||
void setBirthsign(const std::string &sign);
|
void setBirthsign(const std::string &sign);
|
||||||
|
void setResetStats(bool state);
|
||||||
|
|
||||||
int getBounty() const;
|
int getBounty() const;
|
||||||
void setBounty(int bounty);
|
void setBounty(int bounty);
|
||||||
|
@ -148,10 +150,10 @@ public:
|
||||||
float getScale() const;
|
float getScale() const;
|
||||||
void setScale(float newScale);
|
void setScale(float newScale);
|
||||||
|
|
||||||
std::string getCreatureModel() const;
|
std::string getCreatureRefId() const;
|
||||||
void setCreatureModel(const std::string &model);
|
void setCreatureRefId(const std::string &model);
|
||||||
void creatureName(bool useName);
|
bool getCreatureNameDisplayState() const;
|
||||||
bool isCreatureName() const;
|
void setCreatureNameDisplayState(bool useName);
|
||||||
|
|
||||||
std::string getIP() const;
|
std::string getIP() const;
|
||||||
|
|
||||||
|
@ -207,8 +209,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CellController::TContainer cells;
|
CellController::TContainer cells;
|
||||||
int handshakeCounter;
|
|
||||||
int loadState;
|
int loadState;
|
||||||
|
int handshakeCounter;
|
||||||
bool /*statsChanged, attributesChanged, skillsChanged, baseInfoChanged, positionChanged,*/ changedMarkLocation, changedSelectedSpell, changedMap;
|
bool /*statsChanged, attributesChanged, skillsChanged, baseInfoChanged, positionChanged,*/ changedMarkLocation, changedSelectedSpell, changedMap;
|
||||||
CharClass cClass;
|
CharClass cClass;
|
||||||
GameSettings settings;
|
GameSettings settings;
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
#include <MyGUI_ScrollView.h>
|
#include <MyGUI_ScrollView.h>
|
||||||
#include <MyGUI_Gui.h>
|
#include <MyGUI_Gui.h>
|
||||||
|
|
||||||
|
#include <components/settings/settings.hpp>
|
||||||
|
|
||||||
#include "../mwbase/environment.hpp"
|
#include "../mwbase/environment.hpp"
|
||||||
#include "../mwbase/world.hpp"
|
#include "../mwbase/world.hpp"
|
||||||
#include "../mwbase/windowmanager.hpp"
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
@ -72,7 +74,10 @@ namespace MWGui
|
||||||
MWWorld::ActionTeleport::getFollowersToTeleport(player, followers);
|
MWWorld::ActionTeleport::getFollowersToTeleport(player, followers);
|
||||||
|
|
||||||
// Apply followers cost, in vanilla one follower travels for free
|
// Apply followers cost, in vanilla one follower travels for free
|
||||||
price *= std::max(1, static_cast<int>(followers.size()));
|
if (Settings::Manager::getBool("charge for every follower travelling", "Game"))
|
||||||
|
price *= 1 + static_cast<int>(followers.size());
|
||||||
|
else
|
||||||
|
price *= std::max(1, static_cast<int>(followers.size()));
|
||||||
|
|
||||||
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>("SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default);
|
MyGUI::Button* toAdd = mDestinationsView->createWidget<MyGUI::Button>("SandTextButton", 0, mCurrentY, 200, sLineHeight, MyGUI::Align::Default);
|
||||||
toAdd->setEnabled(price <= playerGold);
|
toAdd->setEnabled(price <= playerGold);
|
||||||
|
|
|
@ -1502,7 +1502,20 @@ namespace MWMechanics
|
||||||
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
|
// Attacker is in combat with us, but we are not in combat with the attacker yet. Time to fight back.
|
||||||
// Note: accidental or collateral damage attacks are ignored.
|
// Note: accidental or collateral damage attacks are ignored.
|
||||||
if (!target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
if (!target.getClass().getCreatureStats(target).getAiSequence().hasPackage(AiPackage::TypeIdPursue))
|
||||||
startCombat(target, attacker);
|
{
|
||||||
|
// If an actor has OnPCHitMe declared in his script, his Fight = 0 and the attacker is player,
|
||||||
|
// he will attack the player only if we will force him (e.g. via StartCombat console command)
|
||||||
|
bool peaceful = false;
|
||||||
|
std::string script = target.getClass().getScript(target);
|
||||||
|
if (!script.empty() && target.getRefData().getLocals().hasVar(script, "onpchitme") && attacker == getPlayer())
|
||||||
|
{
|
||||||
|
int fight = std::max(0, target.getClass().getCreatureStats(target).getAiSetting(CreatureStats::AI_Fight).getModified());
|
||||||
|
peaceful = (fight == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!peaceful)
|
||||||
|
startCombat(target, attacker);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -214,7 +214,7 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress)
|
void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &class_, bool preserveProgress, bool readBook)
|
||||||
{
|
{
|
||||||
int base = getSkill (skillIndex).getBase();
|
int base = getSkill (skillIndex).getBase();
|
||||||
|
|
||||||
|
@ -256,9 +256,14 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
||||||
MWBase::Environment::get().getWindowManager()->playSound("skillraise");
|
MWBase::Environment::get().getWindowManager()->playSound("skillraise");
|
||||||
|
|
||||||
std::stringstream message;
|
std::stringstream message;
|
||||||
|
|
||||||
|
if (readBook)
|
||||||
|
message << std::string("#{sBookSkillMessage}\n");
|
||||||
|
|
||||||
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
|
message << boost::format(MWBase::Environment::get().getWindowManager ()->getGameSettingString ("sNotifyMessage39", ""))
|
||||||
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
|
% std::string("#{" + ESM::Skill::sSkillNameIds[skillIndex] + "}")
|
||||||
% static_cast<int> (base);
|
% static_cast<int> (base);
|
||||||
|
|
||||||
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never);
|
MWBase::Environment::get().getWindowManager ()->messageBox(message.str(), MWGui::ShowInDialogueMode_Never);
|
||||||
|
|
||||||
if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt())
|
if (mLevelProgress >= gmst.find("iLevelUpTotal")->getInt())
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace MWMechanics
|
||||||
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
|
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
|
||||||
///< Increase skill by usage.
|
///< Increase skill by usage.
|
||||||
|
|
||||||
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress);
|
void increaseSkill (int skillIndex, const ESM::Class& class_, bool preserveProgress, bool readBook = false);
|
||||||
|
|
||||||
int getLevelProgress() const;
|
int getLevelProgress() const;
|
||||||
|
|
||||||
|
|
|
@ -586,7 +586,7 @@ namespace MWMechanics
|
||||||
ActiveSpells::ActiveEffect effect_ = effect;
|
ActiveSpells::ActiveEffect effect_ = effect;
|
||||||
effect_.mMagnitude *= -1;
|
effect_.mMagnitude *= -1;
|
||||||
absorbEffects.push_back(effect_);
|
absorbEffects.push_back(effect_);
|
||||||
if (reflected && Settings::Manager::getBool("classic reflected absorb attribute behavior", "Game"))
|
if (reflected && Settings::Manager::getBool("classic reflect absorb attribute behavior", "Game"))
|
||||||
target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
|
target.getClass().getCreatureStats(target).getActiveSpells().addSpell("", true,
|
||||||
absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
|
absorbEffects, mSourceName, caster.getClass().getCreatureStats(caster).getActorId());
|
||||||
else
|
else
|
||||||
|
|
|
@ -1,7 +1,3 @@
|
||||||
//
|
|
||||||
// Created by koncord on 02.01.16.
|
|
||||||
//
|
|
||||||
|
|
||||||
#include <boost/algorithm/clamp.hpp>
|
#include <boost/algorithm/clamp.hpp>
|
||||||
#include <components/openmw-mp/Log.hpp>
|
#include <components/openmw-mp/Log.hpp>
|
||||||
#include <apps/openmw/mwmechanics/steering.hpp>
|
#include <apps/openmw/mwmechanics/steering.hpp>
|
||||||
|
@ -50,6 +46,10 @@ DedicatedPlayer::DedicatedPlayer(RakNet::RakNetGUID guid) : BasePlayer(guid)
|
||||||
creatureStats.mDead = false;
|
creatureStats.mDead = false;
|
||||||
movementFlags = 0;
|
movementFlags = 0;
|
||||||
attack.instant = false;
|
attack.instant = false;
|
||||||
|
|
||||||
|
cell.blank();
|
||||||
|
position.pos[0] = position.pos[1] = Main::get().getCellController()->getCellSize() / 2;
|
||||||
|
position.pos[2] = 0;
|
||||||
}
|
}
|
||||||
DedicatedPlayer::~DedicatedPlayer()
|
DedicatedPlayer::~DedicatedPlayer()
|
||||||
{
|
{
|
||||||
|
@ -98,7 +98,7 @@ void DedicatedPlayer::update(float dt)
|
||||||
|
|
||||||
void DedicatedPlayer::move(float dt)
|
void DedicatedPlayer::move(float dt)
|
||||||
{
|
{
|
||||||
if (state != 2) return;
|
if (!reference) return;
|
||||||
|
|
||||||
ESM::Position refPos = ptr.getRefData().getPosition();
|
ESM::Position refPos = ptr.getRefData().getPosition();
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
@ -130,6 +130,61 @@ void DedicatedPlayer::move(float dt)
|
||||||
MWMechanics::zTurn(ptr, position.rot[2], osg::DegreesToRadians(1.0));
|
MWMechanics::zTurn(ptr, position.rot[2], osg::DegreesToRadians(1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DedicatedPlayer::setBaseInfo()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
if (reference)
|
||||||
|
{
|
||||||
|
deleteReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string recId = getNpcRecordId();
|
||||||
|
createReference(recId);
|
||||||
|
|
||||||
|
// Give this new character a temporary high fatigue of at least 1 so it doesn't
|
||||||
|
// spawn on the ground
|
||||||
|
creatureStats.mDynamic[2].mBase = 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DedicatedPlayer::setShapeshift()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
if (reference)
|
||||||
|
{
|
||||||
|
deleteReference();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string recId;
|
||||||
|
|
||||||
|
if (!creatureRefId.empty())
|
||||||
|
{
|
||||||
|
const ESM::Creature *tmpCreature = world->getStore().get<ESM::Creature>().search(creatureRefId);
|
||||||
|
if (tmpCreature != 0)
|
||||||
|
{
|
||||||
|
recId = getCreatureRecordId();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (recId.empty())
|
||||||
|
{
|
||||||
|
recId = getNpcRecordId();
|
||||||
|
}
|
||||||
|
|
||||||
|
createReference(recId);
|
||||||
|
|
||||||
|
if (ptr.getTypeName() == typeid(ESM::NPC).name())
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, isWerewolf);
|
||||||
|
|
||||||
|
if (!isWerewolf)
|
||||||
|
setEquipment();
|
||||||
|
}
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->scaleObject(ptr, scale);
|
||||||
|
}
|
||||||
|
|
||||||
void DedicatedPlayer::setAnimFlags()
|
void DedicatedPlayer::setAnimFlags()
|
||||||
{
|
{
|
||||||
using namespace MWMechanics;
|
using namespace MWMechanics;
|
||||||
|
@ -203,9 +258,8 @@ void DedicatedPlayer::setEquipment()
|
||||||
|
|
||||||
void DedicatedPlayer::setCell()
|
void DedicatedPlayer::setCell()
|
||||||
{
|
{
|
||||||
// Prevent cell update when player hasn't been instantiated yet
|
// Prevent cell update when reference doesn't exist
|
||||||
if (state == 0)
|
if (!reference) return;
|
||||||
return;
|
|
||||||
|
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
@ -240,12 +294,6 @@ void DedicatedPlayer::setCell()
|
||||||
Main::get().getCellController()->getCell(cell)->updateLocal(true);
|
Main::get().getCellController()->getCell(cell)->updateLocal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DedicatedPlayer::setShapeshift()
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getWorld()->scaleObject(ptr, scale);
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->setWerewolf(ptr, isWerewolf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DedicatedPlayer::updateMarker()
|
void DedicatedPlayer::updateMarker()
|
||||||
{
|
{
|
||||||
if (!markerEnabled)
|
if (!markerEnabled)
|
||||||
|
@ -301,16 +349,84 @@ void DedicatedPlayer::playSpeech()
|
||||||
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
|
winMgr->messageBox(MWBase::Environment::get().getDialogueManager()->getVoiceCaption(sound), MWGui::ShowInDialogueMode_Never);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DedicatedPlayer::getNpcRecordId()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
MWWorld::Ptr player = world->getPlayerPtr();
|
||||||
|
|
||||||
|
ESM::NPC newNpc = *player.get<ESM::NPC>()->mBase;
|
||||||
|
|
||||||
|
// To avoid freezes caused by invalid races, only set race if we find it
|
||||||
|
// on our client
|
||||||
|
if (world->getStore().get<ESM::Race>().search(npc.mRace) != 0)
|
||||||
|
newNpc.mRace = npc.mRace;
|
||||||
|
|
||||||
|
newNpc.mHead = npc.mHead;
|
||||||
|
newNpc.mHair = npc.mHair;
|
||||||
|
newNpc.mClass = npc.mClass;
|
||||||
|
newNpc.mName = npc.mName;
|
||||||
|
newNpc.mFlags = npc.mFlags;
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- Creating new NPC record");
|
||||||
|
newNpc.mId = "Dedicated Player";
|
||||||
|
std::string recId = world->createRecord(newNpc)->mId;
|
||||||
|
|
||||||
|
return recId;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string DedicatedPlayer::getCreatureRecordId()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
ESM::Creature creature;
|
||||||
|
|
||||||
|
const ESM::Creature *tmpCreature = world->getStore().get<ESM::Creature>().search(creatureRefId);
|
||||||
|
|
||||||
|
creature = *tmpCreature;
|
||||||
|
creature.mScript = "";
|
||||||
|
if (!displayCreatureName)
|
||||||
|
creature.mName = npc.mName;
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "Player %s looks like %s", npc.mName.c_str(), creatureRefId.c_str());
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- Creating new NPC record");
|
||||||
|
creature.mId = "Dedicated Player";
|
||||||
|
|
||||||
|
std::string recId = world->createRecord(creature)->mId;
|
||||||
|
|
||||||
|
return recId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DedicatedPlayer::createReference(const std::string& recId)
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
reference = new MWWorld::ManualRef(world->getStore(), recId, 1);
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- Creating new reference pointer for %s", npc.mName.c_str());
|
||||||
|
|
||||||
|
ptr = world->placeObject(reference->getPtr(), Main::get().getCellController()->getCellStore(cell), position);
|
||||||
|
|
||||||
|
ESM::CustomMarker mEditingMarker = Main::get().getGUIController()->createMarker(guid);
|
||||||
|
marker = mEditingMarker;
|
||||||
|
setMarkerState(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DedicatedPlayer::deleteReference()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- Deleting reference");
|
||||||
|
world->deleteObject(ptr);
|
||||||
|
delete reference;
|
||||||
|
reference = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
MWWorld::Ptr DedicatedPlayer::getPtr()
|
MWWorld::Ptr DedicatedPlayer::getPtr()
|
||||||
{
|
{
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
MWWorld::Ptr DedicatedPlayer::getLiveCellPtr()
|
|
||||||
{
|
|
||||||
return reference->getPtr();
|
|
||||||
}
|
|
||||||
|
|
||||||
MWWorld::ManualRef *DedicatedPlayer::getRef()
|
MWWorld::ManualRef *DedicatedPlayer::getRef()
|
||||||
{
|
{
|
||||||
return reference;
|
return reference;
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
#define OPENMW_DEDICATEDPLAYER_HPP
|
#define OPENMW_DEDICATEDPLAYER_HPP
|
||||||
|
|
||||||
#include <components/esm/custommarkerstate.hpp>
|
#include <components/esm/custommarkerstate.hpp>
|
||||||
|
#include <components/esm/loadcrea.hpp>
|
||||||
#include <components/esm/loadnpc.hpp>
|
#include <components/esm/loadnpc.hpp>
|
||||||
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
#include <components/openmw-mp/Base/BasePlayer.hpp>
|
||||||
|
|
||||||
|
#include "../mwclass/npc.hpp"
|
||||||
|
|
||||||
#include "../mwmechanics/aisequence.hpp"
|
#include "../mwmechanics/aisequence.hpp"
|
||||||
|
|
||||||
#include "../mwworld/manualref.hpp"
|
#include "../mwworld/manualref.hpp"
|
||||||
|
@ -32,10 +35,11 @@ namespace mwmp
|
||||||
void update(float dt);
|
void update(float dt);
|
||||||
|
|
||||||
void move(float dt);
|
void move(float dt);
|
||||||
|
void setBaseInfo();
|
||||||
|
void setShapeshift();
|
||||||
void setAnimFlags();
|
void setAnimFlags();
|
||||||
void setEquipment();
|
void setEquipment();
|
||||||
void setCell();
|
void setCell();
|
||||||
void setShapeshift();
|
|
||||||
|
|
||||||
void updateMarker();
|
void updateMarker();
|
||||||
void removeMarker();
|
void removeMarker();
|
||||||
|
@ -44,8 +48,13 @@ namespace mwmp
|
||||||
void playAnimation();
|
void playAnimation();
|
||||||
void playSpeech();
|
void playSpeech();
|
||||||
|
|
||||||
|
std::string getNpcRecordId();
|
||||||
|
std::string getCreatureRecordId();
|
||||||
|
|
||||||
|
void createReference(const std::string& recId);
|
||||||
|
void deleteReference();
|
||||||
|
|
||||||
MWWorld::Ptr getPtr();
|
MWWorld::Ptr getPtr();
|
||||||
MWWorld::Ptr getLiveCellPtr();
|
|
||||||
MWWorld::ManualRef* getRef();
|
MWWorld::ManualRef* getRef();
|
||||||
|
|
||||||
void setPtr(const MWWorld::Ptr& newPtr);
|
void setPtr(const MWWorld::Ptr& newPtr);
|
||||||
|
@ -55,7 +64,6 @@ namespace mwmp
|
||||||
DedicatedPlayer(RakNet::RakNetGUID guid);
|
DedicatedPlayer(RakNet::RakNetGUID guid);
|
||||||
virtual ~DedicatedPlayer();
|
virtual ~DedicatedPlayer();
|
||||||
|
|
||||||
int state;
|
|
||||||
MWWorld::ManualRef* reference;
|
MWWorld::ManualRef* reference;
|
||||||
|
|
||||||
MWWorld::Ptr ptr;
|
MWWorld::Ptr ptr;
|
||||||
|
|
|
@ -334,7 +334,7 @@ ESM::CustomMarker mwmp::GUIController::createMarker(const RakNet::RakNetGUID &gu
|
||||||
ESM::CustomMarker mEditingMarker;
|
ESM::CustomMarker mEditingMarker;
|
||||||
if (!player)
|
if (!player)
|
||||||
{
|
{
|
||||||
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Unknown player guid: %lu", guid.g);
|
LOG_MESSAGE_SIMPLE(Log::LOG_ERROR, "Unknown player guid: %s", guid.ToString());
|
||||||
return mEditingMarker;
|
return mEditingMarker;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -431,13 +431,6 @@ void LocalPlayer::updateCell(bool forceUpdate)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LocalPlayer::updateChar()
|
|
||||||
{
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->setPlayerRace(npc.mRace, npc.isMale(), npc.mHead, npc.mHair);
|
|
||||||
MWBase::Environment::get().getMechanicsManager()->setPlayerBirthsign(birthsign);
|
|
||||||
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
|
|
||||||
}
|
|
||||||
|
|
||||||
void LocalPlayer::updateEquipment(bool forceUpdate)
|
void LocalPlayer::updateEquipment(bool forceUpdate)
|
||||||
{
|
{
|
||||||
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
MWWorld::Ptr ptrPlayer = getPlayerPtr();
|
||||||
|
@ -829,6 +822,40 @@ void LocalPlayer::closeInventoryWindows()
|
||||||
MWBase::Environment::get().getWindowManager()->finishDragDrop();
|
MWBase::Environment::get().getWindowManager()->finishDragDrop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LocalPlayer::setCharacter()
|
||||||
|
{
|
||||||
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
||||||
|
// Ignore invalid races
|
||||||
|
if (world->getStore().get<ESM::Race>().search(npc.mRace) != 0)
|
||||||
|
{
|
||||||
|
MWBase::Environment::get().getWorld()->getPlayer().setBirthSign(birthsign);
|
||||||
|
|
||||||
|
if (resetStats)
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->setPlayerRace(npc.mRace, npc.isMale(), npc.mHead, npc.mHair);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ESM::NPC player = *world->getPlayerPtr().get<ESM::NPC>()->mBase;
|
||||||
|
|
||||||
|
player.mRace = npc.mRace;
|
||||||
|
player.mHead = npc.mHead;
|
||||||
|
player.mHair = npc.mHair;
|
||||||
|
player.setIsMale(npc.isMale());
|
||||||
|
world->createRecord(player);
|
||||||
|
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->playerLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
setEquipment();
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWindowManager()->getInventoryWindow()->rebuildAvatar();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- Character update was ignored due to invalid race %s", npc.mRace.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void LocalPlayer::setDynamicStats()
|
void LocalPlayer::setDynamicStats()
|
||||||
{
|
{
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
MWBase::World *world = MWBase::Environment::get().getWorld();
|
||||||
|
|
|
@ -32,7 +32,6 @@ namespace mwmp
|
||||||
void updateReputation(bool forceUpdate = false);
|
void updateReputation(bool forceUpdate = false);
|
||||||
void updatePosition(bool forceUpdate = false);
|
void updatePosition(bool forceUpdate = false);
|
||||||
void updateCell(bool forceUpdate = false);
|
void updateCell(bool forceUpdate = false);
|
||||||
void updateChar();
|
|
||||||
void updateEquipment(bool forceUpdate = false);
|
void updateEquipment(bool forceUpdate = false);
|
||||||
void updateInventory(bool forceUpdate = false);
|
void updateInventory(bool forceUpdate = false);
|
||||||
void updateAttack();
|
void updateAttack();
|
||||||
|
@ -51,6 +50,7 @@ namespace mwmp
|
||||||
|
|
||||||
void closeInventoryWindows();
|
void closeInventoryWindows();
|
||||||
|
|
||||||
|
void setCharacter();
|
||||||
void setDynamicStats();
|
void setDynamicStats();
|
||||||
void setAttributes();
|
void setAttributes();
|
||||||
void setSkills();
|
void setSkills();
|
||||||
|
|
|
@ -34,199 +34,24 @@ void PlayerList::update(float dt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerList::createPlayer(RakNet::RakNetGUID guid)
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Setting up character info");
|
|
||||||
|
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
||||||
|
|
||||||
DedicatedPlayer *dedicPlayer = players[guid];
|
|
||||||
|
|
||||||
ESM::Creature creature;
|
|
||||||
ESM::NPC npc;
|
|
||||||
if (!dedicPlayer->creatureModel.empty())
|
|
||||||
{
|
|
||||||
const ESM::Creature *tmpCreature = world->getStore().get<ESM::Creature>().search(dedicPlayer->creatureModel);
|
|
||||||
if (tmpCreature == 0)
|
|
||||||
{
|
|
||||||
dedicPlayer->creatureModel = "";
|
|
||||||
createPlayer(guid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
creature = *tmpCreature;
|
|
||||||
creature.mScript = "";
|
|
||||||
if (!dedicPlayer->useCreatureName)
|
|
||||||
creature.mName = dedicPlayer->npc.mName;
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "Player %s looks like %s", dedicPlayer->npc.mName.c_str(),
|
|
||||||
dedicPlayer->creatureModel.c_str());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MWWorld::Ptr player = world->getPlayerPtr();
|
|
||||||
|
|
||||||
npc = *player.get<ESM::NPC>()->mBase;
|
|
||||||
|
|
||||||
// To avoid freezes caused by invalid races, only set race if we find it
|
|
||||||
// on our client
|
|
||||||
if (world->getStore().get<ESM::Race>().search(dedicPlayer->npc.mRace) != 0)
|
|
||||||
npc.mRace = dedicPlayer->npc.mRace;
|
|
||||||
|
|
||||||
npc.mHead = dedicPlayer->npc.mHead;
|
|
||||||
npc.mHair = dedicPlayer->npc.mHair;
|
|
||||||
npc.mClass = dedicPlayer->npc.mClass;
|
|
||||||
npc.mName = dedicPlayer->npc.mName;
|
|
||||||
npc.mFlags = dedicPlayer->npc.mFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool reset = false;
|
|
||||||
if (dedicPlayer->reference)
|
|
||||||
{
|
|
||||||
bool isNPC = dedicPlayer->reference->getPtr().getTypeName() == typeid(ESM::NPC).name();
|
|
||||||
if ((!dedicPlayer->creatureModel.empty() && isNPC) ||
|
|
||||||
(dedicPlayer->creatureModel.empty() && !isNPC))
|
|
||||||
{
|
|
||||||
if (dedicPlayer->reference)
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Deleting old reference");
|
|
||||||
dedicPlayer->state = 0;
|
|
||||||
world->deleteObject(dedicPlayer->ptr);
|
|
||||||
delete dedicPlayer->reference;
|
|
||||||
dedicPlayer->reference = nullptr;
|
|
||||||
reset = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Temporarily spawn or move player to the center of exterior 0,0 whenever setting base info
|
|
||||||
ESM::Position spawnPos;
|
|
||||||
spawnPos.pos[0] = spawnPos.pos[1] = Main::get().getCellController()->getCellSize() / 2;
|
|
||||||
spawnPos.pos[2] = 0;
|
|
||||||
MWWorld::CellStore *cellStore = world->getExterior(0, 0);
|
|
||||||
|
|
||||||
if (dedicPlayer->state == 0)
|
|
||||||
{
|
|
||||||
string recid;
|
|
||||||
if (dedicPlayer->creatureModel.empty())
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Creating new NPC record");
|
|
||||||
npc.mId = "Dedicated Player";
|
|
||||||
recid = world->createRecord(npc)->mId;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Creating new Creature record");
|
|
||||||
creature.mId = "Dedicated Player";
|
|
||||||
recid = world->createRecord(creature)->mId;
|
|
||||||
}
|
|
||||||
|
|
||||||
dedicPlayer->reference = new MWWorld::ManualRef(world->getStore(), recid, 1);
|
|
||||||
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Creating new reference pointer for %s", dedicPlayer->npc.mName.c_str());
|
|
||||||
|
|
||||||
MWWorld::Ptr tmp;
|
|
||||||
|
|
||||||
if (reset)
|
|
||||||
{
|
|
||||||
if (dedicPlayer->cell.isExterior())
|
|
||||||
cellStore = world->getExterior(dedicPlayer->cell.mData.mX, dedicPlayer->cell.mData.mY);
|
|
||||||
else
|
|
||||||
cellStore = world->getInterior(dedicPlayer->cell.mName);
|
|
||||||
|
|
||||||
spawnPos = dedicPlayer->position;
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp = world->placeObject(dedicPlayer->reference->getPtr(), cellStore, spawnPos);
|
|
||||||
|
|
||||||
dedicPlayer->ptr.mCell = tmp.mCell;
|
|
||||||
dedicPlayer->ptr.mRef = tmp.mRef;
|
|
||||||
|
|
||||||
if (!reset)
|
|
||||||
{
|
|
||||||
dedicPlayer->cell = *dedicPlayer->ptr.getCell()->getCell();
|
|
||||||
dedicPlayer->position = dedicPlayer->ptr.getRefData().getPosition();
|
|
||||||
}
|
|
||||||
|
|
||||||
ESM::CustomMarker mEditingMarker = Main::get().getGUIController()->createMarker(guid);
|
|
||||||
dedicPlayer->marker = mEditingMarker;
|
|
||||||
dedicPlayer->setMarkerState(true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Updating reference pointer for %s", dedicPlayer->npc.mName.c_str());
|
|
||||||
|
|
||||||
MWWorld::ESMStore *store = const_cast<MWWorld::ESMStore *>(&world->getStore());
|
|
||||||
MWWorld::Store<ESM::Creature> *creature_store = const_cast<MWWorld::Store<ESM::Creature> *> (&store->get<ESM::Creature>());
|
|
||||||
MWWorld::Store<ESM::NPC> *npc_store = const_cast<MWWorld::Store<ESM::NPC> *> (&store->get<ESM::NPC>());
|
|
||||||
|
|
||||||
if (!dedicPlayer->creatureModel.empty())
|
|
||||||
{
|
|
||||||
if (!npc.mId.empty() || npc.mId != "Dedicated Player")
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Deleting NPC record");
|
|
||||||
npc_store->erase(npc.mId);
|
|
||||||
npc.mId.clear();
|
|
||||||
}
|
|
||||||
creature.mId = players[guid]->ptr.get<ESM::Creature>()->mBase->mId;
|
|
||||||
creature_store->insert(creature);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!creature.mId.empty() || creature.mId != "Dedicated Player")
|
|
||||||
{
|
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Deleting Creature record");
|
|
||||||
creature_store->erase(creature.mId);
|
|
||||||
creature.mId.clear();
|
|
||||||
}
|
|
||||||
npc.mId = players[guid]->ptr.get<ESM::NPC>()->mBase->mId;
|
|
||||||
npc_store->insert(npc);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable Ptr to avoid graphical glitches caused by race changes
|
|
||||||
world->disable(players[guid]->ptr);
|
|
||||||
|
|
||||||
dedicPlayer->setPtr(world->moveObject(dedicPlayer->ptr, cellStore, spawnPos.pos[0], spawnPos.pos[1], spawnPos.pos[2]));
|
|
||||||
dedicPlayer->setCell();
|
|
||||||
}
|
|
||||||
|
|
||||||
dedicPlayer->guid = guid;
|
|
||||||
dedicPlayer->state = 2;
|
|
||||||
|
|
||||||
// Give this new character a fatigue of at least 1 so it doesn't spawn
|
|
||||||
// on the ground
|
|
||||||
dedicPlayer->creatureStats.mDynamic[2].mBase = 1;
|
|
||||||
|
|
||||||
world->enable(players[guid]->ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
DedicatedPlayer *PlayerList::newPlayer(RakNet::RakNetGUID guid)
|
DedicatedPlayer *PlayerList::newPlayer(RakNet::RakNetGUID guid)
|
||||||
{
|
{
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Creating new DedicatedPlayer with guid %lu", guid.g);
|
LOG_APPEND(Log::LOG_INFO, "- Creating new DedicatedPlayer with guid %s", guid.ToString());
|
||||||
|
|
||||||
players[guid] = new DedicatedPlayer(guid);
|
players[guid] = new DedicatedPlayer(guid);
|
||||||
players[guid]->state = 0;
|
|
||||||
|
LOG_APPEND(Log::LOG_INFO, "- There are now %i DedicatedPlayers", players.size());
|
||||||
|
|
||||||
return players[guid];
|
return players[guid];
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerList::disconnectPlayer(RakNet::RakNetGUID guid)
|
void PlayerList::deletePlayer(RakNet::RakNetGUID guid)
|
||||||
{
|
{
|
||||||
if (players[guid]->state > 1)
|
if (players[guid]->reference)
|
||||||
{
|
players[guid]->deleteReference();
|
||||||
players[guid]->state = 1;
|
|
||||||
|
|
||||||
// Remove player's marker
|
delete players[guid];
|
||||||
players[guid]->setMarkerState(false);
|
players.erase(guid);
|
||||||
|
|
||||||
MWBase::World *world = MWBase::Environment::get().getWorld();
|
|
||||||
world->disable(players[guid]->getPtr());
|
|
||||||
|
|
||||||
// Move player to exterior 0,0
|
|
||||||
ESM::Position newPos;
|
|
||||||
newPos.pos[0] = newPos.pos[1] = Main::get().getCellController()->getCellSize() / 2;
|
|
||||||
newPos.pos[2] = 0;
|
|
||||||
MWWorld::CellStore *cellStore = world->getExterior(0, 0);
|
|
||||||
|
|
||||||
world->moveObject(players[guid]->getPtr(), cellStore, newPos.pos[0], newPos.pos[1], newPos.pos[2]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlayerList::cleanUp()
|
void PlayerList::cleanUp()
|
||||||
|
|
|
@ -27,10 +27,9 @@ namespace mwmp
|
||||||
|
|
||||||
static void update(float dt);
|
static void update(float dt);
|
||||||
|
|
||||||
static void createPlayer(RakNet::RakNetGUID guid);
|
|
||||||
static DedicatedPlayer *newPlayer(RakNet::RakNetGUID guid);
|
static DedicatedPlayer *newPlayer(RakNet::RakNetGUID guid);
|
||||||
|
|
||||||
static void disconnectPlayer(RakNet::RakNetGUID guid);
|
static void deletePlayer(RakNet::RakNetGUID guid);
|
||||||
static void cleanUp();
|
static void cleanUp();
|
||||||
|
|
||||||
static DedicatedPlayer *getPlayer(RakNet::RakNetGUID guid);
|
static DedicatedPlayer *getPlayer(RakNet::RakNetGUID guid);
|
||||||
|
|
|
@ -32,8 +32,8 @@ namespace mwmp
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOG_APPEND(Log::LOG_INFO, "- Updating LocalPlayer");
|
LOG_APPEND(Log::LOG_INFO, "- Setting character for LocalPlayer");
|
||||||
static_cast<LocalPlayer*>(player)->updateChar();
|
static_cast<LocalPlayer*>(player)->setCharacter();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -49,7 +49,7 @@ namespace mwmp
|
||||||
packet.Read();
|
packet.Read();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerList::createPlayer(guid);
|
static_cast<DedicatedPlayer*>(player)->setBaseInfo();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace mwmp
|
||||||
if (isLocal())
|
if (isLocal())
|
||||||
MWBase::Environment::get().getStateManager()->requestQuit();
|
MWBase::Environment::get().getStateManager()->requestQuit();
|
||||||
else if (player != 0)
|
else if (player != 0)
|
||||||
PlayerList::disconnectPlayer(guid);
|
PlayerList::deletePlayer(guid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,6 +51,16 @@
|
||||||
#include "terrainstorage.hpp"
|
#include "terrainstorage.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
float DLLandFogStart;
|
||||||
|
float DLLandFogEnd;
|
||||||
|
float DLUnderwaterFogStart;
|
||||||
|
float DLUnderwaterFogEnd;
|
||||||
|
float DLInteriorFogStart;
|
||||||
|
float DLInteriorFogEnd;
|
||||||
|
}
|
||||||
|
|
||||||
namespace MWRender
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -173,14 +183,18 @@ namespace MWRender
|
||||||
, mResourceSystem(resourceSystem)
|
, mResourceSystem(resourceSystem)
|
||||||
, mWorkQueue(workQueue)
|
, mWorkQueue(workQueue)
|
||||||
, mUnrefQueue(new SceneUtil::UnrefQueue)
|
, mUnrefQueue(new SceneUtil::UnrefQueue)
|
||||||
, mFogDepth(0.f)
|
, mLandFogStart(0.f)
|
||||||
|
, mLandFogEnd(std::numeric_limits<float>::max())
|
||||||
|
, mUnderwaterFogStart(0.f)
|
||||||
|
, mUnderwaterFogEnd(std::numeric_limits<float>::max())
|
||||||
, mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor"))
|
, mUnderwaterColor(fallback->getFallbackColour("Water_UnderwaterColor"))
|
||||||
, mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight"))
|
, mUnderwaterWeight(fallback->getFallbackFloat("Water_UnderwaterColorWeight"))
|
||||||
, mUnderwaterFog(0.f)
|
|
||||||
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
, mUnderwaterIndoorFog(fallback->getFallbackFloat("Water_UnderwaterIndoorFog"))
|
||||||
, mNightEyeFactor(0.f)
|
, mNightEyeFactor(0.f)
|
||||||
, mFieldOfViewOverride(0.f)
|
, mDistantFog(false)
|
||||||
|
, mDistantTerrain(false)
|
||||||
, mFieldOfViewOverridden(false)
|
, mFieldOfViewOverridden(false)
|
||||||
|
, mFieldOfViewOverride(0.f)
|
||||||
{
|
{
|
||||||
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
resourceSystem->getSceneManager()->setParticleSystemMask(MWRender::Mask_ParticleSystem);
|
||||||
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
|
resourceSystem->getSceneManager()->setShaderPath(resourcePath + "/shaders");
|
||||||
|
@ -216,12 +230,20 @@ namespace MWRender
|
||||||
|
|
||||||
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
|
mWater.reset(new Water(mRootNode, sceneRoot, mResourceSystem, mViewer->getIncrementalCompileOperation(), fallback, resourcePath));
|
||||||
|
|
||||||
const bool distantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
DLLandFogStart = Settings::Manager::getFloat("distant land fog start", "Fog");
|
||||||
|
DLLandFogEnd = Settings::Manager::getFloat("distant land fog end", "Fog");
|
||||||
|
DLUnderwaterFogStart = Settings::Manager::getFloat("distant underwater fog start", "Fog");
|
||||||
|
DLUnderwaterFogEnd = Settings::Manager::getFloat("distant underwater fog end", "Fog");
|
||||||
|
DLInteriorFogStart = Settings::Manager::getFloat("distant interior fog start", "Fog");
|
||||||
|
DLInteriorFogEnd = Settings::Manager::getFloat("distant interior fog end", "Fog");
|
||||||
|
|
||||||
|
mDistantFog = Settings::Manager::getBool("use distant fog", "Fog");
|
||||||
|
mDistantTerrain = Settings::Manager::getBool("distant terrain", "Terrain");
|
||||||
mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"),
|
mTerrainStorage = new TerrainStorage(mResourceSystem, Settings::Manager::getString("normal map pattern", "Shaders"), Settings::Manager::getString("normal height map pattern", "Shaders"),
|
||||||
Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"),
|
Settings::Manager::getBool("auto use terrain normal maps", "Shaders"), Settings::Manager::getString("terrain specular map pattern", "Shaders"),
|
||||||
Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
|
Settings::Manager::getBool("auto use terrain specular maps", "Shaders"));
|
||||||
|
|
||||||
if (distantTerrain)
|
if (mDistantTerrain)
|
||||||
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
mTerrain.reset(new Terrain::QuadTreeWorld(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||||
else
|
else
|
||||||
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
mTerrain.reset(new Terrain::TerrainGrid(sceneRoot, mRootNode, mResourceSystem, mTerrainStorage, Mask_Terrain, Mask_PreCompile));
|
||||||
|
@ -479,14 +501,44 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog);
|
osg::Vec4f color = SceneUtil::colourFromRGB(cell->mAmbi.mFog);
|
||||||
|
|
||||||
configureFog (cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, color);
|
if(mDistantFog)
|
||||||
|
{
|
||||||
|
float density = std::max(0.2f, cell->mAmbi.mFogDensity);
|
||||||
|
mLandFogStart = (DLInteriorFogEnd*(1.0f-density) + DLInteriorFogStart*density);
|
||||||
|
mLandFogEnd = DLInteriorFogEnd;
|
||||||
|
mUnderwaterFogStart = DLUnderwaterFogStart;
|
||||||
|
mUnderwaterFogEnd = DLUnderwaterFogEnd;
|
||||||
|
mFogColor = color;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
configureFog(cell->mAmbi.mFogDensity, mUnderwaterIndoorFog, 1.0f, 0.0f, color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RenderingManager::configureFog(float fogDepth, float underwaterFog, const osg::Vec4f &color)
|
void RenderingManager::configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f &color)
|
||||||
{
|
{
|
||||||
mFogDepth = fogDepth;
|
if(mDistantFog)
|
||||||
|
{
|
||||||
|
mLandFogStart = dlFactor * (DLLandFogStart - dlOffset*DLLandFogEnd);
|
||||||
|
mLandFogEnd = dlFactor * (1.0f-dlOffset) * DLLandFogEnd;
|
||||||
|
mUnderwaterFogStart = DLUnderwaterFogStart;
|
||||||
|
mUnderwaterFogEnd = DLUnderwaterFogEnd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(fogDepth == 0.0)
|
||||||
|
{
|
||||||
|
mLandFogStart = 0.0f;
|
||||||
|
mLandFogEnd = std::numeric_limits<float>::max();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mLandFogStart = mViewDistance * (1 - fogDepth);
|
||||||
|
mLandFogEnd = mViewDistance;
|
||||||
|
}
|
||||||
|
mUnderwaterFogStart = mViewDistance * (1 - underwaterFog);
|
||||||
|
mUnderwaterFogEnd = mViewDistance;
|
||||||
|
}
|
||||||
mFogColor = color;
|
mFogColor = color;
|
||||||
mUnderwaterFog = underwaterFog;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SkyManager* RenderingManager::getSkyManager()
|
SkyManager* RenderingManager::getSkyManager()
|
||||||
|
@ -517,23 +569,15 @@ namespace MWRender
|
||||||
float viewDistance = mViewDistance;
|
float viewDistance = mViewDistance;
|
||||||
viewDistance = std::min(viewDistance, 6666.f);
|
viewDistance = std::min(viewDistance, 6666.f);
|
||||||
setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight));
|
setFogColor(mUnderwaterColor * mUnderwaterWeight + mFogColor * (1.f-mUnderwaterWeight));
|
||||||
mStateUpdater->setFogStart(viewDistance * (1 - mUnderwaterFog));
|
mStateUpdater->setFogStart(mUnderwaterFogStart);
|
||||||
mStateUpdater->setFogEnd(viewDistance);
|
mStateUpdater->setFogEnd(mUnderwaterFogEnd);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
setFogColor(mFogColor);
|
setFogColor(mFogColor);
|
||||||
|
|
||||||
if (mFogDepth == 0.f)
|
mStateUpdater->setFogStart(mLandFogStart);
|
||||||
{
|
mStateUpdater->setFogEnd(mLandFogEnd);
|
||||||
mStateUpdater->setFogStart(0.f);
|
|
||||||
mStateUpdater->setFogEnd(std::numeric_limits<float>::max());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mStateUpdater->setFogStart(mViewDistance * (1 - mFogDepth));
|
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -960,7 +1004,8 @@ namespace MWRender
|
||||||
else if (it->first == "Camera" && it->second == "viewing distance")
|
else if (it->first == "Camera" && it->second == "viewing distance")
|
||||||
{
|
{
|
||||||
mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
|
mViewDistance = Settings::Manager::getFloat("viewing distance", "Camera");
|
||||||
mStateUpdater->setFogEnd(mViewDistance);
|
if(!mDistantFog)
|
||||||
|
mStateUpdater->setFogEnd(mViewDistance);
|
||||||
updateProjectionMatrix();
|
updateProjectionMatrix();
|
||||||
}
|
}
|
||||||
else if (it->first == "General" && (it->second == "texture filter" ||
|
else if (it->first == "General" && (it->second == "texture filter" ||
|
||||||
|
|
|
@ -106,7 +106,7 @@ namespace MWRender
|
||||||
|
|
||||||
void configureAmbient(const ESM::Cell* cell);
|
void configureAmbient(const ESM::Cell* cell);
|
||||||
void configureFog(const ESM::Cell* cell);
|
void configureFog(const ESM::Cell* cell);
|
||||||
void configureFog(float fogDepth, float underwaterFog, const osg::Vec4f& colour);
|
void configureFog(float fogDepth, float underwaterFog, float dlFactor, float dlOffset, const osg::Vec4f& colour);
|
||||||
|
|
||||||
void addCell(const MWWorld::CellStore* store);
|
void addCell(const MWWorld::CellStore* store);
|
||||||
void removeCell(const MWWorld::CellStore* store);
|
void removeCell(const MWWorld::CellStore* store);
|
||||||
|
@ -241,10 +241,12 @@ namespace MWRender
|
||||||
|
|
||||||
osg::ref_ptr<StateUpdater> mStateUpdater;
|
osg::ref_ptr<StateUpdater> mStateUpdater;
|
||||||
|
|
||||||
float mFogDepth;
|
float mLandFogStart;
|
||||||
|
float mLandFogEnd;
|
||||||
|
float mUnderwaterFogStart;
|
||||||
|
float mUnderwaterFogEnd;
|
||||||
osg::Vec4f mUnderwaterColor;
|
osg::Vec4f mUnderwaterColor;
|
||||||
float mUnderwaterWeight;
|
float mUnderwaterWeight;
|
||||||
float mUnderwaterFog;
|
|
||||||
float mUnderwaterIndoorFog;
|
float mUnderwaterIndoorFog;
|
||||||
osg::Vec4f mFogColor;
|
osg::Vec4f mFogColor;
|
||||||
|
|
||||||
|
@ -253,8 +255,10 @@ namespace MWRender
|
||||||
|
|
||||||
float mNearClip;
|
float mNearClip;
|
||||||
float mViewDistance;
|
float mViewDistance;
|
||||||
|
bool mDistantFog : 1;
|
||||||
|
bool mDistantTerrain : 1;
|
||||||
|
bool mFieldOfViewOverridden : 1;
|
||||||
float mFieldOfViewOverride;
|
float mFieldOfViewOverride;
|
||||||
bool mFieldOfViewOverridden;
|
|
||||||
float mFieldOfView;
|
float mFieldOfView;
|
||||||
float mFirstPersonFieldOfView;
|
float mFirstPersonFieldOfView;
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,9 @@ namespace MWRender
|
||||||
|
|
||||||
float mFogDepth;
|
float mFogDepth;
|
||||||
|
|
||||||
|
float mDLFogFactor;
|
||||||
|
float mDLFogOffset;
|
||||||
|
|
||||||
float mWindSpeed;
|
float mWindSpeed;
|
||||||
|
|
||||||
float mCloudSpeed;
|
float mCloudSpeed;
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace MWWorld
|
||||||
playerRef->mBase->mClass
|
playerRef->mBase->mClass
|
||||||
);
|
);
|
||||||
|
|
||||||
npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true);
|
npcStats.increaseSkill (ref->mBase->mData.mSkillId, *class_, true, true);
|
||||||
|
|
||||||
npcStats.flagAsUsed (ref->mBase->mId);
|
npcStats.flagAsUsed (ref->mBase->mId);
|
||||||
|
|
||||||
|
|
|
@ -102,6 +102,8 @@ Weather::Weather(const std::string& name,
|
||||||
const Fallback::Map& fallback,
|
const Fallback::Map& fallback,
|
||||||
float stormWindSpeed,
|
float stormWindSpeed,
|
||||||
float rainSpeed,
|
float rainSpeed,
|
||||||
|
float dlFactor,
|
||||||
|
float dlOffset,
|
||||||
const std::string& particleEffect)
|
const std::string& particleEffect)
|
||||||
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
|
: mCloudTexture(fallback.getFallbackString("Weather_" + name + "_Cloud_Texture"))
|
||||||
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
|
, mSkyColor(fallback.getFallbackColour("Weather_" + name +"_Sky_Sunrise_Color"),
|
||||||
|
@ -141,6 +143,8 @@ Weather::Weather(const std::string& name,
|
||||||
, mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement"))
|
, mFlashDecrement(fallback.getFallbackFloat("Weather_" + name + "_Flash_Decrement"))
|
||||||
, mFlashBrightness(0.0f)
|
, mFlashBrightness(0.0f)
|
||||||
{
|
{
|
||||||
|
mDL.FogFactor = dlFactor;
|
||||||
|
mDL.FogOffset = dlOffset;
|
||||||
mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0");
|
mThunderSoundID[0] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_0");
|
||||||
mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1");
|
mThunderSoundID[1] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_1");
|
||||||
mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2");
|
mThunderSoundID[2] = fallback.getFallbackString("Weather_" + name + "_Thunder_Sound_ID_2");
|
||||||
|
@ -541,16 +545,18 @@ WeatherManager::WeatherManager(MWRender::RenderingManager& rendering, const Fall
|
||||||
mTimeSettings.mSunriseTime = mSunriseTime;
|
mTimeSettings.mSunriseTime = mSunriseTime;
|
||||||
|
|
||||||
mWeatherSettings.reserve(10);
|
mWeatherSettings.reserve(10);
|
||||||
addWeather("Clear", fallback); // 0
|
// These distant land fog factor and offset values are the defaults MGE XE provides. Should be
|
||||||
addWeather("Cloudy", fallback); // 1
|
// provided by settings somewhere?
|
||||||
addWeather("Foggy", fallback); // 2
|
addWeather("Clear", fallback, 1.0f, 0.0f); // 0
|
||||||
addWeather("Overcast", fallback); // 3
|
addWeather("Cloudy", fallback, 0.9f, 0.0f); // 1
|
||||||
addWeather("Rain", fallback); // 4
|
addWeather("Foggy", fallback, 0.2f, 30.0f); // 2
|
||||||
addWeather("Thunderstorm", fallback); // 5
|
addWeather("Overcast", fallback, 0.7f, 0.0f); // 3
|
||||||
addWeather("Ashstorm", fallback, "meshes\\ashcloud.nif"); // 6
|
addWeather("Rain", fallback, 0.5f, 10.0f); // 4
|
||||||
addWeather("Blight", fallback, "meshes\\blightcloud.nif"); // 7
|
addWeather("Thunderstorm", fallback, 0.5f, 20.0f); // 5
|
||||||
addWeather("Snow", fallback, "meshes\\snow.nif"); // 8
|
addWeather("Ashstorm", fallback, 0.2f, 50.0f, "meshes\\ashcloud.nif"); // 6
|
||||||
addWeather("Blizzard", fallback, "meshes\\blizzard.nif"); // 9
|
addWeather("Blight", fallback, 0.2f, 60.0f, "meshes\\blightcloud.nif"); // 7
|
||||||
|
addWeather("Snow", fallback, 0.5f, 40.0f, "meshes\\snow.nif"); // 8
|
||||||
|
addWeather("Blizzard", fallback, 0.16f, 70.0f, "meshes\\blizzard.nif"); // 9
|
||||||
|
|
||||||
Store<ESM::Region>::iterator it = store.get<ESM::Region>().begin();
|
Store<ESM::Region>::iterator it = store.get<ESM::Region>().begin();
|
||||||
for(; it != store.get<ESM::Region>().end(); ++it)
|
for(; it != store.get<ESM::Region>().end(); ++it)
|
||||||
|
@ -718,7 +724,8 @@ void WeatherManager::update(float duration, bool paused, const TimeStamp& time,
|
||||||
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
|
mRendering.getSkyManager()->setMasserState(mMasser.calculateState(time));
|
||||||
mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time));
|
mRendering.getSkyManager()->setSecundaState(mSecunda.calculateState(time));
|
||||||
|
|
||||||
mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mFogColor);
|
mRendering.configureFog(mResult.mFogDepth, underwaterFog, mResult.mDLFogFactor,
|
||||||
|
mResult.mDLFogOffset/100.0f, mResult.mFogColor);
|
||||||
mRendering.setAmbientColour(mResult.mAmbientColor);
|
mRendering.setAmbientColour(mResult.mAmbientColor);
|
||||||
mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView);
|
mRendering.setSunColour(mResult.mSunColor, mResult.mSunColor * mResult.mGlareView);
|
||||||
|
|
||||||
|
@ -863,11 +870,12 @@ void WeatherManager::clear()
|
||||||
|
|
||||||
inline void WeatherManager::addWeather(const std::string& name,
|
inline void WeatherManager::addWeather(const std::string& name,
|
||||||
const Fallback::Map& fallback,
|
const Fallback::Map& fallback,
|
||||||
|
float dlFactor, float dlOffset,
|
||||||
const std::string& particleEffect)
|
const std::string& particleEffect)
|
||||||
{
|
{
|
||||||
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
|
static const float fStromWindSpeed = mStore.get<ESM::GameSetting>().find("fStromWindSpeed")->getFloat();
|
||||||
|
|
||||||
Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, particleEffect);
|
Weather weather(name, fallback, fStromWindSpeed, mRainSpeed, dlFactor, dlOffset, particleEffect);
|
||||||
|
|
||||||
mWeatherSettings.push_back(weather);
|
mWeatherSettings.push_back(weather);
|
||||||
}
|
}
|
||||||
|
@ -1055,6 +1063,8 @@ inline void WeatherManager::calculateResult(const int weatherID, const float gam
|
||||||
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
|
mResult.mNight = (gameHour < mSunriseTime || gameHour > mTimeSettings.mNightStart - 1);
|
||||||
|
|
||||||
mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings);
|
mResult.mFogDepth = current.mLandFogDepth.getValue(gameHour, mTimeSettings);
|
||||||
|
mResult.mDLFogFactor = current.mDL.FogFactor;
|
||||||
|
mResult.mDLFogOffset = current.mDL.FogOffset;
|
||||||
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
|
mResult.mFogColor = current.mFogColor.getValue(gameHour, mTimeSettings);
|
||||||
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
|
mResult.mAmbientColor = current.mAmbientColor.getValue(gameHour, mTimeSettings);
|
||||||
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
|
mResult.mSunColor = current.mSunColor.getValue(gameHour, mTimeSettings);
|
||||||
|
@ -1110,6 +1120,8 @@ inline void WeatherManager::calculateTransitionResult(const float factor, const
|
||||||
mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor);
|
mResult.mAmbientColor = lerp(current.mAmbientColor, other.mAmbientColor, factor);
|
||||||
mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor);
|
mResult.mSunDiscColor = lerp(current.mSunDiscColor, other.mSunDiscColor, factor);
|
||||||
mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor);
|
mResult.mFogDepth = lerp(current.mFogDepth, other.mFogDepth, factor);
|
||||||
|
mResult.mDLFogFactor = lerp(current.mDLFogFactor, other.mDLFogFactor, factor);
|
||||||
|
mResult.mDLFogOffset = lerp(current.mDLFogOffset, other.mDLFogOffset, factor);
|
||||||
mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor);
|
mResult.mWindSpeed = lerp(current.mWindSpeed, other.mWindSpeed, factor);
|
||||||
mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor);
|
mResult.mCloudSpeed = lerp(current.mCloudSpeed, other.mCloudSpeed, factor);
|
||||||
mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor);
|
mResult.mGlareView = lerp(current.mGlareView, other.mGlareView, factor);
|
||||||
|
|
|
@ -78,6 +78,8 @@ namespace MWWorld
|
||||||
const Fallback::Map& fallback,
|
const Fallback::Map& fallback,
|
||||||
float stormWindSpeed,
|
float stormWindSpeed,
|
||||||
float rainSpeed,
|
float rainSpeed,
|
||||||
|
float dlFactor,
|
||||||
|
float dlOffset,
|
||||||
const std::string& particleEffect);
|
const std::string& particleEffect);
|
||||||
|
|
||||||
std::string mCloudTexture;
|
std::string mCloudTexture;
|
||||||
|
@ -107,6 +109,12 @@ namespace MWWorld
|
||||||
// Also appears to modify how visible the sun, moons, and stars are for various weather effects.
|
// Also appears to modify how visible the sun, moons, and stars are for various weather effects.
|
||||||
float mGlareView;
|
float mGlareView;
|
||||||
|
|
||||||
|
// Fog factor and offset used with distant land rendering.
|
||||||
|
struct {
|
||||||
|
float FogFactor;
|
||||||
|
float FogOffset;
|
||||||
|
} mDL;
|
||||||
|
|
||||||
// Sound effect
|
// Sound effect
|
||||||
// This is used for Blight, Ashstorm and Blizzard (Bloodmoon)
|
// This is used for Blight, Ashstorm and Blizzard (Bloodmoon)
|
||||||
std::string mAmbientLoopSoundID;
|
std::string mAmbientLoopSoundID;
|
||||||
|
@ -299,6 +307,7 @@ namespace MWWorld
|
||||||
|
|
||||||
void addWeather(const std::string& name,
|
void addWeather(const std::string& name,
|
||||||
const Fallback::Map& fallback,
|
const Fallback::Map& fallback,
|
||||||
|
float dlFactor, float dlOffset,
|
||||||
const std::string& particleEffect = "");
|
const std::string& particleEffect = "");
|
||||||
|
|
||||||
void importRegions();
|
void importRegions();
|
||||||
|
|
|
@ -339,52 +339,76 @@ namespace Gui
|
||||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||||
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
|
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
|
||||||
|
|
||||||
// More hacks! The french game uses several win1252 characters that are not included
|
// Fall back from unavailable Windows-1252 encoding symbols to similar characters available in the game fonts
|
||||||
// in the cp437 encoding of the font. Fall back to similar available characters.
|
std::multimap<int, int> additional; // fallback glyph index, unicode
|
||||||
if (mEncoding == ToUTF8::CP437)
|
additional.insert(std::make_pair(156, 0x00A2)); // cent sign
|
||||||
|
additional.insert(std::make_pair(89, 0x00A5)); // yen sign
|
||||||
|
additional.insert(std::make_pair(221, 0x00A6)); // broken bar
|
||||||
|
additional.insert(std::make_pair(99, 0x00A9)); // copyright sign
|
||||||
|
additional.insert(std::make_pair(97, 0x00AA)); // prima ordinal indicator
|
||||||
|
additional.insert(std::make_pair(60, 0x00AB)); // double left-pointing angle quotation mark
|
||||||
|
additional.insert(std::make_pair(45, 0x00AD)); // soft hyphen
|
||||||
|
additional.insert(std::make_pair(114, 0x00AE)); // registered trademark symbol
|
||||||
|
additional.insert(std::make_pair(45, 0x00AF)); // macron
|
||||||
|
additional.insert(std::make_pair(241, 0x00B1)); // plus-minus sign
|
||||||
|
additional.insert(std::make_pair(50, 0x00B2)); // superscript two
|
||||||
|
additional.insert(std::make_pair(51, 0x00B3)); // superscript three
|
||||||
|
additional.insert(std::make_pair(44, 0x00B8)); // cedilla
|
||||||
|
additional.insert(std::make_pair(49, 0x00B9)); // superscript one
|
||||||
|
additional.insert(std::make_pair(111, 0x00BA)); // primo ordinal indicator
|
||||||
|
additional.insert(std::make_pair(62, 0x00BB)); // double right-pointing angle quotation mark
|
||||||
|
additional.insert(std::make_pair(63, 0x00BF)); // inverted question mark
|
||||||
|
additional.insert(std::make_pair(65, 0x00C6)); // latin capital ae ligature
|
||||||
|
additional.insert(std::make_pair(79, 0x00D8)); // latin capital o with stroke
|
||||||
|
additional.insert(std::make_pair(97, 0x00E6)); // latin small ae ligature
|
||||||
|
additional.insert(std::make_pair(111, 0x00F8)); // latin small o with stroke
|
||||||
|
additional.insert(std::make_pair(79, 0x0152)); // latin capital oe ligature
|
||||||
|
additional.insert(std::make_pair(111, 0x0153)); // latin small oe ligature
|
||||||
|
additional.insert(std::make_pair(83, 0x015A)); // latin capital s with caron
|
||||||
|
additional.insert(std::make_pair(115, 0x015B)); // latin small s with caron
|
||||||
|
additional.insert(std::make_pair(89, 0x0178)); // latin capital y with diaresis
|
||||||
|
additional.insert(std::make_pair(90, 0x017D)); // latin capital z with caron
|
||||||
|
additional.insert(std::make_pair(122, 0x017E)); // latin small z with caron
|
||||||
|
additional.insert(std::make_pair(102, 0x0192)); // latin small f with hook
|
||||||
|
additional.insert(std::make_pair(94, 0x02C6)); // circumflex modifier
|
||||||
|
additional.insert(std::make_pair(126, 0x02DC)); // small tilde
|
||||||
|
additional.insert(std::make_pair(69, 0x0401)); // cyrillic capital io (no diaeresis latin e is available)
|
||||||
|
additional.insert(std::make_pair(137, 0x0451)); // cyrillic small io
|
||||||
|
additional.insert(std::make_pair(45, 0x2012)); // figure dash
|
||||||
|
additional.insert(std::make_pair(45, 0x2013)); // en dash
|
||||||
|
additional.insert(std::make_pair(45, 0x2014)); // em dash
|
||||||
|
additional.insert(std::make_pair(39, 0x2018)); // left single quotation mark
|
||||||
|
additional.insert(std::make_pair(39, 0x2019)); // right single quotation mark
|
||||||
|
additional.insert(std::make_pair(44, 0x201A)); // single low quotation mark
|
||||||
|
additional.insert(std::make_pair(39, 0x201B)); // single high quotation mark (reversed)
|
||||||
|
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark
|
||||||
|
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark
|
||||||
|
additional.insert(std::make_pair(44, 0x201E)); // double low quotation mark
|
||||||
|
additional.insert(std::make_pair(34, 0x201F)); // double high quotation mark (reversed)
|
||||||
|
additional.insert(std::make_pair(43, 0x2020)); // dagger
|
||||||
|
additional.insert(std::make_pair(216, 0x2021)); // double dagger (note: this glyph is not available)
|
||||||
|
additional.insert(std::make_pair(46, 0x2026)); // ellipsis
|
||||||
|
additional.insert(std::make_pair(37, 0x2030)); // per mille sign
|
||||||
|
additional.insert(std::make_pair(60, 0x2039)); // single left-pointing angle quotation mark
|
||||||
|
additional.insert(std::make_pair(62, 0x203A)); // single right-pointing angle quotation mark
|
||||||
|
additional.insert(std::make_pair(101, 0x20AC)); // euro sign
|
||||||
|
additional.insert(std::make_pair(84, 0x2122)); // trademark sign
|
||||||
|
additional.insert(std::make_pair(45, 0x2212)); // minus sign
|
||||||
|
|
||||||
|
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
|
||||||
{
|
{
|
||||||
std::multimap<int, int> additional; // <cp437, unicode>
|
if (it->first != i)
|
||||||
additional.insert(std::make_pair(39, 0x2019)); // apostrophe
|
continue;
|
||||||
additional.insert(std::make_pair(45, 0x2013)); // dash
|
code = codes->createChild("Code");
|
||||||
additional.insert(std::make_pair(45, 0x2014)); // dash
|
code->addAttribute("index", it->second);
|
||||||
additional.insert(std::make_pair(34, 0x201D)); // right double quotation mark
|
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
||||||
additional.insert(std::make_pair(34, 0x201C)); // left double quotation mark
|
+ MyGUI::utility::toString(y1) + " "
|
||||||
additional.insert(std::make_pair(44, 0x201A));
|
+ MyGUI::utility::toString(w) + " "
|
||||||
additional.insert(std::make_pair(44, 0x201E));
|
+ MyGUI::utility::toString(h));
|
||||||
additional.insert(std::make_pair(43, 0x2020));
|
code->addAttribute("advance", data[i].width);
|
||||||
additional.insert(std::make_pair(94, 0x02C6));
|
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
||||||
additional.insert(std::make_pair(37, 0x2030));
|
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
||||||
additional.insert(std::make_pair(83, 0x0160));
|
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
|
||||||
additional.insert(std::make_pair(60, 0x2039));
|
|
||||||
additional.insert(std::make_pair(79, 0x0152));
|
|
||||||
additional.insert(std::make_pair(90, 0x017D));
|
|
||||||
additional.insert(std::make_pair(39, 0x2019));
|
|
||||||
additional.insert(std::make_pair(126, 0x02DC));
|
|
||||||
additional.insert(std::make_pair(84, 0x2122));
|
|
||||||
additional.insert(std::make_pair(83, 0x0161));
|
|
||||||
additional.insert(std::make_pair(62, 0x203A));
|
|
||||||
additional.insert(std::make_pair(111, 0x0153));
|
|
||||||
additional.insert(std::make_pair(122, 0x017E));
|
|
||||||
additional.insert(std::make_pair(89, 0x0178));
|
|
||||||
additional.insert(std::make_pair(156, 0x00A2));
|
|
||||||
additional.insert(std::make_pair(46, 0x2026));
|
|
||||||
|
|
||||||
for (std::multimap<int, int>::iterator it = additional.begin(); it != additional.end(); ++it)
|
|
||||||
{
|
|
||||||
if (it->first != i)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
code = codes->createChild("Code");
|
|
||||||
code->addAttribute("index", it->second);
|
|
||||||
code->addAttribute("coord", MyGUI::utility::toString(x1) + " "
|
|
||||||
+ MyGUI::utility::toString(y1) + " "
|
|
||||||
+ MyGUI::utility::toString(w) + " "
|
|
||||||
+ MyGUI::utility::toString(h));
|
|
||||||
code->addAttribute("advance", data[i].width);
|
|
||||||
code->addAttribute("bearing", MyGUI::utility::toString(data[i].kerning) + " "
|
|
||||||
+ MyGUI::utility::toString((fontSize-data[i].ascent)));
|
|
||||||
code->addAttribute("size", MyGUI::IntSize(static_cast<int>(data[i].width), static_cast<int>(data[i].height)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ASCII vertical bar, use this as text input cursor
|
// ASCII vertical bar, use this as text input cursor
|
||||||
|
|
|
@ -254,8 +254,9 @@ namespace mwmp
|
||||||
BasePlayer(RakNet::RakNetGUID guid) : guid(guid)
|
BasePlayer(RakNet::RakNetGUID guid) : guid(guid)
|
||||||
{
|
{
|
||||||
spellbookChanges.action = SpellbookChanges::Type::None;
|
spellbookChanges.action = SpellbookChanges::Type::None;
|
||||||
useCreatureName = false;
|
|
||||||
isWerewolf = false;
|
isWerewolf = false;
|
||||||
|
displayCreatureName = false;
|
||||||
|
resetStats = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BasePlayer()
|
BasePlayer()
|
||||||
|
@ -324,10 +325,12 @@ namespace mwmp
|
||||||
std::string sound;
|
std::string sound;
|
||||||
Animation animation;
|
Animation animation;
|
||||||
|
|
||||||
|
bool resetStats;
|
||||||
float scale;
|
float scale;
|
||||||
bool isWerewolf;
|
bool isWerewolf;
|
||||||
std::string creatureModel;
|
|
||||||
bool useCreatureName;
|
bool displayCreatureName;
|
||||||
|
std::string creatureRefId;
|
||||||
|
|
||||||
std::string deathReason;
|
std::string deathReason;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,5 @@ void PacketPlayerBaseInfo::Packet(RakNet::BitStream *bs, bool send)
|
||||||
|
|
||||||
RW(player->birthsign, send, 1);
|
RW(player->birthsign, send, 1);
|
||||||
|
|
||||||
RW(player->creatureModel, send, 1);
|
RW(player->resetStats, send);
|
||||||
RW(player->useCreatureName, send);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,4 +14,7 @@ void PacketPlayerShapeshift::Packet(RakNet::BitStream *bs, bool send)
|
||||||
|
|
||||||
RW(player->scale, send);
|
RW(player->scale, send);
|
||||||
RW(player->isWerewolf, send);
|
RW(player->isWerewolf, send);
|
||||||
|
|
||||||
|
RW(player->displayCreatureName, send);
|
||||||
|
RW(player->creatureRefId, send, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -90,6 +90,24 @@ pointers cache size = 40
|
||||||
# If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells
|
# If true, use paging and LOD algorithms to display the entire terrain. If false, only display terrain of the loaded cells
|
||||||
distant terrain = false
|
distant terrain = false
|
||||||
|
|
||||||
|
[Fog]
|
||||||
|
|
||||||
|
# If true, use extended fog parameters for distant terrain not controlled by
|
||||||
|
# viewing distance. If false, use the standard fog calculations.
|
||||||
|
use distant fog = false
|
||||||
|
|
||||||
|
distant land fog start = 16384
|
||||||
|
|
||||||
|
distant land fog end = 40960
|
||||||
|
|
||||||
|
distant underwater fog start = -4096
|
||||||
|
|
||||||
|
distant underwater fog end = 2457.6
|
||||||
|
|
||||||
|
distant interior fog start = 0
|
||||||
|
|
||||||
|
distant interior fog end = 16384
|
||||||
|
|
||||||
[Map]
|
[Map]
|
||||||
|
|
||||||
# Size of each exterior cell in pixels in the world map. (e.g. 12 to 24).
|
# Size of each exterior cell in pixels in the world map. (e.g. 12 to 24).
|
||||||
|
@ -182,6 +200,9 @@ classic reflect absorb attribute behavior = true
|
||||||
# Show duration of magic effect and lights in the spells window.
|
# Show duration of magic effect and lights in the spells window.
|
||||||
show effect duration = false
|
show effect duration = false
|
||||||
|
|
||||||
|
# Account for the first follower in fast travel cost calculations.
|
||||||
|
charge for every follower travelling = false
|
||||||
|
|
||||||
# Prevents merchants from equipping items that are sold to them.
|
# Prevents merchants from equipping items that are sold to them.
|
||||||
prevent merchant equipping = false
|
prevent merchant equipping = false
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue