Mod:Lua腳本
基礎 |
---|
入門 • 基礎 • Lua腳本 • Data.wak • 實用工具 |
製作指南 |
音頻 • 敵人 • 生物群系 • 天賦 • 法術 • 精靈表 • 材料 • 圖像放射器 • 特殊行為 • CMake使用 |
組件/實體 |
組件文檔 • 枚舉 • 特殊標籤 • 所有標籤列表 |
Lua編程 |
Lua API • 實用腳本 |
其他信息 |
法術和天賦的ID • 聲音事件 • 魔數(Magic Numbers) |
為Noita mods編寫Lua腳本的基本信息和例子。請注意,腳本只是修改的一個組成部分,請務必閱讀ECS-實體組件系統(Entity Component System)有關內容。
Lua腳本基礎內容
init.lua
- 初見最好的文件
- 不需要覆蓋或者修改任何內容,這些內容都只作用於你的mod。
- 參見 模組修改基礎知識
data/scripts/gun/gun.lua
- 每一次使用法杖時都會被調用, 與引擎代碼高度交織在一起。
- 注意兼容性,如下所述
data/scripts/biomes/<biome_name>.lua
- 在進入生物群落時被調用一次
- 注意兼容性,如下所述
<LuaComponent>
- 可以掛載你的任意代碼的最佳與最常用的地方。
- 大多數其他的東西,你可以在
data/scripts/
找到,實際上是通過這個組件在某個實體中定義的。 - 見官方的
lua_api_documentation.txt
以了解如何通過該組件掛載不同行為。
以兼容的方式使用鈎子函數
當處理遊戲本身和其他MOD大量使用的普通腳本文件時,通過ModLuaFileAppend
函數對其進行附加可能是一個好主意,而不是簡單地通過data/
路徑覆蓋它。
如果每個模組製作者都這樣做,他們的代碼會根據玩家的mod加載順序被挨個強行覆蓋,只留下最後加載的那版文件。
-- 任何文件都可以被任何文件所附加,gun.lua只是一个例子。
-- *但*这只能在init.lua内进行。
ModLuaFileAppend("data/scripts/gun/gun.lua", "mods/mymod/files/gun.lua")
Lua說明與提示
受限的庫
一些默認的Lua庫被限制,不能在mod文件中運行。一個不完整的受限庫和函數的列表:
- IO
- OS
- require
這些庫的一些功能已經在Lua API中重新實現。
-- 你没法这样做
local file = require "/mods/MODNAME/files/somefile.lua"
-- 但是你可以这样
local file = dofile_once("/mods/MODNAME/files/somefile.lua")
-- 你没法这样做
local time = os.time()
-- 但是你可以这样
local year,month,day,hour,minute,second = GameGetDateAndTimeLocal()
local time = year .. month .. day .. hour .. minute .. second
因為沒有IO庫,在多局遊戲間保存持久性數據要困難得多。存儲持久數據的僅有兩種方法是使用Flag或mod_settings
文件。
腳本示例
獲取當前實體
local entity = GetUpdatedEntityID()
「當前實體」是指通過<LuaComponent>
(或其他類似觸發器)運行腳本的實體。不過並非所有腳本都是由實體運行的,例如init.lua
。
在上面的代碼片段中,獲得的實體可以是玩家、魔杖、投射物或者其他任何東西,這取決於腳本的運行位置。這是獲取當前運行的實體的最簡單方法,因此值得一提。
注意: 在data/scripts/gun/gun.lua
中這個函數會給你玩家實體。
獲取玩家實體
內置的utility腳本會返回一個玩家實體列表,所以我們必須經過一個小步驟才能得到單個玩家實體。
簡潔起見,下面的示例中省略了獲取玩家實體的操作。許多鈎子都已經能夠獲取玩家實體了,但這段代碼可以留作備用,如果它們失效了沒有返回玩家實體的話。
dofile_once("data/scripts/lib/utilities.lua")
function get_player()
local players = get_players()
if players then
return players[1]
end
-- 当找不到玩家(例如玩家死亡)时
return nil
end
local player = get_player()
獲取當前手持魔杖
dofile_once("data/scripts/gun/procedural/gun_action_utils.lua")
-- 可能适用于任何带有Inventory2Component的实体,例如一些敌人
local wand = find_the_wand_held(player)
獲取當前手持物品(包括魔杖)
function get_held_item(animal)
local inv_comp = EntityGetFirstComponentIncludingDisabled(
animal, "Inventory2Component"
)
-- 尽管这个组件应该永远存在,但是指不定会有人点炒饭
-- (比如另一个模组瞎搞把它搞没了之类的)
if not inv_comp then
return nil
end
return ComponentGetValue2(inv_comp, "mActiveItem")
end
-- 应该返回一个数字ID
local wand = get_held_item(player)
簡單地向物品欄中加入物品
-- 注意,玩家不是唯一具有物品栏的实体
function add_items_to_inventory(player, items)
for _, path in ipairs(items) do
local item = EntityLoad(path)
if item then
GamePickUpInventoryItem(player, item)
else
GamePrint("Error: Couldn't load the item ["..path.."]!")
end
end
end
function OnPlayerSpawned(player)
local items = {
"data/entities/items/pickup/thunderstone.xml",
}
add_items_to_inventory(player, items)
end
生成並啟用天賦
-- 天赋系统有点复杂,所以使用现成的函数
dofile_once("data/scripts/perks/perk.lua")
local perk = perk_spawn(x, y, "PROTECTION_RADIOACTIVITY")
-- 如果你只是想在世界中生成天赋,就把这部分去掉
if perk then
perk_pickup(perk, player, EntityGetName(perk), false, false)
end
生成其他大多數事物
-- 敌人
EntityLoad("data/entities/animals/duck.xml", x, y)
-- 黄金
EntityLoad("data/entities/items/pickup/goldnugget_200.xml", x, y)
只加載一次init.lua
即只在開始新遊戲時才加載,加載保存的已有遊戲時不會加載
local LOAD_KEY = "MYMOD_FIRST_LOAD_DONE"
function OnPlayerSpawned(player)
if GlobalsGetValue(LOAD_KEY, "0") == "1" then
return
end
GlobalsSetValue(LOAD_KEY, "1")
-- 你其他的代码可以继续放在这里
end
通過Lua發射一個投射物
dofile_once("data/scripts/lib/utilities.lua")
-- 根据你想要的发射规则,在此定义投射物发射的位置
-- 以及投射物的速度
shoot_projectile(player, "mods/mymod/files/projectiles/supernuke.xml", from_x, from_y, vel_x, vel_y)
要注意的是,用GameShootProject()
也可以完成此功能,但它需要幾行設置,而這段代碼中包含的utility函數已經幫你完成了這些設置。