提供一个模板:
链接:https://pan.quark.cn/s/fbc0b43aa287 提取码:nFbt
这个模板包含了基础框架,一把武器和汉化部分.
将模板丢到游戏目录mods文件夹内,开始我们的第一步
图片制作分三部分:
武器被手持: \exported\swap_temp_myfirstsword\
武器在地面: \exported\ground_temp_myfirstsword\
武器在物品栏: \images\inventoryimages\xxx.tex
把anim文件夹里原来的两个zip删掉,我们先做手持部分(为了保证武器正确的被握在手部,这一部分我们用替换):
首先我们确定武器名字,例如:mybat
将exported目录下的swap_temp_myfirstsword更名为swap_mybat
将exported\swap_mybat目录下的文件夹swap_temp_myfirstsword更名为swap_mybat
将exported\swap_mybat\swap_mybat\目录下的图片文件名中的temp_myfirstsword改成mybat
将exported\swap_mybat目录下scml文件更名为swap_mybat.scml并用类似notepad++的软件编辑它,搜索所有temp_myfirstsword,全部替换为mybat
将exported\swap_mybat\swap_mybat\swap_mybat-0.png用PS打开,将事先准备好的武器图片丢进去调整好手持位置,再删掉原图保存一下即可(图层大小请勿修改)
地面图片就不用那么讲究了:
将exported\下的ground_temp_myfirstsword更名为ground_mybat,文件夹内东西删掉,把事先准备的图片丢进去
打开spriter,ctrl+N新建项目,将目录粘贴好(…\steam\steamapps\common\Don't Starve Together\mods\mybat\exported\ground_mybat</span>),
将右上角出现的图片拖进中间工作区域,稍微调整下位置到十字线偏下,在拖动图片上的红点到刀柄位置
将右下动画窗格的entity_000改成武器名字mybat,NewAnimation改成idle(这是约定俗成的东西)
保存,文件名mybat.scml
物品栏图片:
打开\images\inventoryimages\
将xml文件更名为mybat.xml,打开将里面的temp_myfirstsword替换成mybat,保存
ps打开png文件,将图片放进去,调整好保存
打开textool,勾上Pre-multiply Alpha,将png转换成tex,记得更名为mybat.tex
到此为止图片部分全部结束
代码部分就非常简单了(全是替换,会就别看了):
将\scripts\prefabs\,目录下的lua文件更名,比如叫study_mybat,打开将里面所有temp_myfirstsword替换成mybat保存
打开modmain,将PrefabFiles = {}里面的temp_myfirstsword(这个就是上面prefabs文件夹下的文件名)替换成study_mybat保存
下面我们还要做一个汉化部分:
打开modmain,替换
1TUNING.CONFIG_TEMP_MYFIRSTSWORD_LANGUAGE = GetModConfigData("temp_myfs_language")
2modimport("scripts/util/temp_myfirstsword_chs.lua")
3modimport("scripts/util/temp_myfirstsword_en.lua")
为
1TUNING.CONFIG_MYBAT_LANGUAGE = GetModConfigData("mybat_language")
2modimport("scripts/util/mybat_chs.lua")
3modimport("scripts/util/mybat_en.lua")
再把
\scripts\util目录下的两个文件分别更名为mybat_chs.lua和mybat_en.lua
再分别打开这两个文件:
将TUNING.CONFIG_TEMP_MYFIRSTSWORD_LANGUAGE改成TUNING.CONFIG_MYBAT_LANGUAGE
将TEMP_MYFIRSTSWORD改成MYBAT
最后打开modinfo:
temp_myfs_language替换为mybat_language
(简单讲下上面这一大串: modimport可以给modmain添加文件,一个chs(汉化)一个en分开方便编辑,GetModConfigData是获取modinfo的配置信息,将它放到tuning表里,就可以用来判断用户选的是en还是chs了)
这代码替换部分看着很麻烦,让大家把名字全改了,主要目的是告诉大家抄的时候,最起码把名字改一改
而不是抄完了之后,mod做好上传工坊,发个简介:本mod可能与xxx mod不兼容.
维护社区环境,从我做起
最后打开游戏,等待两个动画文件自动生成完毕就ok了
控制台c_give("mybat")获取
modimport("scripts/util/mybat_recipes.lua")
为制作栏添加图片:
在images\中添加一个128x128的"mybattab.tex"图片,再拷一个xml过来就ok了
打开mybat_recipes.lua:
1local Ingredient = GLOBAL.Ingredient
2local TECH = GLOBAL.TECH
3local RECIPETABS = GLOBAL.RECIPETABS
4
5RECIPETABS.MYBAT_TAB = {str = "MYBAT_TAB", sort = 999, icon = "mybattab.tex", icon_atlas = "images/mybattab.xml"}
6
7local mybat_recipe = AddRecipe("mybat",
8{GLOBAL.Ingredient("log", 2), GLOBAL.Ingredient("goldnugget", 1), GLOBAL.Ingredient("rope", 1)},
9RECIPETABS.MYBAT_TAB, TECH.SCIENCE_ONE,
10nil, nil, nil, 1, nil,
11"images/inventoryimages/mybat.xml", "mybat.tex")
1local mybatlvlup = Class(function(self, inst)
2 self.inst = inst
3
4 self.level_mybat = 0 --武器基础等级
5 self.updmg = 0 --面板增加值
6end,
7nil,
8{
9})
10----save&load
11function mybatlvlup:OnSave()
12 local data = {
13 level_mybat = self.level_mybat,
14 updmg = self.updmg,
15 }
16 return data
17end
18function mybatlvlup:OnLoad(data)
19 self.level_mybat = data.level_mybat or 0
20 self.updmg = data.updmg or 0
21end
22----
23function mybatlvlup:DoDelta_level_mybat(delta)
24 self.level_mybat = self.level_mybat + delta
25end
26function mybatlvlup:calcupdmg() --设置伤害计算公式
27 self.updmg = math.floor(5*math.exp(math.log10(self.level_mybat)))
28end
29----
30return mybatlvlup
上面这就是一个最简单的component模板,看一下就懂,不逐句解释了.
下面我们在mybat的fn()下面为它添加这个成分:
inst:AddComponent("mybatlvlup") --添加新成分
inst:AddComponent("trader") --添加trader使其能接受可交易物品
inst.components.trader:SetAbleToAcceptTest(itemstype)
inst.components.trader.onaccept = OnGetItems
inst:DoTaskInTime(0, function()
applylevel(inst)
end)
看下itemstype,OnGetItems,applylevel怎么写:
1local function applylevel(inst) --设置武器面板的函数
2 inst.components.mybatlvlup:calcupdmg()
3 inst.components.weapon:SetDamage(31+inst.components.mybatlvlup.updmg)
4end
5
6local function itemstype(inst, item)
7 if item.prefab == "goldnugget" or item.components.tradable.goldvalue > 0 then
8 return true --物品是黄金或黄金价值大于0时才能接受
9 end
10 return false
11end
12
13local function OnGetItems(inst, giver, item)
14 local level_mybat = inst.components.mybatlvlup.level_mybat
15 if item.prefab == "goldnugget" then
16 inst.components.mybatlvlup:DoDelta_level_mybat(1)
17 applylevel(inst)
18 elseif item.components.tradable.goldvalue > 0 then
19 local igv = item.components.tradable.goldvalue
20 inst.components.mybatlvlup:DoDelta_level_mybat(igv)
21 applylevel(inst)
22 end
23end
scripts\components\mybatlvlup.lua:
1local mybatlvlup = Class(function(self, inst)
2 self.inst = inst
3
4 self.level_mybat = 0
5 self.updmg = 0
6
7 self.cc_basic = 0
8 self.cc = 5 --[5,30] 暴击率
9
10 self.cdm_basic = 0
11 self.cdm = 1.2 --爆伤乘数
12end,
13nil,
14{
15})
16----save&load
17function mybatlvlup:OnSave()
18 local data = {
19 level_mybat = self.level_mybat,
20 updmg = self.updmg,
21 cc_basic = self.cc_basic,
22 cc = self.cc,
23 cdm_basic = self.cdm_basic,
24 cdm = self.cdm,
25 }
26 return data
27end
28function mybatlvlup:OnLoad(data)
29 self.level_mybat = data.level_mybat or 0
30 self.updmg = data.updmg or 0
31 self.cc_basic = data.cc_basic or 0
32 self.cc = data.cc or 5
33 self.cdm_basic = data.cdm_basic or 0
34 self.cdm = data.cdm or 1.2
35end
36----
37function mybatlvlup:DoDelta_level_mybat(delta)
38 self.level_mybat = self.level_mybat + delta
39end
40function mybatlvlup:calcupdmg()
41 self.updmg = math.floor(5*math.exp(math.log10(self.level_mybat)))
42end
43
44function mybatlvlup:DoDelta_cc_basic(delta)
45 self.cc_basic = self.cc_basic + delta
46end
47function mybatlvlup:calccc()
48 self.cc = 5 + math.floor(self.cc_basic/10) --每10个cc_basic增加1%暴击率
49end
50
51function mybatlvlup:DoDelta_cdm_basic(delta)
52 self.cdm_basic = self.cdm_basic + delta
53end
54function mybatlvlup:calccdm() --爆伤乘数提升公式,用的是log函数,这样提升空间没有上限,但是越往后越难升
55 self.cdm = math.floor(((math.log10(self.cdm_basic+1)/math.log10(5))+1)*10)/10
56end
57----
58function mybatlvlup:ch(attacker,target,max)
59 if math.random(0,max) <= self.cc then --随机一个0到100的数,小于cc则暴击
60 local wp_panel = 31 + self.updmg
61 local fin_dmg = wp_panel * self.cdm
62 local bonus_dmg = fin_dmg - wp_panel
63 target.components.combat:GetAttacked(attacker, bonus_dmg)
64 --[[这一段我们是要放到武器攻击onattack里触发的,所以GetAttacked可以看成追加伤害
65 追加伤害 = 武器面板*爆伤乘数 - 武器面板
66 下面添加了一个暴击音效和动画
67 ]]
68 if attacker.SoundEmitter and attacker.components.talker then
69 attacker.SoundEmitter:PlaySound("dontstarve/common/whip_large")
70 attacker.components.talker:Say("Critical Hit!".." \n ".." \n ".." \n ")
71 end
72 local chfx = SpawnPrefab("impact")
73 chfx.Transform:SetScale(math.random(1,5), math.random(1,5), math.random(1,5))
74 chfx.Transform:SetPosition(target.Transform:GetWorldPosition())
75 end
76end
77----
78return mybatlvlup
预制物这边很简单:
1local function itemstype(inst, item)
2 if item.prefab == "goldnugget" or item.components.tradable.goldvalue > 0 then
3 return true
4 end
5 if item.prefab == "honey" and inst.components.mybatlvlup.cc_basic < 250 then return true end
6 if item.prefab == "dragon_scales" then return true end
7 return false
8end
9
10local function OnGetItems(inst, giver, item)
11 local level_mybat = inst.components.mybatlvlup.level_mybat
12 if item.prefab == "goldnugget" then
13 inst.components.mybatlvlup:DoDelta_level_mybat(1)
14 applylevel(inst)
15 elseif item.components.tradable.goldvalue > 0 and item.prefab ~= "honey" and item.prefab ~= "dragon_scales" then
16 local igv = item.components.tradable.goldvalue
17 inst.components.mybatlvlup:DoDelta_level_mybat(igv)
18 applylevel(inst)
19 end
20
21 if item.prefab == "honey" then
22 if inst.components.mybatlvlup.cc_basic < 250 then
23 inst.components.mybatlvlup:DoDelta_cc_basic(1)
24 inst.components.mybatlvlup:calccc()
25 if giver.components and giver.components.talker then
26 giver.components.talker:Say("Critical Chance: "..inst.components.mybatlvlup.cc.."%",2,true)
27 end
28 end
29 end
30
31 if item.prefab == "dragon_scales" then
32 inst.components.mybatlvlup:DoDelta_cdm_basic(5)
33 inst.components.mybatlvlup:calccdm()
34 if giver.components and giver.components.talker then
35 giver.components.talker:Say("Critical Dmg Mult: "..inst.components.mybatlvlup.cdm,2,true)
36 end
37 end
38end
39
40inst.components.weapon.onattack = onattack --别忘了加这句
41local function onattack(inst, attacker, target)
42 inst.components.mybatlvlup:ch(attacker,target,100)
43end
由于"dragon_scales"没有可交易component,我们要在modmain里面添加:
1--trade
2local mybatcouldtradetab = {
3 "dragon_scales",
4}
5local function couldtrade( inst )
6 if inst.components and inst.components.tradable then
7 else
8 inst:AddComponent("tradable")
9 end
10end
11for k,v in pairs(mybatcouldtradetab) do
12 AddPrefabPostInit(v, couldtrade)
13end
1local function onkillmybat(inst, data)
2 local victim = data.victim
3 local victim_pos = victim:GetPosition()
4 local killregenmul = 0.01
5 ----killregen
6 if victim.components.health ~= nil then
7 if inst:HasTag("mybat_allowmekillregen") then --如果持有者有Tag,则才能击杀回复
8 local victim_hp = math.ceil(victim.components.health.maxhealth)
9 local killregen = math.ceil(victim_hp*killregenmul)
10 if killregen >= 1 then
11 inst.components.health:DoDelta(killregen) --击杀回复怪物血量1%的hp
12 else
13 inst.components.health:DoDelta(1)
14 end
15 end
16 end
17end
18local function onequip(inst, owner)
19 owner.AnimState:OverrideSymbol("swap_object", "swap_mybat", "swap_mybat")
20 owner.AnimState:Show("ARM_carry")
21 owner.AnimState:Hide("ARM_normal")
22 if inst:HasTag("mybat_allowkillregen") then --装备该武器时判断其是否已解锁能力,是则给持有者一个Tag,并让持有者监听"killed"击杀事件
23 if not owner:HasTag("mybat_allowmekillregen") then
24 owner:AddTag("mybat_allowmekillregen")
25 end
26 owner:ListenForEvent("killed", onkillmybat)
27 end
28end
29
30local function onunequip(inst, owner)
31 owner.AnimState:Hide("ARM_carry")
32 owner.AnimState:Show("ARM_normal")
33 if owner:HasTag("mybat_allowmekillregen") then --卸除该武器,移除持有者的Tag,移除监听的事件函数
34 owner:RemoveTag("mybat_allowmekillregen")
35 end
36 owner:RemoveEventCallback("killed", onkillmybat)
37end
38
39local function itemstype(inst, item)
40 if item.prefab == "x" and not inst:HasTag("mybat_allowkillregen") then
41 return true
42 end
43 return false
44end
45
46local function OnGetItems(inst, giver, item)
47 if item.prefab == "x" then
48 inst:AddTag("mybat_allowkillregen")
49 local handswp = giver.components.inventory:GetEquippedItem(EQUIPSLOTS.HANDS)
50 if giver.components and giver.components.talker then
51 giver.components.talker:Say("unlock Kill Regen",3,true)
52 end
53 if handswp and handswp:HasTag("mybat_allowkillregen") then
54 giver:AddTag("mybat_allowmekillregen")
55 giver:ListenForEvent("killed", onkillmybat)
56 end
57 end
58 --[[这里原本代码是这样写的:
59 if item.prefab == "x" then
60 inst:AddTag("mybat_allowkillregen")
61 giver:AddTag("mybat_allowmekillregen")
62 giver:ListenForEvent("killed", onkillmybat)
63 end
64 但是这样写有个问题:
65 如果把mybat先卸下,装备另一把武器,那么给mybat一个"x"后,玩家依旧会解锁击杀回复能力,并直到下次装备mybat并卸下之前,能力都不会消失
66 所以修改后的代码:
67 获取一次玩家的手部物品,如果手部物品是有击杀恢复Tag的"mybat",那么才给玩家解锁该能力
68 ]]
69end
再加个save和load就大功告成了:
1inst.OnSave = onsave
2inst.OnLoad = onload
3local function onsave(inst, data)
4 if inst:HasTag("mybat_allowkillregen") then
5 data.mybat_allowkillregen = true
6 end
7end
8local function onload( inst,data )
9 if data and data.mybat_allowkillregen then
10 inst:AddTag("mybat_allowkillregen")
11 end
12end
1function mybatlvlup:stun(target,attacker)
2 if target.brain and target.components.combat and target.components.locomotor and not target:HasTag("mybat_stun") and math.random(1,100) <= self.stun then
3 target:AddTag("mybat_stun")
4
5 SpawnPrefab("lightning_rod_fx").Transform:SetPosition(target.Transform:GetWorldPosition())
6
7 target.components.locomotor:Stop()
8 target.brain:Stop()
9
10 target:DoTaskInTime(2,function(target)
11 target.brain:Start()
12 target:RemoveTag("mybat_stun")
13 end)
14 end
15end