Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -------------------------------------------------
- --[[ powerstarEXT.lua v1.0 by KBM-Quine ]]--
- --[[ with code help/advice from: Rednaxela ]]--
- --[[ Based on SMBX source code and ]]--
- --[[ chucks.lua by snoruntpyro ]]--
- -------------------------------------------------
- local npcutils = require("npcs/npcutils")
- local npcManager = require("npcManager")
- local iniParse = require("configFileReader")
- local powerstarEXT = {
- starIDsMap = {},
- starIDs = {}
- }
- local GM_STAR_ADDR = mem(0x00B25714, FIELD_DWORD)
- local function addStar(npc, filename)
- -- do some fact checking since we're shoving our hands in memory addresses
- if filename == nil or type(filename) ~= "string" then
- error("invalid or nil fileString")
- end
- if (npc == nil or type(npc) ~= "NPC") then
- error("invalid or nil NPC")
- end
- if (npc.data._settings.starIndex == nil or type(npc.data._settings.starIndex) ~= "number") then
- error("invalid or nil star index")
- end
- if (mem(0x00B251E0, FIELD_WORD) + 1) == 1001 then return end -- don't add if we're going over internal array limit
- mem(0x00B251E0, FIELD_WORD, mem(0x00B251E0, FIELD_WORD) + 1) -- add to star count...
- mem(GM_STAR_ADDR+(mem(0x00B251E0, FIELD_WORD) - 1)*0x08+0x00, FIELD_STRING, filename) -- set level file it's obtained from...
- mem(GM_STAR_ADDR+(mem(0x00B251E0, FIELD_WORD) - 1)*0x08+0x04, FIELD_WORD, 1000 + npc.data._settings.starIndex ) --and use the section field as an index. use 20 as a base so not to erase basegame stars
- end
- function powerstarEXT.isStarCollected(npc, filename)
- local collected = false
- for i=1, mem(0x00B251E0, FIELD_WORD) do
- if mem(GM_STAR_ADDR+(i - 1)*0x08+0x00, FIELD_STRING) == filename and mem(GM_STAR_ADDR+(i - 1)*0x08+0x04, FIELD_WORD) == (1000 + npc.data._settings.starIndex) then
- collected = true
- end
- end
- return collected
- end
- local match = string.match
- local tableinsert = table.insert
- local function ParselvlxNPCs(objectPath) -- get npcs from a lvlx file, taken from configfilereader
- local finalArray = {}
- if objectPath ~= nil then
- local lns = io.readFileLines(objectPath)
- local readLines = false
- if lns == nil then
- error("Error loading level file "..objectPath, 2)
- end
- for _,line in ipairs(lns) do
- if line == "NPC" then
- readLines = true
- end
- if readLines and not (line == "NPC" or line == "NPC_END") then
- local matchedID = match(line, '%d+') -- since the first number is always the ID and we only need the ID, grab only that
- tableinsert(finalArray, tonumber(matchedID))
- end
- if line == "NPC_END" then
- readLines = false
- end
- end
- return finalArray
- else
- end
- end
- function powerstarEXT.getStarsCollected()
- local t = {}
- for i=1, mem(0x00B251E0, FIELD_WORD) do
- t[i] = {filename = mem(GM_STAR_ADDR+(i - 1)*0x08+0x00, FIELD_STRING), index = mem(GM_STAR_ADDR+(i - 1)*0x08+0x04, FIELD_WORD)}
- end
- return t
- end
- local function addToWarpsonStart()
- if isOverworld then return end
- for _, warp in ipairs(Warp.get()) do
- if warp.levelFilename == "" then return end
- local IDs = ParselvlxNPCs(Misc.episodePath() .. warp.levelFilename)
- for _,v in ipairs(IDs) do
- if powerstarEXT.starIDsMap[v] then
- warp:mem(0x8C, FIELD_WORD, warp:mem(0x8C, FIELD_WORD) + 1)
- end
- end
- end
- end
- local function addToWarpsonCollect(filename)
- for _, warp in ipairs(Warp.get()) do
- if warp.levelFilename == "" then return end
- if filename == warp.levelFilename then
- warp:mem(0x8A, FIELD_WORD, warp:mem(0x8A, FIELD_WORD) + 1)
- end
- end
- end
- function powerstarEXT.collect(star, plyr)
- if not powerstarEXT.isStarCollected(star, Level.filename()) then
- addStar(star, Level.filename())
- addToWarpsonCollect(Level.filename())
- if not star.data._settings.endLevel then
- SFX.play(NPC.config[star.id].collectionsfx)
- end
- else
- Misc.coins(5, true)
- Effect.spawn(11, star.x + (star.width*0.5), star.y + (star.height*0.5))
- end
- if star.data._settings.endLevel then
- Level.endState(LEVEL_END_STATE_STAR)
- for i=1, Player.count() do
- if Player(i) ~= plyr then
- Player(i).section = plyr.section
- Player(i).x = plyr.x
- Player(i).y = plyr.y
- Player(i).forcedState = FORCEDSTATE_INVISIBLE
- Player(i).forcedTimer = -plyr.idx
- end
- end
- SFX.play(NPC.config[star.id].levelendsfx)
- Audio.SeizeStream(-1)
- Audio.MusicStop()
- end
- end
- function powerstarEXT.registerStar(npcID)
- npcManager.registerEvent(npcID, powerstarEXT, "onDrawNPC", "onDrawStar")
- npcManager.registerEvent(npcID, powerstarEXT, "onTickEndNPC", "onTickEndStar")
- powerstarEXT.starIDsMap[npcID] = true
- table.insert(powerstarEXT.starIDs, npcID)
- end
- function powerstarEXT.onInitAPI()
- registerEvent(powerstarEXT, "onStart")
- registerEvent(powerstarEXT, "onNPCKill")
- end
- function powerstarEXT.onStart()
- addToWarpsonStart()
- end
- function powerstarEXT.animateNPC(v)
- v.data.animationTimer = v.data.animationTimer + 1
- if v.data.animationTimer%NPC.config[v.id].framespeed == 0 then
- v.data.frame = v.data.frame + 1
- if v.data.frame > ((NPC.config[v.id].frames*v.data.frameMulti)-1) then
- v.data.frame = ((NPC.config[v.id].frames*v.data.frameMulti)-1)
- end
- v.data.animationTimer = 0
- end
- v.animationFrame = npcutils.getFrameByFramestyle(v, {frame=v.data.frame})
- end
- function powerstarEXT.onDrawStar(v)
- v.animationTimer = -1 -- clamp the basegame animation timer at 0
- end
- function powerstarEXT.onTickEndStar(v)
- local data = v.data
- if not data.initialized then
- data._settings.starIndex = data._settings.starIndex or 1
- data.collected = powerstarEXT.isStarCollected(v, Level.filename())
- if data.collected then
- data.frameMulti = 1
- else
- data.frameMulti = 0.5
- end
- data.frame = ((NPC.config[v.id].frames*data.frameMulti)-1)
- data.animationTimer = 0
- data.initialized = true
- end
- if Defines.levelFreeze then return end
- powerstarEXT.animateNPC(v)
- if NPC.config[v.id].sparkles then
- v.ai4 = v.ai4 + 1
- if v.ai4 >= 10*data.frameMulti then
- v.ai4 = 0
- local e = Effect.spawn(80, v.x + RNG.random()*v.width - 2, v.y + RNG.random()*v.height)
- e.speedX = RNG.random()*1 - 0.5
- e.speedY = RNG.random()*1 - 0.5
- if data.frameMulti == 1 then -- set frame of effects only for collected stars
- e.animationFrame = 1
- end
- end
- end
- if NPC.config[v.id].floats and not v:mem(0x136, FIELD_BOOL) then
- if v.ai2 == 0 then
- v.speedY = v.speedY - 0.04
- if v.speedY <= -1.4 then v.ai2 = 1 end
- else
- v.speedY = v.speedY + 0.04
- if v.speedY >= 1.4 then v.ai2 = 0 end
- end
- -- if v.ai3 == 0 then -- idk what this for but it's in source?
- -- v.speedX = v.speedX - 0.03
- -- if v.speedX <= -0.6 then v.ai3 = 1 end
- -- else
- -- v.speedX = v.speedX + 0.03
- -- if v.speedX >= 0.6 then v.ai3 = 0 end
- -- end
- end
- if NPC.config[v.id].uselayerspeed then -- can't be used in conjunction with floats
- v.speedX, v.speedY = npcutils.getLayerSpeed(v)
- end
- end
- function powerstarEXT.onNPCKill(obj, n, r)
- if powerstarEXT.starIDsMap[n.id] and r == 9 then
- if (npcManager.collected(n, r) or n:mem(0x138, FIELD_WORD) == 5) then
- powerstarEXT.collect(n, npcManager.collected(n, r))
- end
- end
- end
- return powerstarEXT
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement