Hey there,
I come to you with another problem that I ran into.
I'm running SugarCube 2.13.0 and Twine 2.1.0
The issue is the following, I'm trying to implement a way in which the player can interact with the inventory of other objects in the game, by placing and taking items from their containers. I'm basically listing the items inside the player's and the inspected container's contents (items) and then offer actions that can take place on the given object. Such as moving items back and forth, inspecting item properties, etc.
I'm trying to do this using a <<widget>> which calls another <<widget>>. I've tested and been using recursive <<widget>> which had no problems whatsoever (probably because of the same arguments that get passed to them).
In my case I fail to pass the _item object to <<putItemInContainer>>. Since the latter throws an error that .hasOwnProperty of an undefined variable made the whole thing crash and burn. This is very interesting to me since, the other widgets have never been complaining. I imagine the for loop and the temporary _i (iterator value) adds a complication. I'm trying to remedy this by setting up a temporary variable: _item and reference the indexed item ($player.inventory[_i]). This also doesn't seem to help in this case.
I tried to substitute the <<putItemIntoContainer>> widget by taking out the part that was important to me with the hasOwnProperty check and then the calling of other widgets such as unequip and JS function call to transfer the item into the new container. Now, this substitution kinda fails too since I only get the last item that is then put into the container after the second try, which I can't take out, since the wrong item gets put into the container.
There must be a way to call transfertItem() using the correct arguents (_item) I just have no idea how.
Can anyone explain to me what is going on here?
Am I missing something when passing arguments to another widget?
@
<</if>>
<</linkreplace>>
<</nobr>><</widget>>
@color:red;[Error]putItemIntoContainer arg[0] or item is undefined@@
<</if>>
<</if>>
<</nobr>><</widget>>
Comments
You're reassigning _item every loop iteration, which wouldn't be an issue under normal circumstances. The <<putItemIntoContainer>> call, however, happens asynchronously—being inside a <<linkreplace>>. Thus, by the time the player activates any of the generated <<linkreplace>> links, the _item temporary variable is at the last value it was assigned within the loop—unless something else has reassigned it since.
Speaking of something else trampling _item's value, you also reassign it within <<putItemIntoContainer>>.
You may have a similar problem with _container if you ever make multiple calls to <<openContainer>> within the same passage. The final call will be the one to define the value assigned to _container. If you only make one call or make the calls asynchronously, then you should be okay, elsewise….
The easy fix for <<putItemIntoContainer>> is to make its item variable unique—e.g. _piic_item or something like that.
As for <<openContainer>>. If you were passing in primitive types, then you could use the Stupid Print Trick™ to address the <<linkreplace>> issue by causing the value to be resolved early, however, you're passing objects, so that's out. There is, unfortunately, no convenient solution at present—at least off the top of my head. Solving this will likely require me to implement some kind of capture mechanism.
Thank you for your valuable input, I always appreciate them!
For example, the following should work as you'd expect: NOTE: Macro name not finalized.
I assume calling a JS function inside the same widget (openContainer) which (JS function) has _item declared inside but used for other purposes would also be affected. Is this correct or am I overthinking it?
I document all of SugarCube's macros. I'm honestly surprised there was even a question.
My initial implementation was a bit too simple and it remains to be seen if I'll be able to make this work. The core systems really aren't designed to support something like this, so I'm waging an uphill battle.
I tried to capture _i and even tried _item (using <<set>>)
As far as your example code goes. Nothing immediately jumps out as incorrect with how you're attempting to use <<capture>> within that one widget, however, I cannot say that you're not modifying the value of _item within the <<transferItem>> widget as you didn't provide an example of its code—I bring that up, because you were trampling its value in earlier examples.
Beyond that, the second use of <<capture>>, where you localize _i, could be problematic if <<transferItem>> alters the source/destination arrays themselves—if you alter the arrays, you will likely invalidate the captured indices at some point. You should probably be capturing the array member there, rather than its index, as you do with the first use of <<capture>>.
About the the code you requested: I would like to add, that I don't really want to reveal more source code now or in the future. The reason for that is source code tracking, that I really want to avoid when it comes to my Twine projects.
From what I've understood, you are saying that I should look for clues inside my JS code whether the passed temporary variables: _item or _i are being changed there. As soon as I have access to my computer, I'll let you know, if I've found any traces of this.
As soon as I can get back to my comp. I'll post some code. Don't get me wrong, I'm not trying to hide my "crappy" code from anyone, I just don't want people to connect it to me in any way.
By looking at my code, I could not find any problems. I even tried your suggestion of using the "Stupid Speed Trick" tm you suggested, which worked nicely after your help, that is
I'll try and break down the problem into a much simpler one like I did with the jquery.append() jquery.wiki() trouble that I had. I'll come back to you with the results soon.
Also I think @TheMadExile deserves a reward from me