这里收集一些关于 TyranoScript 零散的信息或是使用技巧,以备太久不用忘掉之需。
内核对象
tyrano.js 的这个函数,我一眼看上去,惊呼迷惑:
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 () {};
但是整理了一下(真想吐槽原写法的函数声明真是古早味……),就这:
function object(o) { var f = function () {}; f.prototype = o; let obj = new f(); // 注意 i 为 1,后面的参数才会附加到对象中 for (let i = 1; i < arguments.length; ++i) for (let prop in arguments[i]) obj[prop] = arguments[i][prop]; return obj;}
乍看有点像“热门面试题:自己写一个 new”,细看又不对,这里面就有 new 啊草(日语
这个奇葩函数做的是:
- 传入一个对象
o
,把o
接到构造函数的原型链 - 构造空对象,啥也没有,就是让他继承
o
里的函数(其实就等同于 Object.create) - 然后把 o 后多余的参数附到这个新对象上
总之吧,可以理解成内核实例 TYRANO
就是 object(tyrano.core)
得来的,在调用内核接口时记得用 TYRANO
而不是 tyrano
。
TYRANO.init
后会通过 loadModule 把 /tyrano/plugins/
里的各个模块的东西都塞到 TYRANO.kag 的原型链里,于是——
你就可以用 TYRANO.kag
调用 tyrano.plugin.kag
里的所有东西,例如:
TYRANO.kag.config.defaultSeVolume
获取当前音效音量TYRANO.kag.tag.seopt
修改音效音量
CG
[tb_cg id="cg_main0_1"]
解锁 id 为 cg_main0_1 的 cg,搜一下就知道这其实是个 builder 的宏。
[macro name="tb_cg"] [iscript] sf.cg_id[mp.id] = "on"; [endscript][endmacro]
按这道理,用 TYRANO.kag.variable.sf.cg_id[mp.id]
就能获取 CG 是否已解锁
Log
Log 缓存在 variable.tf.system.backlog
修改 backlog 的是 pushBackLog 函数,有两个地方用到:
- pushlog 标签,用标签插 log
- showMessage 函数,在展示信息的同时插 log,想修改插的 log 的格式就在这改
需要注意的是,存档展示的当前信息也是这里来的,注意调整格式的时候不要影响到。
文档
TyranoScript 的 Tag 文档地址:
英文文档地址 -> http://tyranobuilder.com/tyranoscript-tags-reference/
日文文档地址 -> https://tyrano.jp/tag/
中文文档地址 -> 怎么可能有嘛 (・ω<) てへぺろ
变量
TyranoScript 中变量有三种:
- sf 系统(全局的)
- f 游戏变量(跟存档)
- tf 暂存(关掉游戏就没了)
可以用 eval 标签或 iscript 标签修改,可以这么做的原因是 evalScript
里藏着一个 saveSystemVariable
,确实不太直观。
;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 = 1000tf.flag1 = f.flag2[endscript]
设置
TYRANO.kag.tag.bgmopt.start.call(TYRANO, { volume: v, effect: "true", buf: "",});
current_msg_alpha 透明度
screen_full
fullState
config.alreadyReadTextColor
config.autoRecordLabel
stat.already_read
在没有读入脚本的时候倒是没问题,但是如果在脚本运行中插入一个 call,默认是会调用 nextOrder
跑下一句脚本的,换句话说就是在游戏菜单的设置中做 bgmopt 等调整,对话框中的内容就会跑到下一句。
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;
上面的写法可以回避 nextOrder
。
顺便补充一下,默认配置由 loadConfig
导入 data\system\Config.tjs
文件的内容。
在 js 跑 ks 指令
TYRANO.kag.ftag.startTag('tag')
stat
上面提到的 kag.stat 是 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",];
这意味着在你新增自定义标签时,必须要考虑保存的问题。否则会出现这样的问题:你做了一个特效标签,保存的时候特效在运行,但是读档时却没有了。
这个问题的解决方案就是在标签运行同时在 stat 记录运行状态,我的情况就是设置 currentEffect 属性并记录参数,在设置 stat 后,需要在读档时(loadGameData 函数,kag.menu.js)还原当时的状态,没有状态时还要主动清除当前状态。
加载
setLayerHtml,相对的是保存用的 getLayeyHtml
在 bg 标签记录 stat.currentBG,然后在 setLayerHtml 特殊处理 bg
在加载时同样需要谨慎处理 nextOrder
,因为在 load 的时候调用了自己新增的 setEffect,里面有一句 nextOrder
,导致读档产生诡异的效果(例如突然冒出个例会),并且因为这是异步的操作,很难 debug,这个问题就查了老半天 😂。
存档的截图
关键字 doSave