So what if I want some text to be displayed only when the player first sees a passage and optionally other text displayed on subsequent visits? We could use if/else/endif with the visited function, but let us see if we can create a macro to do. The passage might look like this:
Hi there. <<first>>
First time here, eh?
<<notfirst>>
Back again already?
<<endfirst>> What are you doing?
The principle is not unlike if/else/endif, and so I created a macro based on that code. I have heavily commented it, so if you have at least a little familiarity with code you could adapt it to other uses (for example, to handle male and female characters).
Note that this is for Sugarcube. For Sugarcane (and I guess other formats), you need to comment out one line, and uncomment another, towards the end - it says exactly which in the code.
macros['first'] = {
handler: function (place, macroName, params, parser) {
//var condition = parser.fullArgs();
// This is the place in the text that the first clause starts
var srcOffset = parser.source.indexOf('>>', parser.matchStart) + 2;
// This is the source text, with everything up to the start
// of the first clause chopped off
var src = parser.source.slice(srcOffset);
var endPos = -1;
var firstClause = '';
var notClause = '';
// First we need to scan through the text to extract the first and second clauses.
for (var i = 0, currentClause = true; i < src.length; i++) {
// Have we reached the end of the second clause?
// If so, set endPos (the start of the rest of the text)
// and terminate the loop
// The number 12 is the the length of <<endfirst>>
if (src.substr(i, 12) == '<<endfirst>>') {
endPos = srcOffset + i + 12;
break;
}
// Have we reached the end of the first clause?
// If so, flip to doing the second clause
// and jump ahead to skip the <<notfirst>> characters.
// The number 12 is the the length of <<notfirst>>
if (src.substr(i, 12) == '<<notfirst>>') {
currentClause = false;
i += 12;
}
// We are currently in the middle of one of the clauses, so this character
// should be added to whichever clause we are on.
if (currentClause) {
firstClause += src.charAt(i);
} else {
notClause += src.charAt(i);
}
};
// this could go wrong, so get ready to catch errors!
try {
// Now we want to display the correct clause
// Note that text instead the clause is trimmed to remove
// line breaks and spaces at either end
// This is for Sugarcube, if you are using sugarcane, comment the next line, and uncomment the one after
if (visited(state.active.title) == 1) {
// if (visited(state.history[0].passage.title) == 1) {
new Wikifier(place, firstClause.trim());
} else {
new Wikifier(place, notClause.trim());
}
// Finally push the parser past the entire expression
if (endPos != -1) {
parser.nextMatch = endPos;
} else {
throwError(place, "can't find matching endfirst");
}
// Oh, and just in case there was a problem, catch those errors
} catch (e) {
throwError(place, 'bad condition: ' + e.message);
};
}
};
// Also need to register <<notfirst>> and <<endfirst>> so Twine does
// not throw an error when it hits them.
macros['notfirst'] = macros['endfirst'] = { handler: function() {} };
No comments:
Post a Comment