UndertaleModTool介绍&使用 #4 (分析一个对话object)
由前文我们已经学习了gm和UTMT最最基本的一些内容,接下来我们来结合一个ut内的实例来分析它是如何运作的,并进行相关内容的介绍


我们要分析的是这样一个object,这是遗迹内的一个仙人掌,可以与之进行对话

作为一个无比常见的对话object,它有几个典型特征:
1.Parent是obj_readablesolid,意味着它继承了obj_readablesolid的很多功能
2.从贴图碰撞箱可以看出,它能与玩家碰撞的地方就是白色区域大小

3.有三个事件:Create;Alarm;Step


介于我们现在毫无头绪,不如从它的Create出发吧。其中image_xscale = 1;image_yscale = 1 这两条的意思是,图形横坐标方向拉伸程度为1,图形纵坐标方向拉伸程度为1,如果你修改image_xscale = 5,它就会变得很胖
myinteract = 0
image_xscale = 1
image_yscale = 1

再来看它的Alarm事件
myinteract = 3
global.msc = 0
global.msg[0] = "* Ah^1, the cactus.&* Truly the most tsundere& of plants./%%"
if global.flag[7]
global.msg[0] = "* It's not like this cactus& was waiting for you to come& back or anything.../%%"
global.typer = 5
global.facechoice = 0
global.faceemotion = 0
mydialoguer = instance_create(0, 0, obj_dialoguer)
这里有非常多信息,我们一点点来看,这个myinteract是限制obj_mainchara所用,等于3时意味着玩家不会移动,也就是对话时让玩家不动。global.msc是对话索引数. 不同的数对应不同的文本,内容定义自gml_Script_SCR_TEXT,可以看出等于0时就是直接按照alarm里写的对话进行显示,而不是从SCR_TEXT这个文本中心里读取对话。
global.typer - 决定角色说话音效。5时为普通对话
global.facechoice - 决定文本框显示的角色头像,具体如下
1 - Toriel
2 - Flowey
3 - Sans
4 - Papyrus
5 - Undyne
6 - Alphys
7 - Asgore
8 - Mettaton
9 - Asriel
global.faceemotion - 决定角色是什么表情

其中有这么一行,意思是创建一个obj_dialoguer,并且把它的id赋给mydialoguer这个变量
mydialoguer = instance_create(0, 0, obj_dialoguer)
来看一下obj_dialoguer的draw事件,虽说看起来很复杂,但摘取其中这段,能看出它是用于绘制对话框的。之所以把它的id赋给mydialoguer,是为了便于把它进行消除,以结束对话
if instance_exists(obj_face)
{
if (obj_face.y > (yy + 80))
obj_face.y -= 155
}
draw_set_color(c_white)
draw_rectangle((view_xview[view_current] + 16), (view_yview[view_current] + 5), (view_xview[view_current] + 304), (view_yview[view_current] + 80), 0)
draw_set_color(c_black)
draw_rectangle((view_xview[view_current] + 19), (view_yview[view_current] + 8), (view_xview[view_current] + 301), (view_yview[view_current] + 77), 0)
我们注意到它的create,创建了一个OBJ_WRITER,这个obj是用于绘制文本本身的
count = 0
side = 0
global.facechange = 1
xx = view_xview[view_current]
yy = view_yview[view_current]
if instance_exists(obj_mainchara)
{
if (obj_mainchara.y > (yy + 130))
{
side = 0
if (global.facechoice != 0)
{
writer = instance_create((xx + 68), (yy - 5), OBJ_WRITER)
script_execute(scr_facechoice)
}
else
writer = instance_create((xx + 10), (yy - 5), OBJ_WRITER)
}
else
{
side = 1
if (global.facechoice != 0)
{
writer = instance_create((xx + 68), (yy + 150), OBJ_WRITER)
script_execute(scr_facechoice)
}
else
writer = instance_create((xx + 10), (yy + 150), OBJ_WRITER)
}
}

分析完Alarm,我们再来看Step吧
scr_depth(0, 0, 0, 0, 0)

这是一个让object能和其他object重叠适当的script,就是该谁在前面谁在后面,看着更立体。这里的scr_depth是一个script,script的使用可以大大减少重复代码的出现,让代码更加灵活。一个script可以有输入值和输出值,像scr_depth这个其实没有输入值也没有输出值。
下面是一个二者都有的例子,一个计算绝对值的script,就叫scr_abs吧,代码内容是
if argument0<=0 return -argument0
else return argument0
argument0是指第一个输入值,例如scr_abs(-1)结果就是1。return的意思是结束代码段,并且返回一个值,这个值也可以是一个字符串。例如在某obj的create里写上,会弹窗显示3
var i;
i=scr_abs(-3)
show_message(i)

分析完这个对话object,我们获得了其大部分信息,但其Parent仍然有值得注意的点,这里一并分析
在gml_Object_obj_readablesolid_Step_0中,我们看到了没有对话框obj时,玩家又会被恢复能运动的状态,并且对话的触发机制(使alarm[0] = 1)
if (myinteract == 1)
{
global.interact = 1
alarm[0] = 1
myinteract = 2
}
if (myinteract == 3)
{
if (instance_exists(mydialoguer) == 0)
{
global.interact = 0
myinteract = 0
}
}