Removing items from inv. after x game hours?

Discussions and questions about the CS and mods for Morrowind
Post Reply
Morven Ashwing
Novice
Novice
Posts: 81
Joined: Mon Jun 04, 2018 11:38 am
ES Games: Arena, Daggerfall, Battlespire, Redguard, Morrowind, Oblivion, Skyrim
Platform: PC, Xbox 360, PS3, Xbox One
UESPoints: 0
Contact:

Removing items from inv. after x game hours?

Post by Morven Ashwing »

Today, I have a question about script creation.

Although I have the PDF format of "Morrowind Scripting for Dummies, 8th Edition", I still am struggling with creating a (hypothetically) simple script.

I want to create some scripts that cause alcohol (primarily beer) to go 'off' if it is kept too long in your inventory. Furthermore, I'd like to make it so that bread goes stale, unpreserved meat and vegetation rots, and "drinking water" (stimulated by bottles, goblets, etc, etc.) to go bad.

Here is thusly the intended effect desired:

1) item (e.g. bread) comes into inventory.
2) After x amount of time in the inventory (e.g. 12 hours), a message is created - "The bread has gone stale".
3) After more x amount of time, the item is removed from the inventory and a message is created at the same time - "The bread is rock-hard and inedible. You think you may have also chipped a tooth".

To be repeated with other types of food.

While some of this I belive I can do (creating the message), the getting it out of the inventory has made me stumped.

A little help?
User avatar
Wolfborn
Apprentice
Apprentice
Posts: 158
Joined: Sat Oct 17, 2015 5:10 pm
ES Games: Morrowind, Oblivion, Skyrim (wip)
Platform: PC
Status: Subject to change without notice
UESPoints: 16

Re: Removing items from inv. after x game hours?

Post by Wolfborn »

Getting an item out of inventory is normally very simple. However, given what you're trying to do it becomes a bit more complicated and I'm not certain it will work properly.

The problem is that the items you're dealing with aren't unique. Every jug of mazte is "potion_local_brew_01", every loaf of bread is "ingred_bread_01", etc. If the player is carrying more than one of the same item, there's no way to distinguish between them--they're simply multiple copies of the same item. So your timer script is going to need to be attached to the item itself, i.e. each item needs to run its own local script to tell it when it "expires". So far so good[1], but how to get rid of the item when the timer runs out?

Normally an item is removed from inventory using the "RemoveItem" command. However (as you've probably already found out reading SFD), RemoveItem cannot be used in a local script to refer to the item the script is attached to; it results in a game crash. And it can't be done from a global script because that can cause problems with the remaining items if the player is carrying multiple copies[2]. So using RemoveItem is out.

The only hope I can see is using "Disable" and "SetDelete" to make the item vanish and permanently delete it from the game. The problem here is that this cannot be done while the item is still being carried by the player; it messes up the player's encumbrance if you do. The solution is to drop the item to the ground first using the "Drop" command. So, potentially, the item removal portion of your script could look like this:
Hidden:

Code: Select all

short state

if ( state == 10 )
     Disable
     SetDelete 1
     return
endif

if ( timer > expirytime )
     player->Drop "item_id" 1
     set state to 10
endif
This should work fine if the player is carrying only one copy of the item. However, if the player is carrying multiple copies of the item, I'm not sure that the Drop command will cause the correct item (i.e. the one the calling script is attached to) to drop; it may result in issues similar to using RemoveItem (as above/Note 2). And, unfortunately, it's way past my bedtime and I won't have a chance to try this out anytime soon.

Another thing to consider is that the player could drop the item somewhere along the way before the timer expires. In this case, you don't want to execute the "Drop" command before disabling and deleting the item. So you'll need a local flag to tell you if the item is currently being carried by the player or not; the flag can be set appropriately using OnPCAdd and OnPCDrop.

All I can say is read the section on Enabling and Disabling Objects in SFD and give this a try. If it works, great! If not, then unfortunately I really can't see any solution that would work short of either limiting the player to carrying only one copy of each item at a time (impractical) or making every instance of each item unique (even more impractical). However, if the Drop function works properly, then I think you might be in business.

Hope this helps!

By the way, if you're still using the 8th Edition of Scripting for Dummies, you should be aware that the improved 9th Edition is available here.

Note 1:
Hidden:
I'm not sure how many different ingredients you plan on attaching these scripts to, but be aware that players may potentially be carrying a lot of some types of ingredients (e.g. I've had characters who have harvested over a hundred samples of marshmerrow from certain areas). Having too many local scripts running every frame could potentially cause some serious performance issues. Also, I don't know if the items will still "stack" in inventory if each item has its own local script attached; instead of carrying a stack of 5 jugs of mazte the player might end up with 5 separate jugs of mazte in their inventory. Just something to be aware of as you go forward with this.
Note 2:
Hidden:
"if the player has two or more copies of an object with an attached script in their inventory, using RemoveItem on that Object ID will frequently corrupt data for one of the remaining copies (you may e.g. see corrupted health or count data). Equipping or using that corrupt object may cause the game to crash" - Morrowind Scripting for Dummies, 9th Edition, p37
*Edited to add further thoughts and refine the code snippet after getting some sleep.
CLIFF RACER BODY COUNT: 1059

And I ain't in it for the power
And I ain't in it for my health
I ain't in it for the glory of anything at all
And I sure ain't in it for the wealth
Post Reply