mirror of
https://github.com/OpenMW/openmw.git
synced 2025-01-21 06:23:53 +00:00
Native graphics herbalism support (feature #5010)
This commit is contained in:
parent
0bec84342c
commit
861d41f4a4
18 changed files with 232 additions and 4 deletions
|
@ -105,6 +105,7 @@
|
||||||
Feature #4968: Scalable UI widget skins
|
Feature #4968: Scalable UI widget skins
|
||||||
Feature #4994: Persistent pinnable windows hiding
|
Feature #4994: Persistent pinnable windows hiding
|
||||||
Feature #5000: Compressed BSA format support
|
Feature #5000: Compressed BSA format support
|
||||||
|
Feature #5010: Native graphics herbalism support
|
||||||
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
Task #4686: Upgrade media decoder to a more current FFmpeg API
|
||||||
Task #4695: Optimize Distant Terrain memory consumption
|
Task #4695: Optimize Distant Terrain memory consumption
|
||||||
Task #4721: Add NMake support to the Windows prebuild script
|
Task #4721: Add NMake support to the Windows prebuild script
|
||||||
|
|
|
@ -62,7 +62,7 @@ add_openmw_dir (mwsound
|
||||||
add_openmw_dir (mwworld
|
add_openmw_dir (mwworld
|
||||||
refdata worldimp scene globals class action nullaction actionteleport
|
refdata worldimp scene globals class action nullaction actionteleport
|
||||||
containerstore actiontalk actiontake manualref player cellvisitors failedaction
|
containerstore actiontalk actiontake manualref player cellvisitors failedaction
|
||||||
cells localscripts customdata inventorystore ptr actionopen actionread
|
cells localscripts customdata inventorystore ptr actionopen actionread actionharvest
|
||||||
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
actionequip timestamp actionalchemy cellstore actionapply actioneat
|
||||||
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
store esmstore recordcmp fallback actionrepair actionsoulgem livecellref actiondoor
|
||||||
contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
|
contentloader esmloader actiontrap cellreflist cellref physicssystem weather projectilemanager
|
||||||
|
|
|
@ -578,6 +578,7 @@ namespace MWBase
|
||||||
/// Return the distance between actor's weapon and target's collision box.
|
/// Return the distance between actor's weapon and target's collision box.
|
||||||
virtual float getHitDistance(const MWWorld::ConstPtr& actor, const MWWorld::ConstPtr& target) = 0;
|
virtual float getHitDistance(const MWWorld::ConstPtr& actor, const MWWorld::ConstPtr& target) = 0;
|
||||||
|
|
||||||
|
virtual void addContainerScripts(const MWWorld::Ptr& reference, MWWorld::CellStore* cell) = 0;
|
||||||
virtual void removeContainerScripts(const MWWorld::Ptr& reference) = 0;
|
virtual void removeContainerScripts(const MWWorld::Ptr& reference) = 0;
|
||||||
|
|
||||||
virtual bool isPlayerInJail() const = 0;
|
virtual bool isPlayerInJail() const = 0;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "../mwworld/customdata.hpp"
|
#include "../mwworld/customdata.hpp"
|
||||||
#include "../mwworld/cellstore.hpp"
|
#include "../mwworld/cellstore.hpp"
|
||||||
#include "../mwworld/esmstore.hpp"
|
#include "../mwworld/esmstore.hpp"
|
||||||
|
#include "../mwworld/actionharvest.hpp"
|
||||||
#include "../mwworld/actionopen.hpp"
|
#include "../mwworld/actionopen.hpp"
|
||||||
#include "../mwworld/actiontrap.hpp"
|
#include "../mwworld/actiontrap.hpp"
|
||||||
#include "../mwphysics/physicssystem.hpp"
|
#include "../mwphysics/physicssystem.hpp"
|
||||||
|
@ -22,6 +23,7 @@
|
||||||
|
|
||||||
#include "../mwgui/tooltips.hpp"
|
#include "../mwgui/tooltips.hpp"
|
||||||
|
|
||||||
|
#include "../mwrender/animation.hpp"
|
||||||
#include "../mwrender/objects.hpp"
|
#include "../mwrender/objects.hpp"
|
||||||
#include "../mwrender/renderinginterface.hpp"
|
#include "../mwrender/renderinginterface.hpp"
|
||||||
|
|
||||||
|
@ -40,6 +42,10 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
virtual const ContainerCustomData& asContainerCustomData() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
MWWorld::CustomData *ContainerCustomData::clone() const
|
MWWorld::CustomData *ContainerCustomData::clone() const
|
||||||
|
@ -63,9 +69,20 @@ namespace MWClass
|
||||||
|
|
||||||
// store
|
// store
|
||||||
ptr.getRefData().setCustomData (data.release());
|
ptr.getRefData().setCustomData (data.release());
|
||||||
|
|
||||||
|
MWBase::Environment::get().getWorld()->addContainerScripts(ptr, ptr.getCell());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canBeHarvested(const MWWorld::ConstPtr& ptr)
|
||||||
|
{
|
||||||
|
const MWRender::Animation* animation = MWBase::Environment::get().getWorld()->getAnimation(ptr);
|
||||||
|
if (animation == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return animation->canBeHarvested();
|
||||||
|
}
|
||||||
|
|
||||||
void Container::respawn(const MWWorld::Ptr &ptr) const
|
void Container::respawn(const MWWorld::Ptr &ptr) const
|
||||||
{
|
{
|
||||||
MWWorld::LiveCellRef<ESM::Container> *ref =
|
MWWorld::LiveCellRef<ESM::Container> *ref =
|
||||||
|
@ -175,6 +192,12 @@ namespace MWClass
|
||||||
{
|
{
|
||||||
if(!isTrapped)
|
if(!isTrapped)
|
||||||
{
|
{
|
||||||
|
if (canBeHarvested(ptr))
|
||||||
|
{
|
||||||
|
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionHarvest(ptr));
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionOpen(ptr));
|
std::shared_ptr<MWWorld::Action> action (new MWWorld::ActionOpen(ptr));
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
@ -225,9 +248,18 @@ namespace MWClass
|
||||||
|
|
||||||
bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const
|
bool Container::hasToolTip (const MWWorld::ConstPtr& ptr) const
|
||||||
{
|
{
|
||||||
const MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>();
|
if (getName(ptr).empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
return (ref->mBase->mName != "");
|
if (const MWWorld::CustomData* data = ptr.getRefData().getCustomData())
|
||||||
|
return !canBeHarvested(ptr) || data->asContainerCustomData().mContainerStore.hasVisibleItems();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Container::canBeActivated(const MWWorld::Ptr& ptr) const
|
||||||
|
{
|
||||||
|
return hasToolTip(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
MWGui::ToolTipInfo Container::getToolTipInfo (const MWWorld::ConstPtr& ptr, int count) const
|
||||||
|
|
|
@ -63,6 +63,8 @@ namespace MWClass
|
||||||
const;
|
const;
|
||||||
///< Write additional state from \a ptr into \a state.
|
///< Write additional state from \a ptr into \a state.
|
||||||
|
|
||||||
|
virtual bool canBeActivated(const MWWorld::Ptr& ptr) const;
|
||||||
|
|
||||||
static void registerSelf();
|
static void registerSelf();
|
||||||
|
|
||||||
virtual void respawn (const MWWorld::Ptr& ptr) const;
|
virtual void respawn (const MWWorld::Ptr& ptr) const;
|
||||||
|
|
|
@ -949,6 +949,9 @@ namespace MWMechanics
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!target.getClass().canBeActivated(target))
|
||||||
|
return true;
|
||||||
|
|
||||||
// TODO: implement a better check to check if target is owned bed
|
// TODO: implement a better check to check if target is owned bed
|
||||||
if (target.getClass().isActivator() && target.getClass().getScript(target).compare(0, 3, "Bed") != 0)
|
if (target.getClass().isActivator() && target.getClass().getScript(target).compare(0, 3, "Bed") != 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -131,6 +131,25 @@ namespace
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class HarvestVisitor : public osg::NodeVisitor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HarvestVisitor()
|
||||||
|
: osg::NodeVisitor(TRAVERSE_ALL_CHILDREN)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void apply(osg::Switch& node)
|
||||||
|
{
|
||||||
|
if (node.getName() == Constants::HerbalismLabel)
|
||||||
|
{
|
||||||
|
node.setSingleChildOn(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
traverse(node);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
|
NifOsg::TextKeyMap::const_iterator findGroupStart(const NifOsg::TextKeyMap &keys, const std::string &groupname)
|
||||||
{
|
{
|
||||||
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
|
NifOsg::TextKeyMap::const_iterator iter(keys.begin());
|
||||||
|
@ -1970,6 +1989,30 @@ namespace MWRender
|
||||||
AddSwitchCallbacksVisitor visitor;
|
AddSwitchCallbacksVisitor visitor;
|
||||||
mObjectRoot->accept(visitor);
|
mObjectRoot->accept(visitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ptr.getTypeName() == typeid(ESM::Container).name() &&
|
||||||
|
SceneUtil::hasUserDescription(mObjectRoot, Constants::HerbalismLabel) &&
|
||||||
|
ptr.getRefData().getCustomData() != nullptr)
|
||||||
|
{
|
||||||
|
const MWWorld::ContainerStore& store = ptr.getClass().getContainerStore(ptr);
|
||||||
|
if (!store.hasVisibleItems())
|
||||||
|
{
|
||||||
|
HarvestVisitor visitor;
|
||||||
|
mObjectRoot->accept(visitor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ObjectAnimation::canBeHarvested() const
|
||||||
|
{
|
||||||
|
if (mPtr.getTypeName() != typeid(ESM::Container).name())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const MWWorld::LiveCellRef<ESM::Container>* ref = mPtr.get<ESM::Container>();
|
||||||
|
if (!(ref->mBase->mFlags & ESM::Container::Organic))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return SceneUtil::hasUserDescription(mObjectRoot, Constants::HerbalismLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
Animation::AnimState::~AnimState()
|
Animation::AnimState::~AnimState()
|
||||||
|
|
|
@ -475,6 +475,7 @@ public:
|
||||||
virtual float getHeadPitch() const;
|
virtual float getHeadPitch() const;
|
||||||
virtual float getHeadYaw() const;
|
virtual float getHeadYaw() const;
|
||||||
virtual void setAccurateAiming(bool enabled) {}
|
virtual void setAccurateAiming(bool enabled) {}
|
||||||
|
virtual bool canBeHarvested() const { return false; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Animation(const Animation&);
|
Animation(const Animation&);
|
||||||
|
@ -484,6 +485,8 @@ private:
|
||||||
class ObjectAnimation : public Animation {
|
class ObjectAnimation : public Animation {
|
||||||
public:
|
public:
|
||||||
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight);
|
ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model, Resource::ResourceSystem* resourceSystem, bool animated, bool allowLight);
|
||||||
|
|
||||||
|
bool canBeHarvested() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class UpdateVfxCallback : public osg::NodeCallback
|
class UpdateVfxCallback : public osg::NodeCallback
|
||||||
|
|
93
apps/openmw/mwworld/actionharvest.cpp
Normal file
93
apps/openmw/mwworld/actionharvest.cpp
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
#include "actionharvest.hpp"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include <MyGUI_LanguageManager.h>
|
||||||
|
|
||||||
|
#include <components/misc/stringops.hpp>
|
||||||
|
|
||||||
|
#include "../mwbase/environment.hpp"
|
||||||
|
#include "../mwbase/mechanicsmanager.hpp"
|
||||||
|
#include "../mwbase/windowmanager.hpp"
|
||||||
|
#include "../mwbase/world.hpp"
|
||||||
|
|
||||||
|
#include "class.hpp"
|
||||||
|
#include "containerstore.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
ActionHarvest::ActionHarvest (const MWWorld::Ptr& container)
|
||||||
|
: Action (true, container)
|
||||||
|
{
|
||||||
|
setSound("Item Ingredient Up");
|
||||||
|
}
|
||||||
|
|
||||||
|
void ActionHarvest::executeImp (const MWWorld::Ptr& actor)
|
||||||
|
{
|
||||||
|
if (!MWBase::Environment::get().getWindowManager()->isAllowed(MWGui::GW_Inventory))
|
||||||
|
return;
|
||||||
|
|
||||||
|
MWWorld::Ptr target = getTarget();
|
||||||
|
MWWorld::ContainerStore& store = target.getClass().getContainerStore (target);
|
||||||
|
MWWorld::ContainerStore& actorStore = actor.getClass().getContainerStore(actor);
|
||||||
|
std::map<std::string, int> takenMap;
|
||||||
|
for (MWWorld::ContainerStoreIterator it = store.begin(); it != store.end(); ++it)
|
||||||
|
{
|
||||||
|
if (!it->getClass().showsInInventory(*it))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int itemCount = it->getRefData().getCount();
|
||||||
|
// Note: it is important to check for crime before move an item from container. Otherwise owner check will not work
|
||||||
|
// for a last item in the container - empty harvested containers are considered as "allowed to use".
|
||||||
|
MWBase::Environment::get().getMechanicsManager()->itemTaken(actor, *it, target, itemCount);
|
||||||
|
actorStore.add(*it, itemCount, actor);
|
||||||
|
store.remove(*it, itemCount, getTarget());
|
||||||
|
takenMap[it->getClass().getName(*it)]+=itemCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spawn a messagebox (only for items added to player's inventory)
|
||||||
|
if (actor == MWBase::Environment::get().getWorld()->getPlayerPtr())
|
||||||
|
{
|
||||||
|
std::ostringstream stream;
|
||||||
|
int lineCount = 0;
|
||||||
|
const static int maxLines = 10;
|
||||||
|
for (auto & pair : takenMap)
|
||||||
|
{
|
||||||
|
std::string itemName = pair.first;
|
||||||
|
int itemCount = pair.second;
|
||||||
|
lineCount++;
|
||||||
|
if (lineCount == maxLines)
|
||||||
|
stream << "\n...";
|
||||||
|
else if (lineCount > maxLines)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// The two GMST entries below expand to strings informing the player of what, and how many of it has been added to their inventory
|
||||||
|
std::string msgBox;
|
||||||
|
if (itemCount == 1)
|
||||||
|
{
|
||||||
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("\n#{sNotifyMessage60}");
|
||||||
|
Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msgBox = MyGUI::LanguageManager::getInstance().replaceTags("\n#{sNotifyMessage61}");
|
||||||
|
Misc::StringUtils::replace(msgBox, "%d", std::to_string(itemCount).c_str(), 2);
|
||||||
|
Misc::StringUtils::replace(msgBox, "%s", itemName.c_str(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream << msgBox;
|
||||||
|
}
|
||||||
|
std::string tooltip = stream.str();
|
||||||
|
// remove the first newline (easier this way)
|
||||||
|
if (tooltip.size() > 0 && tooltip[0] == '\n')
|
||||||
|
tooltip.erase(0, 1);
|
||||||
|
|
||||||
|
if (tooltip.size() > 0)
|
||||||
|
MWBase::Environment::get().getWindowManager()->messageBox(tooltip);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update animation object
|
||||||
|
MWBase::Environment::get().getWorld()->disable(target);
|
||||||
|
MWBase::Environment::get().getWorld()->enable(target);
|
||||||
|
}
|
||||||
|
}
|
19
apps/openmw/mwworld/actionharvest.hpp
Normal file
19
apps/openmw/mwworld/actionharvest.hpp
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef GAME_MWWORLD_ACTIONHARVEST_H
|
||||||
|
#define GAME_MWWORLD_ACTIONHARVEST_H
|
||||||
|
|
||||||
|
#include "action.hpp"
|
||||||
|
#include "ptr.hpp"
|
||||||
|
|
||||||
|
namespace MWWorld
|
||||||
|
{
|
||||||
|
class ActionHarvest : public Action
|
||||||
|
{
|
||||||
|
virtual void executeImp (const MWWorld::Ptr& actor);
|
||||||
|
|
||||||
|
public:
|
||||||
|
ActionHarvest (const Ptr& container);
|
||||||
|
///< \param container The Container the Player has activated.
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // ACTIONOPEN_H
|
|
@ -422,6 +422,17 @@ int MWWorld::ContainerStore::remove(const std::string& itemId, int count, const
|
||||||
return count - toRemove;
|
return count - toRemove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MWWorld::ContainerStore::hasVisibleItems() const
|
||||||
|
{
|
||||||
|
for (auto iter(begin()); iter != end(); ++iter)
|
||||||
|
{
|
||||||
|
if (iter->getClass().showsInInventory(*iter))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor)
|
int MWWorld::ContainerStore::remove(const Ptr& item, int count, const Ptr& actor)
|
||||||
{
|
{
|
||||||
assert(this == item.getContainerStore());
|
assert(this == item.getContainerStore());
|
||||||
|
|
|
@ -128,6 +128,8 @@ namespace MWWorld
|
||||||
ContainerStoreIterator begin (int mask = Type_All);
|
ContainerStoreIterator begin (int mask = Type_All);
|
||||||
ContainerStoreIterator end();
|
ContainerStoreIterator end();
|
||||||
|
|
||||||
|
bool hasVisibleItems() const;
|
||||||
|
|
||||||
virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner=false);
|
virtual ContainerStoreIterator add (const Ptr& itemPtr, int count, const Ptr& actorPtr, bool setOwner=false);
|
||||||
///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed)
|
///< Add the item pointed to by \a ptr to this container. (Stacks automatically if needed)
|
||||||
///
|
///
|
||||||
|
|
|
@ -42,6 +42,13 @@ MWClass::ContainerCustomData &CustomData::asContainerCustomData()
|
||||||
throw std::logic_error(error.str());
|
throw std::logic_error(error.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MWClass::ContainerCustomData &CustomData::asContainerCustomData() const
|
||||||
|
{
|
||||||
|
std::stringstream error;
|
||||||
|
error << "bad cast " << typeid(this).name() << " to ContainerCustomData";
|
||||||
|
throw std::logic_error(error.str());
|
||||||
|
}
|
||||||
|
|
||||||
MWClass::DoorCustomData &CustomData::asDoorCustomData()
|
MWClass::DoorCustomData &CustomData::asDoorCustomData()
|
||||||
{
|
{
|
||||||
std::stringstream error;
|
std::stringstream error;
|
||||||
|
|
|
@ -30,6 +30,7 @@ namespace MWWorld
|
||||||
virtual const MWClass::NpcCustomData& asNpcCustomData() const;
|
virtual const MWClass::NpcCustomData& asNpcCustomData() const;
|
||||||
|
|
||||||
virtual MWClass::ContainerCustomData& asContainerCustomData();
|
virtual MWClass::ContainerCustomData& asContainerCustomData();
|
||||||
|
virtual const MWClass::ContainerCustomData& asContainerCustomData() const;
|
||||||
|
|
||||||
virtual MWClass::DoorCustomData& asDoorCustomData();
|
virtual MWClass::DoorCustomData& asDoorCustomData();
|
||||||
virtual const MWClass::DoorCustomData& asDoorCustomData() const;
|
virtual const MWClass::DoorCustomData& asDoorCustomData() const;
|
||||||
|
|
|
@ -42,6 +42,11 @@ namespace
|
||||||
|
|
||||||
bool operator()(const MWWorld::Ptr& containerPtr)
|
bool operator()(const MWWorld::Ptr& containerPtr)
|
||||||
{
|
{
|
||||||
|
// Ignore containers without generated content
|
||||||
|
if (containerPtr.getTypeName() == typeid(ESM::Container).name() &&
|
||||||
|
containerPtr.getRefData().getCustomData() == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr);
|
MWWorld::ContainerStore& container = containerPtr.getClass().getContainerStore(containerPtr);
|
||||||
for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it)
|
for(MWWorld::ContainerStoreIterator it = container.begin(); it != container.end(); ++it)
|
||||||
{
|
{
|
||||||
|
|
|
@ -141,9 +141,9 @@ namespace MWWorld
|
||||||
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
|
MWWorld::Ptr getFacedObject(float maxDistance, bool ignorePlayer=true);
|
||||||
|
|
||||||
public: // FIXME
|
public: // FIXME
|
||||||
|
void addContainerScripts(const Ptr& reference, CellStore* cell) override;
|
||||||
void removeContainerScripts(const Ptr& reference) override;
|
void removeContainerScripts(const Ptr& reference) override;
|
||||||
private:
|
private:
|
||||||
void addContainerScripts(const Ptr& reference, CellStore* cell);
|
|
||||||
void PCDropped (const Ptr& item);
|
void PCDropped (const Ptr& item);
|
||||||
|
|
||||||
void processDoors(float duration);
|
void processDoors(float duration);
|
||||||
|
|
|
@ -27,6 +27,9 @@ const int CellSizeInUnits = 8192;
|
||||||
// A label to mark night/day visual switches
|
// A label to mark night/day visual switches
|
||||||
const std::string NightDayLabel = "NightDaySwitch";
|
const std::string NightDayLabel = "NightDaySwitch";
|
||||||
|
|
||||||
|
// A label to mark visual switches for herbalism feature
|
||||||
|
const std::string HerbalismLabel = "HerbalismSwitch";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -635,6 +635,8 @@ namespace NifOsg
|
||||||
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
const Nif::NiSwitchNode* niSwitchNode = static_cast<const Nif::NiSwitchNode*>(nifNode);
|
||||||
if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel))
|
if (niSwitchNode->name == Constants::NightDayLabel && !SceneUtil::hasUserDescription(rootNode, Constants::NightDayLabel))
|
||||||
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel);
|
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::NightDayLabel);
|
||||||
|
else if (niSwitchNode->name == Constants::HerbalismLabel && !SceneUtil::hasUserDescription(rootNode, Constants::HerbalismLabel))
|
||||||
|
rootNode->getOrCreateUserDataContainer()->addDescription(Constants::HerbalismLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
return node;
|
return node;
|
||||||
|
|
Loading…
Reference in a new issue