forked from teamnwah/openmw-tes3coop
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
6c4920c58e
82 changed files with 683 additions and 404 deletions
|
@ -1,7 +1,7 @@
|
|||
OpenMW
|
||||
======
|
||||
|
||||
[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
[![Build Status](https://img.shields.io/travis/OpenMW/openmw.svg?style=plastic)](https://travis-ci.org/OpenMW/openmw) [![Coverity Scan Build Status](https://scan.coverity.com/projects/3740/badge.svg)](https://scan.coverity.com/projects/3740)
|
||||
|
||||
OpenMW is an attempt at recreating the engine for the popular role-playing game
|
||||
Morrowind by Bethesda Softworks. You need to own and install the original game for OpenMW to work.
|
||||
|
@ -68,7 +68,10 @@ Command line options
|
|||
of the blacklist is enabled)
|
||||
--script-blacklist-use [=arg(=1)] (=1)
|
||||
enable script blacklisting
|
||||
--load-savegame arg load a save game file on game startup
|
||||
--load-savegame arg load a save game file on game startup
|
||||
(specify an absolute filename or a
|
||||
filename relative to the current
|
||||
working directory)
|
||||
--skip-menu [=arg(=1)] (=0) skip main menu on game startup
|
||||
--new-game [=arg(=1)] (=0) run new game sequence (ignored if
|
||||
skip-menu=0)
|
||||
|
|
|
@ -535,10 +535,10 @@ void Record<ESM::Class>::print()
|
|||
std::cout << " Specialization: " << specializationLabel(mData.mData.mSpecialization)
|
||||
<< " (" << mData.mData.mSpecialization << ")" << std::endl;
|
||||
for (int i = 0; i != 5; i++)
|
||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][0])
|
||||
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][0])
|
||||
<< " (" << mData.mData.mSkills[i][0] << ")" << std::endl;
|
||||
for (int i = 0; i != 5; i++)
|
||||
std::cout << " Minor Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
||||
std::cout << " Major Skill: " << skillLabel(mData.mData.mSkills[i][1])
|
||||
<< " (" << mData.mData.mSkills[i][1] << ")" << std::endl;
|
||||
}
|
||||
|
||||
|
@ -837,7 +837,7 @@ void Record<ESM::CreatureLevList>::print()
|
|||
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
|
||||
std::cout << " Flags: " << creatureListFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
|
||||
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
|
||||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Creature: Level: " << iit->mLevel
|
||||
<< " Creature: " << iit->mId << std::endl;
|
||||
|
@ -849,7 +849,7 @@ void Record<ESM::ItemLevList>::print()
|
|||
std::cout << " Chance for None: " << (int)mData.mChanceNone << std::endl;
|
||||
std::cout << " Flags: " << itemListFlags(mData.mFlags) << std::endl;
|
||||
std::cout << " Number of items: " << mData.mList.size() << std::endl;
|
||||
std::vector<ESM::LeveledListBase::LevelItem>::iterator iit;
|
||||
std::vector<ESM::LevelledListBase::LevelItem>::iterator iit;
|
||||
for (iit = mData.mList.begin(); iit != mData.mList.end(); ++iit)
|
||||
std::cout << " Inventory: Level: " << iit->mLevel
|
||||
<< " Item: " << iit->mId << std::endl;
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <components/esm/weatherstate.hpp>
|
||||
#include <components/esm/globalscript.hpp>
|
||||
#include <components/esm/queststate.hpp>
|
||||
#include <components/esm/stolenitems.hpp>
|
||||
|
||||
#include "importcrec.hpp"
|
||||
#include "importcntc.hpp"
|
||||
|
@ -387,24 +388,50 @@ public:
|
|||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
std::string itemid = esm.getHNString("NAME");
|
||||
Misc::StringUtils::toLower(itemid);
|
||||
|
||||
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
|
||||
{
|
||||
if (esm.retSubName().toString() == "FNAM")
|
||||
{
|
||||
std::string factionid = esm.getHString();
|
||||
mFactionStolenItems.insert(std::make_pair(itemid, factionid));
|
||||
mStolenItems[itemid].insert(std::make_pair(Misc::StringUtils::lowerCase(factionid), true));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string ownerid = esm.getHString();
|
||||
mStolenItems.insert(std::make_pair(itemid, ownerid));
|
||||
mStolenItems[itemid].insert(std::make_pair(Misc::StringUtils::lowerCase(ownerid), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void write(ESM::ESMWriter &esm)
|
||||
{
|
||||
ESM::StolenItems items;
|
||||
for (std::map<std::string, std::set<Owner> >::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
|
||||
{
|
||||
std::map<std::pair<std::string, bool>, int> owners;
|
||||
for (std::set<Owner>::const_iterator ownerIt = it->second.begin(); ownerIt != it->second.end(); ++ownerIt)
|
||||
{
|
||||
owners.insert(std::make_pair(std::make_pair(ownerIt->first, ownerIt->second)
|
||||
// Since OpenMW doesn't suffer from the owner contamination bug,
|
||||
// it needs a count argument. But for legacy savegames, we don't know
|
||||
// this count, so must assume all items of that ID are stolen,
|
||||
// like vanilla MW did.
|
||||
,std::numeric_limits<int>::max()));
|
||||
}
|
||||
|
||||
items.mStolenItems.insert(std::make_pair(it->first, owners));
|
||||
}
|
||||
|
||||
esm.startRecord(ESM::REC_STLN);
|
||||
items.write(esm);
|
||||
esm.endRecord(ESM::REC_STLN);
|
||||
}
|
||||
|
||||
private:
|
||||
std::multimap<std::string, std::string> mStolenItems;
|
||||
std::multimap<std::string, std::string> mFactionStolenItems;
|
||||
typedef std::pair<std::string, bool> Owner; // <owner id, bool isFaction>
|
||||
|
||||
std::map<std::string, std::set<Owner> > mStolenItems;
|
||||
};
|
||||
|
||||
/// Seen responses for a dialogue topic?
|
||||
|
|
|
@ -17,6 +17,8 @@ namespace ESSImport
|
|||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
out.mObject.mNpcStats.mSkillIncrease[i] = pcdt.mPNAM.mSkillIncreases[i];
|
||||
for (int i=0; i<27; ++i)
|
||||
out.mObject.mNpcStats.mSkills[i].mRegular.mProgress = pcdt.mPNAM.mSkillProgress[i];
|
||||
out.mObject.mNpcStats.mLevelProgress = pcdt.mPNAM.mLevelProgress;
|
||||
|
||||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Weapon)
|
||||
|
@ -24,9 +26,6 @@ namespace ESSImport
|
|||
if (pcdt.mPNAM.mDrawState & PCDT::DrawState_Spell)
|
||||
out.mObject.mCreatureStats.mDrawState = 2;
|
||||
|
||||
// TODO: convert PNAM.mSkillProgress, needs to be converted to uniform scale
|
||||
// (or change openmw to accept non-uniform skill progress)
|
||||
|
||||
firstPersonCam = (pcdt.mPNAM.mCameraState == PCDT::CameraState_FirstPerson);
|
||||
|
||||
for (std::vector<std::string>::const_iterator it = pcdt.mKnownDialogueTopics.begin();
|
||||
|
|
|
@ -61,7 +61,7 @@ namespace ESSImport
|
|||
bool mHasACSC;
|
||||
ACSC mACSC;
|
||||
|
||||
int mSkills[27][2];
|
||||
int mSkills[27][2]; // skills, base and modified
|
||||
|
||||
// creature combat stats, base and modified
|
||||
// I think these can be ignored in the conversion, because it is not possible
|
||||
|
|
|
@ -22,7 +22,7 @@ namespace ESSImport
|
|||
ActorData::load(esm);
|
||||
if (esm.isNextSub("LVCR"))
|
||||
{
|
||||
// occurs on leveled creature spawner references
|
||||
// occurs on levelled creature spawner references
|
||||
// probably some identifier for the creature that has been spawned?
|
||||
unsigned char lvcr;
|
||||
esm.getHT(lvcr);
|
||||
|
@ -32,7 +32,7 @@ namespace ESSImport
|
|||
mEnabled = true;
|
||||
esm.getHNOT(mEnabled, "ZNAM");
|
||||
|
||||
// DATA should occur for all references, except leveled creature spawners
|
||||
// DATA should occur for all references, except levelled creature spawners
|
||||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||
// alarmvoi0000.ess
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
#define MAC_OS_X_VERSION_MIN_REQUIRED __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__
|
||||
#endif // MAC_OS_X_VERSION_MIN_REQUIRED
|
||||
|
||||
#include <SDL.h>
|
||||
#include <SDL_video.h>
|
||||
|
||||
#include <OgreRoot.h>
|
||||
#include <OgreRenderSystem.h>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include <iostream>
|
||||
#include <csignal>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QTextCodec>
|
||||
|
@ -26,6 +27,8 @@ int main(int argc, char *argv[])
|
|||
qDebug() << "SDL_Init failed: " << QString::fromStdString(SDL_GetError());
|
||||
return 0;
|
||||
}
|
||||
signal(SIGINT, SIG_DFL); // We don't want to use the SDL event loop in the launcher,
|
||||
// so reset SIGINT which SDL wants to redirect to an SDL_Quit event.
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
|
|
|
@ -170,7 +170,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt)
|
|||
|
||||
OMW::Engine::Engine(Files::ConfigurationManager& configurationManager)
|
||||
: mOgre (0)
|
||||
, mFpsLevel(0)
|
||||
, mVerboseScripts (false)
|
||||
, mSkipMenu (false)
|
||||
, mUseSound (true)
|
||||
|
@ -292,16 +291,10 @@ std::string OMW::Engine::loadSettings (Settings::Manager & settings)
|
|||
else
|
||||
throw std::runtime_error ("No default settings file found! Make sure the file \"settings-default.cfg\" was properly installed.");
|
||||
|
||||
// load user settings if they exist, otherwise just load the default settings as user settings
|
||||
// load user settings if they exist
|
||||
const std::string settingspath = mCfgMgr.getUserConfigPath().string() + "/settings.cfg";
|
||||
if (boost::filesystem::exists(settingspath))
|
||||
settings.loadUser(settingspath);
|
||||
else if (boost::filesystem::exists(localdefault))
|
||||
settings.loadUser(localdefault);
|
||||
else if (boost::filesystem::exists(globaldefault))
|
||||
settings.loadUser(globaldefault);
|
||||
|
||||
mFpsLevel = settings.getInt("fps", "HUD");
|
||||
|
||||
// load nif overrides
|
||||
NifOverrides::Overrides nifOverrides;
|
||||
|
@ -377,7 +370,7 @@ void OMW::Engine::prepareEngine (Settings::Manager & settings)
|
|||
mEnvironment.setInputManager (input);
|
||||
|
||||
MWGui::WindowManager* window = new MWGui::WindowManager(
|
||||
mExtensions, mFpsLevel, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
|
||||
mExtensions, mOgre, mCfgMgr.getLogPath().string() + std::string("/"),
|
||||
mCfgMgr.getCachePath ().string(), mScriptConsoleMode, mTranslationDataStorage, mEncoding, mExportFonts, mFallbackMap);
|
||||
mEnvironment.setWindowManager (window);
|
||||
|
||||
|
@ -578,11 +571,6 @@ void OMW::Engine::setSoundUsage(bool soundUsage)
|
|||
mUseSound = soundUsage;
|
||||
}
|
||||
|
||||
void OMW::Engine::showFPS(int level)
|
||||
{
|
||||
mFpsLevel = level;
|
||||
}
|
||||
|
||||
void OMW::Engine::setEncoding(const ToUTF8::FromType& encoding)
|
||||
{
|
||||
mEncoding = encoding;
|
||||
|
|
|
@ -71,7 +71,6 @@ namespace OMW
|
|||
OEngine::Render::OgreRenderer *mOgre;
|
||||
std::string mCellName;
|
||||
std::vector<std::string> mContentFiles;
|
||||
int mFpsLevel;
|
||||
bool mVerboseScripts;
|
||||
bool mSkipMenu;
|
||||
bool mUseSound;
|
||||
|
@ -151,9 +150,6 @@ namespace OMW
|
|||
*/
|
||||
void addContentFile(const std::string& file);
|
||||
|
||||
/// Enable fps counter
|
||||
void showFPS(int level);
|
||||
|
||||
/// Enable or disable verbose script output
|
||||
void setScriptsVerbosity(bool scriptsVerbosity);
|
||||
|
||||
|
|
|
@ -153,7 +153,7 @@ bool parseOptions (int argc, char** argv, OMW::Engine& engine, Files::Configurat
|
|||
->default_value(true), "enable script blacklisting")
|
||||
|
||||
("load-savegame", bpo::value<std::string>()->default_value(""),
|
||||
"load a save game file on game startup")
|
||||
"load a save game file on game startup (specify an absolute filename or a filename relative to the current working directory)")
|
||||
|
||||
("skip-menu", bpo::value<bool>()->implicit_value(true)
|
||||
->default_value(false), "skip main menu on game startup")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#ifndef GAME_BASE_INVIRONMENT_H
|
||||
#define GAME_BASE_INVIRONMENT_H
|
||||
#ifndef GAME_BASE_ENVIRONMENT_H
|
||||
#define GAME_BASE_ENVIRONMENT_H
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define GAME_MWBASE_INPUTMANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
namespace MWBase
|
||||
{
|
||||
|
@ -29,7 +29,7 @@ namespace MWBase
|
|||
|
||||
virtual void changeInputMode(bool guiMode) = 0;
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||
|
||||
virtual void setDragDrop(bool dragDrop) = 0;
|
||||
|
||||
|
|
|
@ -129,16 +129,15 @@ namespace MWBase
|
|||
/// @return false if the attack was considered a "friendly hit" and forgiven
|
||||
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker) = 0;
|
||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count) = 0;
|
||||
/// @param container The container the item is in; may be empty for an item in the world
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||
int count) = 0;
|
||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item) = 0;
|
||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||
/// @return was it illegal, and someone saw you doing it?
|
||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed) = 0;
|
||||
|
||||
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim) = 0;
|
||||
|
||||
enum PersuasionType
|
||||
{
|
||||
PT_Admire,
|
||||
|
@ -203,6 +202,15 @@ namespace MWBase
|
|||
virtual void keepPlayerAlive() = 0;
|
||||
|
||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const = 0;
|
||||
|
||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer) = 0;
|
||||
|
||||
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).
|
||||
/// <Owner, item count>
|
||||
virtual std::vector<std::pair<std::string, int> > getStolenItemOwners(const std::string& itemid) = 0;
|
||||
|
||||
/// Has the player stolen this item from the given owner?
|
||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
#define GAME_MWBASE_SOUNDMANAGER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <set>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace Ogre
|
||||
|
@ -74,7 +72,7 @@ namespace MWBase
|
|||
|
||||
virtual ~SoundManager() {}
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& settings) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& settings) = 0;
|
||||
|
||||
virtual void stopMusic() = 0;
|
||||
///< Stops music if it's playing
|
||||
|
|
|
@ -5,16 +5,20 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
|
||||
#include "../mwmechanics/stat.hpp"
|
||||
|
||||
#include "../mwgui/mode.hpp"
|
||||
|
||||
namespace Loading
|
||||
{
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace Translation
|
||||
{
|
||||
class Storage;
|
||||
}
|
||||
|
||||
namespace MyGUI
|
||||
{
|
||||
class Gui;
|
||||
|
@ -267,7 +271,7 @@ namespace MWBase
|
|||
*/
|
||||
virtual std::string getGameSettingString(const std::string &id, const std::string &default_) = 0;
|
||||
|
||||
virtual void processChangedSettings(const Settings::CategorySettingVector& changed) = 0;
|
||||
virtual void processChangedSettings(const std::set< std::pair<std::string, std::string> >& changed) = 0;
|
||||
|
||||
virtual void windowResized(int x, int y) = 0;
|
||||
|
||||
|
|
|
@ -3,26 +3,23 @@
|
|||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
#include <set>
|
||||
|
||||
#include <components/esm/cellid.hpp>
|
||||
|
||||
#include "../mwworld/globals.hpp"
|
||||
#include "../mwworld/ptr.hpp"
|
||||
|
||||
namespace Ogre
|
||||
{
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Quaternion;
|
||||
class Image;
|
||||
}
|
||||
|
||||
namespace OEngine
|
||||
namespace Loading
|
||||
{
|
||||
namespace Physic
|
||||
{
|
||||
class PhysicEngine;
|
||||
}
|
||||
class Listener;
|
||||
}
|
||||
|
||||
namespace ESM
|
||||
|
@ -390,7 +387,7 @@ namespace MWBase
|
|||
virtual bool canPlaceObject (float cursorX, float cursorY) = 0;
|
||||
///< @return true if it is possible to place on object at specified cursor location
|
||||
|
||||
virtual void processChangedSettings (const Settings::CategorySettingVector& settings) = 0;
|
||||
virtual void processChangedSettings (const std::set< std::pair<std::string, std::string> >& settings) = 0;
|
||||
|
||||
virtual bool isFlying(const MWWorld::Ptr &ptr) const = 0;
|
||||
virtual bool isSlowFalling(const MWWorld::Ptr &ptr) const = 0;
|
||||
|
|
|
@ -59,8 +59,10 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Container> *ref =
|
||||
ptr.get<ESM::Container>();
|
||||
|
||||
// setting ownership not needed, since taking items from a container inherits the
|
||||
// container's owner automatically
|
||||
data->mContainerStore.fill(
|
||||
ref->mBase->mInventory, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank(), MWBase::Environment::get().getWorld()->getStore());
|
||||
ref->mBase->mInventory, "");
|
||||
|
||||
// store
|
||||
ptr.getRefData().setCustomData (data.release());
|
||||
|
@ -82,7 +84,10 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getOwner(), ptr.getCellRef().getFaction(), ptr.getCellRef().getFactionRank());
|
||||
|
||||
// setting ownership not needed, since taking items from a container inherits the
|
||||
// container's owner automatically
|
||||
store.restock(list, ptr, "");
|
||||
}
|
||||
|
||||
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, const std::string& model, MWRender::RenderingInterface& renderingInterface) const
|
||||
|
|
|
@ -139,8 +139,7 @@ namespace MWClass
|
|||
// store
|
||||
ptr.getRefData().setCustomData(data.release());
|
||||
|
||||
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr), "", -1,
|
||||
MWBase::Environment::get().getWorld()->getStore());
|
||||
getContainerStore(ptr).fill(ref->mBase->mInventory, getId(ptr));
|
||||
|
||||
if (ref->mBase->mFlags & ESM::Creature::Weapon)
|
||||
getInventoryStore(ptr).autoEquip(ptr);
|
||||
|
@ -886,7 +885,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId());
|
||||
}
|
||||
|
||||
int Creature::getBaseFightRating(const MWWorld::Ptr &ptr) const
|
||||
|
|
|
@ -384,8 +384,8 @@ namespace MWClass
|
|||
}
|
||||
|
||||
// inventory
|
||||
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr), "", -1,
|
||||
MWBase::Environment::get().getWorld()->getStore());
|
||||
// setting ownership is used to make the NPC auto-equip his initial equipment only, and not bartered items
|
||||
data->mInventoryStore.fill(ref->mBase->mInventory, getId(ptr));
|
||||
|
||||
data->mNpcStats.setGoldPool(gold);
|
||||
|
||||
|
@ -1328,7 +1328,7 @@ namespace MWClass
|
|||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
const ESM::InventoryList& list = ref->mBase->mInventory;
|
||||
MWWorld::ContainerStore& store = getContainerStore(ptr);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId(), "", -1);
|
||||
store.restock(list, ptr, ptr.getCellRef().getRefId());
|
||||
}
|
||||
|
||||
int Npc::getBaseFightRating (const MWWorld::Ptr& ptr) const
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "scripttest.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "../mwworld/manualref.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
|
||||
|
|
|
@ -285,7 +285,7 @@ namespace MWGui
|
|||
if (mPtr.getClass().isActor() && mPtr.getClass().getCreatureStats(mPtr).isDead())
|
||||
return true;
|
||||
else
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, count);
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, item.mBase, mPtr, count);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -339,7 +339,8 @@ namespace MWGui
|
|||
for (int i=0; i<2; ++i)
|
||||
{
|
||||
MWWorld::Ptr item = (i == 0) ? mEnchanting.getOldItem() : mEnchanting.getGem();
|
||||
if (Misc::StringUtils::ciEqual(item.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(item.getCellRef().getRefId(),
|
||||
mPtr.getCellRef().getRefId()))
|
||||
{
|
||||
std::string msg = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sNotifyMessage49")->getString();
|
||||
if (msg.find("%s") != std::string::npos)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <MyGUI_ScrollView.h>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
|
|
@ -65,16 +65,7 @@ MWWorld::Ptr InventoryItemModel::moveItem(const ItemStack &item, size_t count, I
|
|||
if (item.mFlags & ItemStack::Flag_Bound)
|
||||
return MWWorld::Ptr();
|
||||
|
||||
bool setNewOwner = false;
|
||||
|
||||
// Are you dead? Then you wont need that anymore
|
||||
if (mActor.getClass().isActor() && mActor.getClass().getCreatureStats(mActor).isDead()
|
||||
// Make sure that the item is actually owned by the dead actor
|
||||
// Prevents a potential exploit for resetting the owner of any item, by placing the item in a corpse
|
||||
&& Misc::StringUtils::ciEqual(item.mBase.getCellRef().getOwner(), mActor.getCellRef().getRefId()))
|
||||
setNewOwner = true;
|
||||
|
||||
MWWorld::Ptr ret = otherModel->copyItem(item, count, setNewOwner);
|
||||
MWWorld::Ptr ret = otherModel->copyItem(item, count, false);
|
||||
removeItem(item, count);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
#include <MyGUI_InputManager.h>
|
||||
#include <MyGUI_Button.h>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/soundmanager.hpp"
|
||||
|
@ -622,7 +624,7 @@ namespace MWGui
|
|||
throw std::runtime_error("Added item not found");
|
||||
mDragAndDrop->startDrag(i, mSortModel, mTradeModel, mItemView, count);
|
||||
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, count);
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(player, newObject, MWWorld::Ptr(), count);
|
||||
|
||||
if (MWBase::Environment::get().getWindowManager()->getSpellWindow())
|
||||
MWBase::Environment::get().getWindowManager()->getSpellWindow()->updateSpells();
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
#include "itemmodel.hpp"
|
||||
|
||||
#include <set>
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/containerstore.hpp"
|
||||
#include "../mwworld/store.hpp"
|
||||
|
|
|
@ -46,20 +46,27 @@ namespace MWGui
|
|||
ItemModel();
|
||||
virtual ~ItemModel() {}
|
||||
|
||||
typedef int ModelIndex;
|
||||
typedef int ModelIndex; // -1 means invalid index
|
||||
|
||||
/// Throws for invalid index or out of range index
|
||||
virtual ItemStack getItem (ModelIndex index) = 0;
|
||||
///< throws for invalid index
|
||||
|
||||
/// The number of items in the model, this specifies the range of indices you can pass to
|
||||
/// the getItem function (but this range is only valid until the next call to update())
|
||||
virtual size_t getItemCount() = 0;
|
||||
|
||||
/// Returns an invalid index if the item was not found
|
||||
virtual ModelIndex getIndex (ItemStack item) = 0;
|
||||
|
||||
/// Rebuild the item model, this will invalidate existing model indices
|
||||
virtual void update() = 0;
|
||||
|
||||
/// Move items from this model to \a otherModel.
|
||||
/// @note Derived implementations may return an empty Ptr if the move was unsuccessful.
|
||||
virtual MWWorld::Ptr moveItem (const ItemStack& item, size_t count, ItemModel* otherModel);
|
||||
|
||||
/// @param setNewOwner Set the copied item's owner to the actor we are copying to, or keep the original owner?
|
||||
/// @param setNewOwner If true, set the copied item's owner to the actor we are copying to,
|
||||
/// otherwise reset owner to ""
|
||||
virtual MWWorld::Ptr copyItem (const ItemStack& item, size_t count, bool setNewOwner=false) = 0;
|
||||
virtual void removeItem (const ItemStack& item, size_t count) = 0;
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
|
||||
#include <components/misc/utf8stream.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/journal.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
|
|
@ -139,7 +139,6 @@ namespace MWGui
|
|||
|
||||
if(world->getStore().get<ESM::Class>().isDynamic(cls->mId))
|
||||
{
|
||||
// Vanilla uses thief.dds for custom classes.
|
||||
// Choosing Stealth specialization and Speed/Agility as attributes, if possible. Otherwise fall back to first class found.
|
||||
MWWorld::SharedIterator<ESM::Class> it = world->getStore().get<ESM::Class>().begin();
|
||||
for(; it != world->getStore().get<ESM::Class>().end(); ++it)
|
||||
|
@ -173,14 +172,17 @@ namespace MWGui
|
|||
if (pcStats.getAttribute(i).getBase() < 100)
|
||||
{
|
||||
mAttributes[i]->setEnabled(true);
|
||||
mAttributeValues[i]->setEnabled(true);
|
||||
availableAttributes++;
|
||||
|
||||
int mult = pcStats.getLevelupAttributeMultiplier (i);
|
||||
mult = std::min(mult, 100-pcStats.getAttribute(i).getBase());
|
||||
text->setCaption(mult <= 1 ? "" : "x" + MyGUI::utility::toString(mult));
|
||||
}
|
||||
else
|
||||
{
|
||||
mAttributes[i]->setEnabled(false);
|
||||
mAttributeValues[i]->setEnabled(false);
|
||||
|
||||
text->setCaption("");
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include <MyGUI_Gui.h>
|
||||
#include <MyGUI_TextBox.h>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/statemanager.hpp"
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <components/version/version.hpp>
|
||||
|
||||
#include <components/widgets/imagebutton.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <MyGUI_FactoryManager.h>
|
||||
|
||||
#include <components/esm/globalmap.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <SDL_video.h>
|
||||
|
||||
#include <components/widgets/sharedstatebutton.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
|
|
@ -376,18 +376,26 @@ namespace MWGui
|
|||
for (SkillList::const_iterator it = skills.begin(); it != end; ++it)
|
||||
{
|
||||
int skillId = *it;
|
||||
if (skillId < 0 || skillId > ESM::Skill::Length) // Skip unknown skill indexes
|
||||
if (skillId < 0 || skillId >= ESM::Skill::Length) // Skip unknown skill indexes
|
||||
continue;
|
||||
assert(skillId >= 0 && skillId < ESM::Skill::Length);
|
||||
const std::string &skillNameId = ESM::Skill::sSkillNameIds[skillId];
|
||||
const MWMechanics::SkillValue &stat = mSkillValues.find(skillId)->second;
|
||||
int base = stat.getBase();
|
||||
int modified = stat.getModified();
|
||||
int progressPercent = stat.getProgress() * 100;
|
||||
|
||||
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
const MWWorld::ESMStore &esmStore =
|
||||
MWBase::Environment::get().getWorld()->getStore();
|
||||
|
||||
float progressRequirement = player.getClass().getNpcStats(player).getSkillProgressRequirement(skillId,
|
||||
*esmStore.get<ESM::Class>().find(player.get<ESM::NPC>()->mBase->mClass));
|
||||
|
||||
// This is how vanilla MW displays the progress bar (I think). Note it's slightly inaccurate,
|
||||
// due to the int casting in the skill levelup logic. Also the progress label could in rare cases
|
||||
// reach 100% without the skill levelling up.
|
||||
// Leaving the original display logic for now, for consistency with ess-imported savegames.
|
||||
int progressPercent = int(float(stat.getProgress()) / float(progressRequirement) * 100.f + 0.5f);
|
||||
|
||||
const ESM::Skill* skill = esmStore.get<ESM::Skill>().find(skillId);
|
||||
|
||||
std::string icon = "icons\\k\\" + ESM::Skill::sIconNames[skillId];
|
||||
|
|
|
@ -8,10 +8,12 @@
|
|||
#include <MyGUI_ImageBox.h>
|
||||
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/world.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/mechanicsmanager.hpp"
|
||||
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
@ -585,6 +587,15 @@ namespace MWGui
|
|||
ret += getMiscString(cellref.getFaction(), "Faction");
|
||||
if (cellref.getFactionRank() > 0)
|
||||
ret += getValueString(cellref.getFactionRank(), "Rank");
|
||||
|
||||
std::vector<std::pair<std::string, int> > itemOwners =
|
||||
MWBase::Environment::get().getMechanicsManager()->getStolenItemOwners(cellref.getRefId());
|
||||
|
||||
for (std::vector<std::pair<std::string, int> >::const_iterator it = itemOwners.begin(); it != itemOwners.end(); ++it)
|
||||
{
|
||||
ret += std::string("\nStolen from ") + it->first;
|
||||
}
|
||||
|
||||
ret += getMiscString(cellref.getGlobalVariable(), "Global");
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -135,11 +135,9 @@ namespace MWGui
|
|||
if (i == sourceModel->getItemCount())
|
||||
throw std::runtime_error("The borrowed item disappeared");
|
||||
|
||||
// reset owner while copying, but only for items bought by the player
|
||||
bool setNewOwner = (mMerchant.isEmpty());
|
||||
const ItemStack& item = sourceModel->getItem(i);
|
||||
// copy the borrowed items to our model
|
||||
copyItem(item, it->mCount, setNewOwner);
|
||||
copyItem(item, it->mCount);
|
||||
// then remove them from the source model
|
||||
sourceModel->removeItem(item, it->mCount);
|
||||
}
|
||||
|
|
|
@ -300,7 +300,8 @@ namespace MWGui
|
|||
// check if the player is attempting to sell back an item stolen from this actor
|
||||
for (std::vector<ItemStack>::iterator it = merchantBought.begin(); it != merchantBought.end(); ++it)
|
||||
{
|
||||
if (Misc::StringUtils::ciEqual(it->mBase.getCellRef().getOwner(), mPtr.getCellRef().getRefId()))
|
||||
if (MWBase::Environment::get().getMechanicsManager()->isItemStolenFrom(it->mBase.getCellRef().getRefId(),
|
||||
mPtr.getCellRef().getRefId()))
|
||||
{
|
||||
std::string msg = gmst.find("sNotifyMessage49")->getString();
|
||||
if (msg.find("%s") != std::string::npos)
|
||||
|
@ -315,6 +316,8 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: move to mwmechanics
|
||||
|
||||
// Is the player buying?
|
||||
bool buying = (mCurrentMerchantOffer < 0);
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include <MyGUI_ProgressBar.h>
|
||||
|
||||
#include <components/widgets/box.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <MyGUI_InputManager.h>
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@
|
|||
#include <MyGUI_ClipboardManager.h>
|
||||
#include <MyGUI_RenderManager.h>
|
||||
|
||||
#include <SDL_keyboard.h>
|
||||
#include <SDL_clipboard.h>
|
||||
|
||||
#include <openengine/ogre/renderer.hpp>
|
||||
#include <openengine/gui/manager.hpp>
|
||||
|
||||
|
@ -26,6 +29,8 @@
|
|||
|
||||
#include <components/fontloader/fontloader.hpp>
|
||||
|
||||
#include <components/translation/translation.hpp>
|
||||
|
||||
#include <components/widgets/widgets.hpp>
|
||||
#include <components/widgets/tags.hpp>
|
||||
|
||||
|
@ -91,7 +96,7 @@ namespace MWGui
|
|||
{
|
||||
|
||||
WindowManager::WindowManager(
|
||||
const Compiler::Extensions& extensions, int fpsLevel, OEngine::Render::OgreRenderer *ogre,
|
||||
const Compiler::Extensions& extensions, OEngine::Render::OgreRenderer *ogre,
|
||||
const std::string& logpath, const std::string& cacheDir, bool consoleOnlyScripts,
|
||||
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map<std::string, std::string>& fallbackMap)
|
||||
: mConsoleOnlyScripts(consoleOnlyScripts)
|
||||
|
@ -162,7 +167,6 @@ namespace MWGui
|
|||
, mForceHidden(GW_None)
|
||||
, mAllowed(GW_ALL)
|
||||
, mRestAllowed(true)
|
||||
, mShowFPSLevel(fpsLevel)
|
||||
, mFPS(0.0f)
|
||||
, mTriangleCount(0)
|
||||
, mBatchCount(0)
|
||||
|
@ -264,7 +268,7 @@ namespace MWGui
|
|||
trackWindow(mDialogueWindow, "dialogue");
|
||||
mContainerWindow = new ContainerWindow(mDragAndDrop);
|
||||
trackWindow(mContainerWindow, "container");
|
||||
mHud = new HUD(mCustomMarkers, mShowFPSLevel, mDragAndDrop);
|
||||
mHud = new HUD(mCustomMarkers, Settings::Manager::getInt("fps", "HUD"), mDragAndDrop);
|
||||
mToolTips = new ToolTips();
|
||||
mScrollWindow = new ScrollWindow();
|
||||
mBookWindow = new BookWindow();
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
This class owns and controls all the MW specific windows in the
|
||||
GUI. It can enable/disable Gui mode, and is responsible for sending
|
||||
and retrieving information from the Gui.
|
||||
|
||||
MyGUI should be initialized separately before creating instances of
|
||||
this class.
|
||||
**/
|
||||
|
||||
#include <stack>
|
||||
|
||||
#include "../mwbase/windowmanager.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "mapwindow.hpp"
|
||||
|
||||
#include <MyGUI_KeyCode.h>
|
||||
|
@ -96,7 +97,7 @@ namespace MWGui
|
|||
typedef std::pair<std::string, int> Faction;
|
||||
typedef std::vector<Faction> FactionList;
|
||||
|
||||
WindowManager(const Compiler::Extensions& extensions, int fpsLevel,
|
||||
WindowManager(const Compiler::Extensions& extensions,
|
||||
OEngine::Render::OgreRenderer *mOgre, const std::string& logpath,
|
||||
const std::string& cacheDir, bool consoleOnlyScripts,
|
||||
Translation::Storage& translationDataStorage, ToUTF8::FromType encoding, bool exportFonts, const std::map<std::string,std::string>& fallbackMap);
|
||||
|
@ -450,7 +451,6 @@ namespace MWGui
|
|||
|
||||
void updateVisible(); // Update visibility of all windows based on mode, shown and allowed settings
|
||||
|
||||
int mShowFPSLevel;
|
||||
float mFPS;
|
||||
unsigned int mTriangleCount;
|
||||
unsigned int mBatchCount;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <vector>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <list>
|
||||
|
||||
#include "movement.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
#include "creaturestats.hpp"
|
||||
#include "security.hpp"
|
||||
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include "../mwrender/animation.hpp"
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
|
|
@ -12,9 +12,9 @@ namespace MWMechanics
|
|||
{
|
||||
|
||||
/// @return ID of resulting item, or empty if none
|
||||
inline std::string getLevelledItem (const ESM::LeveledListBase* levItem, bool creature, unsigned char failChance=0)
|
||||
inline std::string getLevelledItem (const ESM::LevelledListBase* levItem, bool creature, unsigned char failChance=0)
|
||||
{
|
||||
const std::vector<ESM::LeveledListBase::LevelItem>& items = levItem->mList;
|
||||
const std::vector<ESM::LevelledListBase::LevelItem>& items = levItem->mList;
|
||||
|
||||
const MWWorld::Ptr& player = MWBase::Environment::get().getWorld()->getPlayerPtr();
|
||||
int playerLevel = player.getClass().getCreatureStats(player).getLevel();
|
||||
|
@ -27,7 +27,7 @@ namespace MWMechanics
|
|||
|
||||
std::vector<std::string> candidates;
|
||||
int highestLevel = 0;
|
||||
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
for (std::vector<ESM::LevelledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
if (it->mLevel > highestLevel && it->mLevel <= playerLevel)
|
||||
highestLevel = it->mLevel;
|
||||
|
@ -39,7 +39,7 @@ namespace MWMechanics
|
|||
allLevels = levItem->mFlags & ESM::CreatureLevList::AllLevels;
|
||||
|
||||
std::pair<int, std::string> highest = std::make_pair(-1, "");
|
||||
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
for (std::vector<ESM::LevelledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
|
||||
{
|
||||
if (playerLevel >= it->mLevel
|
||||
&& (allLevels || it->mLevel == highestLevel))
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
#include "mechanicsmanagerimp.hpp"
|
||||
#include "npcstats.hpp"
|
||||
|
||||
#include <components/esm/stolenitems.hpp>
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/inventorystore.hpp"
|
||||
|
||||
|
@ -873,31 +875,31 @@ namespace MWMechanics
|
|||
mAI = true;
|
||||
}
|
||||
|
||||
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim)
|
||||
bool MechanicsManager::isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim)
|
||||
{
|
||||
const std::string& owner = item.getCellRef().getOwner();
|
||||
const std::string& owner = cellref.getOwner();
|
||||
bool isOwned = !owner.empty() && owner != "player";
|
||||
|
||||
const std::string& faction = item.getCellRef().getFaction();
|
||||
const std::string& faction = cellref.getFaction();
|
||||
bool isFactionOwned = false;
|
||||
if (!faction.empty() && ptr.getClass().isNpc())
|
||||
{
|
||||
const std::map<std::string, int>& factions = ptr.getClass().getNpcStats(ptr).getFactionRanks();
|
||||
std::map<std::string, int>::const_iterator found = factions.find(Misc::StringUtils::lowerCase(faction));
|
||||
if (found == factions.end()
|
||||
|| found->second < item.getCellRef().getFactionRank())
|
||||
|| found->second < cellref.getFactionRank())
|
||||
isFactionOwned = true;
|
||||
}
|
||||
|
||||
const std::string& globalVariable = item.getCellRef().getGlobalVariable();
|
||||
const std::string& globalVariable = cellref.getGlobalVariable();
|
||||
if (!globalVariable.empty() && MWBase::Environment::get().getWorld()->getGlobalInt(Misc::StringUtils::lowerCase(globalVariable)) == 1)
|
||||
{
|
||||
isOwned = false;
|
||||
isFactionOwned = false;
|
||||
}
|
||||
|
||||
if (!item.getCellRef().getOwner().empty())
|
||||
victim = MWBase::Environment::get().getWorld()->searchPtr(item.getCellRef().getOwner(), true);
|
||||
if (!cellref.getOwner().empty())
|
||||
victim = MWBase::Environment::get().getWorld()->searchPtr(cellref.getOwner(), true);
|
||||
|
||||
return (!isOwned && !isFactionOwned);
|
||||
}
|
||||
|
@ -916,7 +918,7 @@ namespace MWMechanics
|
|||
}
|
||||
|
||||
MWWorld::Ptr victim;
|
||||
if (isAllowedToUse(ptr, bed, victim))
|
||||
if (isAllowedToUse(ptr, bed.getCellRef(), victim))
|
||||
return false;
|
||||
|
||||
if(commitCrime(ptr, victim, OT_SleepingInOwnedBed))
|
||||
|
@ -931,16 +933,103 @@ namespace MWMechanics
|
|||
void MechanicsManager::objectOpened(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item)
|
||||
{
|
||||
MWWorld::Ptr victim;
|
||||
if (isAllowedToUse(ptr, item, victim))
|
||||
if (isAllowedToUse(ptr, item.getCellRef(), victim))
|
||||
return;
|
||||
commitCrime(ptr, victim, OT_Trespassing);
|
||||
}
|
||||
|
||||
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, int count)
|
||||
std::vector<std::pair<std::string, int> > MechanicsManager::getStolenItemOwners(const std::string& itemid)
|
||||
{
|
||||
MWWorld::Ptr victim;
|
||||
if (isAllowedToUse(ptr, item, victim))
|
||||
std::vector<std::pair<std::string, int> > result;
|
||||
StolenItemsMap::const_iterator it = mStolenItems.find(Misc::StringUtils::lowerCase(itemid));
|
||||
if (it == mStolenItems.end())
|
||||
return result;
|
||||
else
|
||||
{
|
||||
const OwnerMap& owners = it->second;
|
||||
for (OwnerMap::const_iterator ownerIt = owners.begin(); ownerIt != owners.end(); ++ownerIt)
|
||||
result.push_back(std::make_pair(ownerIt->first.first, ownerIt->second));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool MechanicsManager::isItemStolenFrom(const std::string &itemid, const std::string &ownerid)
|
||||
{
|
||||
StolenItemsMap::const_iterator it = mStolenItems.find(Misc::StringUtils::lowerCase(itemid));
|
||||
if (it == mStolenItems.end())
|
||||
return false;
|
||||
const OwnerMap& owners = it->second;
|
||||
OwnerMap::const_iterator ownerFound = owners.find(std::make_pair(Misc::StringUtils::lowerCase(ownerid), false));
|
||||
return ownerFound != owners.end();
|
||||
}
|
||||
|
||||
void MechanicsManager::confiscateStolenItems(const MWWorld::Ptr &player, const MWWorld::Ptr &targetContainer)
|
||||
{
|
||||
MWWorld::ContainerStore& store = player.getClass().getContainerStore(player);
|
||||
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
StolenItemsMap::iterator stolenIt = mStolenItems.find(Misc::StringUtils::lowerCase(it->getClass().getId(*it)));
|
||||
if (stolenIt == mStolenItems.end())
|
||||
continue;
|
||||
OwnerMap& owners = stolenIt->second;
|
||||
int itemCount = it->getRefData().getCount();
|
||||
for (OwnerMap::iterator ownerIt = owners.begin(); ownerIt != owners.end();)
|
||||
{
|
||||
int toRemove = std::min(itemCount, ownerIt->second);
|
||||
itemCount -= toRemove;
|
||||
ownerIt->second -= toRemove;
|
||||
if (ownerIt->second == 0)
|
||||
owners.erase(ownerIt++);
|
||||
else
|
||||
++ownerIt;
|
||||
}
|
||||
|
||||
int toMove = it->getRefData().getCount() - itemCount;
|
||||
|
||||
targetContainer.getClass().getContainerStore(targetContainer).add(*it, toMove, targetContainer);
|
||||
store.remove(*it, toMove, player);
|
||||
}
|
||||
// TODO: unhardcode the locklevel
|
||||
targetContainer.getClass().lock(targetContainer,50);
|
||||
}
|
||||
|
||||
void MechanicsManager::itemTaken(const MWWorld::Ptr &ptr, const MWWorld::Ptr &item, const MWWorld::Ptr& container,
|
||||
int count)
|
||||
{
|
||||
if (ptr != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
return;
|
||||
|
||||
MWWorld::Ptr victim;
|
||||
|
||||
const MWWorld::CellRef* ownerCellRef = &item.getCellRef();
|
||||
if (!container.isEmpty())
|
||||
{
|
||||
// Inherit the owner of the container
|
||||
ownerCellRef = &container.getCellRef();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!item.getCellRef().hasContentFile())
|
||||
{
|
||||
// this is a manually placed item, which means it was already stolen
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (isAllowedToUse(ptr, *ownerCellRef, victim))
|
||||
return;
|
||||
|
||||
Owner owner;
|
||||
owner.first = ownerCellRef->getOwner();
|
||||
owner.second = false;
|
||||
if (owner.first.empty())
|
||||
{
|
||||
owner.first = ownerCellRef->getFaction();
|
||||
owner.second = true;
|
||||
}
|
||||
Misc::StringUtils::toLower(owner.first);
|
||||
mStolenItems[Misc::StringUtils::lowerCase(item.getClass().getId(item))][owner] += count;
|
||||
|
||||
commitCrime(ptr, victim, OT_Theft, item.getClass().getValue(item) * count);
|
||||
}
|
||||
|
||||
|
@ -949,7 +1038,7 @@ namespace MWMechanics
|
|||
// NOTE: victim may be empty
|
||||
|
||||
// Only player can commit crime
|
||||
if (player.getRefData().getHandle() != "player")
|
||||
if (player != MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||
return false;
|
||||
|
||||
// Find all the actors within the alarm radius
|
||||
|
@ -1351,22 +1440,37 @@ namespace MWMechanics
|
|||
|
||||
int MechanicsManager::countSavedGameRecords() const
|
||||
{
|
||||
return 1; // Death counter
|
||||
return 1 // Death counter
|
||||
+1; // Stolen items
|
||||
}
|
||||
|
||||
void MechanicsManager::write(ESM::ESMWriter &writer, Loading::Listener &listener) const
|
||||
{
|
||||
mActors.write(writer, listener);
|
||||
|
||||
ESM::StolenItems items;
|
||||
items.mStolenItems = mStolenItems;
|
||||
writer.startRecord(ESM::REC_STLN);
|
||||
items.write(writer);
|
||||
writer.endRecord(ESM::REC_STLN);
|
||||
}
|
||||
|
||||
void MechanicsManager::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
mActors.readRecord(reader, type);
|
||||
if (type == ESM::REC_STLN)
|
||||
{
|
||||
ESM::StolenItems items;
|
||||
items.load(reader);
|
||||
mStolenItems = items.mStolenItems;
|
||||
}
|
||||
else
|
||||
mActors.readRecord(reader, type);
|
||||
}
|
||||
|
||||
void MechanicsManager::clear()
|
||||
{
|
||||
mActors.clear();
|
||||
mStolenItems.clear();
|
||||
}
|
||||
|
||||
bool MechanicsManager::isAggressive(const MWWorld::Ptr &ptr, const MWWorld::Ptr &target)
|
||||
|
|
|
@ -35,6 +35,11 @@ namespace MWMechanics
|
|||
Objects mObjects;
|
||||
Actors mActors;
|
||||
|
||||
typedef std::pair<std::string, bool> Owner; // < Owner id, bool isFaction >
|
||||
typedef std::map<Owner, int> OwnerMap; // < Owner, number of stolen items with this id from this owner >
|
||||
typedef std::map<std::string, OwnerMap> StolenItemsMap;
|
||||
StolenItemsMap mStolenItems;
|
||||
|
||||
public:
|
||||
|
||||
void buildPlayer();
|
||||
|
@ -121,16 +126,15 @@ namespace MWMechanics
|
|||
/// @return false if the attack was considered a "friendly hit" and forgiven
|
||||
virtual bool actorAttacked (const MWWorld::Ptr& victim, const MWWorld::Ptr& attacker);
|
||||
/// Utility to check if taking this item is illegal and calling commitCrime if so
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, int count);
|
||||
/// @param container The container the item is in; may be empty for an item in the world
|
||||
virtual void itemTaken (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, const MWWorld::Ptr& container,
|
||||
int count);
|
||||
/// Utility to check if opening (i.e. unlocking) this object is illegal and calling commitCrime if so
|
||||
virtual void objectOpened (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item);
|
||||
/// Attempt sleeping in a bed. If this is illegal, call commitCrime.
|
||||
/// @return was it illegal, and someone saw you doing it? Also returns fail when enemies are nearby
|
||||
virtual bool sleepInBed (const MWWorld::Ptr& ptr, const MWWorld::Ptr& bed);
|
||||
|
||||
/// @return is \a ptr allowed to take/use \a item or is it a crime?
|
||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::Ptr& item, MWWorld::Ptr& victim);
|
||||
|
||||
virtual void forceStateUpdate(const MWWorld::Ptr &ptr);
|
||||
|
||||
virtual void playAnimationGroup(const MWWorld::Ptr& ptr, const std::string& groupName, int mode, int number);
|
||||
|
@ -168,9 +172,21 @@ namespace MWMechanics
|
|||
|
||||
virtual bool isReadyToBlock (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
virtual void confiscateStolenItems (const MWWorld::Ptr& player, const MWWorld::Ptr& targetContainer);
|
||||
|
||||
/// List the owners that the player has stolen this item from (the owner can be an NPC or a faction).
|
||||
/// <Owner, item count>
|
||||
virtual std::vector<std::pair<std::string, int> > getStolenItemOwners(const std::string& itemid);
|
||||
|
||||
/// Has the player stolen this item from the given owner?
|
||||
virtual bool isItemStolenFrom(const std::string& itemid, const std::string& ownerid);
|
||||
|
||||
private:
|
||||
void reportCrime (const MWWorld::Ptr& ptr, const MWWorld::Ptr& victim,
|
||||
OffenseType type, int arg=0);
|
||||
|
||||
/// @return is \a ptr allowed to take/use \a cellref or is it a crime?
|
||||
virtual bool isAllowedToUse (const MWWorld::Ptr& ptr, const MWWorld::CellRef& cellref, MWWorld::Ptr& victim);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -125,32 +125,9 @@ bool MWMechanics::NpcStats::isInFaction (const std::string& faction) const
|
|||
return (mFactionRank.find(Misc::StringUtils::lowerCase(faction)) != mFactionRank.end());
|
||||
}
|
||||
|
||||
float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& class_, int usageType,
|
||||
int level, float extraFactor) const
|
||||
float MWMechanics::NpcStats::getSkillProgressRequirement (int skillIndex, const ESM::Class& class_) const
|
||||
{
|
||||
if (level<0)
|
||||
level = static_cast<int> (getSkill (skillIndex).getBase());
|
||||
|
||||
const ESM::Skill *skill =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find (skillIndex);
|
||||
|
||||
float skillFactor = 1;
|
||||
|
||||
if (usageType>=4)
|
||||
throw std::runtime_error ("skill usage type out of range");
|
||||
|
||||
if (usageType>=0)
|
||||
{
|
||||
skillFactor = skill->mData.mUseValue[usageType];
|
||||
|
||||
if (skillFactor<0)
|
||||
throw std::runtime_error ("invalid skill gain factor");
|
||||
|
||||
if (skillFactor==0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
skillFactor *= extraFactor;
|
||||
float progressRequirement = 1 + getSkill (skillIndex).getBase();
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
@ -173,11 +150,15 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
|
|||
break;
|
||||
}
|
||||
|
||||
progressRequirement *= typeFactor;
|
||||
|
||||
if (typeFactor<=0)
|
||||
throw std::runtime_error ("invalid skill type factor");
|
||||
|
||||
float specialisationFactor = 1;
|
||||
|
||||
const ESM::Skill *skill =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find (skillIndex);
|
||||
if (skill->mData.mSpecialization==class_.mData.mSpecialization)
|
||||
{
|
||||
specialisationFactor = gmst.find ("fSpecialSkillBonus")->getFloat();
|
||||
|
@ -185,7 +166,9 @@ float MWMechanics::NpcStats::getSkillGain (int skillIndex, const ESM::Class& cla
|
|||
if (specialisationFactor<=0)
|
||||
throw std::runtime_error ("invalid skill specialisation factor");
|
||||
}
|
||||
return 1.0 / ((level+1) * (1.0/skillFactor) * typeFactor * specialisationFactor);
|
||||
progressRequirement *= specialisationFactor;
|
||||
|
||||
return progressRequirement;
|
||||
}
|
||||
|
||||
void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_, int usageType, float extraFactor)
|
||||
|
@ -194,13 +177,26 @@ void MWMechanics::NpcStats::useSkill (int skillIndex, const ESM::Class& class_,
|
|||
if(mIsWerewolf)
|
||||
return;
|
||||
|
||||
const ESM::Skill *skill =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::Skill>().find (skillIndex);
|
||||
float skillGain = 1;
|
||||
if (usageType>=4)
|
||||
throw std::runtime_error ("skill usage type out of range");
|
||||
if (usageType>=0)
|
||||
{
|
||||
skillGain = skill->mData.mUseValue[usageType];
|
||||
if (skillGain<0)
|
||||
throw std::runtime_error ("invalid skill gain factor");
|
||||
}
|
||||
skillGain *= extraFactor;
|
||||
|
||||
MWMechanics::SkillValue& value = getSkill (skillIndex);
|
||||
|
||||
value.setProgress(value.getProgress() + getSkillGain (skillIndex, class_, usageType, -1, extraFactor));
|
||||
value.setProgress(value.getProgress() + skillGain);
|
||||
|
||||
if (value.getProgress()>=1)
|
||||
if (int(value.getProgress())>=int(getSkillProgressRequirement(skillIndex, class_)))
|
||||
{
|
||||
// skill leveled up
|
||||
// skill levelled up
|
||||
increaseSkill(skillIndex, class_, false);
|
||||
}
|
||||
}
|
||||
|
@ -256,7 +252,7 @@ void MWMechanics::NpcStats::increaseSkill(int skillIndex, const ESM::Class &clas
|
|||
MWBase::Environment::get().getWindowManager ()->messageBox ("#{sLevelUpMsg}", MWGui::ShowInDialogueMode_Never);
|
||||
}
|
||||
|
||||
getSkill (skillIndex).setBase (base);
|
||||
getSkill(skillIndex).setBase (base);
|
||||
if (!preserveProgress)
|
||||
getSkill(skillIndex).setProgress(0);
|
||||
}
|
||||
|
@ -268,13 +264,15 @@ int MWMechanics::NpcStats::getLevelProgress () const
|
|||
|
||||
void MWMechanics::NpcStats::levelUp()
|
||||
{
|
||||
mLevelProgress -= 10;
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSkillIncreases[i] = 0;
|
||||
|
||||
const MWWorld::Store<ESM::GameSetting> &gmst =
|
||||
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>();
|
||||
|
||||
mLevelProgress -= gmst.find("iLevelUpTotal")->getInt();
|
||||
mLevelProgress = std::max(0, mLevelProgress); // might be necessary when levelup was invoked via console
|
||||
|
||||
for (int i=0; i<ESM::Attribute::Length; ++i)
|
||||
mSkillIncreases[i] = 0;
|
||||
|
||||
const int endurance = getAttribute(ESM::Attribute::Endurance).getBase();
|
||||
|
||||
// "When you gain a level, in addition to increasing three primary attributes, your Health
|
||||
|
|
|
@ -23,7 +23,7 @@ namespace MWMechanics
|
|||
class NpcStats : public CreatureStats
|
||||
{
|
||||
int mDisposition;
|
||||
SkillValue mSkill[ESM::Skill::Length];
|
||||
SkillValue mSkill[ESM::Skill::Length]; // SkillValue.mProgress used by the player only
|
||||
SkillValue mWerewolfSkill[ESM::Skill::Length];
|
||||
int mReputation;
|
||||
int mCrimeId;
|
||||
|
@ -74,11 +74,7 @@ namespace MWMechanics
|
|||
|
||||
bool isInFaction (const std::string& faction) const;
|
||||
|
||||
float getSkillGain (int skillIndex, const ESM::Class& class_, int usageType = -1,
|
||||
int level = -1, float extraFactor=1.f) const;
|
||||
///< \param usageType: Usage specific factor, specified in the respective skill record;
|
||||
/// -1: use a factor of 1.0 instead.
|
||||
/// \param level Level to base calculation on; -1: use current level.
|
||||
float getSkillProgressRequirement (int skillIndex, const ESM::Class& class_) const;
|
||||
|
||||
void useSkill (int skillIndex, const ESM::Class& class_, int usageType = -1, float extraFactor=1.f);
|
||||
///< Increase skill by usage.
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <components/esm/loadench.hpp>
|
||||
#include <components/esm/loadstat.hpp>
|
||||
#include <components/misc/resourcehelpers.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <libs/openengine/ogre/lights.hpp>
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <OgreHardwarePixelBuffer.h>
|
||||
|
||||
#include <components/loadinglistener/loadinglistener.hpp>
|
||||
#include <components/settings/settings.hpp>
|
||||
|
||||
#include <components/esm/globalmap.hpp>
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "animationextensions.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <limits>
|
||||
|
||||
#include <components/compiler/extensions.hpp>
|
||||
#include <components/compiler/opcodes.hpp>
|
||||
|
|
|
@ -34,24 +34,24 @@
|
|||
namespace
|
||||
{
|
||||
|
||||
void addToLevList(ESM::LeveledListBase* list, const std::string& itemId, int level)
|
||||
void addToLevList(ESM::LevelledListBase* list, const std::string& itemId, int level)
|
||||
{
|
||||
for (std::vector<ESM::LeveledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end();)
|
||||
for (std::vector<ESM::LevelledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end();)
|
||||
{
|
||||
if (it->mLevel == level && itemId == it->mId)
|
||||
return;
|
||||
}
|
||||
|
||||
ESM::LeveledListBase::LevelItem item;
|
||||
ESM::LevelledListBase::LevelItem item;
|
||||
item.mId = itemId;
|
||||
item.mLevel = level;
|
||||
list->mList.push_back(item);
|
||||
}
|
||||
|
||||
void removeFromLevList(ESM::LeveledListBase* list, const std::string& itemId, int level)
|
||||
void removeFromLevList(ESM::LevelledListBase* list, const std::string& itemId, int level)
|
||||
{
|
||||
// level of -1 removes all items with that itemId
|
||||
for (std::vector<ESM::LeveledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end();)
|
||||
for (std::vector<ESM::LevelledListBase::LevelItem>::iterator it = list->mList.begin(); it != list->mList.end();)
|
||||
{
|
||||
if (level != -1 && it->mLevel != level)
|
||||
{
|
||||
|
|
|
@ -348,29 +348,12 @@ namespace MWScript
|
|||
|
||||
MWMechanics::NpcStats& stats = ptr.getClass().getNpcStats (ptr);
|
||||
|
||||
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
|
||||
|
||||
assert (ref);
|
||||
|
||||
const ESM::Class& class_ =
|
||||
*MWBase::Environment::get().getWorld()->getStore().get<ESM::Class>().find (ref->mBase->mClass);
|
||||
|
||||
float level = stats.getSkill(mIndex).getBase();
|
||||
float progress = stats.getSkill(mIndex).getProgress();
|
||||
|
||||
int newLevel = value - (stats.getSkill(mIndex).getModified() - stats.getSkill(mIndex).getBase());
|
||||
|
||||
if (newLevel<0)
|
||||
newLevel = 0;
|
||||
|
||||
progress = (progress / stats.getSkillGain (mIndex, class_, -1, level))
|
||||
* stats.getSkillGain (mIndex, class_, -1, newLevel);
|
||||
|
||||
if (progress>=1)
|
||||
progress = 0.999999999;
|
||||
|
||||
stats.getSkill (mIndex).setBase (newLevel);
|
||||
stats.getSkill (mIndex).setProgress(progress);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -691,10 +691,10 @@ namespace MWScript
|
|||
if (!ptr.getRefData().getBaseNode())
|
||||
return;
|
||||
|
||||
Ogre::Vector3 worldPos = ptr.getRefData().getBaseNode()->convertLocalToWorldPosition(posChange);
|
||||
|
||||
dynamic_cast<MWScript::InterpreterContext&>(runtime.getContext()).updatePtr(
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x, worldPos.y, worldPos.z));
|
||||
Ogre::Vector3 diff = ptr.getRefData().getBaseNode()->getOrientation() * posChange;
|
||||
Ogre::Vector3 worldPos(ptr.getRefData().getPosition().pos);
|
||||
worldPos += diff;
|
||||
MWBase::Environment::get().getWorld()->moveObject(ptr, worldPos.x, worldPos.y, worldPos.z);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <OgreImage.h>
|
||||
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/operations.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
@ -420,6 +421,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
break;
|
||||
|
||||
case ESM::REC_DCOU:
|
||||
case ESM::REC_STLN:
|
||||
|
||||
MWBase::Environment::get().getMechanicsManager()->readRecord(reader, n.val);
|
||||
break;
|
||||
|
|
|
@ -16,7 +16,7 @@ namespace MWWorld
|
|||
void ActionTake::executeImp (const Ptr& actor)
|
||||
{
|
||||
MWBase::Environment::get().getMechanicsManager()->itemTaken(
|
||||
actor, getTarget(), getTarget().getRefData().getCount());
|
||||
actor, getTarget(), MWWorld::Ptr(), getTarget().getRefData().getCount());
|
||||
actor.getClass().getContainerStore (actor).add (getTarget(), getTarget().getRefData().getCount(), actor);
|
||||
MWBase::Environment::get().getWorld()->deleteObject (getTarget());
|
||||
}
|
||||
|
|
|
@ -117,6 +117,15 @@ namespace MWWorld
|
|||
return mCellRef.mGlobalVariable;
|
||||
}
|
||||
|
||||
void CellRef::resetGlobalVariable()
|
||||
{
|
||||
if (!mCellRef.mGlobalVariable.empty())
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mGlobalVariable.erase();
|
||||
}
|
||||
}
|
||||
|
||||
void CellRef::setFactionRank(int factionRank)
|
||||
{
|
||||
if (factionRank != mCellRef.mFactionRank)
|
||||
|
|
|
@ -75,6 +75,8 @@ namespace MWWorld
|
|||
// Used by bed rent scripts to allow the player to use the bed for the duration of the rent.
|
||||
std::string getGlobalVariable() const;
|
||||
|
||||
void resetGlobalVariable();
|
||||
|
||||
// ID of creature trapped in this soul gem
|
||||
std::string getSoul() const;
|
||||
void setSoul(const std::string& soul);
|
||||
|
|
|
@ -80,6 +80,8 @@ namespace MWWorld
|
|||
virtual std::string getId (const Ptr& ptr) const;
|
||||
///< Return ID of \a ptr or throw an exception, if class does not support ID retrieval
|
||||
/// (default implementation: throw an exception)
|
||||
/// @note This function is currently redundant; the same ID can be retrieved by CellRef::getRefId.
|
||||
/// Leaving it here for now in case we want to optimize later.
|
||||
|
||||
virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const;
|
||||
virtual void insertObject(const Ptr& ptr, const std::string& mesh, MWWorld::PhysicsSystem& physics) const;
|
||||
|
|
|
@ -222,29 +222,22 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|||
|
||||
MWWorld::ContainerStoreIterator it = end();
|
||||
|
||||
if (setOwner && actorPtr.getClass().isActor())
|
||||
// HACK: Set owner on the original item, then reset it after we have copied it
|
||||
// If we set the owner on the copied item, it would not stack correctly...
|
||||
std::string oldOwner = itemPtr.getCellRef().getOwner();
|
||||
if (!setOwner || actorPtr == MWBase::Environment::get().getWorld()->getPlayerPtr()) // No point in setting owner to the player - NPCs will not respect this anyway
|
||||
{
|
||||
// HACK: Set owner on the original item, then reset it after we have copied it
|
||||
// If we set the owner on the copied item, it would not stack correctly...
|
||||
std::string oldOwner = itemPtr.getCellRef().getOwner();
|
||||
if (actorPtr == player)
|
||||
{
|
||||
// No point in setting owner to the player - NPCs will not respect this anyway
|
||||
// Additionally, setting it to "player" would make those items not stack with items that don't have an owner
|
||||
itemPtr.getCellRef().setOwner("");
|
||||
}
|
||||
else
|
||||
itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
|
||||
|
||||
it = addImp(itemPtr, count);
|
||||
|
||||
itemPtr.getCellRef().setOwner(oldOwner);
|
||||
itemPtr.getCellRef().setOwner("");
|
||||
}
|
||||
else
|
||||
{
|
||||
it = addImp(itemPtr, count);
|
||||
itemPtr.getCellRef().setOwner(actorPtr.getCellRef().getRefId());
|
||||
}
|
||||
|
||||
it = addImp(itemPtr, count);
|
||||
|
||||
itemPtr.getCellRef().setOwner(oldOwner);
|
||||
|
||||
// The copy of the original item we just made
|
||||
MWWorld::Ptr item = *it;
|
||||
|
||||
|
@ -258,6 +251,14 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::add (const Ptr& itemPtr
|
|||
pos.pos[1] = 0;
|
||||
pos.pos[2] = 0;
|
||||
item.getCellRef().setPosition(pos);
|
||||
|
||||
// reset ownership stuff, owner was already handled above
|
||||
item.getCellRef().resetGlobalVariable();
|
||||
item.getCellRef().setFaction("");
|
||||
item.getCellRef().setFactionRank(-1);
|
||||
|
||||
// must reset the RefNum on the copied item, so that the RefNum on the original item stays unique
|
||||
// maybe we should do this in the copy constructor instead?
|
||||
item.getCellRef().unsetRefNum(); // destroy link to content file
|
||||
|
||||
std::string script = item.getClass().getScript(item);
|
||||
|
@ -399,19 +400,19 @@ int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor
|
|||
return count - toRemove;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, const std::string& faction, int factionRank, const MWWorld::ESMStore& store)
|
||||
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner)
|
||||
{
|
||||
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
|
||||
++iter)
|
||||
{
|
||||
std::string id = Misc::StringUtils::lowerCase(iter->mItem.toString());
|
||||
addInitialItem(id, owner, faction, factionRank, iter->mCount);
|
||||
addInitialItem(id, owner, iter->mCount);
|
||||
}
|
||||
|
||||
flagAsModified();
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int factionRank,
|
||||
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner,
|
||||
int count, bool topLevel, const std::string& levItem)
|
||||
{
|
||||
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);
|
||||
|
@ -423,7 +424,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|||
if (topLevel && std::abs(count) > 1 && levItem->mFlags & ESM::ItemLevList::Each)
|
||||
{
|
||||
for (int i=0; i<std::abs(count); ++i)
|
||||
addInitialItem(id, owner, faction, factionRank, count > 0 ? 1 : -1, true, levItem->mId);
|
||||
addInitialItem(id, owner, count > 0 ? 1 : -1, true, levItem->mId);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
@ -431,7 +432,7 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|||
std::string id = MWMechanics::getLevelledItem(ref.getPtr().get<ESM::ItemLevList>()->mBase, false);
|
||||
if (id.empty())
|
||||
return;
|
||||
addInitialItem(id, owner, faction, factionRank, count, false, levItem->mId);
|
||||
addInitialItem(id, owner, count, false, levItem->mId);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -447,13 +448,11 @@ void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::
|
|||
count = std::abs(count);
|
||||
|
||||
ref.getPtr().getCellRef().setOwner(owner);
|
||||
ref.getPtr().getCellRef().setFaction(faction);
|
||||
ref.getPtr().getCellRef().setFactionRank(factionRank);
|
||||
addImp (ref.getPtr(), count);
|
||||
}
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction, int factionRank)
|
||||
void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner)
|
||||
{
|
||||
// Remove the items already spawned by levelled items that will restock
|
||||
for (std::map<std::string, int>::iterator it = mLevelledItemMap.begin(); it != mLevelledItemMap.end(); ++it)
|
||||
|
@ -472,13 +471,13 @@ void MWWorld::ContainerStore::restock (const ESM::InventoryList& items, const MW
|
|||
|
||||
if (MWBase::Environment::get().getWorld()->getStore().get<ESM::ItemLevList>().search(it->mItem.toString()))
|
||||
{
|
||||
addInitialItem(item, owner, faction, factionRank, it->mCount, true);
|
||||
addInitialItem(item, owner, it->mCount, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
int currentCount = count(item);
|
||||
if (currentCount < std::abs(it->mCount))
|
||||
addInitialItem(item, owner, faction, factionRank, std::abs(it->mCount) - currentCount, true);
|
||||
addInitialItem(item, owner, std::abs(it->mCount) - currentCount, true);
|
||||
}
|
||||
}
|
||||
flagAsModified();
|
||||
|
|
|
@ -75,7 +75,7 @@ namespace MWWorld
|
|||
mutable float mCachedWeight;
|
||||
mutable bool mWeightUpToDate;
|
||||
ContainerStoreIterator addImp (const Ptr& ptr, int count);
|
||||
void addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, int factionRank, int count, bool topLevel=true, const std::string& levItem = "");
|
||||
void addInitialItem (const std::string& id, const std::string& owner, int count, bool topLevel=true, const std::string& levItem = "");
|
||||
|
||||
template<typename T>
|
||||
ContainerStoreIterator getState (CellRefList<T>& collection,
|
||||
|
@ -112,7 +112,7 @@ namespace MWWorld
|
|||
/// \attention Do not add items to an existing stack by increasing the count instead of
|
||||
/// calling this function!
|
||||
///
|
||||
/// @param setOwner Set the owner of the added item to \a actorPtr?
|
||||
/// @param setOwner Set the owner of the added item to \a actorPtr? If false, the owner is reset to "".
|
||||
///
|
||||
/// @return if stacking happened, return iterator to the item that was stacked against, otherwise iterator to the newly inserted item.
|
||||
|
||||
|
@ -151,10 +151,10 @@ namespace MWWorld
|
|||
virtual bool stacks (const Ptr& ptr1, const Ptr& ptr2);
|
||||
///< @return true if the two specified objects can stack with each other
|
||||
|
||||
void fill (const ESM::InventoryList& items, const std::string& owner, const std::string& faction, int factionRank, const MWWorld::ESMStore& store);
|
||||
void fill (const ESM::InventoryList& items, const std::string& owner);
|
||||
///< Insert items into *this.
|
||||
|
||||
void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner, const std::string& faction, int factionRank);
|
||||
void restock (const ESM::InventoryList& items, const MWWorld::Ptr& ptr, const std::string& owner);
|
||||
|
||||
virtual void clear();
|
||||
///< Empty container.
|
||||
|
|
|
@ -133,12 +133,11 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::add(const Ptr& itemPtr,
|
|||
const MWWorld::ContainerStoreIterator& retVal = MWWorld::ContainerStore::add(itemPtr, count, actorPtr, setOwner);
|
||||
|
||||
// Auto-equip items if an armor/clothing or weapon item is added, but not for the player nor werewolves
|
||||
if ((actorPtr.getRefData().getHandle() != "player")
|
||||
&& !(actorPtr.getClass().isNpc() && actorPtr.getClass().getNpcStats(actorPtr).isWerewolf())
|
||||
&& !actorPtr.getClass().getCreatureStats(actorPtr).isDead())
|
||||
if (actorPtr.getRefData().getHandle() != "player"
|
||||
&& !(actorPtr.getClass().isNpc() && actorPtr.getClass().getNpcStats(actorPtr).isWerewolf()))
|
||||
{
|
||||
std::string type = itemPtr.getTypeName();
|
||||
if ((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()) || (type == typeid(ESM::Weapon).name()))
|
||||
if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name())
|
||||
autoEquip(actorPtr);
|
||||
}
|
||||
|
||||
|
@ -234,7 +233,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor)
|
|||
// ...unless this is a companion, he should always equip items given to him.
|
||||
if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) &&
|
||||
(actor.getClass().getScript(actor).empty() ||
|
||||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion")))
|
||||
!actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))
|
||||
&& !actor.getClass().getCreatureStats(actor).isDead() // Corpses can be dressed up by the player as desired
|
||||
)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
@ -506,8 +507,7 @@ int MWWorld::InventoryStore::remove(const Ptr& item, int count, const Ptr& actor
|
|||
&& !(actor.getClass().isNpc() && actor.getClass().getNpcStats(actor).isWerewolf()))
|
||||
{
|
||||
std::string type = item.getTypeName();
|
||||
if (((type == typeid(ESM::Armor).name()) || (type == typeid(ESM::Clothing).name()))
|
||||
&& !actor.getClass().getCreatureStats(actor).isDead())
|
||||
if (type == typeid(ESM::Armor).name() || type == typeid(ESM::Clothing).name())
|
||||
autoEquip(actor);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
#include "livecellref.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <components/esm/objectstate.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
|
|
|
@ -260,9 +260,20 @@ namespace MWWorld
|
|||
mCellStore = world.getExterior(0,0);
|
||||
}
|
||||
|
||||
if (!player.mBirthsign.empty() &&
|
||||
!world.getStore().get<ESM::BirthSign>().search (player.mBirthsign))
|
||||
throw std::runtime_error ("invalid player state record (birthsign)");
|
||||
if (!player.mBirthsign.empty())
|
||||
{
|
||||
const ESM::BirthSign* sign = world.getStore().get<ESM::BirthSign>().search (player.mBirthsign);
|
||||
if (!sign)
|
||||
throw std::runtime_error ("invalid player state record (birthsign does not exist)");
|
||||
|
||||
// To handle the case where a birth sign was edited in between play sessions (does not yet handle removing the old spells)
|
||||
// Also needed for ess-imported savegames which do not specify the birtsign spells in the player's spell list.
|
||||
for (std::vector<std::string>::const_iterator iter (sign->mPowers.mList.begin());
|
||||
iter!=sign->mPowers.mList.end(); ++iter)
|
||||
{
|
||||
getPlayer().getClass().getCreatureStats(getPlayer()).getSpells().add (*iter);
|
||||
}
|
||||
}
|
||||
|
||||
mCurrentCrimeId = player.mCurrentCrimeId;
|
||||
mPaidCrimeId = player.mPaidCrimeId;
|
||||
|
|
|
@ -2988,18 +2988,10 @@ namespace MWWorld
|
|||
|
||||
if (!closestChest.isEmpty()) //Found a close chest
|
||||
{
|
||||
ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||
for (ContainerStoreIterator it = store.begin(); it != store.end(); ++it) //Move all stolen stuff into chest
|
||||
{
|
||||
MWWorld::Ptr dummy;
|
||||
if (!MWBase::Environment::get().getMechanicsManager()->isAllowedToUse(getPlayerPtr(), *it, dummy))
|
||||
{
|
||||
closestChest.getClass().getContainerStore(closestChest).add(*it, it->getRefData().getCount(), closestChest);
|
||||
store.remove(*it, it->getRefData().getCount(), ptr);
|
||||
}
|
||||
}
|
||||
closestChest.getClass().lock(closestChest,50);
|
||||
MWBase::Environment::get().getMechanicsManager()->confiscateStolenItems(ptr, closestChest);
|
||||
}
|
||||
else
|
||||
std::cerr << "Failed to confiscate items: no stolen_goods container found" << std::endl;
|
||||
}
|
||||
|
||||
void World::goToJail()
|
||||
|
|
|
@ -63,7 +63,7 @@ add_component_dir (esm
|
|||
loadweap records aipackage effectlist spelllist variant variantimp loadtes3 cellref filter
|
||||
savedgame journalentry queststate locals globalscript player objectstate cellid cellstate globalmap inventorystate containerstate npcstate creaturestate dialoguestate statstate
|
||||
npcstats creaturestats weatherstate quickkeys fogstate spellstate activespells creaturelevliststate doorstate projectilestate debugprofile
|
||||
aisequence magiceffects util custommarkerstate
|
||||
aisequence magiceffects util custommarkerstate stolenitems
|
||||
)
|
||||
|
||||
add_component_dir (esmterrain
|
||||
|
|
|
@ -15,8 +15,7 @@ ContentSelectorModel::ContentModel::ContentModel(QObject *parent, QIcon warningI
|
|||
mMimeType ("application/omwcontent"),
|
||||
mMimeTypes (QStringList() << mMimeType),
|
||||
mColumnCount (1),
|
||||
mDragDropFlags (Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled),
|
||||
mDropActions (Qt::CopyAction | Qt::MoveAction)
|
||||
mDropActions (Qt::MoveAction)
|
||||
{
|
||||
setEncoding ("win1252");
|
||||
uncheckAll();
|
||||
|
@ -104,7 +103,7 @@ QModelIndex ContentSelectorModel::ContentModel::indexFromItem(const EsmFile *ite
|
|||
Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return Qt::NoItemFlags;
|
||||
return Qt::ItemIsDropEnabled;
|
||||
|
||||
const EsmFile *file = item(index.row());
|
||||
|
||||
|
@ -152,7 +151,7 @@ Qt::ItemFlags ContentSelectorModel::ContentModel::flags(const QModelIndex &index
|
|||
if (gamefileChecked)
|
||||
{
|
||||
if (allDependenciesFound)
|
||||
returnFlags = returnFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | mDragDropFlags;
|
||||
returnFlags = returnFlags | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled;
|
||||
else
|
||||
returnFlags = Qt::ItemIsSelectable;
|
||||
}
|
||||
|
@ -443,11 +442,6 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
|
|||
filters << "*.esp" << "*.esm" << "*.omwgame" << "*.omwaddon";
|
||||
dir.setNameFilters(filters);
|
||||
|
||||
QTextCodec *codec = QTextCodec::codecForName("UTF8");
|
||||
|
||||
// Create a decoder for non-latin characters in esx metadata
|
||||
QTextDecoder *decoder = codec->makeDecoder();
|
||||
|
||||
foreach (const QString &path, dir.entryList())
|
||||
{
|
||||
QFileInfo info(dir.absoluteFilePath(path));
|
||||
|
@ -467,11 +461,11 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
|
|||
foreach (const ESM::Header::MasterData &item, fileReader.getGameFiles())
|
||||
file->addGameFile(QString::fromStdString(item.name));
|
||||
|
||||
file->setAuthor (decoder->toUnicode(fileReader.getAuthor().c_str()));
|
||||
file->setAuthor (QString::fromUtf8(fileReader.getAuthor().c_str()));
|
||||
file->setDate (info.lastModified());
|
||||
file->setFormat (fileReader.getFormat());
|
||||
file->setFilePath (info.absoluteFilePath());
|
||||
file->setDescription(decoder->toUnicode(fileReader.getDesc().c_str()));
|
||||
file->setDescription(QString::fromUtf8(fileReader.getDesc().c_str()));
|
||||
|
||||
// Put the file in the table
|
||||
addFile(file);
|
||||
|
@ -484,8 +478,6 @@ void ContentSelectorModel::ContentModel::addFiles(const QString &path)
|
|||
|
||||
}
|
||||
|
||||
delete decoder;
|
||||
|
||||
sortFiles();
|
||||
}
|
||||
|
||||
|
|
|
@ -89,7 +89,6 @@ namespace ContentSelectorModel
|
|||
QString mMimeType;
|
||||
QStringList mMimeTypes;
|
||||
int mColumnCount;
|
||||
Qt::ItemFlags mDragDropFlags;
|
||||
Qt::DropActions mDropActions;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,7 +15,8 @@
|
|||
ContentSelectorView::ContentSelector::ContentSelector(QWidget *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
ui.setupUi (parent);
|
||||
ui.setupUi(parent);
|
||||
ui.addonView->setDragDropMode(QAbstractItemView::InternalMove);
|
||||
|
||||
buildContentModel();
|
||||
buildGameFileView();
|
||||
|
|
|
@ -117,6 +117,7 @@ enum RecNameInts
|
|||
REC_MARK = FourCC<'M','A','R','K'>::value,
|
||||
REC_ENAB = FourCC<'E','N','A','B'>::value,
|
||||
REC_CAM_ = FourCC<'C','A','M','_'>::value,
|
||||
REC_STLN = FourCC<'S','T','L','N'>::value,
|
||||
|
||||
// format 1
|
||||
REC_FILT = FourCC<'F','I','L','T'>::value,
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
namespace ESM
|
||||
{
|
||||
|
||||
void LeveledListBase::load(ESMReader &esm)
|
||||
void LevelledListBase::load(ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mFlags, "DATA");
|
||||
esm.getHNT(mChanceNone, "NNAM");
|
||||
|
@ -19,13 +19,17 @@ void LeveledListBase::load(ESMReader &esm)
|
|||
mList.resize(len);
|
||||
}
|
||||
else
|
||||
{
|
||||
esm.skipRecord();
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: Merge with an existing lists here. This can be done
|
||||
// simply by adding the lists together, making sure that they are
|
||||
// sorted by level. A better way might be to exclude repeated
|
||||
// items. Also, some times we don't want to merge lists, just
|
||||
// overwrite. Figure out a way to give the user this option.
|
||||
// If this levelled list was already loaded by a previous content file,
|
||||
// we overwrite the list. Merging lists should probably be left to external tools,
|
||||
// with the limited amount of information there is in the records, all merging methods
|
||||
// will be flawed in some way. For a proper fix the ESM format would have to be changed
|
||||
// to actually track list changes instead of including the whole list for every file
|
||||
// that does something with that list.
|
||||
|
||||
for (size_t i = 0; i < mList.size(); i++)
|
||||
{
|
||||
|
@ -34,7 +38,7 @@ void LeveledListBase::load(ESMReader &esm)
|
|||
esm.getHNT(li.mLevel, "INTV");
|
||||
}
|
||||
}
|
||||
void LeveledListBase::save(ESMWriter &esm) const
|
||||
void LevelledListBase::save(ESMWriter &esm) const
|
||||
{
|
||||
esm.writeHNT("DATA", mFlags);
|
||||
esm.writeHNT("NNAM", mChanceNone);
|
||||
|
@ -47,7 +51,7 @@ void LeveledListBase::save(ESMWriter &esm) const
|
|||
}
|
||||
}
|
||||
|
||||
void LeveledListBase::blank()
|
||||
void LevelledListBase::blank()
|
||||
{
|
||||
mFlags = 0;
|
||||
mChanceNone = 0;
|
||||
|
|
|
@ -11,14 +11,14 @@ class ESMReader;
|
|||
class ESMWriter;
|
||||
|
||||
/*
|
||||
* Leveled lists. Since these have identical layout, I only bothered
|
||||
* Levelled lists. Since these have identical layout, I only bothered
|
||||
* to implement it once.
|
||||
*
|
||||
* We should later implement the ability to merge leveled lists from
|
||||
* We should later implement the ability to merge levelled lists from
|
||||
* several files.
|
||||
*/
|
||||
|
||||
struct LeveledListBase
|
||||
struct LevelledListBase
|
||||
{
|
||||
int mFlags;
|
||||
unsigned char mChanceNone; // Chance that none are selected (0-100)
|
||||
|
@ -43,7 +43,7 @@ struct LeveledListBase
|
|||
///< Set record to default state (does not touch the ID).
|
||||
};
|
||||
|
||||
struct CreatureLevList: LeveledListBase
|
||||
struct CreatureLevList: LevelledListBase
|
||||
{
|
||||
static unsigned int sRecordId;
|
||||
|
||||
|
@ -61,7 +61,7 @@ struct CreatureLevList: LeveledListBase
|
|||
}
|
||||
};
|
||||
|
||||
struct ItemLevList: LeveledListBase
|
||||
struct ItemLevList: LevelledListBase
|
||||
{
|
||||
static unsigned int sRecordId;
|
||||
|
||||
|
@ -72,7 +72,7 @@ struct ItemLevList: LeveledListBase
|
|||
// list is instantiated, instead of
|
||||
// giving several identical items
|
||||
// (used when a container has more
|
||||
// than one instance of one leveled
|
||||
// than one instance of one levelled
|
||||
// list.)
|
||||
AllLevels = 0x02 // Calculate from all levels <= player
|
||||
// level, not just the closest below
|
||||
|
|
47
components/esm/stolenitems.cpp
Normal file
47
components/esm/stolenitems.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
#include "stolenitems.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
#include <components/esm/esmwriter.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
||||
void StolenItems::write(ESMWriter &esm) const
|
||||
{
|
||||
for (StolenItemsMap::const_iterator it = mStolenItems.begin(); it != mStolenItems.end(); ++it)
|
||||
{
|
||||
esm.writeHNString("NAME", it->first);
|
||||
for (std::map<std::pair<std::string, bool>, int>::const_iterator ownerIt = it->second.begin();
|
||||
ownerIt != it->second.end(); ++ownerIt)
|
||||
{
|
||||
if (ownerIt->first.second)
|
||||
esm.writeHNString("FNAM", ownerIt->first.first);
|
||||
else
|
||||
esm.writeHNString("ONAM", ownerIt->first.first);
|
||||
esm.writeHNT("COUN", ownerIt->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StolenItems::load(ESMReader &esm)
|
||||
{
|
||||
while (esm.isNextSub("NAME"))
|
||||
{
|
||||
std::string itemid = esm.getHString();
|
||||
|
||||
std::map<std::pair<std::string, bool>, int> ownerMap;
|
||||
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
|
||||
{
|
||||
std::string subname = esm.retSubName().toString();
|
||||
std::string owner = esm.getHString();
|
||||
bool isFaction = (subname == "FNAM");
|
||||
int count;
|
||||
esm.getHNT(count, "COUN");
|
||||
ownerMap.insert(std::make_pair(std::make_pair(owner, isFaction), count));
|
||||
}
|
||||
|
||||
mStolenItems[itemid] = ownerMap;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
components/esm/stolenitems.hpp
Normal file
24
components/esm/stolenitems.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef OPENMW_COMPONENTS_ESM_STOLENITEMS_H
|
||||
#define OPENMW_COMPONENTS_ESM_STOLENITEMS_H
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
class ESMWriter;
|
||||
|
||||
// format 0, saved games only
|
||||
struct StolenItems
|
||||
{
|
||||
typedef std::map<std::string, std::map<std::pair<std::string, bool>, int> > StolenItemsMap;
|
||||
StolenItemsMap mStolenItems;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
void write(ESM::ESMWriter& esm) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,95 +1,144 @@
|
|||
#include "settings.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
|
||||
#include <OgreResourceGroupManager.h>
|
||||
#include <OgreStringConverter.h>
|
||||
#include <OgreDataStream.h>
|
||||
|
||||
#include <components/files/constrainedfiledatastream.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/filesystem/path.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
|
||||
using namespace Settings;
|
||||
namespace Settings
|
||||
{
|
||||
|
||||
namespace bfs = boost::filesystem;
|
||||
|
||||
Ogre::ConfigFile Manager::mFile = Ogre::ConfigFile();
|
||||
Ogre::ConfigFile Manager::mDefaultFile = Ogre::ConfigFile();
|
||||
CategorySettingValueMap Manager::mDefaultSettings = CategorySettingValueMap();
|
||||
CategorySettingValueMap Manager::mUserSettings = CategorySettingValueMap();
|
||||
CategorySettingVector Manager::mChangedSettings = CategorySettingVector();
|
||||
CategorySettingValueMap Manager::mNewSettings = CategorySettingValueMap();
|
||||
|
||||
void Manager::loadUser (const std::string& file)
|
||||
|
||||
class SettingsFileParser
|
||||
{
|
||||
Ogre::DataStreamPtr stream = openConstrainedFileDataStream(file.c_str());
|
||||
mFile.load(stream);
|
||||
}
|
||||
public:
|
||||
SettingsFileParser() : mLine(0) {}
|
||||
|
||||
void Manager::loadDefault (const std::string& file)
|
||||
{
|
||||
Ogre::DataStreamPtr stream = openConstrainedFileDataStream(file.c_str());
|
||||
mDefaultFile.load(stream);
|
||||
}
|
||||
|
||||
void Manager::saveUser(const std::string& file)
|
||||
{
|
||||
bfs::ofstream fout((bfs::path(file)));
|
||||
|
||||
Ogre::ConfigFile::SectionIterator seci = mFile.getSectionIterator();
|
||||
|
||||
while (seci.hasMoreElements())
|
||||
void loadSettingsFile (const std::string& file, CategorySettingValueMap& settings)
|
||||
{
|
||||
Ogre::String sectionName = seci.peekNextKey();
|
||||
|
||||
if (sectionName.length() > 0)
|
||||
fout << '\n' << '[' << seci.peekNextKey() << ']' << '\n';
|
||||
|
||||
Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext();
|
||||
Ogre::ConfigFile::SettingsMultiMap::iterator i;
|
||||
for (i = settings->begin(); i != settings->end(); ++i)
|
||||
mFile = file;
|
||||
boost::filesystem::ifstream stream;
|
||||
stream.open(boost::filesystem::path(file));
|
||||
std::string currentCategory;
|
||||
mLine = 0;
|
||||
while (!stream.eof() && !stream.fail())
|
||||
{
|
||||
fout << i->first.c_str() << " = " << i->second.c_str() << '\n';
|
||||
}
|
||||
++mLine;
|
||||
std::string line;
|
||||
std::getline( stream, line );
|
||||
|
||||
CategorySettingValueMap::iterator it = mNewSettings.begin();
|
||||
while (it != mNewSettings.end())
|
||||
{
|
||||
if (it->first.first == sectionName)
|
||||
size_t i = 0;
|
||||
if (!skipWhiteSpace(i, line))
|
||||
continue;
|
||||
|
||||
if (line[i] == '#') // skip comment
|
||||
continue;
|
||||
|
||||
if (line[i] == '[')
|
||||
{
|
||||
fout << it->first.second << " = " << it->second << '\n';
|
||||
mNewSettings.erase(it++);
|
||||
size_t end = line.find(']', i);
|
||||
if (end == std::string::npos)
|
||||
fail("unterminated category");
|
||||
|
||||
currentCategory = line.substr(i+1, end - (i+1));
|
||||
boost::algorithm::trim(currentCategory);
|
||||
i = end+1;
|
||||
}
|
||||
else
|
||||
++it;
|
||||
|
||||
if (!skipWhiteSpace(i, line))
|
||||
continue;
|
||||
|
||||
if (currentCategory.empty())
|
||||
fail("empty category name");
|
||||
|
||||
size_t settingEnd = line.find('=', i);
|
||||
if (settingEnd == std::string::npos)
|
||||
fail("unterminated setting name");
|
||||
|
||||
std::string setting = line.substr(i, (settingEnd-i));
|
||||
boost::algorithm::trim(setting);
|
||||
|
||||
size_t valueBegin = settingEnd+1;
|
||||
std::string value = line.substr(valueBegin);
|
||||
boost::algorithm::trim(value);
|
||||
|
||||
if (settings.insert(std::make_pair(std::make_pair(currentCategory, setting), value)).second == false)
|
||||
fail(std::string("duplicate setting: [" + currentCategory + "] " + setting));
|
||||
}
|
||||
}
|
||||
|
||||
std::string category = "";
|
||||
for (CategorySettingValueMap::iterator it = mNewSettings.begin();
|
||||
it != mNewSettings.end(); ++it)
|
||||
private:
|
||||
/// Increment i until it longer points to a whitespace character
|
||||
/// in the string or has reached the end of the string.
|
||||
/// @return false if we have reached the end of the string
|
||||
bool skipWhiteSpace(size_t& i, std::string& str)
|
||||
{
|
||||
if (category != it->first.first)
|
||||
while (i < str.size() && std::isspace(str[i], std::locale::classic()))
|
||||
{
|
||||
category = it->first.first;
|
||||
fout << '\n' << '[' << category << ']' << '\n';
|
||||
++i;
|
||||
}
|
||||
fout << it->first.second << " = " << it->second << '\n';
|
||||
return i < str.size();
|
||||
}
|
||||
|
||||
fout.close();
|
||||
void fail(const std::string& message)
|
||||
{
|
||||
std::stringstream error;
|
||||
error << "Error on line " << mLine << " in " << mFile << ":\n" << message;
|
||||
throw std::runtime_error(error.str());
|
||||
}
|
||||
|
||||
std::string mFile;
|
||||
int mLine;
|
||||
};
|
||||
|
||||
void Manager::loadDefault(const std::string &file)
|
||||
{
|
||||
SettingsFileParser parser;
|
||||
parser.loadSettingsFile(file, mDefaultSettings);
|
||||
}
|
||||
|
||||
std::string Manager::getString (const std::string& setting, const std::string& category)
|
||||
void Manager::loadUser(const std::string &file)
|
||||
{
|
||||
if (mNewSettings.find(std::make_pair(category, setting)) != mNewSettings.end())
|
||||
return mNewSettings[std::make_pair(category, setting)];
|
||||
SettingsFileParser parser;
|
||||
parser.loadSettingsFile(file, mUserSettings);
|
||||
}
|
||||
|
||||
std::string defaultval = mDefaultFile.getSetting(setting, category, "NOTFOUND");
|
||||
std::string val = mFile.getSetting(setting, category, defaultval);
|
||||
void Manager::saveUser(const std::string &file)
|
||||
{
|
||||
boost::filesystem::ofstream stream;
|
||||
stream.open(boost::filesystem::path(file));
|
||||
std::string currentCategory;
|
||||
for (CategorySettingValueMap::iterator it = mUserSettings.begin(); it != mUserSettings.end(); ++it)
|
||||
{
|
||||
if (it->first.first != currentCategory)
|
||||
{
|
||||
currentCategory = it->first.first;
|
||||
stream << "\n[" << currentCategory << "]\n";
|
||||
}
|
||||
stream << it->first.second << " = " << it->second << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (val == "NOTFOUND")
|
||||
throw std::runtime_error("Trying to retrieve a non-existing setting: " + setting + " Make sure the settings-default.cfg file was properly installed.");
|
||||
return val;
|
||||
std::string Manager::getString(const std::string &setting, const std::string &category)
|
||||
{
|
||||
CategorySettingValueMap::key_type key = std::make_pair(category, setting);
|
||||
CategorySettingValueMap::iterator it = mUserSettings.find(key);
|
||||
if (it != mUserSettings.end())
|
||||
return it->second;
|
||||
|
||||
it = mDefaultSettings.find(key);
|
||||
if (it != mDefaultSettings.end())
|
||||
return it->second;
|
||||
|
||||
throw std::runtime_error(std::string("Trying to retrieve a non-existing setting: ") + setting
|
||||
+ ".\nMake sure the settings-default.cfg file file was properly installed.");
|
||||
}
|
||||
|
||||
float Manager::getFloat (const std::string& setting, const std::string& category)
|
||||
|
@ -107,51 +156,20 @@ bool Manager::getBool (const std::string& setting, const std::string& category)
|
|||
return Ogre::StringConverter::parseBool( getString(setting, category) );
|
||||
}
|
||||
|
||||
void Manager::setString (const std::string& setting, const std::string& category, const std::string& value)
|
||||
void Manager::setString(const std::string &setting, const std::string &category, const std::string &value)
|
||||
{
|
||||
CategorySetting s = std::make_pair(category, setting);
|
||||
CategorySettingValueMap::key_type key = std::make_pair(category, setting);
|
||||
|
||||
bool found=false;
|
||||
try
|
||||
CategorySettingValueMap::iterator found = mUserSettings.find(key);
|
||||
if (found != mUserSettings.end())
|
||||
{
|
||||
Ogre::ConfigFile::SettingsIterator it = mFile.getSettingsIterator(category);
|
||||
while (it.hasMoreElements())
|
||||
{
|
||||
Ogre::ConfigFile::SettingsMultiMap::iterator i = it.current();
|
||||
|
||||
if ((*i).first == setting)
|
||||
{
|
||||
if ((*i).second != value)
|
||||
{
|
||||
mChangedSettings.push_back(std::make_pair(category, setting));
|
||||
(*i).second = value;
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
|
||||
it.getNext();
|
||||
}
|
||||
if (found->second == value)
|
||||
return;
|
||||
}
|
||||
catch (Ogre::Exception&)
|
||||
{}
|
||||
|
||||
if (!found)
|
||||
{
|
||||
if (mNewSettings.find(s) != mNewSettings.end())
|
||||
{
|
||||
if (mNewSettings[s] != value)
|
||||
{
|
||||
mChangedSettings.push_back(std::make_pair(category, setting));
|
||||
mNewSettings[s] = value;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mDefaultFile.getSetting(setting, category) != value)
|
||||
mChangedSettings.push_back(std::make_pair(category, setting));
|
||||
mNewSettings[s] = value;
|
||||
}
|
||||
}
|
||||
mUserSettings[key] = value;
|
||||
|
||||
mChangedSettings.insert(key);
|
||||
}
|
||||
|
||||
void Manager::setInt (const std::string& setting, const std::string& category, const int value)
|
||||
|
@ -159,12 +177,12 @@ void Manager::setInt (const std::string& setting, const std::string& category, c
|
|||
setString(setting, category, Ogre::StringConverter::toString(value));
|
||||
}
|
||||
|
||||
void Manager::setFloat (const std::string& setting, const std::string& category, const float value)
|
||||
void Manager::setFloat (const std::string &setting, const std::string &category, const float value)
|
||||
{
|
||||
setString(setting, category, Ogre::StringConverter::toString(value));
|
||||
}
|
||||
|
||||
void Manager::setBool (const std::string& setting, const std::string& category, const bool value)
|
||||
void Manager::setBool(const std::string &setting, const std::string &category, const bool value)
|
||||
{
|
||||
setString(setting, category, Ogre::StringConverter::toString(value));
|
||||
}
|
||||
|
@ -175,3 +193,5 @@ const CategorySettingVector Manager::apply()
|
|||
mChangedSettings.clear();
|
||||
return vec;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
#ifndef COMPONENTS_SETTINGS_H
|
||||
#define COMPONENTS_SETTINGS_H
|
||||
|
||||
#include <OgreConfigFile.h>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
namespace Settings
|
||||
{
|
||||
typedef std::pair < std::string, std::string > CategorySetting;
|
||||
typedef std::vector< std::pair<std::string, std::string> > CategorySettingVector;
|
||||
typedef std::set< std::pair<std::string, std::string> > CategorySettingVector;
|
||||
typedef std::map < CategorySetting, std::string > CategorySettingValueMap;
|
||||
|
||||
///
|
||||
|
@ -15,15 +17,12 @@ namespace Settings
|
|||
class Manager
|
||||
{
|
||||
public:
|
||||
static Ogre::ConfigFile mFile;
|
||||
static Ogre::ConfigFile mDefaultFile;
|
||||
static CategorySettingValueMap mDefaultSettings;
|
||||
static CategorySettingValueMap mUserSettings;
|
||||
|
||||
static CategorySettingVector mChangedSettings;
|
||||
///< tracks all the settings that were changed since the last apply() call
|
||||
|
||||
static CategorySettingValueMap mNewSettings;
|
||||
///< tracks all the settings that are in the default file, but not in user file yet
|
||||
|
||||
void loadDefault (const std::string& file);
|
||||
///< load file as the default settings (can be overridden by user settings)
|
||||
|
||||
|
|
|
@ -98,7 +98,6 @@ namespace Terrain
|
|||
DefaultWorld* getTerrain() { return mTerrain; }
|
||||
|
||||
/// Adjust LODs for the given camera position, possibly splitting up chunks or merging them.
|
||||
/// @param force Always choose to render this node, even if not the perfect LOD.
|
||||
/// @return Did we (or all of our children) choose to render?
|
||||
bool update (const Ogre::Vector3& cameraPos);
|
||||
|
||||
|
@ -124,7 +123,6 @@ namespace Terrain
|
|||
/// call this method on their children.
|
||||
/// @note Do not call this before World::areLayersLoaded() == true
|
||||
/// @param area area in image space to put the quad
|
||||
/// @param quads collect quads here so they can be deleted later
|
||||
void prepareForCompositeMap(Ogre::TRect<float> area);
|
||||
|
||||
/// Create a chunk for this node from the given data.
|
||||
|
|
6
extern/sdl4ogre/events.h
vendored
6
extern/sdl4ogre/events.h
vendored
|
@ -1,8 +1,8 @@
|
|||
#ifndef _SFO_EVENTS_H
|
||||
#define _SFO_EVENTS_H
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include <SDL_types.h>
|
||||
#include <SDL_events.h>
|
||||
|
||||
////////////
|
||||
// Events //
|
||||
|
@ -65,7 +65,7 @@ public:
|
|||
virtual ~WindowListener() {}
|
||||
|
||||
/** @remarks The window's visibility changed */
|
||||
virtual void windowVisibilityChange( bool visible ) {};
|
||||
virtual void windowVisibilityChange( bool visible ) {}
|
||||
|
||||
/** @remarks The window got / lost input focus */
|
||||
virtual void windowFocusChange( bool have_focus ) {}
|
||||
|
|
3
extern/sdl4ogre/sdlcursormanager.cpp
vendored
3
extern/sdl4ogre/sdlcursormanager.cpp
vendored
|
@ -4,6 +4,9 @@
|
|||
#include <OgreTextureManager.h>
|
||||
#include <OgreRoot.h>
|
||||
|
||||
#include <SDL_mouse.h>
|
||||
#include <SDL_endian.h>
|
||||
|
||||
#include <openengine/ogre/imagerotate.hpp>
|
||||
|
||||
namespace SFO
|
||||
|
|
5
extern/sdl4ogre/sdlcursormanager.hpp
vendored
5
extern/sdl4ogre/sdlcursormanager.hpp
vendored
|
@ -1,11 +1,12 @@
|
|||
#ifndef SDL4OGRE_CURSORMANAGER_H
|
||||
#define SDL4OGRE_CURSORMANAGER_H
|
||||
|
||||
#include <SDL.h>
|
||||
|
||||
#include "cursormanager.hpp"
|
||||
#include <map>
|
||||
|
||||
struct SDL_Cursor;
|
||||
struct SDL_Surface;
|
||||
|
||||
namespace SFO
|
||||
{
|
||||
class SDLCursorManager :
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_strength.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeStrength}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal1">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal1">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -64,7 +64,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_int.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeIntelligence}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal2">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal2">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -78,7 +78,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_wilpower.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeWillpower}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal3">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal3">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -92,7 +92,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_agility.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeAgility}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal4">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal4">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -107,7 +107,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_speed.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeSpeed}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal5">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal5">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -121,7 +121,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_endurance.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeEndurance}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal6">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal6">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -135,7 +135,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_personality.dds"/>
|
||||
<Property key="Caption" value="#{sAttributePersonality}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal7">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal7">
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
||||
|
@ -149,7 +149,7 @@
|
|||
<UserString key="ImageTexture_AttributeImage" value="icons\k\attribute_luck.dds"/>
|
||||
<Property key="Caption" value="#{sAttributeLuck}"/>
|
||||
</Widget>
|
||||
<Widget type="AutoSizedTextBox" skin="SandText" name="AttribVal8">
|
||||
<Widget type="AutoSizedTextBox" skin="SandTextButton" name="AttribVal8">
|
||||
</Widget>
|
||||
</Widget>
|
||||
</Widget>
|
||||
|
|
Loading…
Reference in a new issue