本帖最后由 vegetto 于 2022-10-27 11:24 编辑
碰撞专篇应用(1):模型和程序的综合运用---场景物运动辅助及碰撞的妙用之制作自动生成复杂图案阵型系统
前言:我的全体mod都是以txt为基础,所以局部变量都是采用var的写法pos什么不考虑复用slot都是数字序号,你们重在理解即可。且我只讲自己研究的部分,涉及前人的成果的其他办法请自行搜索查找,莫一代代陷入重复劳动和仿写的循环中。https://bbs.mountblade.com.cn/thread-2094114-1-1.html这个是我一系列骑砍战团模型程序研究成果的目录篇,用来汇集一些分散的我的技术贴,还没更新多少,将会持续更新一些你们不常见的冷门技术。(759523711我的魔兽争霸mod开发群可以加群学习,定时分享一些其他技术成果,来自我的一系列自制mod https://bbs.mountblade.com.cn/thread-2093251-1-1.html的研究)
这个功能是其次,注意是给大家强调模型技术和代码技术的结合运用,我们很多modder太偏科了或者存在对模型技术的不屑和鄙视,所以我将例举一些如果你没有相应的模型技术就无法用代码技术实现的能力,即巧妇难为无米之炊。
然后我后面要对碰撞相关的代码知识做一个复杂的总结专项,所以先分开写,后面出一个碰撞专篇的目录帖子。
以下正文:
需要与这个功能相关制作的素材可以下载下面百度云里的demo查看参考,但是素材类的东西不许使用于其他mod,并且下面程序部分内容只允许在2021年以后(含2021)发布的非子mod非使用20个以上他人osp的mod使用。
也就是你是2021年以前发布的mod,或者是人家成熟mod的子mod,或使用了其他人20个以上osp功能的非原创杂交mod,这3类mod不可以使用我的相关成果,包括后面其他成果分享也是这个要求。并且不可以通过改写优化的方式进行加工重新发布新贴osp以及改版后传播他人,目的就是希望你们原创并且有独立思考,避免所有人都学一套模板一家之言,mod内容越做越像越来越杂交。
链接:https://pan.baidu.com/s/1wDIA9K23xlZ7XA-zryFy-Q?pwd=7456 提取码:7456中文站demo发布地址:https://bbs.mountblade.com.cn/thread-2094127-1-1.html
我的外网moddb发布地址
https://www.moddb.com/mods/diy-special-formation-system
首先简单介绍这个功能的作用和原理:
基本作用:你们是不是已经认定或感概过骑砍实现不了复杂阵型或者简单阵型维持阵型运动都很难,所以我来给你们介绍一种可以生成八卦阵、小猪佩奇图案等待复杂图形且可以控制阵型移动的自动化图案阵型生成系统。
基本原理:首先找一些背景纯色有一些简单线条画即简笔画的图片,将图片转换为SVG矢量文件,然后导入blender(blender的导入模型选项里就有SVG这个选项),再用blender导出为OBJ,
这时候你会得到一个类似mesh的只有一个平面的模型,但是这个模型将自己的纯白色背景全部掏空了,按照简笔画线条生成的有一定笔画宽度的图案模型,然后你将模型参照玩家衣服模型的位置将模型重心的左下角对应到brf的坐标系原点,Z值贴合平行OXY平面为0,然后适当放大比例,比如参考我的实例mod里找到xxx.BRF里zxpq-zxpq7这7个模型的相对大小,差不多小叮当哆啦A梦的大小就是极限,最好不要再大于它的等效成方形后的平面范围了。然后利用openbrf自带的生成碰撞体的功能生成碰撞体。
以上介绍了模型技术手段过程
以下是纯程序手段过程:基本原理就是利用这个平面图案有漏空区域的模型生成的碰撞,代码生成这个场景物平放置场景中(后面我统一叫【阵型模板场景物】),从场景上空垂直往下对这个【阵型模板场景物】包含模型碰撞尺寸的一定范围内逐点检测碰撞,循环模型差不多大小的方形点集 (类似0<x<300,0<y<300的点集)中对碰撞点位利用高度差计算判断下方碰撞体的各个碰撞点位形成点阵,然后放置一个无模型外形的场景物标记图案一定精度获取的碰撞点点阵的坐标(后面我统一叫【定位场景物】),并对应【定位场景物】生成agent士兵并利用slot记录序号与定位场景物一一对应进行后续控制,然后控制所有【定位场景物】按同一个角度和速度的移动,将对应序号的agent士兵跟随对应序号的【定位场景物】,这样就可以在运动中和运动停止后恢复这样一种特别复杂图案的阵型。
以下是具体的代码,我写都是只考虑最终效果和思想,写法比较随意,加上txt做mod,你们看看思维角度即可:
所有新增的变量和slot
变量和slot我用到比较随意,你们随便取,最好是根据slot使用对象具有特征联系就优先使用哪个方面的slot。
"$a" 变量控制了阵型移动的条件,值为0静止,1-4代表阵型会整体前后左右运动
"$b" 变量控制了进入战场确认阵型生成后进行摄像机镜头控制prop和阵型碰撞模板prop的一次生成。
"$c" #初始化变量,表示是否开启摄像机镜头
阵型模板slot的prop | | | | | | trpslot玩家 | | | | agentslot | | | | 300 | 判断阵型刷兵阶段生成进程 | | | | | 300 | 记录阵型的模板spr名称 | | | 300 | 记录士兵序号 | | | 301 | 判断是否使用阵型运动停止setpos修正位移 | | | | | 301 | 记录x点位 | | | 301 | 作为玩家启动阵型进程控制 | | | | | | | | | 302 | 记录y点位 | | | 302 | 玩家的记录阵型的序号 | | | | | | | | | 303 | 判断人是否按点位刷完 | | | 303 | 玩家的记录阵型的大小 | | | | | | | | | 304 | 记录阵型的放大倍数 | | | 304 | 玩家的记录阵型单位距离 | | | | | | | | | 305 | 记录阵型的单位间隔倍数 | 基础2,即每个士兵间隔30x2=60cm | | | | | |
所有要用的module_string.py:
("ok", "prepare formation image"),
("pig", "prepare formation soldier"),
("dd", "now formation is no dynamic"),
("ee", "now formation is dynamic"),
("ff", "special formation has created"),
("www", "formation now move front"),
("aaa", "formation now move left"),
("sss", "formation now move back"),
("ddd", "formation now move right"),
("openfix", "keep fix formation everyone pos all moving time"),
("closefix", "close fix formation everyone pos function so everyone should find its right formation pos for a while and may be blocked by other one"),
("formationtype", "now you choose the {s20} as your formation , pls click enter to confirm or click left shift or right shift key to change formation kind"),
("openfix2", "quick fix formation everyone pos at stopping time"),
("formationsize", "now you has comfirmed the {s20} as your formation , pls click enter to confirm its size , current size {reg21} ( original size is 100% ) or click left shift or right shift key to change formation size everytime 10% off or add but remember that the original size is perfect display the image formation but if size smaller or bigger may not display the correct image or make system run error"),
("formationdis", "now you has comfirmed the {s20} as your formation with size {reg21} , pls click enter to confirm its distance between every soldier , current distance {reg22} ( original distance is 60 cm ) or click left shift or right shift key to change formation soldier distance everytime 20 cm off or add but remember that the original size is perfect display the image formation but if size smaller or bigger may not display the correct image or make system run error"),
("formationwait", "do you now warband if create many soldier or object at the first time entering scene , it is easier to run error so you should wait for ten seconds ( now {reg20} seconds ) to start formation system but now you can adjust your position because formation is created in front of your position and move right so be cared that donot make formation created out of scene boundary"),
("formationwait2", "preparing ... pls not click v to move formation now and wait for a while"),
所需要的场景物加module_scene_prop.py(生成阵型模板的关键素材的定义):
("mwm", 0, "0", "0", []), #控制镜头的物体
("zxwz", 0, "0", "0", []), #标记每个阵型士兵位置的物体
("zxpq", 0, "zxpq", "zxpq", []), #阵型模板第1个物体,你可以删掉模型名称即第二个zxpq,只留第3个zxpq的碰撞体名称,因为下面阵型生成只需要碰撞体,下面的场景物是一个作用
("zxpq2", 0, "zxpq2", "zxpq2", []),
("zxpq3", 0, "zxpq3", "zxpq3", []),
("zxpq4", 0, "zxpq4", "zxpq4", []),
("zxpq5", 0, "zxpq5", "zxpq5", []),
("zxpq6", 0, "zxpq6", "zxpq6", []),
("zxpq7", 0, "zxpq7", "zxpq7", []), #阵型模板第7个物体
所需要的装备物品加module_scene_prop.py
["zxpq", "formation_goose_hug", [("zxpq", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq2", "formation_peppa_pig", [("zxpq2", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq3", "formation_chicken_you_are_too_beautiful", [("zxpq3", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq4", "formation_grey_wolf_paralysis_array", [("zxpq4", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq5", "formation_grey_wolf_paralysis_array", [("zxpq5", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq6", "formation_doraemon", [("zxpq6", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpq7", "formation_carrot", [("zxpq7", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
["zxpqend", "not_create_formation", [("zxpq", 0)], itp_type_body_armor|itp_covers_legs|itp_doesnt_cover_hair|itp_can_penetrate_shield|itp_civilian|itp_next_item_as_melee, 0, 348, weight(4.000000)|abundance(100)|difficulty(0)|head_armor(0)|body_armor(14)|leg_armor(4), imodbits_cloth],
#以上物品用来记录对应阵型模板第1-7个物体,利用物品自身名称的item name string来记录阵型的名称,方便传递到阵型生成系统选项来提示玩家怎么选择阵型种类。
以下三组触发器加入module_mission_temple .py中lead_charge,也就是野战场景的控制中:
#下方触发器1是为了初始化一些变量
(ti_before_mission_start, 0.000000, 0.000000,
[
],
[
(assign, "$a", 0), #初始化变量,该变量控制了阵型移动的条件,值为0静止,1-4代表阵型会整体前后左右运动
(assign, "$b", 0), #初始化变量,变量控制了进入战场确认阵型生成后进行摄像机镜头控制prop和阵型碰撞模板prop的一次生成。
(assign, "$c", 0), #初始化变量,表示是否开启摄像机镜头
(troop_set_slot, "trp_player", 300, 0), #初始化变量,表示阵型模板prop的spr名称
(troop_set_slot, "trp_player", 301, 0), #初始化变量,记录在以阵型模板pos为坐标原点和方向的X方向即按30cm每次向右移动检测阵型模板prop的执行次数
(troop_set_slot, "trp_player", 302, 0), #初始化变量,记录在以阵型模板pos为坐标原点和方向的Y方向即按30cm每次向上移动检测阵型模板prop的执行次数
(troop_set_slot, "trp_player", 303, 0), #初始化变量,表示trp player的301slot和302slot乘积,判断是否将检测阵型模板prop的碰撞区域范围执行完毕
(troop_set_slot, "trp_player", 304, 100), #初始化变量,表示阵型的尺寸大小范围,也可以看作阵型模板prop的prop scale,即场景物模型放缩倍数,结合相关op操作来初始化生成prop的尺寸大小倍数
(troop_set_slot, "trp_player", 305, 2), #初始化变量,表示阵型的每个士兵的间隔距离倍数,1代表间距30,也就是碰撞检测执行每次的间距,值为n,则士兵按照30xn厘米来站位
]),
#下方触发器2是为了自由镜头
(0.000000, 0.000000, 0.000000,
[
],
[
(try_begin),
(key_clicked, key_tab),
(call_script, "script_count_mission_casualties_from_agents"),
(finish_mission, 0),
(try_end), #以上表示测试阶段随时退出战斗
(try_begin),
(eq, "$c", 0),
(key_clicked, key_m),
(assign, "$c", 1),
(else_try),
(eq, "$c", 1),
(key_clicked, key_m),
(assign, "$c", 0),
(try_end), #以上表示按M切回镜头控制的状态,$c为1则为自由镜头模式
(get_player_agent_no, ":var_0"),
(agent_set_no_death_knock_down_only, ":var_0", 1), #测试阶段给予玩家不会死亡的状态,即死亡后秒复活
(scene_prop_get_instance, ":var_1", "spr_mwm", 0), #场景物spr mwm用于控制镜头,即控制prop 的运动并使得摄像机与prop位置同步达到控制摄像机的效果
(agent_get_position, pos1, ":var_0"),
(prop_instance_get_position, pos2, ":var_1"),
(try_begin),
(eq, "$c", 1), #$c为1则为自由镜头模式的条件下
(try_begin),
(this_or_next|key_is_down, key_w),
(this_or_next|key_is_down, key_a),
(this_or_next|key_is_down, key_s),
(this_or_next|key_is_down, key_d),
(this_or_next|key_is_down, key_r),
(key_is_down, key_left_control),
(agent_get_look_position, pos3, ":var_0"),
(position_copy_rotation, pos2, pos3),
(else_try),
(position_copy_rotation, pos2, pos1),
(try_end), #以上若干行表示:移动时物体运动平行于视角即镜头方向,静止时镜头保持和玩家agent一样的平放状态
(try_begin),
(key_is_down, key_w),
(position_move_y, pos2, 200),
(else_try),
(key_is_down, key_a),
(position_move_x, pos2, -200),
(else_try),
(key_is_down, key_s),
(position_move_y, pos2, -200),
(else_try),
(key_is_down, key_d),
(position_move_x, pos2, 200),
(else_try),
(key_is_down, key_r),
(position_move_z, pos2, 200),
(else_try),
(key_is_down, key_left_control),
(position_move_z, pos2, -200),
(try_end),
(prop_instance_animate_to_position, ":var_1", 2), #以上若干行表示:表示按wasd r left ctrl 这几个键可以使得物体上下左右前后六个方向进行运动
(try_begin),
(neg|key_is_down, key_w),
(neg|key_is_down, key_a),
(neg|key_is_down, key_s),
(neg|key_is_down, key_d),
(neg|key_is_down, key_r),
(neg|key_is_down, key_left_control),
(agent_get_look_position, pos3, ":var_0"),
(position_copy_rotation, pos2, pos3),
(try_end), #以上若干行表示:与下方摄像机镜头设置结合看看,这样写的目的是为了让摄像机镜头没有运动的时候像玩家一样可以晃动鼠标旋转360度围绕自身查看周边情况
(position_move_y, pos2, -300),
(position_move_z, pos2, 50),
(mission_cam_set_mode, 1),
(mission_cam_set_position, pos2), #以上若干行表示:将镜头设置在spr mwm这个物体后面一定位置,也就是我们控制spr mwm运动可以得到spr mwm稍微远看的镜头范围
(else_try),
(eq, "$c", 0), #$c为0代表战团默认的镜头模式
(mission_cam_set_mode, 0), #mission_cam_set_mode设0为默认镜头模式,为1可以像上面一样随意控制镜头位置,解开与玩家自己的位置绑定。
(prop_instance_set_position, ":var_1", pos1), #表示spr mwm场景物在非自由镜头模式时始终跟随设置在玩家的坐标位置处,避免下次开启自由镜头时,镜头控制场景物距离玩家位置过远显得突兀。
(try_end),
]),
#下方触发器3是图案阵型生成系统的核心
(0.000000, 0.000000, 0.000000,
[
],
[
(set_fixed_point_multiplier, 100), #设置浮点数100,主要为了下面的prop_instance_set_scale放大场景物尺寸大小倍数,即后面参数填100,代表100除以100=1即1倍大小
(get_player_agent_no, ":var_0"), #玩家id
(agent_get_team, ":var_1", ":var_0"), #阵营
(try_begin),
(agent_slot_eq, ":var_0", 301, 0), #玩家的agentslot 301代表阵型准备前的进程控制,为0代表刚进入战场
(agent_set_no_dynamics, ":var_0", 0),
(store_mission_timer_a, ":var_2"),
(assign, reg20, ":var_2"), #记录当前时间过去的秒数为reg20传递给str_formationwait
(tutorial_message_set_background, 1),
(tutorial_message, "str_formationwait", 0, 1), #教程文字:提醒玩家进场先慢慢等10秒,让系统先释放一会内存避免阵型人多反复重进战斗调用时崩溃
(ge, ":var_2", 10),
(agent_set_slot, ":var_0", 301, 1), #agentslot 301为0的进程转到1
(else_try),
(agent_slot_eq, ":var_0", 301, 1), #玩家的agentslot 301代表阵型准备前的进程控制,为1代表选择阵型种类并确认的阶段
(agent_set_no_dynamics, ":var_0", 1), #默认值为0,禁止玩家的一切系统产生的位移效果。防止玩家乱动位置影响后面生成东西。
(agent_get_slot, ":var_3", ":var_0", 302), #玩家的agentslot 302阵型的序号,即目前7种阵型,那么人为给个序号0-7(多一个数是因为7代表玩家不使用阵型)
(try_for_agents, ":var_4"),
(agent_is_alive, ":var_4"),
(agent_get_team, ":var_5", ":var_4"),
(neg|eq, ":var_4", ":var_0"),
(eq, ":var_5", ":var_1"),
(agent_set_slot, ":var_4", 300, -1),
(try_end), #以上若干行表示:将目前玩家自己刷的士兵slot300设为-1,因为下面额外刷的士兵要达到slot300大于等于0才属于阵型系统里的士兵,这个测试阶段的随意处理,如果你需要应用自己大地图带的兵,可以考虑放大战场规模或不停增援然后在下面把刷兵改写成现有兵set pos调整位置
(try_begin),
(key_clicked, key_left_shift),
(try_begin),
(is_between, ":var_3", 1, 8),
(store_sub, ":var_6", ":var_3", 1),
(agent_set_slot, ":var_0", 302, ":var_6"),
(else_try),
(ge, ":var_3", 8),
(agent_set_slot, ":var_0", 302, 7),
(else_try),
(neg|ge, ":var_3", 1),
(agent_set_slot, ":var_0", 302, 7),
(try_end),
(else_try), #以上若干行表示:按左手边的shift按键玩家agentslot 302代表的阵型的序号将依次减1,但是保证在0-7变化
(key_clicked, key_right_shift),
(try_begin),
(is_between, ":var_3", 0, 7),
(store_add, ":var_6", ":var_3", 1),
(agent_set_slot, ":var_0", 302, ":var_6"),
(else_try),
(ge, ":var_3", 7),
(agent_set_slot, ":var_0", 302, 0),
(else_try),
(neg|ge, ":var_3", 0),
(agent_set_slot, ":var_0", 302, 0),
(try_end),
(else_try), #以上若干行表示:按右手边的shift按键玩家agentslot 302代表的阵型的序号将依次加1,但是保证在0-7变化
(key_clicked, key_enter),
(agent_get_slot, ":var_3", ":var_0", 302),
(store_add, ":var_6", ":var_3", "spr_zxpq"),
(troop_set_slot, "trp_player", 300, ":var_6"),
(agent_set_slot, ":var_0", 301, 2),
(try_end), #以上若干行表示:按enter键后设值玩家的trpslot 300代表的阵型模板prop场景物的spr名称,并将agentslot 301代表的阵型准备前的进程控制到2阶段
(agent_get_slot, ":var_7", ":var_0", 302),
(store_add, ":var_8", ":var_7", "itm_zxpq"),
(str_store_item_name, s20, ":var_8"),
(tutorial_message_set_background, 1),
(tutorial_message, "str_formationtype", 0, 1), #以上若干行表示:用s20存储装备物品item的名称(按照prop定义的阵型模板场景物id顺序,记录阵型名称叫什么,这样做也是为了后面重做界面系统利用item的图像生成op来给玩家提前知道会生成什么图案),用tutorial教程文字提示玩家选择了什么阵型
(else_try),
(agent_slot_eq, ":var_0", 301, 2), #玩家的agentslot 301代表阵型准备前的进程控制,为2代表选择阵型种类已确认,但需要确认阵型的尺寸大小范围的阶段
(agent_set_no_dynamics, ":var_0", 1),
(agent_get_slot, ":var_3", ":var_0", 303),
(try_begin),
(key_clicked, key_left_shift),
(try_begin),
(is_between, ":var_3", 40, 400),
(store_sub, ":var_6", ":var_3", 10),
(agent_set_slot, ":var_0", 303, ":var_6"),
(else_try),
(ge, ":var_3", 400),
(agent_set_slot, ":var_0", 303, 100),
(else_try),
(neg|ge, ":var_3", 40),
(agent_set_slot, ":var_0", 303, 100),
(try_end),
(else_try),
(key_clicked, key_right_shift),
(try_begin),
(is_between, ":var_3", 40, 400),
(store_add, ":var_6", ":var_3", 10),
(agent_set_slot, ":var_0", 303, ":var_6"),
(else_try),
(ge, ":var_3", 400),
(agent_set_slot, ":var_0", 303, 100),
(else_try),
(neg|ge, ":var_3", 40),
(agent_set_slot, ":var_0", 303, 100),
(try_end),
(else_try),
(key_clicked, key_enter),
(agent_get_slot, ":var_3", ":var_0", 303),
(troop_set_slot, "trp_player", 304, ":var_3"),
(agent_set_slot, ":var_0", 301, 3),
(try_end),
(try_begin),
(neg|agent_slot_ge, ":var_0", 303, 40),
(agent_set_slot, ":var_0", 303, 100),
(try_end),
(agent_get_slot, ":var_7", ":var_0", 302),
(store_add, ":var_8", ":var_7", "itm_zxpq"),
(str_store_item_name, s20, ":var_8"),
(agent_get_slot, reg21, ":var_0", 303),
(tutorial_message_set_background, 1),
(tutorial_message, "str_formationsize", 0, 1), #以上若干行表示:类比上方阵型种类的确认代码,主要为了左右两个shift调整agent slot303代表的阵型尺寸大小,按照xxx.BRF里面zxpq到zxpq7模型碰撞大小进行40%-400%的放缩控制,往下面看prop_instance_set_scale的op结合看看。enter确认大小尺寸
(else_try),
(agent_slot_eq, ":var_0", 301, 3), #玩家的agentslot 301代表阵型准备前的进程控制,为3代表选择阵型种类已确认且尺寸也确认了,但需要确认阵型中每个相邻士兵初始的间距的阶段
(agent_set_no_dynamics, ":var_0", 1),
(agent_get_slot, ":var_3", ":var_0", 304),
(try_begin),
(key_clicked, key_left_shift),
(try_begin),
(is_between, ":var_3", 2, 10),
(store_sub, ":var_6", ":var_3", 1),
(agent_set_slot, ":var_0", 304, ":var_6"),
(else_try),
(ge, ":var_3", 10),
(agent_set_slot, ":var_0", 304, 2),
(else_try),
(neg|ge, ":var_3", 2),
(agent_set_slot, ":var_0", 304, 2),
(try_end),
(else_try),
(key_clicked, key_right_shift),
(try_begin),
(is_between, ":var_3", 2, 10),
(store_add, ":var_6", ":var_3", 1),
(agent_set_slot, ":var_0", 304, ":var_6"),
(else_try),
(ge, ":var_3", 10),
(agent_set_slot, ":var_0", 304, 2),
(else_try),
(neg|ge, ":var_3", 2),
(agent_set_slot, ":var_0", 304, 2),
(try_end),
(else_try),
(key_clicked, key_enter),
(agent_get_slot, ":var_3", ":var_0", 304),
(troop_set_slot, "trp_player", 305, ":var_3"),
(agent_set_slot, ":var_0", 301, 4),
(try_end),
(try_begin),
(neg|agent_slot_ge, ":var_0", 304, 2),
(agent_set_slot, ":var_0", 304, 2),
(try_end),
(agent_get_slot, ":var_7", ":var_0", 302),
(store_add, ":var_8", ":var_7", "itm_zxpq"),
(str_store_item_name, s20, ":var_8"),
(agent_get_slot, reg21, ":var_0", 303),
(agent_get_slot, reg22, ":var_0", 304),
(tutorial_message_set_background, 1),
(tutorial_message, "str_formationdis", 0, 1), #以上若干行表示:类比上方阵型种类的确认代码,主要为了左右两个shift调整agent slot303代表的阵型每相邻士兵间距倍数,在2-10倍变化,意思就是后面对阵型模板的碰撞检测精度是30cm移动一次检测点,为2时代表相邻士兵间距60cm。enter确认间距
(else_try),
(agent_slot_eq, ":var_0", 301, 4), #玩家的agentslot 301代表阵型准备前的进程控制,为4代表选择阵型的基本参数已确认完毕,准备阶段结束,可以接下来执行阵型的生成进程。
(agent_set_no_dynamics, ":var_0", 0),
(try_end),
(agent_slot_eq, ":var_0", 301, 4), #玩家的agentslot 301代表阵型准备前的进程控制,所以以下代码的执行都是在准备阶段结束后才能执行的
(store_add, ":var_9", 1, "spr_zxpq7"),
(neg|troop_slot_eq, "trp_player", 300, 0), #系统处理复杂时容易抽,保险起见,判断slot300确实存了一个有用的场景物spr名称
(neg|troop_slot_eq, "trp_player", 300, ":var_9"), #表示阵型模板场景物spr名称不应该是目前实装的最后一个场景物spr zxpq7再+1,也就是为这个值时,阵型确认阶段应该是选择了不使用阵型选项。
(troop_get_slot, ":var_8", "trp_player", 300),
(troop_get_slot, ":var_10", "trp_player", 304),
(troop_get_slot, ":var_11", "trp_player", 305),
(agent_get_position, pos1, ":var_0"),
(scene_prop_get_num_instances, ":var_12", "spr_mwm"), #获取场景物spr mwm的数量
(scene_prop_get_num_instances, ":var_13", ":var_8"),
(try_begin),
(eq, ":var_12", 0),
(set_spawn_position, pos1),
(spawn_scene_prop, "spr_mwm"),
(position_move_z, pos1, 10000), #高度要设置到地面高度10000cm以上的原因是防止后续代码进行碰撞检测时检测到树木和可能以后放的建筑物。
(set_spawn_position, pos1),
(spawn_scene_prop, ":var_8"),
(prop_instance_set_scale, reg0, ":var_10", ":var_10", ":var_10"),
(try_end), #以上表示场景物spr mwm的数量为0时生成一个spr mwm场景物和一个阵型模板场景物,阵型模板场景物spr名称取决于上面准备阶段最终确认的trp slot 300的储存量。然后注意上面set scale是为了控制阵型模板场景物的尺寸来达到控制阵型大小的作用
(eq, ":var_12", 1), #当场景物spr mwm的数量为1才可以执行下面的代码,此时呼应上面一个触发器的自由镜头,你控制场景物时必须给它生成出来。
(scene_prop_get_instance, ":var_14", ":var_8", 0), #":var_8"是trpslot300代表的阵型模板场景物的spr名称,在实例mod里代表spr_zxpq到spr_zxpq7,获取确认阵型种类的那一个spr场景物的id为":var_14",":var_14"才是后面我们控制场景物相关行为的对象
(try_begin),
(eq, "$b", 0), #$b全局变量控制利用阵型模板场景物的碰撞体检测来达到匹配阵型士兵形成场景物图案站位的点位记录
(try_for_range, ":var_15", 0, 301),
(try_for_range, ":var_16", 0, 301), #双循环,trpslot301和302代表沿着阵型模板prop场景物横纵两个方向的检测次数,按照30厘米每次的移动频率。
(troop_set_slot, "trp_player", 301, ":var_15"),
(troop_set_slot, "trp_player", 302, ":var_16"),
(prop_instance_get_position, pos2, ":var_14"),
(position_move_z, pos2, 3000),
(store_mul, ":var_17", ":var_15", 30),
(store_mul, ":var_18", ":var_16", 30),
(position_move_y, pos2, ":var_17"),
(position_move_x, pos2, ":var_18"),
(position_get_distance_to_ground_level, ":var_19", pos2), #判断阵型模板场景物自身位置点上方3000厘米处坐标位置在按照循环次数横纵两个方向移动若干距离后的位置点下方的高度,此高度是计算下方的场景物碰撞点为高度h=0点
(position_get_distance_to_terrain, ":var_20", pos2), #判断阵型模板场景物自身位置点上方3000厘米处坐标位置在按照循环次数横纵两个方向移动若干距离后的位置点下方的高度,但是此高度是不计算下方的场景物碰撞点,以随机地形网格生成的最高地形点为高度h=0点
(store_sub, ":var_21", ":var_20", ":var_19"), #将两个高度值作差值
(ge, ":var_21", 200), #这个可以随便写,意思就是两种对阵型模板场景物上方循环检测的同一个点位下方,利用两种不同的高度获取方法获取的高度有较大差值,说明有较大差值的点位就是阵型模板prop场景物的碰撞点,如此循环下去,所有检测出来的碰撞点就可以组成这个阵型模板场景物的外形
(set_spawn_position, pos2),
(spawn_scene_prop, "spr_zxwz"), 在阵型模板场景物被循环检测出碰撞点的地方加一个没有模型外表的spr_zxwz帮助我们记录点位坐标,省的利用3个slot去存储值
(try_end),
(try_end),
(assign, "$b", 1), #封闭变量$b,使得上面检测碰撞的双循环只执行一次
(try_end),
(troop_get_slot, ":var_22", "trp_player", 301),
(troop_get_slot, ":var_23", "trp_player", 302),
(store_mul, ":var_24", ":var_22", ":var_23"), 将上面碰撞检测的双循环两个终值相乘,当乘积如下面一行大于90000即0-301的双循环,值大于300x300=90000,就表示双循环完全执行完毕,检测碰撞过程完全执行完毕
(ge, ":var_24", 90000),
(scene_prop_get_num_instances, ":var_25", "spr_zxwz"),
(scene_prop_get_slot, ":var_26", ":var_14", 300), #阵型模板场景物的propslot 300表示控制阵型士兵生成的进程
(scene_prop_get_slot, ":var_27", ":var_14", 301),
(agent_get_position, pos1, ":var_0"),
(try_begin),
(is_between, ":var_26", 0, 250), #进程控制0-250值变化,模拟进程持续触发的时间
(store_add, ":var_28", ":var_26", 1),
(scene_prop_set_slot, ":var_14", 300, ":var_28"),
(try_begin), #开始控制按阵型图案士兵生成的进程
(eq, ":var_26", 10),
(set_show_messages, 0),
(tutorial_message_set_background, 1),
(tutorial_message, "str_ok", 0, 1),
(copy_position, pos2, pos1),
(position_move_y, pos2, -10000),
(position_move_z, pos2, -10000),
(prop_instance_set_position, ":var_14", pos2),
(scene_prop_set_visibility, ":var_14", 0), #以上若干行代码表示:阵型模板场景物的propslot 300表示的控制阵型士兵生成的进程为10时,将阵型模板的场景物位置移动到场景范围外,避免进行一些后续地面高度获取和设置操作时被天空这个场景物的碰撞影响到。
(else_try),
(eq, ":var_26", 20),
(set_show_messages, 0),
(tutorial_message_set_background, 1),
(tutorial_message, "str_pig", 0, 2),
(try_for_range, ":var_29", 0, ":var_25"),
(scene_prop_get_instance, ":var_30", "spr_zxwz", ":var_29"),
(prop_instance_get_position, pos2, ":var_30"),
(agent_get_position, pos1, ":var_0"),
(position_copy_rotation, pos2, pos1),
(position_move_z, pos2, 2000),
(position_set_z_to_ground_level, pos2),
(prop_instance_set_position, ":var_30", pos2),
(try_begin),
(store_add, ":var_31", ":var_29", 1),
(troop_set_slot, "trp_player", 303, ":var_31"),
(store_mod, ":var_32", ":var_29", ":var_11"),
(eq, ":var_32", 0),
(store_random_in_range, ":var_33", "trp_nord_recruit", "trp_nord_messenger"),
(set_spawn_position, pos2),
(spawn_agent, ":var_33"),
(agent_set_slot, reg0, 300, ":var_29"), #以阵型士兵自己的agentslot 300记录和场景物spr zxwz一样的序号,方便后面一对一进行控制
(agent_set_scripted_destination, reg0, pos2),
(agent_set_team, reg0, ":var_1"),
(agent_add_relation_with_agent, reg0, ":var_0", 1),
(try_end),
(try_end), #以上若干行代码表示:阵型模板场景物的propslot 300表示的控制阵型士兵生成的进程为20时,循环之前已经生成的用于标记阵型图案点位的场景物spr zxwz来依次生成阵型士兵,
(else_try), #但是注意 (store_mod, ":var_32", ":var_29", ":var_11"),是为了控制偶数序号生成士兵,也就是一个跳着一个生成,因为检测精度按30cm检测保证图案精度,但是这个间距对于士兵来说太拥挤了,所以用准备阶段确认的间距trpslot305的":var_11"值来控制。 (is_between, ":var_26", 40, 200), #进程控制40-200值触发时间区间来显示提示文字,提醒玩家生成时间稍微等待一会,避免还没有生成好士兵和设置一些东西就玩家等不及执行了下面对动态移动阵型的相关命令。
(tutorial_message_set_background, 1),
(tutorial_message, "str_formationwait2", 0, 1),
(else_try),
(eq, ":var_26", 240), #进程控制为240值,提醒玩家阵型生成阶段完全结束,玩家可以按下面代码写的,用V和b键控制阵型进行动态移动
(tutorial_message_set_background, 1),
(tutorial_message, "str_ff", 0, 3),
(set_show_messages, 1), #这种大量生成士兵的行为容易红字,所以在前一阶段进行红字屏蔽。
(try_end),
(try_end),
(try_begin),
(ge, ":var_26", 240), #进程控制大于240值,开始对阵型的动态移动进行控制
(troop_slot_ge, "trp_player", 303, ":var_25"),
(try_begin),
(eq, "$a", 0),
(try_begin),
(scene_prop_slot_eq, ":var_14", 301, 0),
(key_clicked, key_b),
(scene_prop_set_slot, ":var_14", 301, 1),
(tutorial_message_set_background, 1),
(tutorial_message, "str_openfix2", 0, 2),
(else_try),
(scene_prop_slot_eq, ":var_14", 301, 1),
(key_clicked, key_b),
(scene_prop_set_slot, ":var_14", 301, 2),
(tutorial_message_set_background, 1),
(tutorial_message, "str_openfix", 0, 2),
(else_try),
(scene_prop_slot_eq, ":var_14", 301, 2),
(key_clicked, key_b),
(scene_prop_set_slot, ":var_14", 301, 0),
(tutorial_message_set_background, 1),
(tutorial_message, "str_closefix", 0, 2),
(try_end),
(try_end), #以上若干行代码表示:阵型处于静态时,切换阵型中士兵的移动模式,有3个模式,分别以阵型模板的propslot301的0-2值来控制
(try_begin),
(eq, "$a", 0),
(key_clicked, key_v),
(assign, "$a", 1),
(tutorial_message_set_background, 1),
(tutorial_message, "str_ee", 0, 2),
(else_try),
(this_or_next|eq, "$a", 1),
(this_or_next|eq, "$a", 3),
(eq, "$a", 4),
(key_clicked, key_down),
(assign, "$a", 2),
(else_try),
(this_or_next|eq, "$a", 2),
(this_or_next|eq, "$a", 3),
(eq, "$a", 4),
(key_clicked, key_up),
(assign, "$a", 1),
(else_try),
(this_or_next|eq, "$a", 1),
(this_or_next|eq, "$a", 2),
(eq, "$a", 4),
(key_clicked, key_left),
(assign, "$a", 3),
(else_try),
(this_or_next|eq, "$a", 1),
(this_or_next|eq, "$a", 2),
(eq, "$a", 3),
(key_clicked, key_right),
(assign, "$a", 4),
(else_try),
(this_or_next|eq, "$a", 1),
(this_or_next|eq, "$a", 2),
(this_or_next|eq, "$a", 3),
(eq, "$a", 4),
(key_clicked, key_v),
(assign, "$a", 0),
(tutorial_message_set_background, 1),
(tutorial_message, "str_dd", 0, 2),
(scene_prop_slot_eq, ":var_14", 301, 1),
(try_for_agents, ":var_4"),
(agent_is_alive, ":var_4"),
(agent_get_team, ":var_5", ":var_4"),
(neg|eq, ":var_4", ":var_0"),
(eq, ":var_5", ":var_1"),
(agent_get_slot, ":var_34", ":var_4", 300),
(ge, ":var_34", 0),
(scene_prop_get_instance, ":var_35", "spr_zxwz", ":var_34"),
(prop_instance_get_position, pos3, ":var_35"),
(agent_set_position, ":var_4", pos3),
(try_end),
(try_end), #以上表示阵型处于静态时,按v切换动态阵型,会先默认到$a为1值的前进状态,按键盘的上下左右箭头按键一下,就可以将这个状态调整到其他方向的阵型移动,而动态阵型按v回到静态阵型时会被前面按b键控制的士兵运动模式影响。
#propslot301为1时代表阵型停止移动后会迅速通过瞬移的方式将士兵位置移动到和自己序号标记slot对应序号的spr zxwz一致的场景物prop的位置上,达到迅速恢复移动散架的阵型图案的作用。
(try_begin),
(scene_prop_slot_eq, ":var_14", 301, 2),
(try_for_agents, ":var_4"),
(agent_is_alive, ":var_4"),
(agent_get_team, ":var_5", ":var_4"),
(neg|eq, ":var_4", ":var_0"),
(eq, ":var_5", ":var_1"),
(agent_get_slot, ":var_34", ":var_4", 300),
(ge, ":var_34", 0),
(scene_prop_get_instance, ":var_35", "spr_zxwz", ":var_34"),
(prop_instance_get_position, pos3, ":var_35"),
(agent_set_position, ":var_4", pos3), #以上若干行代码表示:propslot301为2时代表阵型移动过程中士兵位置会持续移动到和自己序号标记slot对应序号的spr zxwz一致的场景物prop的位置上,达到始终保持阵型图案的作用。
(try_end),
(else_try),
(try_for_agents, ":var_4"),
(agent_is_alive, ":var_4"),
(agent_get_team, ":var_5", ":var_4"),
(neg|eq, ":var_4", ":var_0"),
(eq, ":var_5", ":var_1"),
(agent_get_slot, ":var_34", ":var_4", 300),
(ge, ":var_34", 0),
(scene_prop_get_instance, ":var_35", "spr_zxwz", ":var_34"),
(prop_instance_get_position, pos3, ":var_35"),
(agent_set_scripted_destination, ":var_4", pos3),
(try_end), #以上若干行代码表示:propslot301为0或1时代表阵型移动过程中士兵会以自己对应序号的spr zxwz场景物的坐标位置为移动目标,让引擎使得ai自己往坐标位置走,但是由于地形的多样和ai移速的不同,在移动过程中不能保持阵型的图案相对位置,但是阵型停止运动时可以慢慢恢复到原来的图案形状
(try_end),
(scene_prop_get_num_instances, ":var_12", "spr_zxwz"), # 以下代表"$a"的1-4值表示的阵型集体前后左右移动状态,循环所有的spr_zxwz场景物先代替士兵通过以恒定速度和角度(玩家的视角相对前后左右的垂直或水平调整)来集体运动,这样所有场景物spr zxwz会始终保持好原始的阵型点阵图案,这时候加上上方让agent士兵ai跟随或设置位置于对应序号的spr_zxwz场景物的位置来保证各种运动条件下,阵型士兵都可以恢复自身可以维持阵型图案的站位。
(agent_get_position, pos1, ":var_0"),
(try_begin),
(eq, "$a", 1),
(try_for_range, ":var_13", 0, ":var_12"),
(store_mod, ":var_36", ":var_13", ":var_11"),
(eq, ":var_36", 0),
(scene_prop_get_instance, ":var_14", "spr_zxwz", ":var_13"),
(prop_instance_get_position, pos2, ":var_14"),
(position_copy_rotation, pos2, pos1),
(position_move_y, pos2, 10),
(position_move_z, pos2, 2000),
(position_set_z_to_ground_level, pos2),
(prop_instance_set_position, ":var_14", pos2),
(tutorial_message_set_background, 1),
(tutorial_message, "str_www", 0, 1),
(try_end),
(else_try),
(eq, "$a", 2),
(try_for_range, ":var_13", 0, ":var_12"),
(store_mod, ":var_36", ":var_13", ":var_11"),
(eq, ":var_36", 0),
(scene_prop_get_instance, ":var_14", "spr_zxwz", ":var_13"),
(prop_instance_get_position, pos2, ":var_14"),
(position_copy_rotation, pos2, pos1),
(position_move_y, pos2, -10),
(position_move_z, pos2, 2000),
(position_set_z_to_ground_level, pos2),
(prop_instance_set_position, ":var_14", pos2),
(tutorial_message_set_background, 1),
(tutorial_message, "str_sss", 0, 1),
(try_end),
(else_try),
(eq, "$a", 3),
(try_for_range, ":var_13", 0, ":var_12"),
(store_mod, ":var_36", ":var_13", ":var_11"),
(eq, ":var_36", 0),
(scene_prop_get_instance, ":var_14", "spr_zxwz", ":var_13"),
(prop_instance_get_position, pos2, ":var_14"),
(position_copy_rotation, pos2, pos1),
(position_move_x, pos2, -10),
(position_move_z, pos2, 2000),
(position_set_z_to_ground_level, pos2),
(prop_instance_set_position, ":var_14", pos2),
(tutorial_message_set_background, 1),
(tutorial_message, "str_aaa", 0, 1),
(try_end),
(else_try),
(eq, "$a", 4),
(try_for_range, ":var_13", 0, ":var_12"),
(store_mod, ":var_36", ":var_13", ":var_11"),
(eq, ":var_36", 0),
(scene_prop_get_instance, ":var_14", "spr_zxwz", ":var_13"),
(prop_instance_get_position, pos2, ":var_14"),
(position_copy_rotation, pos2, pos1),
(position_move_x, pos2, 10),
(position_move_z, pos2, 2000),
(position_set_z_to_ground_level, pos2),
(prop_instance_set_position, ":var_14", pos2),
(tutorial_message_set_background, 1),
(tutorial_message, "str_ddd", 0, 1),
(try_end),
(try_end),
(try_end),
]),
|