饥荒联机版mod制作[科技树、原型/制作站、配方]

一、添加模组科技树

1.1  调用

添加新科技树的原理是向“techtree”表中插入新的科技树,所以需要调用“techtree”

local TechTree = require("techtree")

1.2  修改科技树的生成方式

table.insert(TechTree.AVAILABLE_TECH, "SAKURA_TECH")	--添加新科技树名称

local Create_old = TechTree.Create
TechTree.Create = function(t, ...)
	local newt = Create_old(t, ...)
	newt["SAKURA_TECH"] = newt["SAKURA_TECH"] or 0
	return newt
end

1.3  三类等级

1.4及之后的步骤需要我们先了解并区分这三类等级:

1.3.1  制作等级

制作等级是配方制作时的需求水平,通常一个配方的制作等级只会需求一个科技等级。

1.3.2  解锁等级

解锁等级是科技站所能解锁的全部科技的水平,一个科技站可以解锁多个科技等级。(如枝江往事——奇特的构造体)

1.3.3  科技等级

科技等级是一种度量单位,他是制作等级与解锁等级之间的桥梁。

1.4  创建新制作等级

TECH.NONE.SAKURA_TECH = 0
TECH.SAKURA_TECH_ONE =   { SAKURA_TECH = 1 }
-- TECH.ELECOURMALINE_TWO = { SAKURA_TECH = 2 } 
-- 解锁等级中间隔一个等级,能使当前无法解锁的科技不会显示出来
TECH.SAKURA_TECH_THREE = { SAKURA_TECH = 3 }

此处,

TECH.SAKURA_TECH_ONE即为“AddRecipe2”中所使用的制作等级;

{ SAKURA_TECH = 1 }即为制作等级的等级标志,与后面的解锁等级的等级标志为同一数据,用于将制作等级与解锁等级对应起来。

注意:如果modmain函数中没有下面的神奇咒语,则这里的TECH不能直接使用,而需要调用GLOBLE:

-- 神奇咒语
GLOBAL.setmetatable(env, {__index = function(t, k) return GLOBAL.rawget(GLOBAL, k ) end})

-- 如果没有神奇咒语,则需要下面的语句才能使用TECH
local _G = GLOBLE
_G.TECH.NONE.SAKURA_TECH = 0

--或者直接
GLOBLE.TECH.NONE.SAKURA_TECH = 0

1.4  创建新解锁等级

-- TUNING.PROTOTYPER_TREES中存储的是科技站所能解锁的科技等级,这里先将所有科技站所能解锁的新科技等级都初始化为0
for _, v in pairs(TUNING.PROTOTYPER_TREES) do
    v.SAKURA_TECH = 0
end

TUNING.PROTOTYPER_TREES.SAKURA_TECH_ONE = TechTree.Create({ SAKURA_TECH = 1 })
TUNING.PROTOTYPER_TREES.SAKURA_TECH_THREE = TechTree.Create({ SAKURA_TECH = 3 })

如果科技站的解锁等级为TUNING.PROTOTYPER_TREES.SAKURA_TECH_ONE,则这个科技站能解锁的科技等级为{ SAKURA_TECH = 1 }。

这个表可以包含多个科技等级,从而实现一个科技站可以解锁多个科技等级,如:

TUNING.PROTOTYPER_TREES.SAKURA_TECH_THREE = TechTree.Create({ 
    SAKURA_TECH = 1, 
    SAKURA_TECH = 3
})

当我们对科技站的需求不是那么复杂时,完全可以仅用一个科技等级。

1.5  修改不需要新科技就能解锁的配方的科技需求

--如果v.level.SAKURA_TECH == nil,则说明该配方无需新科技就能解锁,将科技等级值设置为0
for _, v in pairs(AllRecipes) do
	if v.level.SAKURA_TECH == nil then
		v.level.SAKURA_TECH = 0
	end
end

注意:这段代码务必在新增需要新科技的配方之前调用,避免原本需要新科技的配方的科技等级需求归0。

1.6  将未解锁的配方显示在制作栏

if not TheNet:IsDedicated() then
	local craftingmenu_widget = require "widgets/redux/craftingmenu_widget"

	local ApplyFilters_old = craftingmenu_widget.ApplyFilters
	craftingmenu_widget.ApplyFilters = function(self, ...)
		if
			(self.current_filter_name == "SAKURA_BOOK") and
			CRAFTING_FILTERS[self.current_filter_name] ~= nil
		then
			self.filtered_recipes = {}
			local filter_recipes = FunctionOrValue(CRAFTING_FILTERS[self.current_filter_name].default_sort_values) or nil
			if filter_recipes == nil then
				return ApplyFilters_old(self, ...)
			end
			for i, recipe_name in metaipairs(self.sort_class) do
				local data = self.crafting_hud.valid_recipes[recipe_name]
				if data and filter_recipes[recipe_name] ~= nil then
					table.insert(self.filtered_recipes, data)
				end
			end
			if self.crafting_hud:IsCraftingOpen() then
				self:UpdateRecipeGrid(self.focus and not TheFrontEnd.tracking_mouse)
			else
				self.recipe_grid.dirty = true
			end
		else
			return ApplyFilters_old(self, ...)
		end
	end
end

将上面的“SAKURA_BOOK”改为需要显示的过滤器,也就是制作栏名称即可。

二、添加原型站/制作站

2.1  prefabs文件

在原型站/制作站实体的代码中加入原型组件,使其具有解锁等级:

inst:AddComponent("prototyper")
inst.components.prototyper.onturnon = onturnon  --打开时的函数
inst.components.prototyper.onturnoff = onturnoff  --关闭时的函数
inst.components.prototyper.onactivate = onactivate  --使用时的函数
inst.components.prototyper.trees = TUNING.PROTOTYPER_TREES.SAKURA_TECH_ONE  --设置解锁等级

2.2  modmain文件

2.1仅设置了原型站/制作站的解锁等级,但还不能使用。想要使用,就要为实体添加靠近后解锁科技功能:

AddPrototyperDef("sakura_book", --第一个参数是指玩家靠近时会解锁科技的prefab名
 { 
	icon_atlas = "images/sakura_book.xml",       --科技栏图标资源
    icon_image = "sakura_book.tex",
	is_crafting_station = true,                  --是否为制作站
	action_str = "SAKURA_BOOK",                  --建造时显示的文字
	filter_text = "小樱的魔法书",                --鼠标悬浮在制作栏(过滤器)时的文字
})

设置is_crafting_station = true时,该机器为制作站,左上角会出现相应的制作栏;

设置is_crafting_station = false时,该机器为原型站,左上角不会出现相应的制作栏。

此时打开的制作栏会自动显示:

1.需要该制作站科技才能解锁

2.只能在制作站附近制作

的配方,当且仅当配方同时满足上面两个条件时,才会出现在这个制作栏。

 三、添加制作栏(过滤器)

如果想要平常就能找到这一配方,就需要添加一个过滤器,也就是我们常说的“制作栏”:

AddRecipeFilter({--添加自定义的过滤器(即新的制作栏)
	name = "SAKURA_BOOK",	            --独一无二的过滤器名
	atlas = "images/sakura_book.xml",	--原始贴图54x54像素,64x64的也会默认缩放成54x54
	image = "sakura_book.tex",
    custom_pos = true
})
STRINGS.UI.CRAFTING_FILTERS.SAKURA_BOOK ="小樱的魔法书" 

AddRecipeFilter中的常用变量说明如下:

  • name (string): 过滤器的ID。主要用于两处,一是 STRINGS.UI.CRAFTING_FILTERS[name]。赋值给出在UI界面上显示的过滤器名字,二是在其它API使用过滤器作为参数时用于指代。
  • atlas (string 或 function): 图标的图集,可以是字符串或函数。
  • image (string 或 function): 显示在制作菜单中的图标,可以是字符串或函数。
  • (可选) image_size (table): 自定义图像尺寸,默认64。
  • (可选) custom_pos (table): 自定义的过滤器位置,默认为false。 如果为 true,则过滤器图标不会被添加到网格中,而是把这个分类下的物品都放在mod物品分类下。 

 此时制作栏内还没有任何配方,若想添加配方到这个制作栏,有以下两种方法:

3.1  添加已有配方到制作栏

--第一个参数为配方名称,第二个参数为过滤器名称
AddRecipeToFilter("sakura_card","SAKURA_BOOK")

3.2  添加新配方到制作栏

AddRecipe2(
    "sakura_pinkcard",                       --配方名称
    --配方(如果使用mod物品则需要注册图片)
    {Ingredient("pink_gem", 1,"images/pink_gem.xml",nil,"pink_gem.tex"),    
    Ingredient("sakura_card", 1,"images/sakura_card.xml",nil,"sakura_card.tex")},
    TECH.SAKURA_TECH_ONE,  --所需科技
    {
        nounlock = true,   --是否可解锁,即制作一次后永久解锁,true为不可解锁,false为可解锁
        numtogive = 2      --一次制作的数量,默认为1 
        atlas="images/sakura_pinkcard.xml",  --配方图
        image="sakura_pinkcard.tex",   
        product="pink_gem"                   --产品,默认产品即为配方名称
    },
    {"WEAPONS","SAKURA_BOOK"}                --添加到过滤器(制作栏)
)

注意:如果在添加制作栏之前添加了使用该制作栏的配方,则配方中添加的制作栏无效

 四、全部代码

上面除为原型站/制作站实体添加原型站/制作站组件的代码应添加到对应实体中,其余代码均应严格按顺序添加到modmain中。

如果想使modmain界面简捷,使用“modimport(“scrips/文件名”)”将代码移动到scrips文件夹下的“文件名.lua”中,可按喜好将代码转移到多个文件中,但一定要保证调用顺序不变!

所有modmain代码如下:


local TechTree = require("techtree")

--------------------------------------------------------------------------
--[[ 修改默认的科技树生成方式 ]]
--------------------------------------------------------------------------

table.insert(TechTree.AVAILABLE_TECH, "SAKURA_TECH")	--其实就是加个自己的科技树名称

local Create_old = TechTree.Create
TechTree.Create = function(t, ...)
	local newt = Create_old(t, ...)
	newt["SAKURA_TECH"] = newt["SAKURA_TECH"] or 0
	return newt
end



--------------------------------------------------------------------------
--[[ 制作等级 ]]
--------------------------------------------------------------------------

TECH.NONE.SAKURA_TECH = 0
TECH.SAKURA_TECH_ONE = { SAKURA_TECH = 1 }
-- _G.TECH.ELECOURMALINE_TWO = { SAKURA_TECH = 2 } --解锁等级中间隔一个等级,能使得没法解锁时,不会显示出来
TECH.SAKURA_TECH_THREE = { SAKURA_TECH = 3 }

--------------------------------------------------------------------------
--[[ 解锁等级 ]]
--------------------------------------------------------------------------

for _, v in pairs(TUNING.PROTOTYPER_TREES) do
    v.SAKURA_TECH = 0
end

--ELECOURMALINE_ONE可以改成任意的名字,这里和TECH.ELECOURMALINE_ONE名字相同只是懒得改了
TUNING.PROTOTYPER_TREES.SAKURA_TECH_ONE = TechTree.Create({ SAKURA_TECH = 1 })
TUNING.PROTOTYPER_TREES.SAKURA_TECH_THREE = TechTree.Create({ SAKURA_TECH = 3 })

--------------------------------------------------------------------------
--[[ 修改全部制作配方,对缺失的值进行补充 ]]
--------------------------------------------------------------------------

for _, v in pairs(AllRecipes) do
	if v.level.SAKURA_TECH == nil then
		v.level.SAKURA_TECH = 0
	end
end

--------------------------------------------------------------------------
--[[ 显示不能解锁的配方 ]]
--------------------------------------------------------------------------

if not TheNet:IsDedicated() then
	local craftingmenu_widget = require "widgets/redux/craftingmenu_widget"

	local ApplyFilters_old = craftingmenu_widget.ApplyFilters
	craftingmenu_widget.ApplyFilters = function(self, ...)
		if
			(self.current_filter_name == "SAKURA_BOOK") and
			CRAFTING_FILTERS[self.current_filter_name] ~= nil
		then
			self.filtered_recipes = {}
			local filter_recipes = FunctionOrValue(CRAFTING_FILTERS[self.current_filter_name].default_sort_values) or nil
			if filter_recipes == nil then
				return ApplyFilters_old(self, ...)
			end
			for i, recipe_name in metaipairs(self.sort_class) do
				local data = self.crafting_hud.valid_recipes[recipe_name]
				if data and filter_recipes[recipe_name] ~= nil then
					table.insert(self.filtered_recipes, data)
				end
			end
			if self.crafting_hud:IsCraftingOpen() then
				self:UpdateRecipeGrid(self.focus and not TheFrontEnd.tracking_mouse)
			else
				self.recipe_grid.dirty = true
			end
		else
			return ApplyFilters_old(self, ...)
		end
	end
end

--------------------------------------------------------------------------
--[[ 添加制作站 ]]
--------------------------------------------------------------------------

AddPrototyperDef("sakura_book", { --第一个参数是指玩家靠近时会解锁科技的prefab名
	icon_atlas = "images/sakura_book.xml", icon_image = "sakura_book.tex",
	is_crafting_station = true,
	action_str = "SAKURA_BOOK", --台词已在语言文件中
	filter_text = "小樱的魔法书",
})

--------------------------------------------------------------------------
--[[ 添加配方 ]]
--------------------------------------------------------------------------

AddRecipe2(
    "sakura_pinkcard",
    {Ingredient("pink_gem", 1,"images/pink_gem.xml",nil,"pink_gem.tex"),
    Ingredient("sakura_card", 1,"images/sakura_card.xml",nil,"sakura_card.tex")},
    TECH.SAKURA_TECH_ONE,
    {
        nounlock = true,
        atlas="images/sakura_pinkcard.xml",
        image="sakura_pinkcard.tex",
        product="pink_gem"
    },
    {"WEAPONS","SAKURA_BOOK"}
)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值