[utility] smw lakitu animation fix
Posted: Sun Jul 27, 2025 1:20 pm
recently i discovered that the smw lakitu's animation is completely hardcoded, making it impossible to change its frame count or animation speed properly via config files. here's some lua code that fixes this, letting you animate the lakitu however you want (create a file for this called npc-284.lua and place it inside your level/episode folder for it to take effect):
your custom graphics should be ordered in the same way as the vanilla smw lakitu graphics (moving left -> moving right -> throwing left -> throwing right)
there's a limitation where you can't necessarily have a full loop (frames * framespeed) be longer than 150 ticks otherwise some visual bugs might happen and maybe some other edge cases but as far as i can see it works
(also, don't use this if you're not trying to change the lakitu's frame count)
Code: Select all
local npcManager = require("npcManager")
local npcID = NPC_ID
local lakitu = {}
function lakitu.onInitAPI()
npcManager.registerEvent(npcID, lakitu, "onTickNPC")
npcManager.registerEvent(npcID, lakitu, "onTickEndNPC")
end
function lakitu.onTickNPC(v)
if Defines.levelFreeze then return end
if(v.despawnTimer <= 0) then
v.data.didThrow = false
return
end
if(not v.data.didThrow and v.ai3 == 3) then
v.data.didThrow = true
end
end
function lakitu.onTickEndNPC(v)
if Defines.levelFreeze then return end
if(v.despawnTimer <= 0) then
v.data.didThrow = false
return
end
local frameCount = NPC.config[v.id].frames or 3
local frameSpeed = NPC.config[v.id].framespeed or 8
v.data.frame = v.data.frame or v.animationFrame
v.data.animTimer = v.data.animTimer or v.animationTimer
if(not v.data.didThrow and v.ai3 == 3) then
v.data.didThrow = true
end
v.data.animTimer = v.data.animTimer + 1
if(v.data.animTimer >= frameSpeed) then
v.data.frame = v.data.frame + 1
if(v.data.frame >= frameCount) then
v.data.frame = 0
end
v.data.animTimer = 0
end
local frameOffset = 0
if(v.direction == DIR_RIGHT) then
frameOffset = frameOffset + frameCount
end
if(v.data.didThrow and v.ai5 < (frameSpeed * frameCount)) then
frameOffset = frameOffset + 2 * frameCount
end
v.animationFrame = v.data.frame + frameOffset
end
return lakitu
there's a limitation where you can't necessarily have a full loop (frames * framespeed) be longer than 150 ticks otherwise some visual bugs might happen and maybe some other edge cases but as far as i can see it works
(also, don't use this if you're not trying to change the lakitu's frame count)