Merge remote-tracking branch 'zini/master' into nifogre

Conflicts:
	components/nifogre/ogrenifloader.cpp
actorid
Chris Robinson 12 years ago
commit 01a1a0b846

@ -36,6 +36,7 @@ opencs_units (model/tools
opencs_units_noqt (model/tools
stage verifier mandatoryid skillcheck classcheck factioncheck racecheck soundcheck regioncheck
birthsigncheck
)

@ -0,0 +1,39 @@
#include "birthsigncheck.hpp"
#include <sstream>
#include <map>
#include <components/esm/loadbsgn.hpp>
#include "../world/universalid.hpp"
CSMTools::BirthsignCheckStage::BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns)
: mBirthsigns (birthsigns)
{}
int CSMTools::BirthsignCheckStage::setup()
{
return mBirthsigns.getSize();
}
void CSMTools::BirthsignCheckStage::perform (int stage, std::vector<std::string>& messages)
{
const ESM::BirthSign& birthsign = mBirthsigns.getRecord (stage).get();
CSMWorld::UniversalId id (CSMWorld::UniversalId::Type_Birthsign, birthsign.mId);
// test for empty name, description and texture
if (birthsign.mName.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty name");
if (birthsign.mDescription.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " has an empty description");
if (birthsign.mTexture.empty())
messages.push_back (id.toString() + "|" + birthsign.mId + " is missing a texture");
/// \todo test if the texture exists
/// \todo check data members that can't be edited in the table view
}

@ -0,0 +1,29 @@
#ifndef CSM_TOOLS_BIRTHSIGNCHECK_H
#define CSM_TOOLS_BIRTHSIGNCHECK_H
#include <components/esm/loadbsgn.hpp>
#include "../world/idcollection.hpp"
#include "stage.hpp"
namespace CSMTools
{
/// \brief VerifyStage: make sure that birthsign records are internally consistent
class BirthsignCheckStage : public Stage
{
const CSMWorld::IdCollection<ESM::BirthSign>& mBirthsigns;
public:
BirthsignCheckStage (const CSMWorld::IdCollection<ESM::BirthSign>& birthsigns);
virtual int setup();
///< \return number of steps
virtual void perform (int stage, std::vector<std::string>& messages);
///< Messages resulting from this tage will be appended to \a messages.
};
}
#endif

@ -18,6 +18,7 @@
#include "racecheck.hpp"
#include "soundcheck.hpp"
#include "regioncheck.hpp"
#include "birthsigncheck.hpp"
CSMTools::Operation *CSMTools::Tools::get (int type)
{
@ -69,6 +70,8 @@ CSMTools::Verifier *CSMTools::Tools::getVerifier()
mVerifier->appendStage (new SoundCheckStage (mData.getSounds()));
mVerifier->appendStage (new RegionCheckStage (mData.getRegions()));
mVerifier->appendStage (new BirthsignCheckStage (mData.getBirthsigns()));
}
return mVerifier;

@ -650,6 +650,31 @@ namespace CSMWorld
return true;
}
};
template<typename ESXRecordT>
struct TextureColumn : public Column<ESXRecordT>
{
TextureColumn() : Column<ESXRecordT> ("Texture", ColumnBase::Display_String) {}
virtual QVariant get (const Record<ESXRecordT>& record) const
{
return QString::fromUtf8 (record.get().mTexture.c_str());
}
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
{
ESXRecordT record2 = record.get();
record2.mTexture = data.toString().toUtf8().constData();
record.setModified (record2);
}
virtual bool isEditable() const
{
return true;
}
};
}
#endif

@ -93,6 +93,12 @@ CSMWorld::Data::Data()
mRegions.addColumn (new MapColourColumn<ESM::Region>);
mRegions.addColumn (new SleepListColumn<ESM::Region>);
mBirthsigns.addColumn (new StringIdColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new RecordStateColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new NameColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new TextureColumn<ESM::BirthSign>);
mBirthsigns.addColumn (new DescriptionColumn<ESM::BirthSign>);
addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global);
addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst);
addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill);
@ -102,6 +108,7 @@ CSMWorld::Data::Data()
addModel (new IdTable (&mSounds), UniversalId::Type_Sounds, UniversalId::Type_Sound);
addModel (new IdTable (&mScripts), UniversalId::Type_Scripts, UniversalId::Type_Script);
addModel (new IdTable (&mRegions), UniversalId::Type_Regions, UniversalId::Type_Region);
addModel (new IdTable (&mBirthsigns), UniversalId::Type_Birthsigns, UniversalId::Type_Birthsign);
}
CSMWorld::Data::~Data()
@ -200,6 +207,16 @@ CSMWorld::IdCollection<ESM::Region>& CSMWorld::Data::getRegions()
return mRegions;
}
const CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns() const
{
return mBirthsigns;
}
CSMWorld::IdCollection<ESM::BirthSign>& CSMWorld::Data::getBirthsigns()
{
return mBirthsigns;
}
QAbstractItemModel *CSMWorld::Data::getTableModel (const UniversalId& id)
{
std::map<UniversalId::Type, QAbstractItemModel *>::iterator iter = mModelIndex.find (id.getType());
@ -243,6 +260,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base)
case ESM::REC_SOUN: mSounds.load (reader, base); break;
case ESM::REC_SCPT: mScripts.load (reader, base); break;
case ESM::REC_REGN: mRegions.load (reader, base); break;
case ESM::REC_BSGN: mBirthsigns.load (reader, base); break;
default:

@ -15,6 +15,7 @@
#include <components/esm/loadsoun.hpp>
#include <components/esm/loadscpt.hpp>
#include <components/esm/loadregn.hpp>
#include <components/esm/loadbsgn.hpp>
#include "idcollection.hpp"
#include "universalid.hpp"
@ -34,6 +35,7 @@ namespace CSMWorld
IdCollection<ESM::Sound> mSounds;
IdCollection<ESM::Script> mScripts;
IdCollection<ESM::Region> mRegions;
IdCollection<ESM::BirthSign> mBirthsigns;
std::vector<QAbstractItemModel *> mModels;
std::map<UniversalId::Type, QAbstractItemModel *> mModelIndex;
@ -86,6 +88,10 @@ namespace CSMWorld
IdCollection<ESM::Region>& getRegions();
const IdCollection<ESM::BirthSign>& getBirthsigns() const;
IdCollection<ESM::BirthSign>& getBirthsigns();
QAbstractItemModel *getTableModel (const UniversalId& id);
///< If no table model is available for \a id, an exception is thrown.
///

@ -26,6 +26,7 @@ namespace
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Sounds, "Sounds" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Scripts, "Scripts" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Regions, "Regions" },
{ CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Birthsigns, "Birthsigns" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};
@ -41,6 +42,7 @@ namespace
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Sound, "Sound" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Script, "Script" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Region, "Region" },
{ CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Birthsign, "Birthsign" },
{ CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker
};

@ -51,7 +51,9 @@ namespace CSMWorld
Type_Scripts,
Type_Script,
Type_Regions,
Type_Region
Type_Region,
Type_Birthsigns,
Type_Birthsign
};
private:

@ -117,6 +117,10 @@ void CSVDoc::View::setupWorldMenu()
QAction *regions = new QAction (tr ("Regions"), this);
connect (regions, SIGNAL (triggered()), this, SLOT (addRegionsSubView()));
world->addAction (regions);
QAction *birthsigns = new QAction (tr ("Birthsigns"), this);
connect (birthsigns, SIGNAL (triggered()), this, SLOT (addBirthsignsSubView()));
world->addAction (birthsigns);
}
void CSVDoc::View::setupUi()
@ -307,6 +311,11 @@ void CSVDoc::View::addRegionsSubView()
addSubView (CSMWorld::UniversalId::Type_Regions);
}
void CSVDoc::View::addBirthsignsSubView()
{
addSubView (CSMWorld::UniversalId::Type_Birthsigns);
}
void CSVDoc::View::abortOperation (int type)
{
mDocument->abortOperation (type);

@ -129,6 +129,8 @@ namespace CSVDoc
void addScriptsSubView();
void addRegionsSubView();
void addBirthsignsSubView();
};
}

@ -23,6 +23,7 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager)
CSMWorld::UniversalId::Type_Sounds,
CSMWorld::UniversalId::Type_Scripts,
CSMWorld::UniversalId::Type_Regions,
CSMWorld::UniversalId::Type_Birthsigns,
CSMWorld::UniversalId::Type_None // end marker
};

@ -159,4 +159,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mAppas.insert(*ref), &cell);
}
bool Apparatus::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Apparatus;
}
}

@ -54,6 +54,8 @@ namespace MWClass
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -315,4 +315,9 @@ namespace MWClass
return ref->mBase->mData.mEnchant;
}
bool Armor::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Armor;
}
}

@ -74,6 +74,8 @@ namespace MWClass
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -183,4 +183,9 @@ namespace MWClass
return ref->mBase->mData.mEnchant;
}
bool Book::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Books;
}
}

@ -59,6 +59,8 @@ namespace MWClass
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -262,4 +262,9 @@ namespace MWClass
return ref->mBase->mData.mEnchant;
}
bool Clothing::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Clothing;
}
}

@ -68,6 +68,8 @@ namespace MWClass
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -197,4 +197,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mIngreds.insert(*ref), &cell);
}
bool Ingredient::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Ingredients;
}
}

@ -56,6 +56,8 @@ namespace MWClass
///< Return name of inventory icon.
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -203,4 +203,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mLights.insert(*ref), &cell);
}
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Lights;
}
}

@ -57,6 +57,8 @@ namespace MWClass
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -176,4 +176,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mLockpicks.insert(*ref), &cell);
}
bool Lockpick::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Picks;
}
}

@ -57,6 +57,8 @@ namespace MWClass
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -246,4 +246,12 @@ namespace MWClass
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionSoulgem(ptr));
}
bool Miscellaneous::canSell (const MWWorld::Ptr& item, int npcServices) const
{
MWWorld::LiveCellRef<ESM::Miscellaneous> *ref =
item.get<ESM::Miscellaneous>();
return !ref->mBase->mData.mIsKey && (npcServices & ESM::NPC::Misc);
}
}

@ -53,6 +53,8 @@ namespace MWClass
virtual boost::shared_ptr<MWWorld::Action> use (const MWWorld::Ptr& ptr)
const;
///< Generate action for using via inventory menu
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -194,4 +194,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mPotions.insert(*ref), &cell);
}
bool Potion::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Potions;
}
}

@ -52,6 +52,8 @@ namespace MWClass
///< Return name of inventory icon.
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -175,4 +175,9 @@ namespace MWClass
return MWWorld::Ptr(&cell.mProbes.insert(*ref), &cell);
}
bool Probe::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Probes;
}
}

@ -57,6 +57,8 @@ namespace MWClass
///< Generate action for using via inventory menu
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -175,4 +175,9 @@ namespace MWClass
{
return boost::shared_ptr<MWWorld::Action>(new MWWorld::ActionRepair(ptr));
}
bool Repair::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::RepairItem;
}
}

@ -61,6 +61,8 @@ namespace MWClass
virtual int getItemMaxHealth (const MWWorld::Ptr& ptr) const;
///< Return item max health or throw an exception, if class does not have item health
/// (default implementation: throw an exceoption)
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
};
}

@ -409,4 +409,9 @@ namespace MWClass
return ref->mBase->mData.mEnchant;
}
bool Weapon::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return npcServices & ESM::NPC::Weapon;
}
}

@ -73,6 +73,8 @@ namespace MWClass
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
virtual short getEnchantmentPoints (const MWWorld::Ptr& ptr) const;
};
}

@ -150,6 +150,7 @@ namespace MWGui
it = invStore.add(ptr);
(*it).getRefData().setCount(mDragAndDrop->mDraggedCount);
ptr = *it;
mDragAndDrop->mDraggedFrom->notifyItemDragged(ptr, -mDragAndDrop->mDraggedCount);
}
/// \todo scripts

@ -114,15 +114,9 @@ MWGui::JournalWindow::JournalWindow (MWBase::WindowManager& parWindowManager)
//displayLeftText(list.front());
}
void MWGui::JournalWindow::close()
{
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
}
void MWGui::JournalWindow::open()
{
mPageNumber = 0;
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
if(MWBase::Environment::get().getJournal()->begin()!=MWBase::Environment::get().getJournal()->end())
{
book journal;

@ -16,7 +16,6 @@ namespace MWGui
public:
JournalWindow(MWBase::WindowManager& parWindowManager);
virtual void open();
virtual void close();
private:
void displayLeftText(std::string text);

@ -257,6 +257,12 @@ namespace MWGui
MWBase::Environment::get().getDialogueManager()->applyTemporaryDispositionChange(iBarterSuccessDisposition);
// success! make the item transfer.
MWWorld::ContainerStore& playerBoughtItems = mWindowManager.getInventoryWindow()->getBoughtItems();
for (MWWorld::ContainerStoreIterator it = playerBoughtItems.begin(); it != playerBoughtItems.end(); ++it)
{
if (Misc::StringUtils::ciEqual(it->getCellRef().mOwner, MWWorld::Class::get(mPtr).getId(mPtr)))
it->getCellRef().mOwner = "";
}
transferBoughtItems();
mWindowManager.getInventoryWindow()->transferBoughtItems();
@ -356,32 +362,7 @@ namespace MWGui
services = ref->mBase->mAiData.mServices;
}
/// \todo what about potions, there doesn't seem to be a flag for them??
if (item.getTypeName() == typeid(ESM::Weapon).name())
return services & ESM::NPC::Weapon;
else if (item.getTypeName() == typeid(ESM::Armor).name())
return services & ESM::NPC::Armor;
else if (item.getTypeName() == typeid(ESM::Clothing).name())
return services & ESM::NPC::Clothing;
else if (item.getTypeName() == typeid(ESM::Book).name())
return services & ESM::NPC::Books;
else if (item.getTypeName() == typeid(ESM::Ingredient).name())
return services & ESM::NPC::Ingredients;
else if (item.getTypeName() == typeid(ESM::Lockpick).name())
return services & ESM::NPC::Picks;
else if (item.getTypeName() == typeid(ESM::Probe).name())
return services & ESM::NPC::Probes;
else if (item.getTypeName() == typeid(ESM::Light).name())
return services & ESM::NPC::Lights;
else if (item.getTypeName() == typeid(ESM::Apparatus).name())
return services & ESM::NPC::Apparatus;
else if (item.getTypeName() == typeid(ESM::Repair).name())
return services & ESM::NPC::RepairItem;
else if (item.getTypeName() == typeid(ESM::Miscellaneous).name())
return services & ESM::NPC::Misc;
return false;
return MWWorld::Class::get(item).canSell(item, services);
}
std::vector<MWWorld::Ptr> TradeWindow::itemsToIgnore()

@ -156,6 +156,7 @@ namespace MWGui
MWBase::Environment::get().getWorld()->advanceTime(time);
}
MWBase::Environment::get().getWorld()->moveObject(player,*cell,pos.pos[0],pos.pos[1],pos.pos[2]);
MWWorld::Class::get(player).adjustPosition(player);
mWindowManager.removeGuiMode(GM_Travel);
mWindowManager.removeGuiMode(GM_Dialogue);
MWBase::Environment::get().getWorld ()->getFader ()->fadeOut(0);

@ -656,9 +656,15 @@ namespace MWInput
bool gameMode = !mWindows.isGuiMode();
if(gameMode)
{
MWBase::Environment::get().getSoundManager()->playSound ("book open", 1.0, 1.0);
mWindows.pushGuiMode(MWGui::GM_Journal);
}
else if(mWindows.getMode() == MWGui::GM_Journal)
{
MWBase::Environment::get().getSoundManager()->playSound ("book close", 1.0, 1.0);
mWindows.popGuiMode();
}
// .. but don't touch any other mode.
}

@ -45,7 +45,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->mBase->mInventory, mStore);
iter->mBase->mInventory, container.getCellRef().mOwner, mStore);
}
for (CellRefList<ESM::Creature>::List::iterator iter (
@ -55,7 +55,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->mBase->mInventory, mStore);
iter->mBase->mInventory, Class::get(container).getId(container), mStore);
}
for (CellRefList<ESM::NPC>::List::iterator iter (
@ -65,7 +65,7 @@ void MWWorld::Cells::fillContainers (Ptr::CellStore& cellStore)
Ptr container (&*iter, &cellStore);
Class::get (container).getContainerStore (container).fill (
iter->mBase->mInventory, mStore);
iter->mBase->mInventory, Class::get(container).getId(container), mStore);
}
}

@ -47,6 +47,11 @@ namespace MWWorld
throw std::runtime_error ("class does not represent an actor");
}
bool Class::canSell (const MWWorld::Ptr& item, int npcServices) const
{
return false;
}
MWMechanics::CreatureStats& Class::getCreatureStats (const Ptr& ptr) const
{
throw std::runtime_error ("class does not have creature stats");

@ -238,6 +238,9 @@ namespace MWWorld
virtual void adjustRotation(const MWWorld::Ptr& ptr,float& x,float& y,float& z) const;
virtual bool canSell (const MWWorld::Ptr& item, int npcServices) const;
///< Determine whether or not \a item can be sold to an npc with the given \a npcServices
virtual std::string getModel(const MWWorld::Ptr &ptr) const;
virtual void applyEnchantment(const MWWorld::Ptr &ptr, const std::string& enchId, int enchCharge, const std::string& newName) const;

@ -14,6 +14,8 @@
#include "../mwbase/world.hpp"
#include "../mwbase/scriptmanager.hpp"
#include "../mwmechanics/creaturestats.hpp"
#include "manualref.hpp"
#include "refdata.hpp"
#include "class.hpp"
@ -175,24 +177,76 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::addImpl (const Ptr& ptr
return it;
}
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const MWWorld::ESMStore& store)
void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store)
{
for (std::vector<ESM::ContItem>::const_iterator iter (items.mList.begin()); iter!=items.mList.end();
++iter)
{
ManualRef ref (store, iter->mItem.toString());
std::string id = iter->mItem.toString();
addInitialItem(id, owner, iter->mCount);
}
flagAsModified();
}
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, int count, unsigned char failChance, bool topLevel)
{
count = std::abs(count); /// \todo implement item restocking (indicated by negative count)
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id);
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
{
const ESM::ItemLevList* levItem = ref.getPtr().get<ESM::ItemLevList>()->mBase;
const std::vector<ESM::LeveledListBase::LevelItem>& items = levItem->mList;
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayer().getPlayer();
int playerLevel = MWWorld::Class::get(player).getCreatureStats(player).getLevel();
failChance += levItem->mChanceNone;
if (ref.getPtr().getTypeName()==typeid (ESM::ItemLevList).name())
if (topLevel && count > 1 && levItem->mFlags & ESM::ItemLevList::Each)
{
/// \todo implement leveled item lists
continue;
for (int i=0; i<count; ++i)
addInitialItem(id, owner, 1, failChance, false);
return;
}
ref.getPtr().getRefData().setCount (std::abs(iter->mCount)); /// \todo implement item restocking (indicated by negative count)
float random = static_cast<float> (std::rand()) / RAND_MAX;
if (random >= failChance/100.f)
{
std::vector<std::string> candidates;
int highestLevel = 0;
for (std::vector<ESM::LeveledListBase::LevelItem>::const_iterator it = items.begin(); it != items.end(); ++it)
{
if (it->mLevel > highestLevel)
highestLevel = it->mLevel;
}
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)
{
if (playerLevel >= it->mLevel
&& (levItem->mFlags & ESM::ItemLevList::AllLevels || it->mLevel == highestLevel))
{
candidates.push_back(it->mId);
if (it->mLevel >= highest.first)
highest = std::make_pair(it->mLevel, it->mId);
}
}
if (!candidates.size())
return;
std::string item = candidates[std::rand()%candidates.size()];
addInitialItem(item, owner, count, failChance, false);
}
}
else
{
ref.getPtr().getRefData().setCount (count);
ref.getPtr().getCellRef().mOwner = owner;
addImp (ref.getPtr());
}
flagAsModified();
}
void MWWorld::ContainerStore::clear()

@ -53,6 +53,7 @@ namespace MWWorld
mutable float mCachedWeight;
mutable bool mWeightUpToDate;
ContainerStoreIterator addImp (const Ptr& ptr);
void addInitialItem (const std::string& id, const std::string& owner, int count, unsigned char failChance=0, bool topLevel=true);
public:
@ -84,7 +85,7 @@ namespace MWWorld
public:
void fill (const ESM::InventoryList& items, const MWWorld::ESMStore& store);
void fill (const ESM::InventoryList& items, const std::string& owner, const MWWorld::ESMStore& store);
///< Insert items into *this.
void clear();

@ -24,4 +24,12 @@ void BirthSign::save(ESMWriter &esm)
mPowers.save(esm);
}
void BirthSign::blank()
{
mName.clear();
mDescription.clear();
mTexture.clear();
mPowers.mList.clear();
}
}

@ -20,6 +20,9 @@ struct BirthSign
void load(ESMReader &esm);
void save(ESMWriter &esm);
void blank();
///< Set record to default state (does not touch the ID/index).
};
}
#endif

@ -22,17 +22,20 @@ struct LeveledListBase
{
enum Flags
{
AllLevels = 0x01, // Calculate from all levels <= player
// level, not just the closest below
// player.
Each = 0x02 // Select a new item each time this
Each = 0x01, // Select a new item each time this
// list is instantiated, instead of
// giving several identical items
}; // (used when a container has more
// (used when a container has more
// than one instance of one leveled
// list.)
AllLevels = 0x02 // Calculate from all levels <= player
// level, not just the closest below
// player.
};
int mFlags;
unsigned char mChanceNone; // Chance that none are selected (0-255?)
unsigned char mChanceNone; // Chance that none are selected (0-100)
std::string mId;
// Record name used to read references. Must be set before load() is

@ -35,11 +35,11 @@ struct NPC
Apparatus = 0x00100,
RepairItem = 0x00200,
Misc = 0x00400,
Potions = 0x02000,
// Other services
Spells = 0x00800,
MagicItems = 0x01000,
Potions = 0x02000,
Training = 0x04000, // What skills?
Spellmaking = 0x08000,
Enchanting = 0x10000,

@ -1109,16 +1109,28 @@ static Ogre::String getMaterial(const Nif::ShapeData *shapedata,
instance->setProperty("diffuseMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BaseTexture]));
instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture]));
instance->setProperty("detailMap", sh::makeProperty(texName[Nif::NiTexturingProperty::DetailTexture]));
instance->setProperty("emissiveMap", sh::makeProperty(texName[Nif::NiTexturingProperty::GlowTexture]));
if (!texName[Nif::NiTexturingProperty::GlowTexture].empty())
{
instance->setProperty("use_emissive_map", sh::makeProperty(new sh::BooleanValue(true)));
instance->setProperty("emissiveMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::GlowTexture].uvSet)));
}
if (!texName[Nif::NiTexturingProperty::DetailTexture].empty())
{
instance->setProperty("use_detail_map", sh::makeProperty(new sh::BooleanValue(true)));
instance->setProperty("detailMapUVSet", sh::makeProperty(new sh::IntValue(texprop->textures[Nif::NiTexturingProperty::DetailTexture].uvSet)));
}
if (!texName[Nif::NiTexturingProperty::BumpTexture].empty())
{
// force automips on normal maps for now
instance->setProperty("normalMap", sh::makeProperty(texName[Nif::NiTexturingProperty::BumpTexture] + " 4"));
}
for(int i = 0;i < 7;i++)
{
if(i == Nif::NiTexturingProperty::BaseTexture ||
i == Nif::NiTexturingProperty::DetailTexture ||
i == Nif::NiTexturingProperty::BumpTexture ||
i == Nif::NiTexturingProperty::GlowTexture)
continue;
@ -1390,17 +1402,19 @@ class NIFObjectLoader : Ogre::ManualResourceLoader
size_t numUVs = data->uvlist.size();
if(numUVs)
{
size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size()*numUVs,
Ogre::HardwareBuffer::HBU_STATIC);
for(size_t i = 0;i < numUVs;i++)
{
size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2);
vbuf = hwBufMgr->createVertexBuffer(elemSize, srcVerts.size(),
Ogre::HardwareBuffer::HBU_STATIC);
const std::vector<Ogre::Vector2> &uvlist = data->uvlist[i];
vbuf->writeData(i*srcVerts.size()*elemSize, elemSize*srcVerts.size(), &uvlist[0], true);
decl->addElement(nextBuf, i*srcVerts.size()*elemSize, Ogre::VET_FLOAT2,
vbuf->writeData(0, elemSize*srcVerts.size(), &uvlist[0], true);
decl->addElement(nextBuf, 0, Ogre::VET_FLOAT2,
Ogre::VES_TEXTURE_COORDINATES, i);
bind->setBinding(nextBuf++, vbuf);
}
bind->setBinding(nextBuf++, vbuf);
}
// Triangle faces

@ -9,9 +9,10 @@ material openmw_objects_base
normalMap
emissiveMap
use_emissive_map false
use_detail_map false
emissiveMapUVSet 0
detailMapUVSet 0
is_transparent false // real transparency, alpha rejection doesn't count here
scene_blend default
depth_write default
depth_check default
@ -27,10 +28,11 @@ material openmw_objects_base
shader_properties
{
vertexcolor_mode $vertmode
is_transparent $is_transparent
normalMap $normalMap
emissiveMapUVSet $emissiveMapUVSet
detailMapUVSet $detailMapUVSet
emissiveMap $emissiveMap
detailMap $detailMap
}
diffuse $diffuse
@ -53,7 +55,7 @@ material openmw_objects_base
texture_unit normalMap
{
direct_texture $normalMap
texture $normalMap
}
texture_unit emissiveMap
@ -63,6 +65,14 @@ material openmw_objects_base
direct_texture $emissiveMap
tex_coord_set $emissiveMapUVSet
}
texture_unit detailMap
{
create_in_ffp $use_detail_map
colour_op_ex modulate_x2 src_current src_texture
direct_texture $detailMap
tex_coord_set $detailMapUVSet
}
texture_unit shadowMap0
{

@ -16,9 +16,10 @@
#define NORMAL_MAP @shPropertyHasValue(normalMap)
#define EMISSIVE_MAP @shPropertyHasValue(emissiveMap)
#define DETAIL_MAP @shPropertyHasValue(detailMap)
// right now we support 2 UV sets max. implementing them is tedious, and we're probably not going to need more
#define SECOND_UV_SET @shPropertyString(emissiveMapUVSet)
#define SECOND_UV_SET (@shPropertyString(emissiveMapUVSet) || @shPropertyString(detailMapUVSet))
// if normal mapping is enabled, we force pixel lighting
#define VERTEX_LIGHTING (!@shPropertyHasValue(normalMap))
@ -238,6 +239,10 @@
shSampler2D(emissiveMap)
#endif
#if DETAIL_MAP
shSampler2D(detailMap)
#endif
shInput(float4, UV)
#if NORMAL_MAP
@ -315,6 +320,14 @@
{
shOutputColour(0) = shSample(diffuseMap, UV.xy);
#if DETAIL_MAP
#if @shPropertyString(detailMapUVSet)
shOutputColour(0) *= shSample(detailMap, UV.zw)*2;
#else
shOutputColour(0) *= shSample(detailMap, UV.xy)*2;
#endif
#endif
#if NORMAL_MAP
float3 normal = normalPassthrough;
float3 binormal = cross(tangentPassthrough.xyz, normal.xyz);
@ -421,7 +434,7 @@
#endif
#if EMISSIVE_MAP
#if SECOND_UV_SET
#if @shPropertyString(emissiveMapUVSet)
shOutputColour(0).xyz += shSample(emissiveMap, UV.zw).xyz;
#else
shOutputColour(0).xyz += shSample(emissiveMap, UV.xy).xyz;

Loading…
Cancel
Save