If you are requesting technical assistance with Twine, please specify:
Twine Version: 2.3.16
Story Format: Sugarcube 2.36.1
Hi,
I’ve been working on my inventory system today. Inventories for each character are saved as a list like [[‘item1’,count],[‘item2’,count],…] under the ‘$inventory’ object, as ‘$inventory.Name’, and they’re all loaded in from an external JS file at game start, because I found it easier to keep that (and the plethora of other data I’m storing in JS) as separate files. It’s largely all my own work within the widgets system, so it’s not the greatest (and there probably are better ways to do this, but I’m most comfortable with it), but after getting my ‘read inventory in several ways’ widgets working, I added an ‘add item’ widget.
Except that I got it to work, in that it still set inventories how I wanted, but it was throwing an error almost every time. As far as I could tell, something in the ‘increase item count by 1’ portion was amiss, as any time I was creating a new item entry, nothing went wrong. It was also referencing an input that shouldn’t have even been there as the reason it threw an error. So, I removed the main line for setting the main inventory to the temporary inventory to see if that got rid of the error. And, lo and behold, it did.
Except the code still works. Despite never asking the code to actually set it as such, or even referencing it after the original temporary inventory setting. And I have no idea why this is. I know that some programming languages link variables together, so that changing one changes the other, but I can’t seem to reproduce that elsewhere so I don’t think it’s the case.
If this is fine and there’s no hitches, I am more than happy to use it, but I just want to make sure there’s nothing untoward happening here that will come back to bite me later. I’ve included below a sort of example of the code that shows that it works.
For readability, inventoryRead takes the character’s name as an argument, and just sets the temporary variable _inventoryRead to whatever the character’s inventory is. So for James below, it returns the nested list [[‘coins’,5],[‘busPass’,1]]. It sets the variable _inventoryRead.
getInventoryContents takes the character’s name as an argument, and returns a list of all the items in the character’s inventory. So for James down below, it returns the list [‘coins’,‘busPass’]. It calls inventoryRead, and sets the variable _getInventoryContents.
addItem takes the character’s name, the item you wish to add, and the amount as arguments. The amount just decides how many times the widget runs on the same inventory. It calls getInventoryContents, checks to see if the item you wish to add is in _getInventoryContents, and if so it checks through the list until it gets to where the item is, then increases the value of _inventoryRead by 1. It used to have something which then set $inventory.Name to _inventoryRead, but it would throw errors for some reason. If _getInventoryContents doesn’t contain the item you’re adding, it simply pushes a new list for the item to the end of $inventory.Name.
Many thanks.
<<set $inventory to {}>>
<<set $inventory.James to []>>
<<run $inventory.James.push(['coins',5])>>
<<run $inventory.James.push(['busPass',1])>>
$inventory.James
<<widget "inventoryRead">>\
<<print '<<set _inventoryRead to $inventory.'+_args[0]+'>>'>>\
<</widget>>\
<<widget "getInventoryContents">>\
<<inventoryRead _args[0]>>\
<<set _getInventoryContents to []>>\
<<for _i to 0; _i < _inventoryRead.length; _i++>>\
<<run _getInventoryContents.push(_inventoryRead[_i][0])>>\
<</for>>\
<</widget>>\
<<widget "addItem">>\
<<for _j to 0; _j < _args[2]; _j++>>\
<<getInventoryContents _args[0]>>\
<<if _getInventoryContents.contains(_args[1])>>\
<<for _i to 0; _i < _getInventoryContents.length; _i++>>\
<<if _getInventoryContents[_i] is _args[1]>>\
<<set _inventoryRead[_i][1] to _inventoryRead[_i][1]+1>>\
<<break>>\
<</if>>\
<</for>>\
<<else>>\
<<print '<<run $inventory.'+_args[0]+'.push(["'+_args[1]+'",1])>>'>>\
<</if>>\
<</for>>\
<<unset _i>>\
<<unset _j>>\
<<unset _getInventoryContents>>\
<<unset _inventoryRead>>\
<</widget>>\
<<addItem 'James' 'busPass' 1>>
$inventory.James
<<addItem 'James' 'coins' 5>>
$inventory.James
<<addItem 'James' 'phone' 1>>
$inventory.James