Tracking an object, from inventory to world and back again.

Post » Mon Nov 19, 2012 10:47 am

One of the biggest challenges facing Frostfall is persistently tracking certain values for n number of items across many different manifestations of that item.

Example: Tents that the player can set up have durability. For instance, the Small Hide Tent can be set up and torn down 10 times. The way I currently implement this is with 10 different Misc Items (for carrying them in the inventory) and 10 different Activators when "rolled up" (before they are set up), and 10 more Activators (for their in-world display once set up). This lets me associate the item directly to its durability level. So to support one type of tent with a durability of 10, I need 30 in-game objects and a lot of scripting glue to tie it all together. If I decide to create tents with even higher durability, this is going to get very unwieldy very fast.

I was wondering if anyone had come up with more inventive or better methods of tracking arbitrary data about an undefined number of items, and linking data directly back to a particular item? Scripts tied to the items themselves has always been a complete bust since the second it goes from the world into the player's inventory or vice versa, you lose your object reference ID 9 times out of 10.

Another example are Woodcutter's Axes, which in Frostfall also now have durability. I've had to create numerous duplicates of this axes as well and swap them out at particular times when the durability rating increases or decreases.

Appreciate any feedback, insight, or just general commiserating.
User avatar
Logan Greenwood
 
Posts: 3416
Joined: Mon Jul 30, 2007 5:41 pm

Post » Mon Nov 19, 2012 3:58 pm

What about storing an array in a remote "master" script and having each individual object store an index value that could then be used to retrieve a value from the array? If you need to store more than 128 values, then just couple multiple arrays together in a pseudo-property:
ScriptName Test extends QuestInt[] Array1Int[] Array2Event OnInit()	Array1 = new Int[128]	Array2 = new Int[128]EndEventInt Function GetValue(Int aiIndex)	Int iArrayNum = aiIndex / 128	aiIndex = aiIndex % 128	If (iArrayNum == 0)		Return Array1[aiIndex]	ElseIf (iArrayNum == 1)		Return Array2[aiIndex]	Else		Return 0	EndIfEndFunctionFunction SetValue(Int aiIndex, Int aiValue)	Int iArrayNum = aiIndex / 128	aiIndex = aiIndex % 128	If (iArrayNum == 0)		Array1[aiIndex] = aiValue	ElseIf (iArrayNum == 1)		Array2[aiIndex] = aiValue	EndIfEndFunction

Cipscis
User avatar
Marquis deVille
 
Posts: 3409
Joined: Thu Jul 26, 2007 8:24 am

Post » Mon Nov 19, 2012 9:41 am

I am not sure if I understand exactly what the problem is, but is it that you can't store information on an object's instance itself, because there are no properties for you to store it in? I.e. if you want 5 weapons to have independant durability, you need to store the data for each one in some external place?

If so, I understand this problem, and I just thought of a solution that sounds silly but might actually work.
User avatar
Quick draw II
 
Posts: 3301
Joined: Thu Nov 08, 2007 4:11 pm

Post » Mon Nov 19, 2012 3:14 pm

Is all of the swapping because you want to be able to display the item health/uses left on individual items?

And so I suppose an issue is that players can have more than one of these items...?
User avatar
Smokey
 
Posts: 3378
Joined: Mon May 07, 2007 11:35 pm

Post » Mon Nov 19, 2012 12:36 am

What about storing an array in a remote "master" script and having each individual object store an index value that could then be used to retrieve a value from the array? If you need to store more than 128 values, then just couple multiple arrays together in a pseudo-property

Very good code, but I'm still not sure of how to overcome the problem of differentiating between, say, Tent A, B, and C, and associating Data C with Tent C. There is currently nothing about Tent C that tells me what array index it belongs to. ObjectReference ID is the first obvious choice, but this can easily change / get lost between picking up and putting down the item, and many items in a player's inventory have no ObjectRef ID at all.

I am not sure if I understand exactly what the problem is, but is it that you can't store information on an object's instance itself, because there are no properties for you to store it in? I.e. if you want 5 weapons to have independant durability, you need to store the data for each one in some external place?

If so, I understand this problem, and I just thought of a solution that sounds silly but might actually work.

That is exactly the problem. Currently the "data" is being stored on the item itself, by virtue of it being a unique item. i.e. Axe_Durability01, Axe_Durability02, Axe_Durability03, etc.

Is all of the swapping because you want to be able to display the item health/uses left on individual items?

And so I suppose an issue is that players can have more than one of these items...?

Sorta. Different items does allow me to give them different names, but it wouldn't kill me to not have this ability. On the second comment: Yes, they can craft and possess n number of tents, woodcutter's axes, and so on. I can't control how many of these they have.
User avatar
Hannah Barnard
 
Posts: 3421
Joined: Fri Feb 09, 2007 9:42 am

Post » Mon Nov 19, 2012 2:36 am

Very good code, but I'm still not sure of how to overcome the problem of differentiating between, say, Tent A, B, and C, and associating Data C with Tent C. There is currently nothing about Tent C that tells me what array index it belongs to. ObjectReference ID is the first obvious choice, but this can easily change / get lost between picking up and putting down the item, and many items in a player's inventory have no ObjectRef ID at all.
Yeah, that occurred to me as well soon after I made that post. It seems the index stored in the object's script might be just as inaccessible as the data that you'd tried to stored directly on the object in that you can't get a handle on it because of that problem with inventory items. Presumably, if that problem can be solved, then that'd negate any need for the whole array business.

If I remember correctly, creating ObjectReferences as inventory objects (e.g. via http://www.creationkit.com/AddItem_-_Actor will cause issues with them not having proper referenceIDs, whereas creating them as references (e.g. via http://www.creationkit.com/PlaceAtMe_-_ObjectReference) then adding them to an inventory will, or at least can, create them "correctly".

Perhaps what you need to do is make use of both PlaceAtMe and http://www.creationkit.com/Activate_-_ObjectReference (to add the item to the player's inventory when activated) instead of AddItem when creating objects. I don't know if it's a requirement for them to be http://www.creationkit.com/Persistence_(Papyrus), but if they do then that should be simple enough to force by storing "Self" in a variable on that object's script.

Cipscis
User avatar
YO MAma
 
Posts: 3321
Joined: Thu Dec 21, 2006 8:24 am

Post » Mon Nov 19, 2012 12:20 pm

You could fill an alias with the item or use a persistent reference of it and it will retain its FormID. ghostblade, for instance, is persistent, so it'll remain [REFR:00094A2C] throughout the game even when added/removed from your inventory.

You can add a persistent REFR to the player's inventory with
PlayerREF.AddItem(PersistentREF)
...or...
PersistentREF.Activate(PlayerREF)

If it's a ReferenceAlias
PlayerREF.AddItem(AliasName.GetReference())
...or...
AliasName.GetReference().Activate(PlayerREF)

You should be able to manage with a single tent of each type, incrementing an iUses var or something similar.
User avatar
Len swann
 
Posts: 3466
Joined: Mon Jun 18, 2007 5:02 pm

Post » Mon Nov 19, 2012 5:10 am

Thanks Cipscis, Justin. I'll run some tests based on this information.
User avatar
Lewis Morel
 
Posts: 3431
Joined: Thu Aug 16, 2007 7:40 pm

Post » Mon Nov 19, 2012 12:51 am

I do this for my fetch quests. My scripts could easily be expanded to use a system you're after. Just a simple case of adding more functions to do different things.

You're welcome to have a nosey. I use a player alias to track the OnItemAdded/Removed, and to AddInventoryFilter. Then a script attached to the quest with all my functions. Instead of tracking the global as an item count, you could use it for your goal.
User avatar
joeK
 
Posts: 3370
Joined: Tue Jul 10, 2007 10:22 am

Post » Mon Nov 19, 2012 5:06 am

The alias idea I think is really promising, assuming it works. It wouldn't cost me much of anything to add, say, 20 aliases to a quest to track tents (it's possible but 99.9% unlikely anyone would ever want to possess that many tents of the same type). After that it's a simple matter of tying an alias to an array value. The only thing I would lose is the ability to display the durability rating of the item on the name of the item itself. If I can do this some other acceptable way (such as displaying a notification displaying the durability when the item is used) then I will have a go at it.
User avatar
Kathryn Medows
 
Posts: 3547
Joined: Sun Nov 19, 2006 12:10 pm


Return to V - Skyrim