前言

Gameplay相关部分

先用Lua做一个简单的mod,在文档\My Games\Sid Meier’s Civilzation VI\Mods下新建一个文件夹,然后在里面创建一个lua脚本文件(demo.lua)

要编写游戏脚本,首先必须要知道游戏接口(API),官方没有资料,以下是网友总结的:

在表格底下点击Events切换,文明6的脚步是事件驱动(当某一事件发生时,游戏自动调用我们准备好的函数),我们需要做的就是为事件创建一个函数(function)

  • 例如:事件ResearchCompleted是完成科技,参数包含玩家ID和科技序号

  • 假设要让我们每完成一项科技,都能获得100金币:

    1
    2
    3
    4
    5
    6
    7
    function OnResearchCompleted(iPlayerID, iTech)
    local pPlayer = Players[iPlayerID]
    pPlayer:GetTreasury():ChangeGoldBalance(100)

    end

    Events.ResearchCompleted.Add(OnResearchCompleted)

    具体可以看表格的Lua Objects部分(难免有错误的地方),所以最好去看官方文件,下面这是一款用来查询游戏自带文件的软件:

    https://www.mythicsoft.com/agentransack/

    具体操作如下,打开软件,在File name这里输入*.lua,表示所有后缀名为lua的文件,在Containing text一栏输入要搜索的字符串,选择搜索目录为文明6的游戏根目录,点击start开始搜索,即可找到游戏源文件中 所有包含该字符串的文件

    脚本写好之后,需要创建modinfo文件来加载

    前面的写法与其他mod类似

    接下来是Components部分,添加游戏脚步的操作

    最后是包含的全部文件,就做完了

    image-20240718133920362

利用官方工具调试

1.初步调试

利用官方提供的工具对代码进行调试,首先在游戏选项里面启用调谐器

然后打开官方的开发工具(Development Tools),在启动界面那里选择Fire Tuner(调谐器)

进入游戏后,左上角选择打开面板(Open Pannel)

进入Debug文件夹(在游戏根目录\Debug),其中

City.ltp是城市

Map.ltp是地图

Player.ltp是玩家

Unit.ltp是单位

Forge.ltp是界面

2.调节玩家数据

选一个和城市有关的举例,在空白的地方选择新的动作(New Action Control)

名字随便填,下面Action方框内就是测试代码的地方,输进来后点击测试点OK,如下图的输出结果就表明没有问题

最经常操作的lua对象就是以下四种,上面改金币的例子就是第一种

很多事件在触发的时候 会把玩家的ID给传递过来,于是就可以根据ID获得指定玩家,有的是获取单位的ID

可以参考lua手册检索常用功能:

3.调节单位数据

接下来对单位进行测试,获取单位根据玩家ID和单位ID,打开Unit文件,单人游戏本地玩家ID都是0,于是在代码框中如下输入即可

4.调节城市数据

接下来对城市进行测试,获取城市可以根据ID或者坐标,打开City文件,如下操作输出即可

  • 有一种显示浮动文本的方式如下:第一项填0,第二项是要显示的字符串,最后两个是坐标

5.调节单元格数据

接下来对单元格进行测试,通过坐标获取,根据格位可以查询上面的地貌资源等

还有常见判断,比如判断是不是平原、海洋等

6.其他和实例

除此之外还有3个全局表,它们不是类的实例,所以调用方法用的是点号,而不是冒号,具体写法参考文档

  • gameinfo是访问数据库用到的,接下来通过例子来介绍

    由下图可见,当城市建造完成会传递五个参数:

    第一个就是玩家的ID,根据ID获取所属的玩家,这一步经常要用到(即第二行):

    1
    2
    3
    4
    5
    6
    7
    function OnCityProdComp(playerID, cityID, iConstructionType, itemID, bCancelled)
    local pPlayer = Players[playerID]


    end

    Events.CityProductionCompleted.Add(OnCityProdComp)

    为了增强代码的健壮性,建议在这里判断结果是否为空,如果要判断是否是人类玩家的话就用IsHuman() 这个方法(第四行):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function OnCityProdComp(playerID, cityID, iConstructionType, itemID, bCancelled)
    local pPlayer = Players[playerID]

    if pPlayer:IsHuman()

    end

    end

    Events.CityProductionCompleted.Add(OnCityProdComp)

    第三个参数iConstructionType是建造的种类,0表示单位,1表示建筑或奇观,2表示区域,3表示项目

    我们来获取刚造好的这个单位,用到的是第四个参数(第四行):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function OnCityProdComp(playerID, cityID, iConstructionType, itemID, bCancelled)
    local pPlayer = Players[playerID]

    if pPlayer:IsHuman() and iConstructionType==0 then

    end

    end

    Events.CityProductionCompleted.Add(OnCityProdComp)

    用SQ Lite Studio打开数据库(操作在(4)中有),找到Units这个表,切换到数据选项卡,第四个参数其实就是表中的序号,比如0是开拓者,1是建造者,上面获取的结果相当于表中的第一行,然后通过点号来获取其中的具体内容(如下)

    同时此处也建议先判断结果是否存在

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    function OnCityProdComp(playerID, cityID, iConstructionType, itemID, bCancelled)
    local pPlayer = Players[playerID]

    if pPlayer:IsHuman() and iConstructionType==0 then
    local unit = Gameinfo.Units[itemID]

    if unit ~= nil then

    end

    end

    end

    Events.CityProductionCompleted.Add(OnCityProdComp)

    现在要确定添加的位置,,正好第二个参数就是城市的ID,接下来获取城市并找出它的坐标值(8-10),建议用第11行的这种方法来添加单位,它能把新的单位放到指定坐标上,放不下也会放在相邻位置,第一个参数是玩家ID,第二个是单位类型,第三个和第四个是横纵坐标,第五个是单位数量:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    function OnCityProdComp(playerID, cityID, iConstructionType, itemID, bCancelled)
    local pPlayer = Players[playerID]

    if pPlayer:IsHuman() and iConstructionType==0 then
    local unit = Gameinfo.Units[itemID]

    if unit ~= nil then
    local pCity = CityManager.GetCity(playerID, cityID)
    local iX = pCity:GetX()
    local iY = pCity:GetY()
    UnitManager.InitUnitValidAdjacentHex(playerID, unit.UnitType, iX, iY, 1)
    end

    end

    end

    Events.CityProductionCompleted.Add(OnCityProdComp) --只要任意城市完成一项建造就会触发