0 votes
by (870 points)

This is a bit of a complicated one, I'm not entirely sure how to phrase it. Please tell me if I'm not explaining properly.

In my RPG, I have a mechanic that allows players to make spells more powerful by charging them with additional MP. I accomplish this through a <<textbox>> macro like so:

<<textbox "$action.cost" $B.mincost "spell check" autofocus>>

Then, in "spell check", I run this code:

<<run console.log("$action.cost before adjust = "+$action.cost)>>
<<run $action.cost *= 1>>
<<if ($action.cost < $B.mincost) or ($subject[0].en < $action.cost) or isNaN($action.cost)>>
<<goto "spell phase">>
<<else>>

<<run console.log("$action.cost after adjust = "+$action.cost)>>
<<run $action.spellMod()>>

spellMod() is a class function I define in the story JS. For the spell I'm testing, it looks like this:

this.spellMod = () => {
					console.log("spellMod called\n");
					console.log(`cost = ${this.cost}\n`);
					console.log(`$action cost = ${V().action.cost}`);
					switch (this.cost){
						case 10:
							V().action = new Action("Indignant Variati");
							break;
						default:
							this.weight = this.weight + 0.25*(this.cost - V().B.mincost);
					}
					console.log("weight = "+this.weight+"\n");
				}

But when I look at the console, this is what I get:

$action.cost before adjust = 5
$action.cost after adjust = 5
spellMod called
cost = 3
$action cost = 5
weight = 1

...So by all appearances, the cost manipulation is working fine within Twine, but for some reason it's not being carried over to the JavaScript, even though I'm calling spellMod() on $action, which the console tells me has the correct cost.

Since this is a complex object, I wrote my own clone function for it:

Action.prototype.clone = function () {
	// Return a new instance containing our current data.
	return new Action(this);
};

This clones an action by recreating it from the database, as the only constructor variable passed is the ID tag. I would have thought this was the issue, as that would reset the cost attribute to default, but if that were true, shouldn't $action get its attributes reset upon loading of the "spell check" passage too?

I'll try making a more faithful clone function after this and seeing if that works, but this is very confusing. Is there something I'm not aware of regarding the relationship between Twine variables and JavaScript?

1 Answer

0 votes
by (68.6k points)
selected by
 
Best answer

How and where, exactly, are you attaching your .spellMod() method?

That aside for the moment.  The first thing I'd try would be to use a normal function, rather than an arrow function.  Arrow functions are not simply a shorter way to write a function.  There are important differences between the two, notably arrow functions lexically binding the current this.  You generally do not want to subject functions which rely on binding of any flavor to the history, as you'll loose the binding every time.

by (870 points)

The first thing I'd try would be to use a normal function, rather than an arrow function.

That solved it, thanks!

How and where, exactly, are you attaching your .spellMod() method?

It's defined under the spell's case in the Action class definition. When an Action is constructed, it's passed an ID tag that is passed to a switch, and the attributes are defined according to the ID.

window.Action = class Action {
	constructor(name){
		switch (name) {
			case "Blast":
				this.cost =		3;
				this.weight =	1;
				this.phase =	"spell phase";
				this.spellMod = () => {
					console.log("spellMod called\n");
					console.log(`cost = ${this.cost}\n`);
					console.log(`$action cost = ${V().action.cost}`);
					switch (V().action.cost){
						case 10:
							V().action = new Action("Indignant Variati");
							break;
						default:
							console.log("default case active");
							this.weight = this.weight + 0.25*(V().action.cost - V().B.mincost);
					}
					console.log("weight = "+this.weight+"\n");
				}

 

by (159k points)

warning: You are using ES6 features in your project and unfortunately support for ES6 is inconsistent accoss the many brands & versions of web-browsers in common use.

This means there is a possiblty that the JavaScript code in your project will not run successfully for all your potential users. You may want to either:

1. Run your JavaScript code through a ES6 to ES5 transpiler (like Babel) before adding it to your project.

2. Use ES5 featues instead of ES6.

...