Starbound mod制作教程(四) 来写lua啦!

你猜怎么着?原版居然没有acid状态,我惊了!

那我们写一个吧。。

按名称可以找到状态都放在了stats/effects里面,我们找一个大概差不多的看看,比如foodposion,里面三个文件,.animation .statuseffect .lua,前两个都是JSON,后面的是lua文件,lua是控制物品自定义逻辑的脚本。

惯例不管animation,打开statuseffect看看里面。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name" : "foodpoison",
"blockingStat" : "poisonStatusImmunity",

"effectConfig" : {},
"defaultDuration" : 60,

"scripts" : [
"foodpoison.lua"
],

"animationConfig" : "foodpoison.animation",

"label" : "Food Poisoning",
"icon" : "/interface/statuses/foodpoison.png"
}

貌似没什么难理解的,不懂的下面评论吧。
scripts一项指向了foodpoison.lua,那么该状态会使用该lua脚本的函数。我们打开看看。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function init()
animator.setParticleEmitterOffsetRegion("drips", mcontroller.boundBox())
animator.setParticleEmitterActive("drips", true)

script.setUpdateDelta(5)

self.tickDamagePercentage = 0.010
self.tickTime = 1.0
self.tickTimer = self.tickTime
end

function update(dt)
self.tickTimer = self.tickTimer - dt
if self.tickTimer <= 0 then
self.tickTimer = self.tickTime
status.applySelfDamageRequest({
damageType = "IgnoresDef",
damage = math.floor(status.resourceMax("health") * self.tickDamagePercentage) + 1,
damageSourceKind = "poison",
sourceEntityId = entity.id()
})
end

effect.setParentDirectives(string.format("fade=00AA00=%.1f", self.tickTimer * 0.4))
end

function uninit()

end

基本语法请参阅菜鸟教程,我也是半吊子,不会事无巨细地说明lua语法,只做简单解释。

  • init函数是该物品/道具/状态等等对象产生的时候调用的函数,你可以在屎大棒的各种lua脚本中看到这个函数名。uninit也是。这些函数具体参阅wiki的lua/Hooks/Quest页面
  • animator是一个公有模块,请参阅wiki或者starbound/doc/lua里的md文件说明。
  • script也是公有模块,其doc里的文件是updatablescript.md
  • self指的是自己。
  • update(dt)函数是每dt帧调用一次的函数。dt可以通过之前出现的setUpdateDelta来设置,单位是帧。这里面写的逻辑就是计时变量tickTimer初始等于tickTime,每次调用都会减去dt,然后等降到零的时候就执行一次后面的逻辑。
  • status是公有模块,参阅statuscontroller.md
  • effect也是公有模块,参阅statuseffect.md
  • 注意到status.applySelfDamageRequest的参数类型是个DamageRequest类型,遇到这种不知道里面应该写点啥的类型,参阅wiki的datatype页面

这个lua介绍到这里,不懂的评论区问。

ok那我们来做一个差不多的好了,也就是每次受伤害一定百分比。因此可以直接复制来用。那就复制整个foodpoison的文件去XSWL/stats/effects/acid,先改名为acid。然后打开acid.statuseffect开始修改。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"name" : "acid",
"blockingStat" : "poisonStatusImmunity",

"effectConfig" : {},
"defaultDuration" : 5,

"scripts" : [
"acid.lua"
],

"animationConfig" : "acid.animation",

"label" : "Food Poisoning",
"icon" : "/interface/statuses/acid.png"
}

懒得再搞一个对应免疫了,直接用poison的免疫好了。然后就是注意到还有个icon要做,一会别忘了。。

接下来改lua

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function init()
animator.setParticleEmitterOffsetRegion("drips", mcontroller.boundBox())
animator.setParticleEmitterActive("drips", true)

script.setUpdateDelta(5)

self.tickDamagePercentage = 0.050
self.tickTime = 1
self.tickTimer = self.tickTime
end

function update(dt)
self.tickTimer = self.tickTimer - dt
if self.tickTimer <= 0 then
self.tickTimer = self.tickTime
status.applySelfDamageRequest({
damageType = "IgnoresDef",
damage = math.floor(status.resourceMax("health") * self.tickDamagePercentage) + 1,
damageSourceKind = "acid",
sourceEntityId = entity.id()
})
end

effect.setParentDirectives(string.format("fade=d3ff00=%.1f", self.tickTimer * 0.4))
end

function uninit()

end

也没大改,修改了持续时间ticktime,伤害百分比,伤害类型acid,effect颜色为d3ff00,即一种偏黄的颜色。

其实到这里基本上可以用了,不过我们再看看animation文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
"particleEmitters" : {
"drips" : {
"enabled" : true,
"emissionRate" : 1.0,
"particles" : [
{
"particle" : {
"type" : "ember",
"size" : 1.0,
"color" : [30, 250, 30, 120],
"fade" : 0.9,
"destructionAction" : "shrink",
"destructionTime" : 0.8,
"position" : [0.0, 0.0],
"offsetRegion" : [0, 0, 0, 0],
"initialVelocity" : [0, -1.0],
"finalVelocity" : [0, -6],
"approach" : [0, 10],
"timeToLive" : 0.6,
"variance" : {
"initialVelocity" : [0.2, 0],
"size" : 0.5
}
}
}
]
}
}
}

这个JSON看起来很麻烦,我们先梳理下结构吧
particleEmitters下只有一个键值对,名字为drips。
drips下有三个键值对,enable emissionRate particles。
particles的值是个数组,不过里面只有一个对象。
这个对象里面有好多键值对,从type一直到variance,
其中variance的值还是个对象,里面有两个,initialVelocity和size。

想要更直观地看到JSON结构,可以去菜鸟教程在线JSON格式化工具里看,将其中的结构一个一个展开来看,应该更好理解。

那么不多解释啦,这里就说下这个type:ember,指的是particle目录下的粒子效果文件,其实ember这个就是个像素块。。剩下的顾名思义啦,不懂的评论。

我们修改一下。。等等貌似没啥好改的,这个动画效果也就是一堆像素块往下掉,然后有个初末y速度,同时在x上有个随机速度,作为acid的效果挺ok的。那么顶多改改颜色,和上面那个一样,这次换成RGB形式,是 [211, 255, 0, 120] 。保存。

接下来要做的就是制作一下炸弹爆炸的动画,并附加acid状态。