树结构菜单
功能扩展
26.7
11-19
高拓展性的树结构菜单,玩家操作简单方便

菜单操作方式

  • 长按近战键打开菜单,再次按下关闭
  • A后退,D前进或确认
  • WS上下切换选项,长按WS快速翻页

代码详解

变量描述
menu_tree树结构本体,储存每层选择的索引,无法查询更深层
menu_treename储存每层选择的内容
menu_text当前页面所有的选项内容
menu_content当前页面所有的选项备注,与menu_text对应
menu_treeindex储存每层选择的索引,可以查询更深层。如果页面查询它的子页面选择的索引需要使用该变量
menu_state[3]当前页面的深度
menu_state[4]当前页面标题,有默认值生成方式,也可自行定义
menu_state[5]当前页面每页最大行数,取值1~6;默认6
menu_state[12]定义当前页面选项的前进操作(D),为0则打开新页面,为1则返回上级,其他值为无动作,或者可以自行定义其他动作,对当前页面所有选项生效;默认0
menu_state[17]打开当前页面时,往回后退menu_state[17]个页面,可用于不需要页面的动作型选项

菜单的编写都在最后一条规则html子程序中,联合menu_trees和menu_state[3]来定位每个选项位置,用menu_text和menu_content定义页面内容,并使用相关参数和动作来控制页面和选项行为

其他

该菜单选项的内容绑定数组变量为menu_text和menu_content,对于这两个数组的修改会直接更新到菜单上,如果某些场景下需要更新当前页面,直接调用refresh_menu子程序或者直接修改这两个变量都可以

编程思想是当打开一个页面前,定义页面的属性并执行相应代码,再最后呈现该页面,所以如果你希望为某个选项添加动作,需要打开它的子页面下并在子页面下编写代码,按照需要是否退回之前的页面

全部代码如下,需要自行理解子程序html的编写方式

变量
{
	玩家:
		0: menu_content
		1: menu_state
		2: menu_text
		3: menu_dqtext
		4: menu_tree
		5: menu_treename
		6: menu_treeindex
}

子程序
{
	0: html
	1: refresh_menu
	2: default_page
	3: refresh_menupage
}

规则("老王不在橱柜 玩家初始化 不需要修改")
{
	事件
	{
		持续 - 每名玩家;
		队伍1;
		全部;
	}

	动作
	{
		事件玩家.menu_tree = 数组(0);
		事件玩家.menu_treename = 数组(自定义字符串("主菜单"));
		事件玩家.menu_state[20] = 自定义字符串("打开菜单");
		事件玩家.menu_state[21] = 自定义字符串("长按");
		事件玩家.menu_state[22] = 自定义字符串("————————————————————————————————————————————————————————————————————————————————————————————");
		创建HUD文本(事件玩家, 自定义字符串("{0}", 自定义字符串("{1}{0}{2}", 输入绑定字符串(按钮(近身攻击)), 事件玩家.menu_state[21], 事件玩家.menu_state[20])), 无, 无, 左边, 9, 颜色(橙色),
			颜色(白色), 颜色(白色), 可见和字符串, 默认可见度);
		事件玩家.menu_state[14] = 上一个文本ID;
		中止;
		事件玩家.menu_tree[0] = 0;
		事件玩家.menu_tree[1] = 2;
		事件玩家.menu_treename[1] = 自定义字符串("说明");
	}
}

规则("老王不在橱柜 打开背包 不需要修改")
{
	事件
	{
		持续 - 每名玩家;
		队伍1;
		全部;
	}

	条件
	{
		按钮被按下(事件玩家, 按钮(近身攻击)) == 真;
	}

	动作
	{
		If(事件玩家.menu_state[0] == 真);
			事件玩家.menu_state[20] = 自定义字符串("打开菜单");
			事件玩家.menu_state[21] = 自定义字符串("长按");
			停止限制阈值(事件玩家);
			事件玩家.menu_state[0] = 假;
			消除HUD文本(事件玩家.menu_state[1]);
			消除HUD文本(事件玩家.menu_state[2]);
			中止;
		End;
		等待(0.500, 当为“假”时中止);
		If(事件玩家.menu_state[0] == 假);
			事件玩家.menu_state[20] = 自定义字符串("关闭菜单\r\nWS上下 A返回 D确认");
			事件玩家.menu_state[21] = 自定义字符串("按下");
			开始限制阈值(事件玩家, 0, 0.010, 0, 0.010, 0, 0.010);
			事件玩家.menu_state[0] = 真;
			事件玩家.menu_state[13] = 1;
			调用子程序(refresh_menu);
			创建HUD文本(事件玩家, 事件玩家.menu_content[事件玩家.menu_state[6]] ? 事件玩家.menu_content[事件玩家.menu_state[6]] : 自定义字符串(""), 无, 无, 左边, 11, 颜色(橙色), 颜色(
				白色), 颜色(白色), 可见和字符串, 默认可见度);
			事件玩家.menu_state[2] = 上一个文本ID;
			创建HUD文本(事件玩家, 自定义字符串("◇{0}\r\n——————————{1}{2}", 事件玩家.menu_state[4], 自定义字符串("{0}{1}", 自定义字符串("{0}{1}{2}",
				事件玩家.menu_dqtext[0] ? 自定义字符串("\r\n{0}{1}", 事件玩家.menu_state[7] == 0 ? 自定义字符串("● ") : 自定义字符串("○ "), 事件玩家.menu_dqtext[0])
				: 自定义字符串(""), 事件玩家.menu_dqtext[1] ? 自定义字符串("\r\n{0}{1}", 事件玩家.menu_state[7] == 1 ? 自定义字符串("● ") : 自定义字符串("○ "),
				事件玩家.menu_dqtext[1]) : 自定义字符串(""), 事件玩家.menu_dqtext[2] ? 自定义字符串("\r\n{0}{1}", 事件玩家.menu_state[7] == 2 ? 自定义字符串("● ") : 自定义字符串(
				"○ "), 事件玩家.menu_dqtext[2]) : 自定义字符串("")), 自定义字符串("{0}{1}{2}", 事件玩家.menu_dqtext[3] ? 自定义字符串("\r\n{0}{1}",
				事件玩家.menu_state[7] == 3 ? 自定义字符串("● ") : 自定义字符串("○ "), 事件玩家.menu_dqtext[3]) : 自定义字符串(""), 事件玩家.menu_dqtext[4] ? 自定义字符串(
				"\r\n{0}{1}", 事件玩家.menu_state[7] == 4 ? 自定义字符串("● ") : 自定义字符串("○ "), 事件玩家.menu_dqtext[4]) : 自定义字符串(""),
				事件玩家.menu_dqtext[5] ? 自定义字符串("\r\n{0}{1}", 事件玩家.menu_state[7] == 5 ? 自定义字符串("● ") : 自定义字符串("○ "), 事件玩家.menu_dqtext[5])
				: 自定义字符串(""))), 事件玩家.menu_state[9] > 1 ? 自定义字符串("\r\n◇◇第{0}/{1}页◇◇", 事件玩家.menu_state[8] + 1, 事件玩家.menu_state[9]) : 自定义字符串("")),
				无, 无, 左边, 10, 颜色(橙色), 颜色(白色), 颜色(白色), 可见和字符串, 默认可见度);
			事件玩家.menu_state[1] = 上一个文本ID;
		End;
	}
}

规则("老王不在橱柜 打开菜单操作 不需要修改")
{
	事件
	{
		持续 - 每名玩家;
		队伍1;
		全部;
	}

	条件
	{
		事件玩家.menu_state[0] == 真;
		阈值(事件玩家) != 矢量(0, 0, 0);
	}

	动作
	{
		"左"
		If(X方向分量(阈值(事件玩家)) > 0);
			If(数量(事件玩家.menu_tree) > 1);
				修改玩家变量(事件玩家, menu_tree, 根据索引从数组中移除, 数量(事件玩家.menu_tree) - 1);
				事件玩家.menu_state[13] = 1;
				调用子程序(refresh_menu);
			End;
		"右"
		Else If(X方向分量(阈值(事件玩家)) < 0);
			事件玩家.menu_state[11] = 事件玩家.menu_state[6];
			事件玩家.menu_state[16] = 事件玩家.menu_text[事件玩家.menu_state[11]];
			事件玩家.menu_treename[事件玩家.menu_state[3] + 1] = 事件玩家.menu_state[16];
			事件玩家.menu_treeindex[事件玩家.menu_state[3] + 1] = 事件玩家.menu_state[11];
			"选择"
			If(事件玩家.menu_state[12] == 0);
				修改玩家变量(事件玩家, menu_tree, 添加至数组, 事件玩家.menu_state[11]);
				事件玩家.menu_state[13] = 0;
				调用子程序(refresh_menu);
			"返回"
			Else If(事件玩家.menu_state[12] == 1);
				修改玩家变量(事件玩家, menu_tree, 根据索引从数组中移除, 数量(事件玩家.menu_tree) - 1);
				事件玩家.menu_state[13] = 1;
				调用子程序(refresh_menu);
			"无动作"
			Else If(事件玩家.menu_state[12] == -1);
			End;
		"上"
		Else If(Z方向分量(阈值(事件玩家)) > 0);
			事件玩家.menu_state[6] -= 1;
			事件玩家.menu_state[7] -= 1;
			If(事件玩家.menu_state[6] < 0);
				事件玩家.menu_state[6] = 事件玩家.menu_state[10] - 1;
				事件玩家.menu_state[7] = 事件玩家.menu_state[6] % 事件玩家.menu_state[5];
				事件玩家.menu_state[8] = 事件玩家.menu_state[9] - 1;
				调用子程序(refresh_menupage);
			Else If(事件玩家.menu_state[7] < 0);
				事件玩家.menu_state[7] = 事件玩家.menu_state[5] - 1;
				事件玩家.menu_state[8] -= 1;
				调用子程序(refresh_menupage);
			End;
			根据条件中止(事件玩家.menu_state[9] <= 1);
			等待直到 (Z方向分量(阈值(事件玩家)) <= 0, 0.400);
			While(Z方向分量(阈值(事件玩家)) > 0);
				事件玩家.menu_state[8] -= 1;
				事件玩家.menu_state[6] -= 事件玩家.menu_state[5];
				If(事件玩家.menu_state[8] < 0);
					事件玩家.menu_state[8] = 事件玩家.menu_state[9] - 1;
					事件玩家.menu_state[6] = 事件玩家.menu_state[10] - 1;
					事件玩家.menu_state[7] = 事件玩家.menu_state[6] % 事件玩家.menu_state[5];
				End;
				调用子程序(refresh_menupage);
				等待直到 (Z方向分量(阈值(事件玩家)) <= 0, 0.400);
			End;
		"下"
		Else If(Z方向分量(阈值(事件玩家)) < 0);
			事件玩家.menu_state[6] += 1;
			事件玩家.menu_state[7] += 1;
			If(事件玩家.menu_state[6] >= 事件玩家.menu_state[10]);
				事件玩家.menu_state[6] = 0;
				事件玩家.menu_state[7] = 0;
				事件玩家.menu_state[8] = 0;
				调用子程序(refresh_menupage);
			Else If(事件玩家.menu_state[7] >= 事件玩家.menu_state[5]);
				事件玩家.menu_state[7] = 0;
				事件玩家.menu_state[8] += 1;
				调用子程序(refresh_menupage);
			End;
			根据条件中止(事件玩家.menu_state[9] <= 1);
			等待直到 (Z方向分量(阈值(事件玩家)) >= 0, 0.400);
			While(Z方向分量(阈值(事件玩家)) < 0);
				事件玩家.menu_state[8] += 1;
				事件玩家.menu_state[6] += 事件玩家.menu_state[5];
				If(事件玩家.menu_state[8] > 事件玩家.menu_state[9] - 1);
					事件玩家.menu_state[8] = 0;
					事件玩家.menu_state[6] = 0;
					事件玩家.menu_state[7] = 0;
				Else If(事件玩家.menu_state[6] > 事件玩家.menu_state[10] - 1);
					事件玩家.menu_state[6] = 事件玩家.menu_state[10] - 1;
					事件玩家.menu_state[7] = 事件玩家.menu_state[6] % 事件玩家.menu_state[5];
				End;
				调用子程序(refresh_menupage);
				等待直到 (Z方向分量(阈值(事件玩家)) >= 0, 0.400);
			End;
		End;
	}
}

规则("老王不在橱柜 refresh_menu 更新背包页面 不需要修改")
{
	事件
	{
		子程序;
		refresh_menu;
	}

	动作
	{
		While(真);
			事件玩家.menu_state[17] = 0;
			事件玩家.menu_state[19] = 0;
			"当前深度"
			事件玩家.menu_state[3] = 数量(事件玩家.menu_tree) - 1;
			调用子程序(default_page);
			调用子程序(html);
			"阻止打开新页面并刷新"
			While(事件玩家.menu_state[17] > 0);
				事件玩家.menu_state[17] -= 1;
				事件玩家.menu_state[19] = 1;
				修改玩家变量(事件玩家, menu_tree, 根据索引从数组中移除, 数量(事件玩家.menu_tree) - 1);
				事件玩家.menu_state[13] = 1;
			End;
			If(事件玩家.menu_state[19] == 0);
				中断;
			End;
		End;
		"为空则添加返回上级选项"
		If(事件玩家.menu_text == 空数组);
			事件玩家.menu_text = 数组(自定义字符串("没有内容->返回"));
			事件玩家.menu_state[12] = 1;
		End;
		事件玩家.menu_state[10] = 数量(事件玩家.menu_text);
		"下标位置不能超出数量"
		事件玩家.menu_state[6] = 较小(事件玩家.menu_state[6], 事件玩家.menu_state[10] - 1);
		"总页数(从1开始)"
		事件玩家.menu_state[9] = 取整(较大(0, 事件玩家.menu_state[10] - 0) / 事件玩家.menu_state[5], 上);
		"当前页选中的行的下标(0~最大行数-1)"
		事件玩家.menu_state[7] = 事件玩家.menu_state[6] % 事件玩家.menu_state[5];
		"当前页数(从0开始)"
		事件玩家.menu_state[8] = 取整((0 + 事件玩家.menu_state[6]) / 事件玩家.menu_state[5], 下);
		"更新当前页面"
		调用子程序(refresh_menupage);
	}
}

规则("老王不在橱柜 default_page 默认页面属性 定义了页面的默认生成方式 按需要修改")
{
	事件
	{
		子程序;
		default_page;
	}

	动作
	{
		"每页最大行数,不能超过6"
		事件玩家.menu_state[5] = 6;
		"页面标题,这里提供了两种标题方法,如需切换,启用该动作并禁用下面6条动作"
		禁用 事件玩家.menu_state[4] = 事件玩家.menu_treename[事件玩家.menu_state[3] + 0];
		"生成页面标题"
		事件玩家.menu_state[23] = 0;
		事件玩家.menu_state[4] = 自定义字符串("主菜单");
		While(事件玩家.menu_state[23] < 事件玩家.menu_state[3]);
			事件玩家.menu_state[4] = 自定义字符串("{0}\r\n{1}{2}", 事件玩家.menu_state[4], 截取字符串(事件玩家.menu_state[22], 0, 1 * (事件玩家.menu_state[23] + 1)),
				事件玩家.menu_treename[事件玩家.menu_state[23] + 1]);
			事件玩家.menu_state[23] += 1;
		End;
		"当前页面是否为新打开"
		If(事件玩家.menu_state[13] == 1);
			"为1则光标置于记录点位置"
			事件玩家.menu_state[6] = 事件玩家.menu_treeindex[事件玩家.menu_state[3] + 1];
			事件玩家.menu_state[13] = 0;
		Else;
			"为0则将光标置于0"
			事件玩家.menu_state[6] = 0;
		End;
		"文本数据数组"
		事件玩家.menu_text = 空数组;
		"右键的操作,0钻取 1返回上一级 2自定义 (对所有行生效)"
		事件玩家.menu_state[12] = 假;
		"文本备注数组"
		事件玩家.menu_content = 空数组;
	}
}

规则("老王不在橱柜 refresh_menupage 更新背包当前页面 不需要修改")
{
	事件
	{
		子程序;
		refresh_menupage;
	}

	动作
	{
		事件玩家.menu_dqtext = 数组分割(事件玩家.menu_text, 事件玩家.menu_state[8] * 事件玩家.menu_state[5], 事件玩家.menu_state[5]);
	}
}

规则("老王不在橱柜 html 菜单界面 需要自己编写")
{
	事件
	{
		子程序;
		html;
	}

	动作
	{
		If(事件玩家.menu_state[3] == 0);
			"选项文本"
			事件玩家.menu_text = 字符串分割(自定义字符串("选项0\\选项1\\选项2\\关于"), 自定义字符串("\\"));
			"备注文本"
			事件玩家.menu_content = 字符串分割(自定义字符串("多级菜单示例\\动作类型选项示例\\树分叉优先写法"), 自定义字符串("\\"));
		Else If(事件玩家.menu_state[3] >= 1);
			"选项0 多级菜单示例"
			If(事件玩家.menu_tree[1] == 0);
				"深度为1"
				If(事件玩家.menu_state[3] == 1);
					事件玩家.menu_text = 字符串分割(自定义字符串("选项0-0\\选项0-1\\选项0-2"), 自定义字符串("\\"));
				"深度为2"
				Else If(事件玩家.menu_state[3] == 2);
					"选项0-0-"
					If(事件玩家.menu_tree[2] == 0);
						"不钻取下一层"
						事件玩家.menu_state[12] = -1;
						事件玩家.menu_text = 字符串分割(自定义字符串("选项0-0-0\\选项0-0-1\\选项0-0-2"), 自定义字符串("\\"));
					"选项0-1-"
					Else If(事件玩家.menu_tree[2] == 1);
						"继续钻取下一层,若没有内容则自动添加一个返回上级的选项,此为默认值"
						事件玩家.menu_state[12] = 0;
						事件玩家.menu_text = 字符串分割(自定义字符串("选项0-1-0\\选项0-1-1\\选项0-1-2"), 自定义字符串("\\"));
					End;
				End;
			"选项1 动作类型选项示例"
			Else If(事件玩家.menu_tree[1] == 1);
				"深度为1"
				If(事件玩家.menu_state[3] == 1);
					事件玩家.menu_text = 字符串分割(自定义字符串("发送语音\\切换英雄\\添加机器人"), 自定义字符串("\\"));
				"深度为2"
				Else If(事件玩家.menu_state[3] == 2);
					"发送你好动作"
					If(事件玩家.menu_tree[2] == 0);
						"打开该页面时,往回后退menu_state[17]即1个页面"
						事件玩家.menu_state[17] = 1;
						交流(事件玩家, 语音(上));
					"切换英雄"
					Else If(事件玩家.menu_tree[2] == 1);
						事件玩家.menu_text = 全部英雄;
					"添加机器人动作"
					Else If(事件玩家.menu_tree[2] == 2);
						"打开该页面时,往回后退menu_state[17]即1个页面"
						事件玩家.menu_state[17] = 1;
						生成机器人(英雄(D.Va), 所在队伍(事件玩家), -1, 所选位置(事件玩家), 所选位置(事件玩家));
					End;
				"深度为3"
				Else If(事件玩家.menu_state[3] == 3);
					"切换英雄动作,该定位的是深度为3,且tree[2]为1即“切换英雄”的子页面,这里的if判断可省略因为深度为3没有其他页面,但不建议,会导致语义理解困难,影响后续添加其他页面"
					If(事件玩家.menu_tree[2] == 1);
						"打开该页面时,往回后退menu_state[17]即2个页面,改成1也可以"
						事件玩家.menu_state[17] = 2;
						"menu_tree记录每层选择的选项索引,menu_treename记录每层选择的选项内容,这里的menu_treename[3]记录了上一级你选择的英雄"
						开始强制玩家选择英雄(事件玩家, 事件玩家.menu_treename[3]);
					End;
				End;
			"选项2 以上两个选项为深度优先写法,有时深度较大要使用树分叉优先写法"
			Else If(事件玩家.menu_tree[1] == 2);
				"深度为1"
				If(事件玩家.menu_state[3] == 1);
					事件玩家.menu_text = 字符串分割(自定义字符串("选项2-0\\选项2-1"), 自定义字符串("\\"));
				"深度为2及以上"
				Else;
					"优先分叉 选项2-0-"
					If(事件玩家.menu_tree[2] == 0);
						"深度为2"
						If(事件玩家.menu_state[3] == 2);
							事件玩家.menu_text = 字符串分割(自定义字符串("选项2-0-0\\选项2-0-1"), 自定义字符串("\\"));
						"深度为3及以上"
						Else;
							"选项2-0-0-"
							If(事件玩家.menu_tree[3] == 0);
								"深度为3 最末一层该If判断深度可省略"
								If(事件玩家.menu_state[3] == 3);
									事件玩家.menu_text = 字符串分割(自定义字符串("选项2-0-0-0\\选项2-0-0-1"), 自定义字符串("\\"));
								End;
							"选项2-0-1-"
							Else If(事件玩家.menu_tree[3] == 1);
								"深度为3 最末一层该If判断深度可省略"
								If(事件玩家.menu_state[3] == 3);
									事件玩家.menu_text = 字符串分割(自定义字符串("选项2-0-1-0\\选项2-0-1-1"), 自定义字符串("\\"));
								End;
							End;
						End;
					"优先分叉 选项2-1-"
					Else If(事件玩家.menu_tree[2] == 1);
						"深度为2"
						If(事件玩家.menu_state[3] == 2);
							事件玩家.menu_text = 字符串分割(自定义字符串("选项2-1-0\\选项2-1-1"), 自定义字符串("\\"));
						"深度为3及以上"
						Else;
							"选项2-1-0-"
							If(事件玩家.menu_tree[3] == 0);
								"深度为3 最末一层该If判断深度可省略"
								If(事件玩家.menu_state[3] == 3);
									事件玩家.menu_text = 字符串分割(自定义字符串("选项2-1-0-0\\选项2-1-0-1"), 自定义字符串("\\"));
								End;
							"选项2-1-1-"
							Else If(事件玩家.menu_tree[3] == 1);
								"深度为3 最末一层该If判断深度可省略"
								If(事件玩家.menu_state[3] == 3);
									事件玩家.menu_text = 字符串分割(自定义字符串("选项2-1-1-0\\选项2-1-1-1"), 自定义字符串("\\"));
								End;
							End;
						End;
					End;
				End;
			Else If(事件玩家.menu_tree[1] == 3);
				If(事件玩家.menu_state[3] == 1);
					事件玩家.menu_state[12] = -1;
					事件玩家.menu_text = 字符串分割(自定义字符串("作者:老王不在橱柜\\Q群:863964203\\更新时间:2021-11-19\\熔火工坊链接"), 自定义字符串("\\"));
					事件玩家.menu_content = 字符串分割(自定义字符串("\\\\\\owmod.net/work/view/1859"), 自定义字符串("\\"));
				End;
			End;
		End;
	}
}
评论
这里空空如也~
这里空空如也~