Feature #1323: Implement restocking items (does not handle levelled lists yet)

This commit is contained in:
scrawl 2014-05-17 14:30:31 +02:00
parent ae66d28c87
commit b4ed828e21
12 changed files with 87 additions and 40 deletions

View file

@ -70,6 +70,22 @@ namespace MWClass
} }
} }
void Container::restock(const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Container> *ref = ptr.get<ESM::Container>();
const ESM::InventoryList& list = ref->mBase->mInventory;
for (std::vector<ESM::ContItem>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
{
if (it->mCount < 0)
{
MWWorld::ContainerStore& store = getContainerStore(ptr);
int currentCount = store.count(it->mItem.toString());
if (currentCount < std::abs(it->mCount))
store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr);
}
}
}
void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const void Container::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const
{ {
const std::string model = getModel(ptr); const std::string model = getModel(ptr);

View file

@ -66,6 +66,8 @@ namespace MWClass
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;
virtual void restock (const MWWorld::Ptr &ptr) const;
virtual std::string getModel(const MWWorld::Ptr &ptr) const; virtual std::string getModel(const MWWorld::Ptr &ptr) const;
}; };
} }

View file

@ -123,9 +123,6 @@ namespace MWClass
else else
data->mContainerStore = new MWWorld::ContainerStore(); data->mContainerStore = new MWWorld::ContainerStore();
// Relates to NPC gold reset delay
data->mCreatureStats.setTradeTime(MWWorld::TimeStamp(0.0, 0));
data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold); data->mCreatureStats.setGoldPool(ref->mBase->mData.mGold);
// store // store
@ -842,6 +839,22 @@ namespace MWClass
} }
} }
void Creature::restock(const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::Creature> *ref = ptr.get<ESM::Creature>();
const ESM::InventoryList& list = ref->mBase->mInventory;
for (std::vector<ESM::ContItem>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
{
if (it->mCount < 0)
{
MWWorld::ContainerStore& store = getContainerStore(ptr);
int currentCount = store.count(it->mItem.toString());
if (currentCount < std::abs(it->mCount))
store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr);
}
}
}
const ESM::GameSetting* Creature::fMinWalkSpeedCreature; const ESM::GameSetting* Creature::fMinWalkSpeedCreature;
const ESM::GameSetting* Creature::fMaxWalkSpeedCreature; const ESM::GameSetting* Creature::fMaxWalkSpeedCreature;
const ESM::GameSetting *Creature::fEncumberedMoveEffect; const ESM::GameSetting *Creature::fEncumberedMoveEffect;

View file

@ -145,6 +145,8 @@ namespace MWClass
virtual int getBaseGold(const MWWorld::Ptr& ptr) const; virtual int getBaseGold(const MWWorld::Ptr& ptr) const;
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;
virtual void restock (const MWWorld::Ptr &ptr) const;
}; };
} }

View file

@ -1330,6 +1330,22 @@ namespace MWClass
} }
} }
void Npc::restock(const MWWorld::Ptr& ptr) const
{
MWWorld::LiveCellRef<ESM::NPC> *ref = ptr.get<ESM::NPC>();
const ESM::InventoryList& list = ref->mBase->mInventory;
for (std::vector<ESM::ContItem>::const_iterator it = list.mList.begin(); it != list.mList.end(); ++it)
{
if (it->mCount < 0)
{
MWWorld::ContainerStore& store = getContainerStore(ptr);
int currentCount = store.count(it->mItem.toString());
if (currentCount < std::abs(it->mCount))
store.add (it->mItem.toString(), std::abs(it->mCount) - currentCount, ptr);
}
}
}
const ESM::GameSetting *Npc::fMinWalkSpeed; const ESM::GameSetting *Npc::fMinWalkSpeed;
const ESM::GameSetting *Npc::fMaxWalkSpeed; const ESM::GameSetting *Npc::fMaxWalkSpeed;
const ESM::GameSetting *Npc::fEncumberedMoveEffect; const ESM::GameSetting *Npc::fEncumberedMoveEffect;

View file

@ -180,6 +180,8 @@ namespace MWClass
} }
virtual void respawn (const MWWorld::Ptr& ptr) const; virtual void respawn (const MWWorld::Ptr& ptr) const;
virtual void restock (const MWWorld::Ptr& ptr) const;
}; };
} }

View file

@ -84,7 +84,7 @@ namespace MWGui
mCurrentBalance = 0; mCurrentBalance = 0;
mCurrentMerchantOffer = 0; mCurrentMerchantOffer = 0;
checkTradeTime(); restock();
std::vector<MWWorld::Ptr> itemSources; std::vector<MWWorld::Ptr> itemSources;
MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources); MWBase::Environment::get().getWorld()->getContainersOwnedBy(actor, itemSources);
@ -364,8 +364,6 @@ namespace MWGui
mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance ); mPtr.getClass().getCreatureStats(mPtr).getGoldPool() - mCurrentBalance );
} }
updateTradeTime();
MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse( MWBase::Environment::get().getWindowManager()->getDialogueWindow()->addResponse(
MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString()); MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("sBarterDialog5")->getString());
@ -475,30 +473,26 @@ namespace MWGui
return merchantGold; return merchantGold;
} }
// Relates to NPC gold reset delay void TradeWindow::restock()
void TradeWindow::checkTradeTime()
{ {
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr); MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt()); float delay = MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getFloat();
// if time stamp longer than gold reset delay, reset gold. if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getLastRestockTime() + delay)
if (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() + delay)
{ {
sellerStats.setGoldPool(mPtr.getClass().getBaseGold(mPtr)); sellerStats.setGoldPool(mPtr.getClass().getBaseGold(mPtr));
}
}
void TradeWindow::updateTradeTime() mPtr.getClass().restock(mPtr);
{
MWWorld::ContainerStore store = mPtr.getClass().getContainerStore(mPtr);
MWMechanics::CreatureStats &sellerStats = mPtr.getClass().getCreatureStats(mPtr);
double delay = boost::lexical_cast<double>(MWBase::Environment::get().getWorld()->getStore().get<ESM::GameSetting>().find("fBarterGoldResetDelay")->getInt());
// If trade timestamp is within reset delay don't set // Also restock any containers owned by this merchant, which are also available to buy in the trade window
if ( ! (MWBase::Environment::get().getWorld()->getTimeStamp() >= sellerStats.getTradeTime() && std::vector<MWWorld::Ptr> itemSources;
MWBase::Environment::get().getWorld()->getTimeStamp() < sellerStats.getTradeTime() + delay) ) MWBase::Environment::get().getWorld()->getContainersOwnedBy(mPtr, itemSources);
{ for (std::vector<MWWorld::Ptr>::iterator it = itemSources.begin(); it != itemSources.end(); ++it)
sellerStats.setTradeTime(MWBase::Environment::get().getWorld()->getTimeStamp()); {
it->getClass().restock(*it);
}
sellerStats.setLastRestockTime(MWBase::Environment::get().getWorld()->getTimeStamp());
} }
} }
} }

View file

@ -101,9 +101,7 @@ namespace MWGui
int getMerchantGold(); int getMerchantGold();
// Relates to NPC gold reset delay void restock();
void checkTradeTime();
void updateTradeTime();
}; };
} }

View file

@ -22,7 +22,7 @@ namespace MWMechanics
mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false), mFallHeight(0), mRecalcDynamicStats(false), mKnockdown(false), mKnockdownOneFrame(false),
mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false), mKnockdownOverOneFrame(false), mHitRecovery(false), mBlock(false),
mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f), mMovementFlags(0), mDrawState (DrawState_Nothing), mAttackStrength(0.f),
mTradeTime(0,0), mGoldPool(0), mActorId(-1) mLastRestock(0,0), mGoldPool(0), mActorId(-1)
{ {
for (int i=0; i<4; ++i) for (int i=0; i<4; ++i)
mAiSettings[i] = 0; mAiSettings[i] = 0;
@ -477,7 +477,7 @@ namespace MWMechanics
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
mDynamic[i].writeState (state.mDynamic[i]); mDynamic[i].writeState (state.mDynamic[i]);
state.mTradeTime = mTradeTime.toEsm(); state.mTradeTime = mLastRestock.toEsm();
state.mGoldPool = mGoldPool; state.mGoldPool = mGoldPool;
state.mDead = mDead; state.mDead = mDead;
@ -515,7 +515,7 @@ namespace MWMechanics
for (int i=0; i<3; ++i) for (int i=0; i<3; ++i)
mDynamic[i].readState (state.mDynamic[i]); mDynamic[i].readState (state.mDynamic[i]);
mTradeTime = MWWorld::TimeStamp(state.mTradeTime); mLastRestock = MWWorld::TimeStamp(state.mTradeTime);
mGoldPool = state.mGoldPool; mGoldPool = state.mGoldPool;
mFallHeight = state.mFallHeight; mFallHeight = state.mFallHeight;
@ -546,15 +546,14 @@ namespace MWMechanics
mActiveSpells.readState(state.mActiveSpells); mActiveSpells.readState(state.mActiveSpells);
} }
// Relates to NPC gold reset delay void CreatureStats::setLastRestockTime(MWWorld::TimeStamp tradeTime)
void CreatureStats::setTradeTime(MWWorld::TimeStamp tradeTime)
{ {
mTradeTime = tradeTime; mLastRestock = tradeTime;
} }
MWWorld::TimeStamp CreatureStats::getTradeTime() const MWWorld::TimeStamp CreatureStats::getLastRestockTime() const
{ {
return mTradeTime; return mLastRestock;
} }
void CreatureStats::setGoldPool(int pool) void CreatureStats::setGoldPool(int pool)

View file

@ -56,9 +56,12 @@ namespace MWMechanics
// Do we need to recalculate stats derived from attributes or other factors? // Do we need to recalculate stats derived from attributes or other factors?
bool mRecalcDynamicStats; bool mRecalcDynamicStats;
MWWorld::TimeStamp mTradeTime; // Relates to NPC gold reset delay // For merchants: the last time items were restocked and gold pool refilled.
MWWorld::TimeStamp mLastRestock;
// The pool of merchant gold (not in inventory)
int mGoldPool;
int mGoldPool; // the pool of merchant gold not in inventory
int mActorId; int mActorId;
protected: protected:
@ -241,9 +244,8 @@ namespace MWMechanics
static void writeActorIdCounter (ESM::ESMWriter& esm); static void writeActorIdCounter (ESM::ESMWriter& esm);
static void readActorIdCounter (ESM::ESMReader& esm); static void readActorIdCounter (ESM::ESMReader& esm);
// Relates to NPC gold reset delay void setLastRestockTime(MWWorld::TimeStamp tradeTime);
void setTradeTime(MWWorld::TimeStamp tradeTime); MWWorld::TimeStamp getLastRestockTime() const;
MWWorld::TimeStamp getTradeTime() const;
void setGoldPool(int pool); void setGoldPool(int pool);
int getGoldPool() const; int getGoldPool() const;

View file

@ -343,6 +343,8 @@ namespace MWWorld
virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const; virtual void setDoorState (const MWWorld::Ptr &ptr, int state) const;
virtual void respawn (const MWWorld::Ptr& ptr) const {} virtual void respawn (const MWWorld::Ptr& ptr) const {}
virtual void restock (const MWWorld::Ptr& ptr) const {}
}; };
} }

View file

@ -376,7 +376,8 @@ void MWWorld::ContainerStore::fill (const ESM::InventoryList& items, const std::
void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction, void MWWorld::ContainerStore::addInitialItem (const std::string& id, const std::string& owner, const std::string& faction,
int count, bool topLevel) int count, bool topLevel)
{ {
count = std::abs(count); /// \todo implement item restocking (indicated by negative count) // A negative count indicates restocking items, but this is implemented elsewhere
count = std::abs(count);
ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count); ManualRef ref (MWBase::Environment::get().getWorld()->getStore(), id, count);