奥妮吧 关注:3,220贴子:34,928
  • 20回复贴,共1

修改bsl基础入门

只看楼主收藏回复

入门级的攻略,完全没基础的人也可看得懂。
其实吧里早就有教程了,那我写这个就应该尽量避免雷同,所以我从更基础的说起吧。
bsl文件都放在\GameDataFolder\IGMD文件夹下的各个文件夹里,比如第3关的放在lab文件夹中,就从它下手吧。
打开lab文件夹,里面有4个bsl文件:lab_main.bsl、particle_scripts.bsl、lab_cutscene.bsl、lab_level_logic.bsl。
lab_main.bsl 里面必有1个func void main(void)这样的东西,这是每关都有的,这东西是一个“函数”,名字是“main”,main的意思是“主要的”。这个函数是优先执行的,它一般是布置好关卡开始时的环境、设置视野范围、设置起雾的范围、设置红绿蓝三色光线强度等等,就是下面的部分:
env_show 776 0
env_show 777 0
gl_fog_blue=.15
gl_fog_red=.30
gl_fog_green=.17
gl_fog_start=.99
gs_farclipplane_set 5000 这些东西是一行一行往下按顺序执行的。
再下面有个level_start,这是另一个函数的名字,写在这里意思就是叫level_start函数干活了。
再再下面是if (my_save_point eq 0),if是“假如、如果”的意思,括号里面eq表示“等于”,整句翻译过来就是 如果“my_save_point”等于0,就执行后面的括号{}里面的内容。my_save_point最早出现在这个文件的开头部分,在main函数的外面,是这么写的:
var int my_save_point;
var 表示有一个东西,数值和内容是可以变的;int,是my_save_point这个东西的类型,简单理解为整数吧;my_save_point,这个东西的名字。整句翻译过来就是:有个叫“my_save_point”的东西,是一个整数。然后在main函数中这个my_save_point = save_point就是让my_save_point的值等于存档点的数字。
每个函数的内容都要用{}括起来,格式写错的话就可能会出错了。
以前coool大写过一个教程,就是直接用main函数编完整个关卡流程的,不过原版中一般不这么做,原版里的main只要做好开头一点事情就由别的函数接班了。
http://tieba.baidu.com/p/500912982 coool大的教程。


IP属地:广西1楼2012-11-13 19:14回复
    particle_scripts.bsl
    各种控制粒子效果的函数一般就放在这里,比如下雨、下雪、门锁的灯的颜色、剧情中的一些爆炸效果等等。
    lab_cutscene.bsl
    过场动画一般放这里,有点复杂,最好有点基础了再来看。
    lab_level_logic.bsl
    这个就是关卡的大体流程了,那个level_start就在这里,出敌人的顺序、存档命令、胜利、失败什么的都在这文件,这个文件的函数应该比其它3个要多。不过函数不会无缘无故执行,除了main函数外,其它的要么是被触发效果触发(暂不讨论),要么是被别的正在执行的函数催起来干活,因为一开始只有main会被执行,所以这里用main来带出level_start,再由level_start带出别的函数。当然main函数可以带出不止1个函数。
    在main函数中,15行写了level_start,这样写的作用就是main函数执行到这行就停下手头的活,换level_start上场,等level_start完事儿了main再接下去做剩下的那几行,如果不想让main暂停,就要用fork level_start这样的写法。
    基础就这样了,看得懂格式就算入门了吧,剩下的就是熟悉各个命令了,找命令可以去ssg.oni2.net/commands.htm
    或者在游戏中按·叫出控制台,输入dump_docs,游戏会帮你保存一份所有命令和变量的txt文档在游戏文件夹下,叫script_commands.txt
    在游戏中的控制台输入命令有个小技巧,当打了个开头后系统会用灰色字补完后面的部分,按左右箭头可以切换灰字内容,找到想要的命令后按tap键确认即可马上输入完成,再按tap键可以换下一个命令,shift + tap可以换上一个。


    IP属地:广西2楼2012-11-13 20:30
    回复
      2025-12-24 22:22:54
      广告
      不感兴趣
      开通SVIP免广告
      感谢X客
      X客现在大几?


      3楼2012-11-14 21:58
      收起回复
        bsl里的大部分函数的括号里面都是void,但也有一些例外,会有(int flag, string char, float xxx)之类的内容,这个就跟上面的var int XXX类似,string是一串字母,或一串字母加数字,但不能是纯数字;float是数字,但可以带小数点,后面别超过7位小数。而括号里的这些这些数据只在这个函数使用,或者有这个函数交给别的函数用,其它函数不能直接使用这些数据。
        要修改bsl就得动动手,光看是是学不会的,下面咱们来模仿OTA做一个对战的bsl吧。
        规则很简单,就是分两个队,出兵对打,挂了的人换个地方重生接着打,当某方歹匕够一定人数了就算输。
        就拿梦境关的地图来做,先吧dream_lab文件夹中的文件清理掉,只留下dream_lab_main.bsl
        然后稍稍改下main函数:删掉24到27行的内容,也就是:
        if (my_save_point eq 0)
        {
        intro
        }
        然后开头的一堆var int的内容可以全删掉,留着也可以,只是它们都没用了。


        IP属地:广西4楼2012-11-15 18:11
        收起回复
          # 出了点差错,忘了给CPU回满血了……干脆重写!
          var int flags;
          # flag随机数,如果不设定数值,会被默认是0
          var int end_round = 1;
          # 判断是否结束战斗的数,随便给个初始值,满足条件后让它变化,再用if命令判断它是否变了,变了就结束战斗
          var int enemy;
          # 计算敌方被击败次数
          var int friend;
          # 计算我方被击败次数
          func void randflag(void)
          {
          # 这函数是让flags这个数不断变化;
          flags = flags + 1;
          # flags增加1;
          if(flags > 15) flags = 0;
          # flags大于15时就变0;
          sleep 1; # 等待1帧,等待时间越短,变化越快,这里60帧是1秒
          fork randflag
          # 重复这个函数;
          }
          func void GoWhere(string name)
          {
          # 传送角色的函数
          if(flags eq 0) chr_teleport(name, 0); # 根据flags的值的变化来传到不同的flag;
          if(flags eq 1) chr_teleport(name, 5);
          if(flags eq 2) chr_teleport(name, 7);
          if(flags eq 3) chr_teleport(name, 14);
          if(flags eq 4) chr_teleport(name, 19);
          if(flags eq 5) chr_teleport(name, 23);
          if(flags eq 6) chr_teleport(name, 31);
          if(flags eq 7) chr_teleport(name, 34);
          if(flags eq 8) chr_teleport(name, 37);
          if(flags > 8) chr_teleport(name, 5); # flags大于8就传去5,因为我不想写太多flag了- -;
          chr_animate(name, KONCOMsuper_kick); # OTA经典动作;
          }
          func void spawn_ai(string name, string team, int flag)
          {
          # 函数名随便起,我这里叫spawn_ai;
          ai2_spawn(name, force); # 这个命令用来生成角色,而且是强制的;
          chr_changeteam(name, team); # 改变所属队伍;
          chr_unkillable(name, 1); # 让角色变成打不si死;
          chr_teleport(name, flag); # 传去指定地点;
          fork respawn(name, team); # 没spawn_ai什么事了,换另一个函数上;
          # 这个函数用到的数据name和team就这样传给下一个函数
          }
          # 函数结束,不要忘了格式要完整,写错一点都不行;
          func void respawn(string name, string team)
          {
          chr_inv_reset(name); # 没收他所有武器、物品;
          chr_wait_health(name, 1); # 当角色只剩下1血时;
          fork score(team); # 呼叫一个用来计分的函数,后面再写;
          chr_pain(name, death); # 让他惨叫;
          chr_givepowerup(name, invis, -1); # 让他隐形;
          sleep 60
          # 等待1秒;
          GoWhere(name)
          # 传去随机一处;
          chr_full_health(name); # 给他回血;
          fork respawn(name, team); # 重复这个函数,再次等他只剩1血。
          }
          # 下面是计分函数;
          func void score(string team)
          {
          dmsg "[r.Someone has been slayed...]"
          if(team eq Syndicate) enemy = enemy + 1;
          # 如果是敌人,击破敌方数+1
          if(team eq TCTF) friend = friend + 1;
          # 如果是友军,被击破数+1
          if(enemy eq 10) end_round = 0;
          # 击破数到10时,end_round变成0
          if(friend eq 10) end_round = 0;
          # 被击破数到10时,end_round变成0
          if(end_round eq 0) fork end_fight
          # 如果end_round为1,执行判断胜负的函数
          }
          # 下面是判断胜负的函数
          func void end_fight(bool win)
          {
          ai2_allpassive 1
          # 都停下来别打了
          if(enemy > friend) dmsg "[y. NI YING LE!]"
          # 如果敌军伤亡更大,显示你赢了
          if(enemy < friend) dmsg "[y. NI SHU LE!]"
          # 反之显示你输了
          if(enemy eq friend) dmsg "[y. PING JU!]"
          # 一样的话,平局
          }
          # 好了,接下来写开始战斗的,就叫start吧,因为main函数最后呼叫了一个叫start的函数
          func void start(void)
          {
          env_show 1976 0
          # 隐藏毒液池的水面,不然到处都看得到它
          sound_dialog_play c03_10_01barabas
          # 来一句巴拉巴斯的台词
          fork randflag
          chr_teleport(0, 7); # 送主角去7号flag;
          chr_changeteam konoko TCTF
          # 主角加入TCTF
          spawn_ai IntroMuro Syndicate 5
          # 制作名叫IntroMuro的敌人,队伍是Syndicate,并把他送去5号flag
          spawn_ai griffin TCTF 7
          # 来个友军,添加人物就这么简单,我只加两个人,想添加更多人就自己动手吧
          }
          # 然后改造一下you_lose函数,让主角可以重生
          func void you_lose(void)
          {
          fork score(TCTF); # 计分,按TCTF队的牺牲来算
          sleep 180
          chr_full_health 0
          # 主角回满血
          GoWhere(konoko)
          # 送主角去随机flag
          }
          # 熟悉了这个bsl后,下次咱们在这个的基础上加随机武器和道具


          IP属地:广西7楼2012-11-16 03:41
          收起回复
            可以先从基础说起 比如只考虑ai出现的情况:清空任意一个关卡下的目录文件,建立一个后缀为.bsl的文本 写好主体部分后直接写人物出现情况 首先移动自己的坐标 例如chr_teleport xxx 0 然后设置血量 chr_set_health xxx 100 之后不断刷人 ai2_spawn xxx chr_teleport xxx 0 如果要讨论刷人的先后顺序 就要设置等待命令:chr_wait_health xxx 100 即剩下100hp时下面的命令才会生效 这样就能一个一个的出来 总之一个简单的敌人轮流出现的关卡就能完成 当然这是不考虑其他环境的情况下的最简单的方法


            IP属地:山东来自手机贴吧8楼2012-11-16 11:41
            收起回复