概要
前回、Lua実装で独自ギミックを追加しました。
実はもう1つだけ未実装の機能があるので、Luaでの実装を続けます。
ただし、今回はソース紹介とポイントのみの解説となります。1
※ 今回もLuaによる実装の解説になりますので、読み飛ばして頂いても構いません。
LuaによるMOD開発を進めたい方は、参考までにご参照ください。
1. 独自ギミックについて
撲殺バットは全部で3グレードあり、ティア1とティア2はレシピによるアップグレードで取得可能な仕様を実装しました。ただ、ティア3についてはレシピでの入手も無く、またレシピ本の時のような湧き設定もしていません。そこで、ティア3は「とある場所に固定で1つだけ湧く」といったギミックを実装したいと思います。
今回の湧きギミックは私が個人的に開発したものです。
これ以外の方法もあると思いますので、参考程度としてください。
2. アイテム固定湧きの実装
今回の独自ギミックは、前回のLuaファイルとは別のファイルに実装しました。
local P4BokusatsuBatSpawn = {}
P4BokusatsuBatSpawn.isEventAdded = false
P4BokusatsuBatSpawn.spawnList = {
-- [Bokusatsu Bat] Art Gallery of Louisville
{ id="bbt3", item="P4BokusatsuBat.P4BokusatsuBatT3", locx=12522, locy=1417, locz=2, x=1.0, y=1.0, z=0.85, r=0.0 },
}
-- *****************************************************************************
-- * ModData functions
-- *****************************************************************************
P4BokusatsuBatSpawn.getSpawnReserves = function()
local modData = ModData.getOrCreate("P4BokusatsuBatSpawn")
if not modData.spawnReserves then
modData.spawnReserves = {}
end
return modData.spawnReserves
end
P4BokusatsuBatSpawn.getReserveResults = function()
local modData = ModData.getOrCreate("P4BokusatsuBatSpawn")
if not modData.reserveResults then
modData.reserveResults = {}
end
return modData.reserveResults
end
P4BokusatsuBatSpawn.reserveSpawn = function()
local spawnReserves = P4BokusatsuBatSpawn.getSpawnReserves()
local reserveResults = P4BokusatsuBatSpawn.getReserveResults()
for _,spawnData in ipairs(P4BokusatsuBatSpawn.spawnList) do
local needsReserve = true
for _,reservedId in ipairs(reserveResults) do
if reservedId == spawnData.id then
needsReserve = false
break
end
end
if needsReserve then
table.insert(spawnReserves, spawnData)
table.insert(reserveResults, spawnData.id)
end
end
local needsEventAdd = false
for k,v in pairs(spawnReserves) do
if v then
needsEventAdd = true
break
end
end
if needsEventAdd and not P4BokusatsuBatSpawn.isEventAdded then
Events.EveryTenMinutes.Add(P4BokusatsuBatSpawn.CheckSpawn)
P4BokusatsuBatSpawn.isEventAdded = true
end
end
-- *****************************************************************************
-- * Event trigger functions
-- *****************************************************************************
P4BokusatsuBatSpawn.OnGameStart = function()
P4BokusatsuBatSpawn.reserveSpawn()
end
Events.OnGameStart.Add(P4BokusatsuBatSpawn.OnGameStart)
P4BokusatsuBatSpawn.CheckSpawn = function()
local spawnReserves = P4BokusatsuBatSpawn.getSpawnReserves()
for k,v in pairs(spawnReserves) do
local square = getSquare(v.locx, v.locy, v.locz)
if square then
local spawnItem = square:AddWorldInventoryItem(v.item, v.x, v.y, v.z)
spawnItem:setWorldZRotation(v.r)
spawnItem:getWorldItem():setIgnoreRemoveSandbox(true)
spawnItem:getWorldItem():transmitCompleteItemToServer()
spawnReserves[k] = nil
end
end
end
前回解説した技術と同じものしか使っていませんので、宜しければソースを追って内容を理解してみてください。なお、実装時のポイントは下記になります。
グローバルMODデータの利用
湧き設定や湧き状態はMODデータで保持していますが、「セーブデータで1回だけ湧かせる」ために、グローバルMODデータを利用しています。こうすることで、同じセーブデータで別キャラを作成した場合も、撲殺バット(ティア3)が湧くのは最初の1回だけとなり、世界に1つだけの武器となります。
湧き処理の性能対策
実際の湧き処理は「CheckSpawn」関数で実施しており、「EveryTenMinutes」イベントで定期的に呼び出しています。アイテムを湧かすためには、ゲーム内でそのスクエア(=タイル)が読み込まれている必要があります。「LoadGridsquare」イベントを使えば、マップのスクエアが読み込まれた際に処理ができ、読み込まれたスクエアが対象かどうか判定することができます。ただし、このスクエアの読込はかなりの頻度で発生するため、マップロードの度にラグが生じやすくなります。
そこで、リアルタイム性は犠牲になりますが、湧き処理はゲーム内時間で10分に一回とし、また湧き対象のグリッドが存在しているか(=読み込まれているか)どうかを、湧き予定タイルごとに調べる方式にしています。
また、既に湧き予定の全てのアイテムが湧いた場合は、10分に一回の湧きチェックも不要となりますので、「Events.EveryTenMinutes」に登録しないようにフラグ制御をしています。
3. 独自ギミックの確認
今回追加したアイテム固定湧きの確認をします。指定した湧き場所に行ってみると、ティア3の撲殺バットが湧いていることが確認できます。
あとがき
これで全ての機能の実装が完了し、MOD公開できる状態になりました。
次回はWorkshopへのMOD公開について解説します。
索引:Project ZomboidのMODを開発する
前:6. 撲殺バットMODの作成(独自ギミック追加1)
次:8. 撲殺バットMODの作成(MOD公開)
-
今回の内容を反映したMODファイルは下記。
💾 P4BokusatsuBat_07.zip(MD5チェックサム:BF617DB120134C3C416B531E18579AB6) ↩