文明5mod吧 关注:2,318贴子:6,506
  • 7回复贴,共1

从零开始做MOD(六)

只看楼主收藏回复

上一篇:http://tieba.baidu.com/p/3379426404
上次提了一下XML的相关写法,这次介绍SQL的相关写法
SQL写法至少没有XML看上去直观,不过正如之前所说,SQL和XML很多时候所做的事情是类似的:XML语句会先转换成SQL语句,然后操作数据库。
就结论而言,做一个MOD,SQL并不是必须的。所以这里假定大家懂一点SQL语言,和基本的编程思想。


IP属地:浙江1楼2014-11-12 16:09回复
    上次提过,C5运行时的数据库在这里:

    文明5运行时的静态文本游戏数据大部分是保存在数据库中的,比如你新定义的文明、单位、建筑、设施等等。素材文件,比如图片、音频、lua脚本不在其中,这类关系型数据库也很少用来保存多媒体文件。
    当然理论上既然是数据库,运行的时候也能更改,不过多数情况下还是以查询为主。
    当你运行游戏后,那么长的loading时间基本就是在建立这些数据库;而对于MOD,选择并加载后也有很长的loading时间,基本也是在根据你写的XML和SQL等修改数据库(当然也会加载一些别的媒体文件,我没研究过)。
    对于做MOD而言,最重要的一个数据库文件是Civ5DebugDatabase.db,MOD对游戏所做的修改几乎集中体现在这里。
    文明5用的数据库引擎是sqlite,你可以随便上网找个数据库查看软件看里面的东西,据说firefox还有个插件能直接打开本地数据库,作为一只Chrome狗我表示压力甚大。

    比如这里Traits表的最后一条记录,就是由MOD的相关XML语句生成,进而修改了数据库。这些上次都有提过,不再赘述。


    IP属地:浙江2楼2014-11-12 16:21
    收起回复
      如果不使用事务处理的话,一个SQL文件会依次执行里面的每行SQL语句,直到执行完或者出错(语法错或者执行出错都一样),这和XML是不同的——后者大概是翻译成了一套事务,一旦出错会回滚。
      与XML相比,用SQL操作数据库相对来说灵活一些。当然XML也有优势,比如要插入一列很长的数据,XML看起来很规则

      虽然长了一些,不过表项和值的对应关系还是很明确的;而如果用SQL写:

      就很乱了
      尽管如此,很多情况下用SQL还是能很大程度上精简你的代码。我对SQL基本也停留在小学生阶段,不过基本上也够用了。如果你想学SQL,最好自己找本书看。
      C5中最常用的SQL语句是insert ... values,比如你要新建一个UA,可以这么写:
      insert into Traits(Type, Description, ShortDescription) values(*TRAIT_FOO*, *TXT_KEY_TRAIT_FOO*, *TXT_KEY_TRAIT_FOO*);
      注意表项名且不论,你要插入的值,除了NULL,都要用单引号括起来。
      SQLITE对引号的处理很怪,C5用的版本也不是那么标准,反正最好用单引号了。
      你也可以一次插入很多数据,比如
      insert into Traits(Type, Description, ShortDescription) values
      (*TRAIT_FOO1*, *TXT_KEY_TRAIT_FOO1*, *TXT_KEY_TRAIT_FOO1*),
      (*TRAIT_FOO2*, *TXT_KEY_TRAIT_FOO2*, *TXT_KEY_TRAIT_FOO2*),
      (*TRAIT_FOO3*, *TXT_KEY_TRAIT_FOO3*, *TXT_KEY_TRAIT_FOO3*),
      (*TRAIT_FOO4*, *TXT_KEY_TRAIT_FOO4*, *TXT_KEY_TRAIT_FOO4*),
      (*TRAIT_FOO5*, *TXT_KEY_TRAIT_FOO5*, *TXT_KEY_TRAIT_FOO5*);
      据说标准的sqlite引擎不支持这种语法,但C5用的是可以的。
      有时候你会想根据已有的东西弄个新东西出来,比如想弄一个远古高达——名字、类型、造价、依赖科技和高达有些不同,那么你就可以先找到高达的定义:

      把它用到的列提取出来,然后写成SQL语句:

      这样你就可以根据高达的相关资料生成一个造价为1的远古高达。注意那个NULL,如果你要把某个值置空的话,是不能加引号的。
      另外SQLITE里实际是没有boolean类型的,如果某个值是真的话那么实际值为1,反之为0。所以不要写什么values(False)了。
      可能有人会问了:那我直接写成<Row>...</Row>或者insert into Units... values...,把具体的值写进去不好吗?
      这么写有几个好处。其一,你的代码避免了大量魔数;其二,你的数据必然和你当前的游戏数据是同步的
      例如你的MOD依赖于某个MOD,而这个MOD对高达进行了某些修改(比如把高达的攻击力增加到了250),那么你的高达的力量也会自动调整到250;当然,如果GK的高达力是150,BNW是250的话,那么你的高达在两个版本里也会不同,而不用多写代码。
      insert...select...可能会插入多行数据。举个例子,你想把未来主义的效果增加“生产空军单位时对所有文明增加300的影响力”,一行一行的写无疑是很累的,那么你可以简写为

      同样的,如果你依赖了某个MOD,而那个MOD里增加很多新空军单位,你的代码对那个MOD是自然生效的


      IP属地:浙江本楼含有高级字体3楼2014-11-12 21:04
      回复
        第二个常用的操作是update,这个用来修改某些已有的数据。比如你想直接把高达的造价改成1,前置科技去掉,那么就直接写

        update可以一次修改多行,比如你想把所有骑乘单位的造价都改成1,那么可以这么写:

        你也可以做一些比较复杂的操作,比如想把所有的UU成本都改成1,那么可以这么写:

        总之Sqlite还是蛮灵活的。多表联合查询我也不是很懂,这里就不多说了。
        第三个常用的操作是delete。比如你想把高达的铀限制去掉,可以这么写:

        还有些比如insert or replace, replace之类的我也不是很懂,想用的话大概自己看看就行了
        另外replace会删除原数据、产生一条新的数据,这和你的预期很可能是不同的,用的时候注意点


        IP属地:浙江4楼2014-11-12 21:24
        回复
          最后一个常用的操作是触发器。比如你写了一个MOD,让所有骑乘单位拥有某个特殊晋升;而你也想让其他引用这个MOD的子MOD的单位也自动拥有这个晋升,那么你可以这么写

          于是任何Units表的新条目被插入到数据库后都将自动执行begin和end间的语句,也就是说任何骑乘单位会获得这个特殊晋升。
          个人常用的SQL语句大概就这么几类,这里也只是简单介绍了下相关功能,具体用法请自己找本SQL教程看。
          除了插入固定数据,这里提到的大部分操作都是顺序敏感的。最典型的,比如你想根据已有的高达弄个远古高达,还有一条修改高达的语句修改了高达的力为10,那么
          1. 如果这个语句在前,那么你的高达力也是10
          2. 如果你的语句在前,那么你的高达力是150
          这些会导致一些很神奇的后果,最要命的是你不一定知道到底你的语句在前还是它的语句在前。不过有些顺序还是可以控制的:
          1. 同一个SQL里的语句,自然是顺序执行的
          2. 同一个MOD里的文件,会根据文件的加载顺序依次执行每个文件

          比如这里,RemoveCivs.sql这个文件必然在TouhouTechTweak.sql文件后执行
          3. 如果MOD1依赖MOD2,那么MOD2的代码必然在MOD1之前执行
          至于XML就很难说了。


          IP属地:浙江本楼含有高级字体5楼2014-11-12 21:39
          回复
            说一下如何调试XML和SQL,因为这些文件执行错了相关错误不会反应到控制台
            首先你要开启日志,自己看这个地址http://forums.civfanatics.com/showthread.p
            hp?t=487482
            然后去找这个文件

            然后就会发现一堆数据库报错

            值得一提的是这里截的图是未加载MOD前报的错,换句话说是游戏本身的报错。
            不清楚到底是因为我的游戏版本是D版,还是原版就这样,反正既然官方也出错,那作为modder出错也很正常
            除了致命错误外,C5会对外键进行检查,这个图里基本上都是外键错误。
            外键检查应该是在所有操作做完后逐表检查外键,而不是边操作边检查。
            当然外键错一般错就错了,执行反正是能执行下去的,所以它只是个warning而不是error。


            IP属地:浙江6楼2014-11-12 21:48
            回复
              楼主高才,文明5有没有武侠类的mod


              IP属地:河南来自Android客户端8楼2016-09-16 23:08
              回复