If you are requesting technical assistance with Twine, please specify:
Twine Version: Tweego 2.1.1
Story Format: SugarCube 2.34.1
Hello everyone. Thank you for taking the time to read this, and help out if you can!
I’ve decided to try my hand at writing in Twine and come from a background of some experience with JavaScript and lots of PHP/HTML/CSS. I understand the basic flow of the stories and passages and all seems to be working. However, I’ve run into a “gotcha!” with the back button and I’d like to sort it out before I go any further.
The basic problem is that objects within the Player object seem to be keeping the state they had at the end of the passage instead of at the beginning. So if a passage adds one to a stat and increases it from 9 to 10, then if the user goes back to the passage (using the SugarCube back button) the stat is seems to start at 10 then is boosted to 11.
If I understand the state system correctly, the state is saved at the beginning of each passage (before the “:passagestart” event). So, when you go “back” everything should be reset to how it was at the beginning of the passage and then the passage happens. That all makes sense - but let me know if I’ve got any of that wrong!
OK. To the problem in hand.
I have a Stat class which keeps track of values, progress to the next level, level caps, buffs and all manner of stat-ly things. It looks a bit like this:
MyGame.Stat = function (initObject) {
this.progress = 0; // 100 progress to get to the next level
// and more properties here, they're all strings, ints or bools
$.extend(this, initObject);
}
MyGame.Stat.prototype = {
toJSON: function() {
var ownData = {
progress: this.progress,
// and so on with other properties
};
return JSON.reviveWrapper('new MyGame.Stat($ReviveData$)', ownData);
},
clone: function() {
return new MyGame.Stat(this);
},
// then lots more functions
}
I then have a Player class which does Player-ly things and also contains some stats. It looks a bit like this:
MyGame.Player = function (initObject) {
this.testSkill = new MyGame.Stat({});
// and more properties here, they're all strings, ints, bools or Maps
$.extend(true, this, initObject);
}
MyGame.Player.prototype = {
toJSON: function() {
var ownData = {
'testSkill': this.testSkill, // I have also tried "this.testSkill.toJSON()" here
// and so on with other properties
};
return JSON.reviveWrapper('new MyGame.Player($ReviveData$)', ownData);
},
clone: function() {
return new MyGame.Player(this);
},
// then lots more functions
}
For testing purposes I also created a standalone stat in _config.twee to try and isolate the problem and see if it was a problem with the Stat itself or with it being part of the Player. In _config.twee:
<<set $player to new MyGame.Player({})>>
<<set $rawSkill to new MyGame.Stat({})>>
This is all sweetness and light. It all works fine and I can progress the stat when I want to. The Player object seems happy, state seems to work fine when the games are saved and loaded. Until the dreaded BACK button rears its ugly head.
Passage 1:
$player.testSkill.progress is 0
$rawSkill.progress is 0
Passage 2:
On entry the values are:
$player.testSkill.progress is 0
$rawSkill.progress is 0
The passage then adds 1 to the progress of both Stats. At the end the values are:
$player.testSkill.progress is 1
$rawSkill.progress is 1
Passage 3:
On entry the values are:
$player.testSkill.progress is 1
$rawSkill.progress is 1
Press the back button:
On entry the values are:
$player.testSkill.progress is 1 ← this should be 0
$rawSkill.progress is 0
The passage then adds 1 to the progress of both Stats. At the end the values are:
$player.testSkill.progress is 2 ← this should be 1
$rawSkill.progress is 1
So… any idea where I’m going wrong?
How do I ensure that the Player object properly keeps its state if the user goes “back” in the story? Should I be doing something different in Player.toJSON()?
I’ve spent north of 10 hours trying to debug this so far… it’s killing me. I hope somebody can help! At this point I’d even be happy with some pointers of where to look or what to try!