Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -------------------------------------------------------------------
- --[[ blockBuster.lua v0.1 by KBM-Quine ]]--
- --[[ name suggested by Enjl. ]]--
- --[[ code help from: ]]--
- --[[ MrDoubleA ]]--
- --[[ with code heavily borrowed from modernReserveItems.lua ]]--
- -------------------------------------------------------------------
- local blockBuster = {}
- local blockManager = require("blockManager")
- local blockutils = require("blocks/blockutils")
- blockBuster.enabled = true
- blockBuster.npcOwnersToBlocks = false
- blockBuster.playSounds = true
- blockBuster.bumpAmount = 12
- blockBuster.useCustomCoinHandling = false
- blockBuster.useCustomItemHandling = false
- -- setup constants for reference throughout code
- COIN_STYLE_MARIO = 1
- COIN_STYLE_TOAD = 2
- COIN_STYLE_OTHER = 3
- ITEM_STYLE_DEFAULT = 1
- PROCESS_COINS = 1
- PROCESS_ITEMS = 2
- BB_ALIGNMENT_TOPLEFT = 0
- BB_ALIGNMENT_MIDDLE = 0.5
- BB_ALIGNMENT_BOTTMRIGHT = 1
- function blockBuster.randomizeLinkCoins(table) -- function to randomize links coins
- if table == nil then return end
- local npcID = table[1]
- if RNG.random() * 20 <= 3 then
- npcID = table[2]
- elseif RNG.random() * 60 <= 3 then
- npcID = table[3]
- end
- return npcID
- end
- local properties = {
- defaults = {transforms = {transformID = 2, centred = false}, coins = {style = COIN_STYLE_MARIO, npc = 10, sound = 14, effect = 11}, items = {style = ITEM_STYLE_DEFAULT, sound = 7, direction = 0, usePlayerDirection = false, forcedState = 1, forcedState2 = 0, upperForcedState = 3, upperForcedStateState2 = 0, speedX = 0, speedY = 0, upperSpeedX = 0, upperSpeedY = 0, offsetX = 0, offsetY = 0, xAlign = BB_ALIGNMENT_MIDDLE, yAlign = BB_ALIGNMENT_TOPLEFT, upperOffsetX = 0, upperOffsetY = 4, upperXAlign = BB_ALIGNMENT_MIDDLE, upperYAlign = BB_ALIGNMENT_BOTTMRIGHT, ai = {}, upperAI = {}, despawnTimer = 1000}},
- mario = {transforms = {}, coins = {style = COIN_STYLE_MARIO}, items = {progressivePowerups = true}},
- luigi = {transforms = {}, coins = {style = COIN_STYLE_OTHER, coinClusterMax = 21, coinClusterNulls = true}, items = {progressivePowerups = true}},
- peach = {transforms = {}, coins = {style = COIN_STYLE_MARIO}, items = {progressivePowerups = true, mountID = 35}},
- toad = {transforms = {}, coins = {style = COIN_STYLE_TOAD, npc = 138, multiHitAmount = 3}, items = {progressivePowerups = true, mountID = 35}},
- link = {transforms = {}, coins = {style = COIN_STYLE_OTHER, coinClusterMax = 6, coinClusterNulls = true, coinTable = {251, 252, 253}, sound = 81, coinFunc = blockBuster.randomizeLinkCoins}, items = {mushID = 250, coinID = 251, progressivePowerups = false}},
- }
- local characterProperties = {}
- local propertyPresets = { -- take this table...
- mario = {CHARACTER_MARIO, CHARACTER_WARIO, CHARACTER_UNCLEBROADSWORD},
- luigi = {CHARACTER_LUIGI, CHARACTER_BOWSER, CHARACTER_ZELDA},
- peach = {CHARACTER_PEACH, CHARACTER_NINJABOMBERMAN, CHARACTER_ROSALINA},
- toad = {CHARACTER_TOAD, CHARACTER_MEGAMAN, CHARACTER_KLONOA, CHARACTER_ULTIMATERINKA},
- link = {CHARACTER_LINK, CHARACTER_SNAKE, CHARACTER_SAMUS}
- }
- for k,v in pairs(propertyPresets) do -- and copy the defaults to the appropriate character
- for _,v2 in ipairs(v) do
- characterProperties[v2] = table.join(characterProperties[v2] or {}, properties[k])
- end
- end
- local blockProperties = {
- [55] = {transforms = {transformID = 55}}, -- redigit, why?
- [60] = {transforms = {transformID = 192}, coins = {npc = 88}},
- [88] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [89] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [90] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [159] = {transforms = {transformID = 159}}, -- again. redigit, why?
- [171] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [174] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [177] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [180] = {transforms = {transformID = 89}, coins = {npc = 33}},
- [188] = {transforms = {transformID = 192}, coins = {npc = 88}},
- [192] = {transforms = {transformID = 192}, coins = {npc = 88}},
- [193] = {transforms = {transformID = 192}, coins = {npc = 88}},
- [224] = {transforms = {transformID = 225}},
- [225] = {transforms = {transformID = 225}},
- [226] = {transforms = {transformID = 225}},
- [369] = {transforms = {transformID = 192}, coins = {npc = 88}},
- }
- sourceNPCTimeOffScreen = mem(0x00B2C85A, FIELD_WORD)
- local itemProperties = {
- [9] = {items = {isMush = true}},
- [10] = {items = {isCoin = true}},
- [14] = {items = {isPowerup = true, mushID = 9}},
- [33] = {items = {isCoin = true}},
- [34] = {items = {forcedState = 0, speedY = -6, ai = {ai1 = 0}, offsetY = -32, isPowerup = true, mushID = 9}},
- [88] = {items = {isCoin = true}},
- [96] = {items = {forcedState = 0, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}}, -- egg handling
- [98] = {items = {forcedState = 0, frame = 1, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [99] = {items = {forcedState = 0, frame = 2, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [100] = {items = {forcedState = 0, frame = 3, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [138] = {items = {isCoin = true}},
- [148] = {items = {forcedState = 0, frame = 4, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [149] = {items = {forcedState = 0, frame = 5, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [150] = {items = {forcedState = 0, frame = 6, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [182] = {items = {isPowerup = true, mushID = 184}},
- [183] = {items = {isPowerup = true, mushID = 185}},
- [184] = {items = {isMush = true}},
- [185] = {items = {isMush = true}},
- [228] = {items = {forcedState = 0, frame = 7, despawnTimer = sourceNPCTimeOffScreen*20, offsetY = -32, isEgg = true}},
- [249] = {items = {isMush = true}},
- [258] = {items = {isCoin = true, altItemID = 252}},
- [264] = {items = {isPowerup = true, mushID = 9}},
- [277] = {items = {isPowerup = true, mushID = 185}},
- }
- local blockBlacklist = {
- [622] = true, -- character switches
- [623] = true,
- [624] = true,
- [625] = true,
- [639] = true,
- [641] = true,
- [643] = true,
- [645] = true,
- [647] = true,
- [649] = true,
- [651] = true,
- [653] = true,
- [655] = true,
- [659] = true,
- [663] = true,
- [1279] = true, -- crash switches
- [1281] = true,
- }
- local BlocksToProcess = {}
- function blockBuster.onInitAPI()
- registerEvent(blockBuster, "onPostBlockHit", false)
- registerEvent(blockBuster, "onTickEnd", false)
- registerCustomEvent(blockBuster, "onCustomCoinEvent")
- registerCustomEvent(blockBuster, "onCustomItemEvent")
- registerCustomEvent(blockBuster, "onBlockProcess")
- end
- function blockBuster.blacklistBlock(blockID, bool) -- set whether a block ID is blacklisted from the system
- if blockBlacklist[blockID] == nil then
- table.insert(blockBlacklist, blockID)
- end
- blockBlacklist[blockID] = bool
- end
- function blockBuster.getItemProperties(npcID) -- get the properties for an item
- return itemProperties[npcID]
- end
- function blockBuster.getBlockProperties(blockID) -- get the properties for a block
- return blockProperties[blockID]
- end
- function blockBuster.getCharaterProperties(characterID) -- get the properties for a character
- return characterProperties[characterID]
- end
- function blockBuster.setItemProperties(npcID, properties) -- set the properties for an item
- itemProperties[npcID] = table.join(itemProperties[npcID] or {}, properties) -- so ids without default tables work
- for k,_ in pairs(properties) do -- then merge any that DO have default tables
- itemProperties[npcID][k] = table.join(itemProperties[npcID][k] or {}, properties[k])
- for k2,_ in pairs(properties[k]) do
- itemProperties[npcID][k][k2] = properties[k][k2]
- end
- end
- end
- function blockBuster.setBlockProperties(blockID, properties) -- set the properties for a block
- blockProperties[blockID] = table.join(blockProperties[blockID] or {}, properties)
- for k,_ in pairs(properties) do
- blockProperties[blockID][k] = table.join(blockProperties[blockID][k] or {}, properties[k])
- for k2,_ in pairs(properties[k]) do
- blockProperties[blockID][k][k2] = properties[k][k2]
- end
- end
- end
- function blockBuster.setCharacterProperties(characterID, properties) -- set the properties for a character
- characterProperties[characterID] = table.join(characterProperties[characterID] or {}, properties)
- for k,_ in pairs(properties) do
- characterProperties[characterID][k] = table.join(characterProperties[characterID][k] or {}, properties[k])
- for k2,_ in pairs(properties[k]) do
- characterProperties[characterID][k][k2] = properties[k][k2]
- end
- end
- end
- function blockBuster.decrementCoinContents(block) -- made solely to allow users easier access. decrements coins
- block.data.BBTable.oldContents = block.data.BBTable.oldContents - 1
- end
- function blockBuster.transformBlock(block, transformID, centred) -- handles block transforming
- if block.data.BBTable.oldContents <= 0 then
- block:transform(transformID, centred)
- end
- end
- function blockBuster.getContentsID(block) -- gets the proper npcID from the blocks contents
- return block.data.BBTable.oldContents - 1000
- end
- function blockBuster.setTrueContentsID(block) -- sets the contents back to the normal block contents system
- if not (block.data.BBTable.oldContents > 1000) and block.data.BBTable.oldContents > 0 then -- shooould pervent rewritting data already formatted to the default contents ID range
- block.data.BBTable.oldContents = block.data.BBTable.oldContents + 1000
- end
- end
- -- iBlocks (or interesting blocks/blocks of interest according to comments), blocks that are doing something interesting. messing with this so bumps hurt npcs. given to me by MDA
- local IBLOCK_COUNT = 0x00B25784 -- iBlocks in source. holds the total amount of iBlocks
- local IBLOCK_ADDR = mem(0x00B25798,FIELD_DWORD) -- iBlock in source. the array of iBlocks
- local function setasIBlock(block) -- sets a block as an iBlock, basic stuff
- mem(IBLOCK_COUNT,FIELD_WORD, mem(IBLOCK_COUNT,FIELD_WORD) + 1)
- mem(IBLOCK_ADDR + mem(IBLOCK_COUNT,FIELD_WORD)*2,FIELD_WORD, block.idx)
- end
- function blockBuster.setAsBlockToProcess(block) -- adds a block to the list that needs processing
- table.insert(BlocksToProcess, block.idx)
- end
- local function sourceShakeUp(block) -- clone of sources' BlockShakeUp https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L823
- if not block.isHidden then
- block:mem(0x52, FIELD_WORD, -blockBuster.bumpAmount)
- block:mem(0x54, FIELD_WORD, blockBuster.bumpAmount)
- block:mem(0x56, FIELD_WORD, 0)
- end
- if not (block.idx == mem(IBLOCK_ADDR + mem(IBLOCK_COUNT,FIELD_WORD)*2,FIELD_WORD)) then
- setasIBlock(block)
- end
- end
- local function sourceShakeDown(block) -- clone of sources' BlockShakeDown https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L851
- if not block.isHidden then
- block:mem(0x52, FIELD_WORD, blockBuster.bumpAmount)
- block:mem(0x54, FIELD_WORD, -blockBuster.bumpAmount)
- block:mem(0x56, FIELD_WORD, 0)
- end
- if not (block.idx == mem(IBLOCK_ADDR + mem(IBLOCK_COUNT,FIELD_WORD)*2,FIELD_WORD)) then
- setasIBlock(block)
- end
- end
- function blockBuster.resolveBumps(block, upper) -- performs the shake of the proper direction, as per this https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L101
- if not upper then
- sourceShakeUp(block)
- else
- sourceShakeDown(block)
- end
- end
- function blockBuster.resolveProperty(id, pl, type, table, field) -- returns the value of the supplied to the field arguement, based on the table arguement supplied
- local key
- local pTable = type
- if (pl ~= nil and characterProperties[pl.character] ~= nil and characterProperties[pl.character][table] ~= nil and characterProperties[pl.character][table][field] ~= nil)then
- key = characterProperties[pl.character][table][field]
- end
- if (pTable[id] ~= nil and pTable[id][table] ~= nil and pTable[id][table][field] ~= nil) then
- key = pTable[id][table][field]
- end
- if key == nil then
- key = properties.defaults[table][field]
- end
- return key
- end
- function blockBuster.defaultCoinAction(block, soundID, transformID, centred, effectID) -- the default 1.3 coins stuff remade in lua. taken from various parts of modBlock.bas
- Misc.coins(1,false)
- if blockBuster.playSounds then
- SFX.play(soundID or properties.defaults.coins.sound)
- end
- if not (effectID == nil or effectID == 0) then
- Effect.spawn(effectID, block.x + block.width*0.5, block.y)
- end
- blockBuster.decrementCoinContents(block)
- blockBuster.transformBlock(block, transformID, centred)
- end
- function blockBuster.doMultiSetup(block, pl) -- setup blocks to be RapidHit (name from source), toad style. may allow items to use this, not sure yet
- local multihit = blockBuster.resolveProperty(block.id, pl, blockProperties, "coins", "multiHitAmount") -- amount of times RapidHit is applied
- block.data.BBTable.oldMulti = math.floor(RNG.random() * multihit) + 1
- block.data.BBTable.isMulti = true
- block.data.BBTable.player = pl
- block:mem(0x04, FIELD_WORD, block.data.BBTable.oldMulti)
- end
- function blockBuster.checkCollisionUp(block) -- based on https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L194
- for _,v in ipairs(Block.getIntersecting(block.x + 1, block.y - 31, (block.x + 1) + 30, (block.y - 31) + 30)) do
- if v and not (v == block) and not Block.config[v.id].semisolid and not v.isHidden and not Block.config[v.id].sizable then
- return true
- end
- end
- end
- function blockBuster.checkCollisionDown(block) -- vaugely based on https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L79
- for _,v in ipairs(Block.getIntersecting(block.x, block.y + block.height, block.x + block.width, (block.y + block.height) + 17)) do
- if v and not (v == block) then
- return true
- end
- end
- end
- function blockBuster.spawnCoin(block, upper, pl, npcID) -- the default coin spawning stuff roughly translated to lua https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L200
- local spawnLayer = blockBuster.resolveProperty(block.id, pl, blockProperties, "coins", "spawnLayer") -- layer the coins are put on upon spawning
- local s = NPC.spawn(npcID, block.x + (block.width*0.5) - (NPC.config[npcID].width*0.5), block.y-NPC.config[npcID].height - 0.01, blockutils.getBlockSection(block), false, false)
- if spawnLayer then
- s.layerName = spawnLayer
- end
- s.ai1 = 1
- s.speedX = RNG.random() * 3 - 1.5
- s.speedY = -RNG.random() * 4 - 3
- if upper then
- s.speedY = -s.speedY * 0.5
- s.y = block.y+block.height
- end
- s:mem(0x156, FIELD_WORD, 20) -- timer to make npcs immune to harm. makes it so iBlocks don't collect them instantly
- end
- function blockBuster.filterPowerups(npcID, pl) -- approximation of powerup handling for source https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L345
- local mushID = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "mushID") -- id of the mushroom to turn into
- local isPowerup = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "isPowerup") -- if the item is a powerup
- local progressivePowerups = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "progressivePowerups") -- if the character or block should do progressive powerups
- local mushroom = false
- if pl and pl.powerup == PLAYER_SMALL and not mem(0x00B2D740, FIELD_BOOL) and progressivePowerups then mushroom = true end --0x00B2D740: battle mode bool address
- if (isPowerup and mushID and mushroom) then
- npcID = mushID
- end
- return npcID
- end
- function blockBuster.filterCharacterItems(npcID, ai1, pl) -- approximation of CharStuff for source https://github.com/smbx/smbx-legacy-source/blob/master/modNPC.bas#L12271
- local mushID = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "mushID") -- id of the mushroom to turn into
- local isMush = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "isMush") -- if the item is a mushroom it's self
- local isEgg = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "isEgg") -- if the item should be an egg on spawn
- local mountID = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "mountID") -- id of mount to turn into if not yoshi
- local isCoin = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "isCoin") -- if the item is a coin
- local coinID = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "coinID") -- the id of the coin to turn into
- local altItemID = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "altItemID") -- the id of the item to turn into if being transformed
- if isMush then
- if mushID then
- npcID = mushID
- end
- end
- if isEgg then
- local altItemID = blockBuster.resolveProperty(ai1, pl, itemProperties, "items", "altItemID")
- if mountID then
- -- ai1 = mountID this is overridden by 1.3 on npc creation/transformation anyways. it makes eggs not keep their frames either
- if altItemID then
- ai1 = altItemID
- end
- end
- end
- if isCoin then
- if coinID then
- npcID = coinID
- if altItemID then
- npcID = altItemID
- end
- end
- end
- return npcID, ai1
- end
- function blockBuster.spawnItem(block, upper, pl, npcID) -- this looks familiar lol. loosely based around this https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L400
- local blockTransformID = blockBuster.resolveProperty(block.id, pl, blockProperties, "transforms", "transformID") -- ID of block to transform. used here for positioning only
- local forced = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "forcedState") -- the state/"effect" the npc is under upon spawning
- local forced2 = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "forcedState2") -- npc dependant timer for the forced state
- local direction = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "direction") -- npc direction on spawn
- local usePlayerDirection = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "usePlayerDirection") -- whether the npc uses the players direction or behaves according to source (oppisite of the players direction)
- local speedX = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "speedX") -- horizontal speed upon spawning
- local speedY = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "speedY") -- vertical speed upon spawning
- local offsetX = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "offsetX") -- horizontal offset of the item from the items' alignment
- local offsetY = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "offsetY") -- vertical offset of the item from the items' alignment
- local xAlign = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "xAlign") -- items' horizontal alignment from the block
- local yAlign = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "yAlign") -- items' vertical alignment from the block
- local ai = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "ai") -- items' AI table upon spawn
- local data = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "data") -- items' data table upon spawn
- local despawnTimer = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "despawnTimer") -- items' despawn timer upon spawn
- local isEgg = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "isEgg") -- if the item should spawn in an egg
- local frame = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "frame") -- frame of the item upon spawning. only used by eggs in source?
- local immunity = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "immunity") -- immunity frames upon spawn. used to keep things from being instant harmed when spawned.
- local upperOffsetX = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperOffsetX") -- same as offsetX, used for being hit from above
- local upperOffsetY = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperOffsetY") -- same as offsetY, used for being hit from above
- local upperXAlign = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperXAlign") -- same as xAlign, used for being hit from above
- local upperYAlign = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperYAlign") -- same as YAlign, used for being hit from above
- local upperSpeedX = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperSpeedX") -- same as speedX, used for being hit from above
- local upperSpeedY = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperSpeedY") -- same as speedY, used for being hit from above
- local upperAI = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperAI") -- same as ai, used for being hit from above
- local upperData = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperData") -- same as data, used for being hit from above
- local upperForced = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperForcedState") -- same as forcedState, used for being hit from above
- local upperForced2 = blockBuster.resolveProperty(npcID, pl, itemProperties, "items", "upperForcedState2") -- same as forcedState2, used for being hit from above
- local tempWidth = Block.config[blockTransformID].width
- local tempX = block.x
- if tempWidth == 32 then
- tempWidth = Block.config[blockTransformID].width - 0.1
- tempX = block.x - 0.05
- end
- if upper then
- xAlign = upperXAlign
- yAlign = upperYAlign
- offsetX = upperOffsetX
- offsetY = upperOffsetY
- speedX = upperSpeedX
- speedY = upperSpeedY
- ai = upperAI
- data = upperData
- forced = upperForced
- forced2 = upperForcedState2
- end
- if isEgg then -- if it's meant to be in an egg, put it in one
- ai.ai1 = npcID
- npcID = 96
- end
- npcID = blockBuster.filterPowerups(npcID, pl) -- makes fire flowers, leafs, ect. into mushrooms when needed
- npcID, ai.ai1 = blockBuster.filterCharacterItems(npcID, ai.ai1, pl) -- does character specific things with items like yoshi's to boots or coins to rupees
- local s = NPC.spawn(npcID, tempX + (tempWidth*xAlign) - (NPC.config[npcID].width*xAlign) + offsetX, block.y + (Block.config[blockTransformID].height*yAlign) - (NPC.config[npcID].height*yAlign) + offsetY, blockutils.getBlockSection(block), false, false)
- if spawnLayer then
- s.layerName = spawnLayer
- end
- if frame then
- s.animationFrame = frame
- end
- if data ~= nil then -- append data to the item's data table
- for k,_ in pairs(data) do
- if not (s.data[k] == data[k]) then
- s.data[k] = data[k]
- end
- end
- end
- if ai ~= nil then -- set an item's ai# fields
- for k,_ in pairs(ai) do
- if not (s[k] == ai[k]) then
- s[k] = ai[k]
- end
- end
- end
- s:mem(0x124, FIELD_BOOL, true) -- active flag
- if despawnTimer then
- s.despawnTimer = despawnTimer
- end
- if direction and usePlayerDirection ~= nil and not usePlayerDirection then -- set direction to either a defined one or the player, as per properties set. uses -player.direction if 0 https://github.com/smbx/smbx-legacy-source/blob/master/modNPC.bas#L3486
- s.direction = direction
- elseif usePlayerDirection ~= nil and usePlayerDirection then
- s.direction = pl.direction
- end
- if forced then
- s:mem(0x138, FIELD_WORD, forced) -- forced state/effect
- end
- if forced2 then
- s:mem(0x13C, FIELD_DFLOAT, forced2) -- a forced state timer/effect2
- end
- s.speedY = speedY
- s.speedX = speedX
- if forced == 1 then
- s.height = 0
- end
- if immunity then
- s:mem(0x156, FIELD_WORD, immunity) -- immune timer
- end
- return s
- end
- function blockBuster.onPostBlockHit(v, upper, pl)
- if not blockBuster.enabled then return end
- if blockBlacklist[v.id] then return end -- make it so the lib doesn't work for blacklisted blocks
- if v:mem(0x52, FIELD_WORD) ~= 0 or v:mem(0x54, FIELD_WORD) ~= 0 or v:mem(0x56, FIELD_WORD) ~= 0 then return end -- "if the block has just been hit, ignore" comment from source https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L68
- v.data.BBTable = v.data.BBTable or {}
- local data = v.data.BBTable
- if not (v.contentID == 0) then
- if mem(0x00B2D740, FIELD_BOOL) and v:mem(0x02, FIELD_WORD) == 0 then --because why not at this point, yeah? https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L15
- v:mem(0x02, FIELD_WORD, 1)
- end
- v:mem(0x5A , FIELD_BOOL, false) -- allows invisible blocks to work properly with blockBuster
- data.oldContents = v.contentID -- save block contents
- data.oldMulti = v:mem(0x04, FIELD_WORD) -- save the multihit
- v.contentID = 0 -- void contents
- v:mem(0x04, FIELD_WORD, 0) -- void multihit
- blockBuster.setAsBlockToProcess(v) -- set the block to be processed in onTickEnd
- end
- if pl == nil then
- if data.player and not (pl == data.player) then -- should make RapidHit work with character configs
- pl = data.player
- end
- if blockBuster.npcOwnersToBlocks then -- allow transferring this system from thrown npcs
- for _,n in ipairs(NPC.getIntersecting(v.x-1,v.y-1,v.x+v.width+1,v.y+v.height+1)) do
- if n:mem(0x132,FIELD_WORD) > 0 and n:mem(0x136,FIELD_BOOL) and pl == nil then
- pl = Player.get()[n:mem(0x132,FIELD_WORD)]
- end
- end
- end
- end
- if upper and data.oldContents then
- upper = not blockBuster.checkCollisionDown(v)
- end
- if data.oldContents and data.oldContents > 0 and data.oldContents < 100 then -- coin handling. loosely based on this https://github.com/smbx/smbx-legacy-source/blob/master/modBlocks.bas#L183
- data.process = PROCESS_COINS -- mark for coin processing
- local coinStyle = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "style") -- style used by the block/player
- local multiHitTimes = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "multiHitAmount") -- mutihit amount as per block/player settings
- local npcSpawnID = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "npc") -- coin npc spawned per-block/player
- local coinSoundID = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "sound") -- sound played upon hitting the block
- local blockTransformID = blockBuster.resolveProperty(v.id, pl, blockProperties, "transforms", "transformID") -- what the block transforms into upon being depleted or voided
- local centred = blockBuster.resolveProperty(v.id, pl, blockProperties, "transforms", "centred") -- bool for if the transformation is centred on the blocks' location or at the blocks' cords as per source
- local effectID = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "effect") -- effect spawned for default coins actions as per block/player settings
- local coinFunction = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "coinFunc") -- function ran for COIN_STYLE_OTHER characters
- local coinClusterMax = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "coinClusterMax") -- max amount of coins for COIN_STYLE_OTHER characters
- local coinClusterNulls = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "coinClusterNulls") -- if COIN_STYLE_OTHER characters void block contents upon hit, regardless if there's more coins
- local coinTable = blockBuster.resolveProperty(v.id, pl, blockProperties, "coins", "coinTable") -- table containing coin variants. currently only used by link characters
- if not (multiHitTimes == nil) and multiHitTimes > 0 then
- if v:mem(0x04, FIELD_WORD) == 0 and not data.isMulti then
- blockBuster.doMultiSetup(v, pl)
- else
- data.oldMulti = data.oldMulti - 1
- end
- elseif not multiHitTimes and not data.isMulti then
- data.oldMulti = 0 -- pervent vanilla multihitting
- end
- if blockBuster.useCustomCoinHandling then -- allow making one's own coin code
- return EventManager.callEvent("onCustomCoinEvent", v, upper, pl, data)
- end
- if coinStyle == COIN_STYLE_MARIO then -- covers mario and peachs' coin styles
- blockBuster.defaultCoinAction(v, coinSoundID, blockTransformID, centred, effectID)
- blockBuster.resolveBumps(v, upper)
- elseif coinStyle == COIN_STYLE_TOAD then -- covers toads' coin style
- if not blockBuster.checkCollisionUp(v) then
- blockBuster.spawnCoin(v, upper, pl, npcSpawnID)
- if blockBuster.playSounds then
- SFX.play(coinSoundID)
- end
- blockBuster.decrementCoinContents(v)
- blockBuster.transformBlock(v, blockTransformID, centred)
- else
- blockBuster.defaultCoinAction(v, coinSoundID, blockTransformID, centred, effectID)
- end
- blockBuster.resolveBumps(v, upper)
- elseif coinStyle == COIN_STYLE_OTHER then -- covers luigi and links' coin styles
- if not blockBuster.checkCollisionUp(v) then
- local max = 0
- if data.oldContents < coinClusterMax then
- max = data.oldContents
- else
- max = coinClusterMax --characterProperties[pl.character].coins.coinClusterMax
- end
- for i=1, max do
- local tempCoinID = npcSpawnID
- if coinFunction then
- tempCoinID = coinFunction(coinTable)
- end
- blockBuster.spawnCoin(v, upper, pl, tempCoinID)
- if not coinClusterNulls then
- blockBuster.decrementCoinContents(v)
- end
- end
- if blockBuster.playSounds then
- SFX.play(coinSoundID)
- end
- if coinClusterNulls then
- data.oldContents = 0
- end
- blockBuster.transformBlock(v, blockTransformID, centred)
- else
- blockBuster.defaultCoinAction(v, nil, blockTransformID, centred, effectID)
- end
- blockBuster.resolveBumps(v, upper)
- end
- end
- if data.oldContents and data.oldContents >= 1000 then -- npc/item handling
- data.process = PROCESS_ITEMS -- mark for item processing
- local itemStyle = blockBuster.resolveProperty(v.id, pl, blockProperties, "items", "style") -- style used for items. currently there is only one
- local blockTransformID = blockBuster.resolveProperty(v.id, pl, blockProperties, "transforms", "transformID") -- what the block transforms into upon being depleted or voided
- local centred = blockBuster.resolveProperty(v.id, pl, blockProperties, "transforms", "centred") -- bool for if the transformation is centred on the blocks' location or at the blocks' cords as per source
- local itemSoundID = blockBuster.resolveProperty(v.id, pl, blockProperties, "items", "sound") -- sound played upon hitting the block
- if blockBuster.useCustomItemHandling then -- allow making one's own item code
- return EventManager.callEvent("onCustomItemEvent", v, upper, pl, data)
- end
- if itemStyle == ITEM_STYLE_DEFAULT then
- npcSpawnID = blockBuster.getContentsID(v)
- blockBuster.spawnItem(v, upper, pl, npcSpawnID)
- data.oldContents = 0
- if blockBuster.playSounds then
- SFX.play(itemSoundID)
- end
- blockBuster.transformBlock(v, blockTransformID, centred)
- blockBuster.resolveBumps(v, upper)
- end
- end
- end
- function blockBuster.onTickEnd()
- if not blockBuster.enabled and #BlocksToProcess == 0 then return end
- for k,v in ipairs(BlocksToProcess) do
- local block = Block(v)
- local data = block.data.BBTable
- EventManager.callEvent("onBlockProcess", block) -- allows custom handling to do things for clean up in necessary
- if data.process == PROCESS_COINS then
- block.contentID = data.oldContents -- restore old contents so coins work
- data.oldContents = nil
- elseif data.process == PROCESS_ITEMS then
- blockBuster.setTrueContentsID(block)
- block.contentID = data.oldContents -- restore old contents incase we ever add multiple items per block ever
- data.oldContents = nil
- end
- block:mem(0x04, FIELD_WORD, data.oldMulti)
- data.oldMulti = nil
- data.process = nil -- reset process incase we're multihitting
- if block:mem(0x04, FIELD_WORD) <= 0 then -- only get rid of other feilds if not using them for multihitting
- data.player = nil
- data.isMulti = nil
- block:mem(0x04, FIELD_WORD, 0)
- end
- table.remove(BlocksToProcess, k)
- end
- end
- blockBuster.properties = properties
- blockBuster.properties.blockProperties = blockProperties
- blockBuster.properties.itemProperties = itemProperties
- blockBuster.properties.characterProperties = characterProperties
- return blockBuster
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement