skip to content
usubeni fantasy logo Usubeni Fantasy

TyranoScript Tutorial Part 7: Notes

/ 4 min read

This Post is Available In: CN EN

This post collects assorted notes and practical tips about TyranoScript—mostly as a memory aid so I won’t forget them after a long break.

Core object

There’s a function in tyrano.js that baffled me at first glance:

function object(o) {
var f = object.f,
i,
len,
n,
prop;
f.prototype = o;
n = new f();
for (i = 1, len = arguments.length; i < len; ++i)
for (prop in arguments[i]) n[prop] = arguments[i][prop];
return n;
}
object.f = function () {};

Rewritten a bit (the original declaration is delightfully old‑school), it becomes:

function object(o) {
var f = function () {};
f.prototype = o;
let obj = new f();
// Note i starts at 1; only subsequent arguments are merged into the object
for (let i = 1; i < arguments.length; ++i)
for (let prop in arguments[i]) obj[prop] = arguments[i][prop];
return obj;
}

At first glance it looks like the classic interview prompt “implement new,” but it isn’t—there’s already a new in there, lol.

What this quirky function does is:

  • Take an object o and put it on a temporary constructor’s prototype.
  • Instantiate an empty object just so it inherits from o (basically the same as Object.create).
  • Then merge any additional argument objects into that new object.

In short, the engine instance TYRANO is produced by object(tyrano.core). When calling engine APIs, use TYRANO rather than tyrano.

After TYRANO.init, loadModule attaches everything under /tyrano/plugins/ to TYRANO.kag’s prototype chain, which means—

You can then call anything from tyrano.plugin.kag via TYRANO.kag, for example:

  • TYRANO.kag.config.defaultSeVolume — get the current SE volume
  • TYRANO.kag.tag.seopt — change the SE volume

CG

[tb_cg id="cg_main0_1"] unlocks the CG with id cg_main0_1. If you search the source you’ll find it’s just a Builder macro.

[macro name="tb_cg"]
[iscript]
sf.cg_id[mp.id] = "on";
[endscript]
[endmacro]

Following this, TYRANO.kag.variable.sf.cg_id[mp.id] tells you whether a CG has been unlocked.

Log

The backlog is cached at variable.tf.system.backlog.

The function that updates the backlog is pushBackLog, and it’s used in two places:

  • The pushlog tag, which inserts a log via a tag.
  • The showMessage function, which inserts a log while displaying text. If you want to change the log format, change it there.

Note that the text shown in save slots also comes from here—be careful not to break it when adjusting formats.

Documentation

TyranoScript tag reference:

English -> http://tyranobuilder.com/tyranoscript-tags-reference/

Japanese -> https://tyrano.jp/tag/

Chinese -> As if that existed (・ω<) てへぺろ

Variables

There are three kinds of variables in TyranoScript:

  • sf — system (global)
  • f — game variables (saved with your game data)
  • tf — temporary (lost when you close the game)

You can modify them via the eval tag or iscript. This works because evalScript quietly calls saveSystemVariable—not very obvious at first glance.

;This assigns a text string to a system variable
[eval exp="sf.variable1 = 'Sample Text'"]
;This assigns a number to a game variable
[eval exp="f.flag1 = 1000"]
;This assigns a temporary variable
[eval exp="tf.flag1 = f.flag2"]
[iscript]
sf.variable1 = 'Sample Text'
f.flag1 = 1000
tf.flag1 = f.flag2
[endscript]

Settings

TYRANO.kag.tag.bgmopt.start.call(TYRANO, {
volume: v,
effect: "true",
buf: "",
});

current_msg_alpha — message opacity

screen_full

fullState

config.alreadyReadTextColor

config.autoRecordLabel

stat.already_read

This is fine before any script is loaded, but if you insert a call while a script is running, it will call nextOrder by default and advance to the next line. In other words, changing bgmopt (etc.) from the in‑game settings will push the message box to the next line.

TYRANO.kag.stat.is_strong_stop = true;
TYRANO.kag.tag.bgmopt.start.call(TYRANO, {
volume: v,
effect: "true",
buf: "",
});
TYRANO.kag.stat.is_strong_stop = false;

The snippet above avoids nextOrder.

By the way, default configuration is loaded by loadConfig from data\\system\\Config.tjs.

Run a KS tag from JS

TYRANO.kag.ftag.startTag('tag')

stat

As mentioned above, kag.stat is the key state store for Tyrano.

[
"map_label",
"map_macro",
"vertical",
"f",
"mp",
"current_layer",
"current_page",
"is_stop",
"is_wait",
"is_trans",
"is_wait_anim",
"is_strong_stop",
"strong_stop_recover_index",
"is_nowait",
"current_message_str",
"current_save_str",
"current_keyframe",
"map_keyframe",
"is_script",
"buff_script",
"is_html",
"map_html",
"cssload",
"save_img",
"stack",
"set_text_span",
"current_scenario",
"is_skip",
"is_auto",
"current_bgm",
"current_bgm_vol",
"current_se",
"enable_keyconfig",
"current_bgmovie",
"current_camera",
"current_camera_layer",
"is_move_camera",
"is_wait_camera",
"current_line",
"is_hide_message",
"is_click_text",
"is_adding_text",
"flag_ref_page",
"ruby_str",
"ch_speed",
"skip_link",
"log_join",
"log_clear",
"f_chara_ptext",
"flag_glyph",
"current_cursor",
"font",
"locate",
"default_font",
"sysview",
"chara_pos_mode",
"chara_effect",
"chara_ptext",
"chara_time",
"chara_memory",
"chara_anim",
"pos_change_time",
"chara_talk_focus",
"chara_brightness_value",
"chara_blur_value",
"chara_talk_anim",
"chara_talk_anim_time",
"chara_talk_anim_value",
"apply_filter_str",
"video_stack",
"is_wait_bgmovie",
"charas",
"jcharas",
"play_bgm",
"play_se",
"map_se_volume",
"map_bgm_volume",
"map_vo",
"vostart",
"log_write",
"buff_label_name",
"already_read",
"visible_menu_button",
"title",
];

This implies that when you add custom tags, you must plan for persistence. Otherwise you may encounter this: a special‑effect tag is running when you save, but after loading the save, the effect is gone.

The solution is to record the running state in stat while the tag executes. In my case, I set a currentEffect property and recorded its parameters. After updating stat, restore the state when loading (the loadGameData function in kag.menu.js), and proactively clear it when no state exists.

Loading

setLayerHtml, paired with getLayeyHtml for saving.

Record stat.currentBG in the bg tag, then handle bg specially inside setLayerHtml.

When loading, be equally careful with nextOrder. In my case, my custom setEffect was invoked during load and contained a nextOrder, which caused bizarre behavior after loading (like suddenly jumping to a meeting scene). Because it’s asynchronous, it’s hard to debug—this took me ages to track down 😂.

Save thumbnails

Keyword doSave

Loading comments...