战争之人吧 关注:33,895贴子:734,898

浅谈GEM引擎的脚本语言及对象——从MoW系列Mod制作的角度

只看楼主收藏回复

没事随手开个长文坑,涉及这个游戏的脚本编写和其他一些相关内容。慢慢更,有兴趣的同好可以看看。


IP属地:海南1楼2017-10-28 22:30回复
      众所周知,MoW是一个多产Mod的游戏系列,籍由使用自带的直观易学的编辑器,或解开并修改官方正作从不加密的pak包中的资源文件,MoW系列游戏的玩家常常可以很快地了解部分游戏机制,从而转变为游戏内容的制作者,推出自己的Mod。
      然而,由于能力、偏好等的影响,Mod作者群往往出现偏科情况,即对上述的两种Mod制作途径(即编辑器制作和修改资源包内容)中的一种颇有了解,对另一种却知之甚少。这点在Mod制作上,常常演变为任务派和修改派,一方用心地了制作大量游戏中可玩的任务(以单机任务为主),另一方则专精于改造、增加游戏中的各类事物,两派中均有大量的高质量Mod产生,但能同时兼具两派特色的高质量Mod则较为少见。
      其实,不论是编辑器制作还是资源包修改,其大多数内容最终都是在GEM引擎的世界中创建脚本和对象,也即是给一个虚拟的3D世界物色剧本和演员,殊途同归于演好这部剧。个人认为,Mod作者作为导演,应该全面地了解自己的剧本和演员,这样才能选择合适的演员来演出合适的情节,用决斗,给观众们带来笑容(。
      我不是啥dalao,也没有什么特别知名或者受欢迎的Mod作品,对编程语言知识的了解也比较浅,只是恰好在制作Mod的过程中对GEM引擎的脚本语言及对象有了一些理解,所以就随手一写,希望能对大家的顺利地制作出想要的Mod有所帮助。


    IP属地:海南2楼2017-10-28 22:33
    回复
        一、从脚本语言开始
        脚本语言,就是用来写脚本的编程语言。(废话删除线
        总之,计算机之所以兴起,很大一个原因就是因为它提高了做事的效率,尤其是自动化程序的广泛使用,使得计算机能够更快更好地完成一些本应由人类亲自完成的工作。而脚本,就是自动化程序的主要内容之一,它描述了完成一项工作所需要的逻辑和操作,没有它,计算机就不知道如何自己去处理指定的工作事项。
        这些工作,也包括操作游戏中的单位。
        在MoW中,若你把士兵修改为自行移动模式,那么他们就会在某种逻辑下寻找掩体、冲向敌人或败退逃跑,这种简单的判断-执行逻辑就是脚本的最直观样貌——在无人干预或少量干预的情况下自动化地实现功能。
        事实上,GEM引擎中的脚本远不止是一个士兵或者玩家的某个单位如何自主行动这么简单(因为这样说来似乎脚本只不过和愚蠢的AI相关而已)。在GEM引擎中,一切的交互特性都是由脚本完成的,包括但不限于:玩家点击控制按钮的效果、子弹击中穿透物体的效应、车辆间碰撞的后果、装甲的损伤损毁表现等等。毫不夸张地说,使用GEM引擎的游戏里发生的一切,都有事先写好的脚本背书,正确地理解、制作脚本,是掌握GEM引擎的前提。
        那么,如何制作脚本呢?
        在远古时期,脚本并没有什么特殊的制作工具,只是用通用编程语言来制作它们。然而,通用编程语言功能复杂繁多,用在写脚本上过于臃肿,从而催生了脚本语言的诞生:一套针对高效写作脚本优化过的,易于理解使用但功能依旧强大的编程语言。因为用途广泛,脚本语言出现在诸多领域中,如今流行的Python甚至打回了通用编程语言领域,成为脚本语言大家庭中最耀眼一个。而在游戏引擎领域,为了给使用本引擎的游戏开发者一个编写能够被引擎识别使用的脚本的途径,每一个游戏引擎基本都会自带一套脚本语言,如初代雷神之锤的quake引擎(在此赞美卡马克!)就自带一套模仿C语言格式的脚本语言quakeC,通过掌握quakeC,玩家可以向游戏中增加武器,修改各类效应等等(值得一提的是,quakeC经改造后,被植入了IW引擎中,成为了使命召唤系列的脚本语言,那些智能强悍的AI,无不出自quakeC语言的函数中,当然,这是后话了),在当时曾兴起了一阵Mod热潮。
        MoW系列使用的是GEM引擎。这套由乌克兰Best Way工作室开发的引擎中,也有一套这群乌克兰人自己开发的无名脚本语言(官方无心对语言取名,现在只会安静地躺着卖引擎数钱和挖坑,详见Best Way官网)。就像quakeC模仿了C语言一样,GEM引擎的脚本语言语法模仿了一个很古老的语言——LISP,大量地使用括号为边界(如有兴趣深入了解,可自行百度相关信息),使得MoW系列的脚本在外观上非常独特,基本不会和其他语言混淆,而且简单易上手,代码可读性强,甚至可以通过自带的编辑器可视化制作部分脚本(编辑器的触发器部分)。只能说,毕竟乌克兰毛子也是毛子,做程序都这么有个性。
        好了废话不多说,姑且将这一脚本语言称为GEM语言,开始下一部分内容。


      IP属地:海南3楼2017-10-28 22:42
      收起回复
        坐等楼主的技术文


        IP属地:广西7楼2017-10-29 09:27
        回复
          前排帮顶!


          IP属地:立陶宛来自Android客户端8楼2017-10-29 16:15
          回复
            好久没人出教程了,前排支持


            IP属地:河北来自Android客户端9楼2017-10-29 16:20
            回复
              LZ写的很不错,但是继续更啊,别太监了。


              IP属地:安徽11楼2017-10-30 09:05
              回复
                顶大神


                IP属地:北京来自Android客户端12楼2017-10-30 09:16
                回复
                  赞!


                  IP属地:安圭拉来自iPhone客户端13楼2017-10-30 16:38
                  回复
                    资磁


                    IP属地:湖北来自Android客户端14楼2017-10-31 12:15
                    回复
                      这个要顶,支持。。。


                      15楼2017-10-31 14:57
                      回复
                        野生花妹!


                        来自iPhone客户端16楼2017-11-05 02:23
                        收起回复
                            修正前文一个错误,If和Switch、While等一样,是编程语言保留字,而不是函数。
                          条件(Condition)
                            条件,通常续接在If、Switch和While保留字之后,用于判断某个变量是否为某个值或在某个值域内,进而执行不同的函数序列。完整的条件(如If a > 1中的a > 1)又可称为Expression,即条件表达式。
                            大多数时候,编程其实是一个逻辑游戏。逻辑代表着判断和选择,因此有了编程三大结构中的选择结构,而条件正是选择结构的基础。同样地,If、Switch在GEM语言中也占有重要地位(While因为不能正常运作,不谈),一段脚本里(特别是INC文件里,因为里面只支持If)经常会出现大量的If保留字及其后接的条件表达式,对从物体炸飞、士兵受伤、坦克损毁到对象距离、物体存在、任务成败等情况进行判断。可以这么说,GEM引擎世界的规则,半数以上都是出自这些额外写好的条件判断中(还有一部分已内置于引擎程序中,无法再修改或添加)。
                            在编辑器触发器里,允许使用If、Switch和While来构建条件表达式。如不作特殊要求,默认使用专有格式的If保留字,其条件表达式可使用C语言式的&、|、!等逻辑运算符,非常方便。
                            &,即AND,中文意为“和”,表示同时满足多个或多组条件。
                            |,即OR,中文意为“或”,表示满足多个条件中的其中一个或一组。
                            !,即NOT,中文意为“非”。表示不满足某一个或一组条件。
                            逻辑运算符之间还可以使用括号“(”“)”进行组合。如(1 & 2) | (1 & !3)就表示“同时满足1和2条件,或满足1条件时不满足3条件(时就会执行指定函数序列)” 。又如1 & 2 & !3表示“同时满足1条件和2条件,且不满足3条件(时就会执行指定函数序列)”。

                            在编辑器条件框(Condition)下面的小框里点击右键,可以修改条件表达式的规则,可以看到官方已经准备好了全“和”和全“或”两种选择(默认为全“和”),如果需要更复杂的条件玩家可以点击edit修改。

                            如图,1 & !2,表示满足1条件且不满足2条件。此处为左边带tag“1”的士兵距离带tag“2”的士兵相距不超过5m,且带tag“2”的士兵没有看见敌对对象时,达成触发条件。

                            Condition框条件表达式的真实样貌,官方明确将其命名为expression,也即条件表达式。

                            在编辑器命令的“泛型”(generic)组中,亦有If、Switch保留字可用。

                            此处的If除了不能使用逻辑运算符和需要使用add inside插入函数执行序列外,和Condition框没有太大区别,但是因为可以连续使用多组,比Condition框更为灵活。
                            Switch则是更为灵活,效率更高的保留字,能够一次根据多个条件逐个判断执行,判断顺序从首个case开始,以default结束。保底执行default不需设置特殊条件,只要其他case不被满足,最后一定会执行default,也因此default一定是在最后被判断的,即使default被放置于case前。

                          图中意为:当带tag“2”的对象存在(数量>0)时,执行带tag“1”的对象移动的事件,如果带tag“2”的对象不存在,则有50%的概率执行带tag“1”的对象移动的事件,如果这50%的概率也没随机到,则default保底执行带tag“1”的对象移动的事件。没错,如果只有rand的case的话,default就是给10连不出卡的非洲人保底用的(删除线),也可不加default只搞case,气死非洲人(删除线)。


                          IP属地:海南17楼2017-11-05 13:27
                          回复
                            而在INC文件中,因为只能使用If保留字,且能够使用else来表示“或”(也即OR,|),NOT来表示“非”(也即!),因此脚本整体看起来反倒更加规整严谨。

                            这是一段在bullet_hit(子弹命中)事件下的if条件表达式,其中的stuff为子弹tag,总的来说其实条件表达式中都是在判断布尔变量的值,如被“shell fg”命中,那即返回Ture,执行函数,否则返回false,又判断是否被“bazooka”命中,继续返回Ture或False。顺带一提,{bullet_detanate}是子弹爆炸函数,此处前两段逻辑是高爆弹和火箭弹命中步兵会即刻爆炸。

                            一个“非”(也即If not)的例子,此处意为,在非白昼天气(属于天气参数/变量),可操作(属于对象参数/变量)的载具会开启车灯。


                            IP属地:海南18楼2017-11-05 13:45
                            回复
                              在最重要的“事件”和“条件”到来之前,先对GEM语言中函数及其参数,还有条件进行整理一下。
                              GEM语言元素整理
                              编程保留字:
                              If(编辑器、INC),条件判断保留字,可直译为“如果”,后接条件表达式,编辑器和INC中条件表达式语法有别。
                              Switch(编辑器),功能同If,语法有区别,比If更高效。
                              Call(编辑器、INC),可直译为“触发”,编辑器和INC中功能有别。编辑器中为触发指定自定义函数(在F9的Function内预先制好),INC中为触发指定事件。
                              Con(编辑器、INC),为Context(注释)的简称,无实际作用,仅用于写注释文本,方便他人研读脚本。
                              Loop(编辑器),循环,可指定次数参数,内置函数序列循环执行指定次数。
                              Thread(编辑器),线程,多个有先后顺序的Thread将不分先后顺序同时执行,可以将一般情况下按顺序执行的函数序列变为一瞬间同时执行,也即所谓的“多线程”。
                              While(编辑器),本为“条件-循环”保留字,但是编辑器里无效,等同于If。


                              IP属地:海南19楼2017-11-05 14:03
                              回复