@Commissar64 requested the source to my recent Twine game “The Whispering Thing.” We’ll do that sometime soon, but for now I can easily share the modifications to the CyclingLink macro necessary to make it work with the Sugarcube header without creating JS errors.
The code follows. It’s basically just a modification to how the anchor element is created. I can’t guarantee that this will do everything you want it to, as it’s a bit hacky.
version.extensions.cyclinglinkMacro = { major: 3, minor: 3, revision: 0 }; macros.cyclinglink = { handler: function (a, b, c) { var rl = "cyclingLink"; function toggleText(w) { w.classList.remove("cyclingLinkInit"); w.classList.toggle(rl + "Enabled"); w.classList.toggle(rl + "Disabled"); w.style.display = ((w.style.display == "none") ? "inline" : "none") } switch (c[c.length - 1]) { case "end": var end = true; c.pop(); break; case "out": var out = true; c.pop(); break } var v = ""; if (c.length && c[0][0] == "$") { v = c[0].slice(1); c.shift() } var h = state.active.variables; if (out && h[v] === "") { return } var l = document.createElement("a"); a.appendChild(l); l.className = "internalLink cyclingLink"; l.setAttribute("data-cycle", 0); for (var i = 0; i < c.length; i++) { var on = (i == Math.max(c.indexOf(h[v]), 0)); var d = insertElement(null, "span", null, "cyclingLinkInit cyclingLink" + ((on) ? "En" : "Dis") + "abled"); if (on) { h[v] = c[i]; l.setAttribute("data-cycle", i) } else { d.style.display = "none" } insertText(d, c[i]); if (on && end && i == c.length - 1) { l.parentNode.replaceChild(d, l) } else { l.appendChild(d) } } l.onclick = function () { var t = this.childNodes; var u = this.getAttribute("data-cycle") - 0; var m = t.length; toggleText(t[u]); u = (u + 1); if (!(out && u == m)) { u %= m; if (v) { h[v] = c[u] } } else { h[v] = "" } if ((end || out) && u == m - (end ? 1 : 0)) { if (end) { var n = this.removeChild(t[u]); n.className = rl + "End"; n.style.display = "inline"; this.parentNode.replaceChild(n, this) } else { this.parentNode.removeChild(this); return } return } toggleText(t[u]); this.setAttribute("data-cycle", u) } } };
Hello, the author of SugarCube here.
For the above to work correctly, you’ll need to change the line:
var h = state.history[0].variables;
To:
var h = state.active.variables;
SugarCube’s History class, which is what the state variable contains an instance of, is somewhat different from its counterpart in the vanilla headers.
Ah! Yes! I remember looking at that and then not bothering to fix it because I didn’t care about history for cycling links. I’ll fix it in this post!
Oh, one thing I should mention for those that do want $variable manipulation. When you call the macro, you’ll need to quote the $variable. This is because all macros in SugarCube get $variable substitution automatically, unlike the old headers where each macro had to perform $variable substitution itself. So, if you don’t quote the $variable, instead of getting the $variable name the macro will get the value instead.
For example, do this:
<<cyclinglink “$heat” “off” “low” “high” “fearsome”>>
Not this:
<<cyclinglink $heat “off” “low” “high” “fearsome”>>