Share and discuss custom LunaLua code and content packs for SMBX2.
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Wed May 22, 2024 11:32 am
(Acronym pronounced as DEE-kawl)
This is just a really basic pack that aims to add new things that fit in with the base game. It includes the following features:
Mega Maverick Thwomp: A giant version of the Maverick Thwomp which can smash through fragile blocks.
Extra Plant Variants: Includes sideways Fire-Spewing Piranha Plants and Piranhacus Giganticus, and vertical red smb3 plant.
Very Fast/Slow line guide NPCs: Includes the Engine Block, Grinder, and YI Platform.
More Goomba Variants: Includes Giant and Mega Gloomba, Goombrat, and Para-Goombrat.
Charged Spiny Egg: A variant of the Spiny Egg that cannot be spinjumped on. Upon hitting the ground, it turns into a Charged Spiny.
Charged Fuzzy: A variant of the Fuzzy that cannot be spinjumped on. Moves slightly faster than the regular variant.
More Yoshi's House Bird Colors: Specifically teal, pink, and white.
Blert: A previously unused enemy! Gradually spreads into its surroundings through mitosis. Killing the core wipes out all the duplicates.
Various .ini files: These primarily fix errors in the editor, such as typos, descriptions, and animations.
From left to right, we have...
Donkey Kong: Goes over Bowser. Comes with a custom sound. (Sprites made by PetoMico on TSR)
Shawn Cobalt: An original character made by me (painful self-insert). Goes over Uncle Broadsword.
Minesweeper: Goes over Ultimate Rinka, comes with an overhaul of all its sounds (Sprites ripped by Black Squirrel, edited by me)
Gabriel Chimes: Another original character made by me, and is also the girlfriend of Shawn. Goes over Zelda.
A resprite of the Muncher to make it not look ugly.
BeforeAfter
One of the NPC passthrough blocks has been moved one pixel down, too.
Passthrough Synced Switches: Upon contact with a player or NPC, they'll toggle to the respective polarity.
Various .ini files (same goes for this as the NPC category.)
To download the latest version, Click the logo at the top!
V1.0: Initial release
V1.0.1: added a few new things
V1.1: Removed Golden Clawgrip and added various .ini files and sprite fixes
V1.1.1: Fixed Goombrat and Mega Gloomba, and added Passthrough Synced Switches
V1.1.2: Fixed numerous issues with costumes, added Blert and Gabby Chimes
All showcases use MrDoubleA's ExtraBGOProperties.lua.
Last edited by Donkdonker124 on Thu Jun 06, 2024 8:25 am, edited 11 times in total.
|
|
|
|
|
|
|
|
|
-
Just_Thomas
- Spike
- Posts: 296
- Joined: Sat Dec 16, 2023 3:32 am
- Pronouns: he/him
Postby Just_Thomas » Wed May 22, 2024 4:10 pm
Ok, the packs highlight is the DK costume, this is for sure. It is really really well done and does fit SMBX so nice. Great job!
It really looks great and will work quite well with all these DK based npcs which have been already created.
BUT I see 2 flaws here:
The Bowser Icon is very likely not a problem to replace (a DK logo like on the barrels should work best here)
https://www.mariowiki.com/DK_Barrel
\data\graphics\bowser
(bowser-hud-hit and bowser-hud-hit-empty)
Second one is very likely much harder to solve: You might see it already; I don`t think DK has a good reason to hire bowsers minions.
Somehow this should be "programmed out". It simply does not make any sense.
(I admit I have no idea if something like that is already done by somebody else and also can not judge how difficult this might be).
A flaw to hear are missing or rather fitting sounds.
You might find some good ones here:
http://www.dkc-atlas.com/forum/viewtopic.php?t=1604
Normally a good costume is everything, but unfortunately in this particular case the difference between the characters as a base and as a costume is just too big. So I'm not complaining for no reason (therefore sorry about that). Without these changes, it will be almost impossible to make good use of this work and that would be a shame in the end. Maybe some of the big guys here on the forum is willing to help out, if you are stuck (at least it does happen quite a lot, from my impression).
Code: Select all function onStart()
player:transform(CHARACTER_BOWSER);
player.speedX = -1
Player.setCostume(CHARACTER_BOWSER, "PetoMico-Donkey Kong")
end
[project whatever]\costumes\bowser\PetoMico-Donkey Kong
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Wed May 22, 2024 5:52 pm
Just_Thomas wrote: ↑Wed May 22, 2024 4:10 pm
The Bowser Icon is very likely not a problem to replace (a DK logo like on the barrels should work best here)
A flaw to hear are missing or rather fitting sounds.
I made a simple addition to DK, which is the replacement for the Bowser icon.
As for the sounds... I could only find two used, which are internally referred to as sound-5 and sound-77.
These are his hit and punching sounds respectively.
|
|
|
|
|
|
|
|
|
-
Just_Thomas
- Spike
- Posts: 296
- Joined: Sat Dec 16, 2023 3:32 am
- Pronouns: he/him
Postby Just_Thomas » Thu May 23, 2024 8:23 am
Donkdonker124 wrote: ↑Wed May 22, 2024 5:52 pm
Just_Thomas wrote: ↑Wed May 22, 2024 4:10 pm
The Bowser Icon is very likely not a problem to replace (a DK logo like on the barrels should work best here)
A flaw to hear are missing or rather fitting sounds.
I made a simple addition to DK, which is the replacement for the Bowser icon.
As for the sounds... I could only find two used, which are internally referred to as sound-5 and sound-77.
These are his hit and punching sounds respectively.
I actually do not know how this stuff works, but according to "...\data\graphics\bowser" there are more used sounds.
But it is hard to figure WHERE they are used (situation based I mean).
*caught* Emral? Now would be a good time for you to write - once again - a clarifying post here. ... please!
|
|
|
|
|
|
|
|
|
-
fexhvhbdsf864
- Shy Guy
- Posts: 6
- Joined: Mon Jan 30, 2023 2:57 am
Postby fexhvhbdsf864 » Thu May 23, 2024 10:56 am
This Asset Pack zip is empty,Please Added File.
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Thu May 23, 2024 12:17 pm
fexhvhbdsf864 wrote: ↑Thu May 23, 2024 10:56 am
This Asset Pack zip is empty,Please Added File.
Oh! It should be fixed now. Sorry 'bout that.
|
|
|
|
|
|
|
|
|
-
Just_Thomas
- Spike
- Posts: 296
- Joined: Sat Dec 16, 2023 3:32 am
- Pronouns: he/him
Postby Just_Thomas » Thu May 23, 2024 1:10 pm
sound-5 does not get loaded from the costume directory. It still uses the "stock" file from the ...\data\graphics\bowser directory.
Makes me wonder, if this is a bug related to SMBX itself, but I can not tell through.
I was about to seek for proper replacement sound files for DK, but if this does not even work, it barely makes sense atm.
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Tue May 28, 2024 6:36 am
Oh. My bad
Added in 7 minutes 47 seconds:
Re: DQoL - SMBX2 V1.1
Yo.
Version 1.1 just dropped. Here's the changelog
- Removed Golden Clawgrip (It was just made as a joke :\)
- Added various .ini files to fix editor-related stuffs
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Wed Jun 05, 2024 9:20 am
Yet another update has came out! This time, it adds...
- Gabriel Chimes as a costume for Zelda
- Blert (an unused enemy restored)
- Numerous costume fixes
Oh also before anyone asks, no I'm not adding the Golblert to the pack, as it seems unfinished.
|
|
|
|
|
|
|
|
|
-
mariobrigade2018
- Flurry
- Posts: 354
- Joined: Wed May 24, 2023 7:00 pm
- Flair: Normie in coding who dreams of making a Mario game
- Pronouns: he/him
Postby mariobrigade2018 » Wed Jun 05, 2024 10:23 am
Donkdonker124 wrote: ↑Wed Jun 05, 2024 9:20 am
Yet another update has came out! This time, it adds...
- Blert (an unused enemy restored)
Oh also before anyone asks, no I'm not adding the Golblert to the pack, as it seems unfinished.
What do you mean the golblerts are unfinished?
Last edited by mariobrigade2018 on Thu Jun 06, 2024 1:09 am, edited 1 time in total.
|
|
|
|
|
|
|
|
|
-
AToMIC
- Hoopster
- Posts: 106
- Joined: Fri Jan 24, 2014 2:57 pm
- Flair: I'm here
- Pronouns: He/Him
Postby AToMIC » Wed Jun 05, 2024 2:47 pm
Are the very majestic SMW bushes in the background of all these demonstrations included in the package too?
|
|
|
|
|
|
|
|
|
-
mariobrigade2018
- Flurry
- Posts: 354
- Joined: Wed May 24, 2023 7:00 pm
- Flair: Normie in coding who dreams of making a Mario game
- Pronouns: he/him
Postby mariobrigade2018 » Wed Jun 05, 2024 4:22 pm
AToMIC wrote: ↑Wed Jun 05, 2024 2:47 pm
Are the very majestic SMW bushes in the background of all these demonstrations included in the package too?
No. You use this:
viewtopic.php?t=28888
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Thu Jun 06, 2024 8:24 am
mariobrigade2018 wrote: ↑Wed Jun 05, 2024 4:22 pm
AToMIC wrote: ↑Wed Jun 05, 2024 2:47 pm
Are the very majestic SMW bushes in the background of all these demonstrations included in the package too?
No. You use this:
viewtopic.php?t=28888
Yeah I forgot to mention that. I'll update the post.
mariobrigade2018 wrote: ↑Wed Jun 05, 2024 10:23 am
Donkdonker124 wrote: ↑Wed Jun 05, 2024 9:20 am
Yet another update has came out! This time, it adds...
- Blert (an unused enemy restored)
Oh also before anyone asks, no I'm not adding the Golblert to the pack, as it seems unfinished.
What do you mean the golblerts are unfinished?
As seen in this code, the (presumed) functionality of the Golblerts seem to be inactive.
Note: The function in question is located all the way at the bottom.
Edit: This code seems to be very similar to the Arrow Lift Platform.
Code: Select all local blert = {}
local npcManager = require("npcManager")
local blertID = {
normal = 490,
gol = 491
}
local blertIDMap = {}
local killEffect = 10
-- Register properties, harm types, etc. for each blert type
local blertBase = {}
for k,v in pairs(blertID) do
blertIDMap[v] = k
blertBase[k] = {
config = npcManager.setNpcSettings({
id = v,
gfxwidth = 36,
gfxheight = 36,
gfxoffsety = 0,
width = 32,
height = 32,
frames = 6,
framespeed = 8,
framestyle = 0,
score = 0,
blocknpctop = 0,
blocknpc = 0,
playerblocktop = 0,
playerblock = 0,
nohurt = 0,
nogravity = 1,
noblockcollision = 1,
jumphurt = 0
})
}
npcManager.registerHarmTypes(
v,
{
HARM_TYPE_JUMP,
HARM_TYPE_FROMBELOW,
HARM_TYPE_NPC,
HARM_TYPE_HELD,
HARM_TYPE_TAIL,
HARM_TYPE_SPINJUMP,
HARM_TYPE_SWORD,
HARM_TYPE_LAVA
},
{
[HARM_TYPE_JUMP]=10,
[HARM_TYPE_FROMBELOW]=10,
[HARM_TYPE_NPC]=10,
[HARM_TYPE_HELD]=10,
[HARM_TYPE_TAIL]=10,
[HARM_TYPE_SPINJUMP]=10,
[HARM_TYPE_LAVA]={id=13, xoffset=0.5, xoffsetBack = 0, yoffset=1, yoffsetBack = 1.5}
}
)
end
local function round(val)
local int,frac = math.modf(val)
if frac >= 0.5 then
return math.ceil(val)
else
return math.floor(val)
end
end
local function cor_spawnBlert(args)
local blob = args.parent
local parentData = blob.data._basegame
args.x = round(args.x or 0)
args.y = round(args.y or 0)
local w,h = round(blob.width),round(blob.height)
--windowDebug (tostring(args.x)..", "..tostring(args.y))
local x1,y1,x2,y2 = blob.x+args.x+2, blob.y+args.y+2, blob.x+args.x+w-2, blob.y+args.y+h-2
local npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
local blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree and blob.isValid then
parentData.animFrame = 1
Routine.waitFrames(20)
if blob.isValid then
npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree then
SFX.play(72)
local child = NPC.spawn (blob.id, blob.x+args.x, blob.y+args.y, player.section, false)
child.data._basegame = {
parent = parentData.parent or blob,
radius = parentData.radius,
growrate = parentData.growrate,
spawned = true
}
end
end
end
end
local function cor_trySpawn(v)
local blob = v
local size = {}
local data = blob.data._basegame
local parent = data.parent or blob
if blob.isValid and parent.isValid then
local x1,x2,y1,y2 = blob.x+0.5*blob.width,parent.x+0.5*parent.width, blob.y+0.5*blob.height,parent.y+0.5*parent.height
--windowDebug(tostring(x1)..","..tostring(x2)..","..tostring(y1)..","..tostring(y2))
local distance = math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
data.distance = distance
local surrounding = NPC.getIntersecting(blob.x-0.5*blob.width, blob.y-0.5*blob.height, blob.x+1.5*blob.width, blob.y+1.5*blob.height)
if #surrounding < 9 and distance < data.radius*math.min(blob.width, blob.height) and not data.killChain then
for _,v in ipairs{{x=blob.width},{x=-blob.width},{y=blob.height},{y=-blob.height}} do
v.parent = blob
Routine.run(cor_spawnBlert, v)
end
end
Routine.skip()
if blob.isValid then
if data.animFrame ~= 0 then
if blob.isValid then
data.animFrame = 1
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 2
Routine.waitFrames(16)
end
if blob.isValid then
data.animFrame = 3
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 0
end
end
end
end
end
local function cor_blertDie(args)
SFX.play(38)
local blob = args.npc
local data = blob.data._basegame
data.animFrame = 1
Routine.waitFrames(4)
data.animFrame = 2
if blob.isValid then
local size = {width=round(blob.width), height=round(blob.height), id=blob.id}
blob.speedX = 0
blob.speedY = 0
-- Only go through with the pop effect and ripple kill if the parent reference is a valid normal blert
if data.parent.isValid and size.id == blertID.normal then
-- If killing the core, destroy all others in a ripple
if data.parent == blob then
-- Make all the surrounding blerts look dead
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local x2,y2,x3,y3 = x1-size.width*(data.radius+1), y1-size.height*(data.radius+1), x1+size.width*(data.radius+1), y1+size.height*(data.radius+1)
local surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Make the core invisible
blob.isHidden = true
Routine.waitFrames(32)
-- Double-check (I'm sure there's a much better way to handle this)
surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Kill the blerts ring by ring
SFX.play(41)
for i=1,data.radius+1,0.25 do
local surroundingB = NPC.getIntersecting(x1-i*size.width, y1-i*size.height, x1+i*size.width, y1+i*size.height)
for k,v in ipairs(surroundingB) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.killChain == true then
v.data._basegame.dead = true
v:kill()
end
end
end
Routine.skip()
end
else
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local surroundingA = NPC.getIntersecting(x1-2*size.width, y1-2*size.height, x1+2*size.width, y1+2*size.height)
local surroundingB = NPC.getIntersecting(x1-size.width, y1-1, x1+size.width, y1+1)
local surroundingC = NPC.getIntersecting(x1-1, y1-size.height, x1+1, y1+size.height)
for k,v in ipairs(surroundingA) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
v.data._basegame.timer = v.data._basegame.growrate*32 or 32
end
end
for k,v in ipairs(table.append(surroundingB,surroundingC)) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) and v ~= args.npc then
if v ~= v.data._basegame.parent then
v.data._basegame.dead = true
end
v:kill()
end
end
end
end
-- Final kill
Routine.waitFrames(4)
if blob.isValid then
data.dead = true
blob:kill()
end
end
end
function dieCheck(v)
end
function blert.onTickNPC(v)
local blob = v
-- Initialize properties
if blob.data._basegame == nil then
blob.data._basegame = {spawned = false}
end
local data = blob.data._basegame
data.growrate = data.growrate or blob.data.growrate or 1
data.radius = data.radius or blob.data.radius or 3
data.parent = data.parent or blob
data.distance = data.distance or 0
-- Never despawn offscreen, but don't start multiplying until onscreen
if blob:mem(0x12A, FIELD_WORD) == 180 then
data.spawned = true
end
if data.spawned == true then
blob:mem(0x12A, FIELD_WORD, 179)
end
-- Manage animation
data.animFrame = data.animFrame or 0
if not data.parent.isValid or data.killChain == true then
data.animFrame = 4
end
blob.animationFrame = data.animFrame
-- Manage multiplication timer
if data.timer == nil then data.timer = data.growrate*65; end;
data.timer = data.timer-1
if data.timer <= 0 and blob.isValid and not data.killChain and data.spawned then
data.timer = data.growrate*65
Routine.run(cor_trySpawn, blob)
dieCheck (blob)
end
-- Force speed to 0
--blob.speedX = 0
--blob.speedY = 0
end
function blert.onNPCKill(eventobj, npc, reason)
if (not npc.isValid) then
return;
end
if npc.id == blertID.normal and not npc:mem(0x64,FIELD_BOOL) and reason ~= HARM_TYPE_OFFSCREEN then
local blob = npc
local data = blob.data._basegame
if data.dead ~= true then
eventobj.cancelled = true
Routine.run(cor_blertDie, {npc=npc})
else
Animation.spawn(killEffect, npc.x, npc.y)
end
end
end
function blert.onInitAPI()
for k,v in pairs(blertID) do
npcManager.registerEvent(v, blert, "onTickNPC")
end
registerEvent(blert, "onNPCKill")
end
return blert
--BASE
-- v.ai1 // v.data.type {
-- /What Type?
-- 0 = !
-- 1 = Up
-- 2 = Left
-- 3 = Right
-- }
-- v.ai2 v.data.life {
-- /How long should the ghost created last?
-- }
--Ghost
-- v.ai1 v.data.type {
-- /Direction?
-- 0 = up
-- 1 = Left
-- 2 = Right
-- }
-- v.ai2 v.data.sp {
-- /Should change direction when jumped?
-- true = Yes
-- false = No
-- }
-- v.ai3 v.data.life {
-- /How long should the ghost last?
-- }
|
|
|
|
|
|
|
|
|
-
mariobrigade2018
- Flurry
- Posts: 354
- Joined: Wed May 24, 2023 7:00 pm
- Flair: Normie in coding who dreams of making a Mario game
- Pronouns: he/him
Postby mariobrigade2018 » Thu Jun 06, 2024 9:35 pm
Donkdonker124 wrote: ↑Thu Jun 06, 2024 8:31 am
As seen in this code, the (presumed) functionality of the Golblerts seem to be inactive.
Note: The function in question is located all the way at the bottom.
Edit: This code seems to be very similar to the Arrow Lift Platform.
Code: Select all local blert = {}
local npcManager = require("npcManager")
local blertID = {
normal = 490,
gol = 491
}
local blertIDMap = {}
local killEffect = 10
-- Register properties, harm types, etc. for each blert type
local blertBase = {}
for k,v in pairs(blertID) do
blertIDMap[v] = k
blertBase[k] = {
config = npcManager.setNpcSettings({
id = v,
gfxwidth = 36,
gfxheight = 36,
gfxoffsety = 0,
width = 32,
height = 32,
frames = 6,
framespeed = 8,
framestyle = 0,
score = 0,
blocknpctop = 0,
blocknpc = 0,
playerblocktop = 0,
playerblock = 0,
nohurt = 0,
nogravity = 1,
noblockcollision = 1,
jumphurt = 0
})
}
npcManager.registerHarmTypes(
v,
{
HARM_TYPE_JUMP,
HARM_TYPE_FROMBELOW,
HARM_TYPE_NPC,
HARM_TYPE_HELD,
HARM_TYPE_TAIL,
HARM_TYPE_SPINJUMP,
HARM_TYPE_SWORD,
HARM_TYPE_LAVA
},
{
[HARM_TYPE_JUMP]=10,
[HARM_TYPE_FROMBELOW]=10,
[HARM_TYPE_NPC]=10,
[HARM_TYPE_HELD]=10,
[HARM_TYPE_TAIL]=10,
[HARM_TYPE_SPINJUMP]=10,
[HARM_TYPE_LAVA]={id=13, xoffset=0.5, xoffsetBack = 0, yoffset=1, yoffsetBack = 1.5}
}
)
end
local function round(val)
local int,frac = math.modf(val)
if frac >= 0.5 then
return math.ceil(val)
else
return math.floor(val)
end
end
local function cor_spawnBlert(args)
local blob = args.parent
local parentData = blob.data._basegame
args.x = round(args.x or 0)
args.y = round(args.y or 0)
local w,h = round(blob.width),round(blob.height)
--windowDebug (tostring(args.x)..", "..tostring(args.y))
local x1,y1,x2,y2 = blob.x+args.x+2, blob.y+args.y+2, blob.x+args.x+w-2, blob.y+args.y+h-2
local npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
local blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree and blob.isValid then
parentData.animFrame = 1
Routine.waitFrames(20)
if blob.isValid then
npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree then
SFX.play(72)
local child = NPC.spawn (blob.id, blob.x+args.x, blob.y+args.y, player.section, false)
child.data._basegame = {
parent = parentData.parent or blob,
radius = parentData.radius,
growrate = parentData.growrate,
spawned = true
}
end
end
end
end
local function cor_trySpawn(v)
local blob = v
local size = {}
local data = blob.data._basegame
local parent = data.parent or blob
if blob.isValid and parent.isValid then
local x1,x2,y1,y2 = blob.x+0.5*blob.width,parent.x+0.5*parent.width, blob.y+0.5*blob.height,parent.y+0.5*parent.height
--windowDebug(tostring(x1)..","..tostring(x2)..","..tostring(y1)..","..tostring(y2))
local distance = math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
data.distance = distance
local surrounding = NPC.getIntersecting(blob.x-0.5*blob.width, blob.y-0.5*blob.height, blob.x+1.5*blob.width, blob.y+1.5*blob.height)
if #surrounding < 9 and distance < data.radius*math.min(blob.width, blob.height) and not data.killChain then
for _,v in ipairs{{x=blob.width},{x=-blob.width},{y=blob.height},{y=-blob.height}} do
v.parent = blob
Routine.run(cor_spawnBlert, v)
end
end
Routine.skip()
if blob.isValid then
if data.animFrame ~= 0 then
if blob.isValid then
data.animFrame = 1
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 2
Routine.waitFrames(16)
end
if blob.isValid then
data.animFrame = 3
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 0
end
end
end
end
end
local function cor_blertDie(args)
SFX.play(38)
local blob = args.npc
local data = blob.data._basegame
data.animFrame = 1
Routine.waitFrames(4)
data.animFrame = 2
if blob.isValid then
local size = {width=round(blob.width), height=round(blob.height), id=blob.id}
blob.speedX = 0
blob.speedY = 0
-- Only go through with the pop effect and ripple kill if the parent reference is a valid normal blert
if data.parent.isValid and size.id == blertID.normal then
-- If killing the core, destroy all others in a ripple
if data.parent == blob then
-- Make all the surrounding blerts look dead
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local x2,y2,x3,y3 = x1-size.width*(data.radius+1), y1-size.height*(data.radius+1), x1+size.width*(data.radius+1), y1+size.height*(data.radius+1)
local surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Make the core invisible
blob.isHidden = true
Routine.waitFrames(32)
-- Double-check (I'm sure there's a much better way to handle this)
surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Kill the blerts ring by ring
SFX.play(41)
for i=1,data.radius+1,0.25 do
local surroundingB = NPC.getIntersecting(x1-i*size.width, y1-i*size.height, x1+i*size.width, y1+i*size.height)
for k,v in ipairs(surroundingB) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.killChain == true then
v.data._basegame.dead = true
v:kill()
end
end
end
Routine.skip()
end
else
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local surroundingA = NPC.getIntersecting(x1-2*size.width, y1-2*size.height, x1+2*size.width, y1+2*size.height)
local surroundingB = NPC.getIntersecting(x1-size.width, y1-1, x1+size.width, y1+1)
local surroundingC = NPC.getIntersecting(x1-1, y1-size.height, x1+1, y1+size.height)
for k,v in ipairs(surroundingA) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
v.data._basegame.timer = v.data._basegame.growrate*32 or 32
end
end
for k,v in ipairs(table.append(surroundingB,surroundingC)) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) and v ~= args.npc then
if v ~= v.data._basegame.parent then
v.data._basegame.dead = true
end
v:kill()
end
end
end
end
-- Final kill
Routine.waitFrames(4)
if blob.isValid then
data.dead = true
blob:kill()
end
end
end
function dieCheck(v)
end
function blert.onTickNPC(v)
local blob = v
-- Initialize properties
if blob.data._basegame == nil then
blob.data._basegame = {spawned = false}
end
local data = blob.data._basegame
data.growrate = data.growrate or blob.data.growrate or 1
data.radius = data.radius or blob.data.radius or 3
data.parent = data.parent or blob
data.distance = data.distance or 0
-- Never despawn offscreen, but don't start multiplying until onscreen
if blob:mem(0x12A, FIELD_WORD) == 180 then
data.spawned = true
end
if data.spawned == true then
blob:mem(0x12A, FIELD_WORD, 179)
end
-- Manage animation
data.animFrame = data.animFrame or 0
if not data.parent.isValid or data.killChain == true then
data.animFrame = 4
end
blob.animationFrame = data.animFrame
-- Manage multiplication timer
if data.timer == nil then data.timer = data.growrate*65; end;
data.timer = data.timer-1
if data.timer <= 0 and blob.isValid and not data.killChain and data.spawned then
data.timer = data.growrate*65
Routine.run(cor_trySpawn, blob)
dieCheck (blob)
end
-- Force speed to 0
--blob.speedX = 0
--blob.speedY = 0
end
function blert.onNPCKill(eventobj, npc, reason)
if (not npc.isValid) then
return;
end
if npc.id == blertID.normal and not npc:mem(0x64,FIELD_BOOL) and reason ~= HARM_TYPE_OFFSCREEN then
local blob = npc
local data = blob.data._basegame
if data.dead ~= true then
eventobj.cancelled = true
Routine.run(cor_blertDie, {npc=npc})
else
Animation.spawn(killEffect, npc.x, npc.y)
end
end
end
function blert.onInitAPI()
for k,v in pairs(blertID) do
npcManager.registerEvent(v, blert, "onTickNPC")
end
registerEvent(blert, "onNPCKill")
end
return blert
--BASE
-- v.ai1 // v.data.type {
-- /What Type?
-- 0 = !
-- 1 = Up
-- 2 = Left
-- 3 = Right
-- }
-- v.ai2 v.data.life {
-- /How long should the ghost created last?
-- }
--Ghost
-- v.ai1 v.data.type {
-- /Direction?
-- 0 = up
-- 1 = Left
-- 2 = Right
-- }
-- v.ai2 v.data.sp {
-- /Should change direction when jumped?
-- true = Yes
-- false = No
-- }
-- v.ai3 v.data.life {
-- /How long should the ghost last?
-- }
But aren't Golblert just normal ones with no reproduction cap?
|
|
|
|
|
|
|
|
|
-
Donkdonker124
- Rex
- Posts: 31
- Joined: Wed Mar 27, 2024 10:31 am
- Flair: Fictionally stronger than man
- Pronouns: he/him
-
Contact:
Postby Donkdonker124 » Fri Jun 07, 2024 6:56 am
mariobrigade2018 wrote: ↑Thu Jun 06, 2024 9:35 pm
Donkdonker124 wrote: ↑Thu Jun 06, 2024 8:31 am
As seen in this code, the (presumed) functionality of the Golblerts seem to be inactive.
Note: The function in question is located all the way at the bottom.
Edit: This code seems to be very similar to the Arrow Lift Platform.
Code: Select all local blert = {}
local npcManager = require("npcManager")
local blertID = {
normal = 490,
gol = 491
}
local blertIDMap = {}
local killEffect = 10
-- Register properties, harm types, etc. for each blert type
local blertBase = {}
for k,v in pairs(blertID) do
blertIDMap[v] = k
blertBase[k] = {
config = npcManager.setNpcSettings({
id = v,
gfxwidth = 36,
gfxheight = 36,
gfxoffsety = 0,
width = 32,
height = 32,
frames = 6,
framespeed = 8,
framestyle = 0,
score = 0,
blocknpctop = 0,
blocknpc = 0,
playerblocktop = 0,
playerblock = 0,
nohurt = 0,
nogravity = 1,
noblockcollision = 1,
jumphurt = 0
})
}
npcManager.registerHarmTypes(
v,
{
HARM_TYPE_JUMP,
HARM_TYPE_FROMBELOW,
HARM_TYPE_NPC,
HARM_TYPE_HELD,
HARM_TYPE_TAIL,
HARM_TYPE_SPINJUMP,
HARM_TYPE_SWORD,
HARM_TYPE_LAVA
},
{
[HARM_TYPE_JUMP]=10,
[HARM_TYPE_FROMBELOW]=10,
[HARM_TYPE_NPC]=10,
[HARM_TYPE_HELD]=10,
[HARM_TYPE_TAIL]=10,
[HARM_TYPE_SPINJUMP]=10,
[HARM_TYPE_LAVA]={id=13, xoffset=0.5, xoffsetBack = 0, yoffset=1, yoffsetBack = 1.5}
}
)
end
local function round(val)
local int,frac = math.modf(val)
if frac >= 0.5 then
return math.ceil(val)
else
return math.floor(val)
end
end
local function cor_spawnBlert(args)
local blob = args.parent
local parentData = blob.data._basegame
args.x = round(args.x or 0)
args.y = round(args.y or 0)
local w,h = round(blob.width),round(blob.height)
--windowDebug (tostring(args.x)..", "..tostring(args.y))
local x1,y1,x2,y2 = blob.x+args.x+2, blob.y+args.y+2, blob.x+args.x+w-2, blob.y+args.y+h-2
local npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
local blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree and blob.isValid then
parentData.animFrame = 1
Routine.waitFrames(20)
if blob.isValid then
npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree then
SFX.play(72)
local child = NPC.spawn (blob.id, blob.x+args.x, blob.y+args.y, player.section, false)
child.data._basegame = {
parent = parentData.parent or blob,
radius = parentData.radius,
growrate = parentData.growrate,
spawned = true
}
end
end
end
end
local function cor_trySpawn(v)
local blob = v
local size = {}
local data = blob.data._basegame
local parent = data.parent or blob
if blob.isValid and parent.isValid then
local x1,x2,y1,y2 = blob.x+0.5*blob.width,parent.x+0.5*parent.width, blob.y+0.5*blob.height,parent.y+0.5*parent.height
--windowDebug(tostring(x1)..","..tostring(x2)..","..tostring(y1)..","..tostring(y2))
local distance = math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
data.distance = distance
local surrounding = NPC.getIntersecting(blob.x-0.5*blob.width, blob.y-0.5*blob.height, blob.x+1.5*blob.width, blob.y+1.5*blob.height)
if #surrounding < 9 and distance < data.radius*math.min(blob.width, blob.height) and not data.killChain then
for _,v in ipairs{{x=blob.width},{x=-blob.width},{y=blob.height},{y=-blob.height}} do
v.parent = blob
Routine.run(cor_spawnBlert, v)
end
end
Routine.skip()
if blob.isValid then
if data.animFrame ~= 0 then
if blob.isValid then
data.animFrame = 1
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 2
Routine.waitFrames(16)
end
if blob.isValid then
data.animFrame = 3
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 0
end
end
end
end
end
local function cor_blertDie(args)
SFX.play(38)
local blob = args.npc
local data = blob.data._basegame
data.animFrame = 1
Routine.waitFrames(4)
data.animFrame = 2
if blob.isValid then
local size = {width=round(blob.width), height=round(blob.height), id=blob.id}
blob.speedX = 0
blob.speedY = 0
-- Only go through with the pop effect and ripple kill if the parent reference is a valid normal blert
if data.parent.isValid and size.id == blertID.normal then
-- If killing the core, destroy all others in a ripple
if data.parent == blob then
-- Make all the surrounding blerts look dead
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local x2,y2,x3,y3 = x1-size.width*(data.radius+1), y1-size.height*(data.radius+1), x1+size.width*(data.radius+1), y1+size.height*(data.radius+1)
local surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Make the core invisible
blob.isHidden = true
Routine.waitFrames(32)
-- Double-check (I'm sure there's a much better way to handle this)
surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Kill the blerts ring by ring
SFX.play(41)
for i=1,data.radius+1,0.25 do
local surroundingB = NPC.getIntersecting(x1-i*size.width, y1-i*size.height, x1+i*size.width, y1+i*size.height)
for k,v in ipairs(surroundingB) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.killChain == true then
v.data._basegame.dead = true
v:kill()
end
end
end
Routine.skip()
end
else
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local surroundingA = NPC.getIntersecting(x1-2*size.width, y1-2*size.height, x1+2*size.width, y1+2*size.height)
local surroundingB = NPC.getIntersecting(x1-size.width, y1-1, x1+size.width, y1+1)
local surroundingC = NPC.getIntersecting(x1-1, y1-size.height, x1+1, y1+size.height)
for k,v in ipairs(surroundingA) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
v.data._basegame.timer = v.data._basegame.growrate*32 or 32
end
end
for k,v in ipairs(table.append(surroundingB,surroundingC)) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) and v ~= args.npc then
if v ~= v.data._basegame.parent then
v.data._basegame.dead = true
end
v:kill()
end
end
end
end
-- Final kill
Routine.waitFrames(4)
if blob.isValid then
data.dead = true
blob:kill()
end
end
end
function dieCheck(v)
end
function blert.onTickNPC(v)
local blob = v
-- Initialize properties
if blob.data._basegame == nil then
blob.data._basegame = {spawned = false}
end
local data = blob.data._basegame
data.growrate = data.growrate or blob.data.growrate or 1
data.radius = data.radius or blob.data.radius or 3
data.parent = data.parent or blob
data.distance = data.distance or 0
-- Never despawn offscreen, but don't start multiplying until onscreen
if blob:mem(0x12A, FIELD_WORD) == 180 then
data.spawned = true
end
if data.spawned == true then
blob:mem(0x12A, FIELD_WORD, 179)
end
-- Manage animation
data.animFrame = data.animFrame or 0
if not data.parent.isValid or data.killChain == true then
data.animFrame = 4
end
blob.animationFrame = data.animFrame
-- Manage multiplication timer
if data.timer == nil then data.timer = data.growrate*65; end;
data.timer = data.timer-1
if data.timer <= 0 and blob.isValid and not data.killChain and data.spawned then
data.timer = data.growrate*65
Routine.run(cor_trySpawn, blob)
dieCheck (blob)
end
-- Force speed to 0
--blob.speedX = 0
--blob.speedY = 0
end
function blert.onNPCKill(eventobj, npc, reason)
if (not npc.isValid) then
return;
end
if npc.id == blertID.normal and not npc:mem(0x64,FIELD_BOOL) and reason ~= HARM_TYPE_OFFSCREEN then
local blob = npc
local data = blob.data._basegame
if data.dead ~= true then
eventobj.cancelled = true
Routine.run(cor_blertDie, {npc=npc})
else
Animation.spawn(killEffect, npc.x, npc.y)
end
end
end
function blert.onInitAPI()
for k,v in pairs(blertID) do
npcManager.registerEvent(v, blert, "onTickNPC")
end
registerEvent(blert, "onNPCKill")
end
return blert
--BASE
-- v.ai1 // v.data.type {
-- /What Type?
-- 0 = !
-- 1 = Up
-- 2 = Left
-- 3 = Right
-- }
-- v.ai2 v.data.life {
-- /How long should the ghost created last?
-- }
--Ghost
-- v.ai1 v.data.type {
-- /Direction?
-- 0 = up
-- 1 = Left
-- 2 = Right
-- }
-- v.ai2 v.data.sp {
-- /Should change direction when jumped?
-- true = Yes
-- false = No
-- }
-- v.ai3 v.data.life {
-- /How long should the ghost last?
-- }
But aren't Golblert just normal ones with no reproduction cap?
According to their .ini description, they would've behaved much like Conway's Game of Life.
|
|
|
|
|
|
|
|
|
-
mariobrigade2018
- Flurry
- Posts: 354
- Joined: Wed May 24, 2023 7:00 pm
- Flair: Normie in coding who dreams of making a Mario game
- Pronouns: he/him
Postby mariobrigade2018 » Fri Jun 07, 2024 12:33 pm
Donkdonker124 wrote: ↑Fri Jun 07, 2024 6:56 am
mariobrigade2018 wrote: ↑Thu Jun 06, 2024 9:35 pm
Donkdonker124 wrote: ↑Thu Jun 06, 2024 8:31 am
As seen in this code, the (presumed) functionality of the Golblerts seem to be inactive.
Note: The function in question is located all the way at the bottom.
Edit: This code seems to be very similar to the Arrow Lift Platform.
Code: Select all local blert = {}
local npcManager = require("npcManager")
local blertID = {
normal = 490,
gol = 491
}
local blertIDMap = {}
local killEffect = 10
-- Register properties, harm types, etc. for each blert type
local blertBase = {}
for k,v in pairs(blertID) do
blertIDMap[v] = k
blertBase[k] = {
config = npcManager.setNpcSettings({
id = v,
gfxwidth = 36,
gfxheight = 36,
gfxoffsety = 0,
width = 32,
height = 32,
frames = 6,
framespeed = 8,
framestyle = 0,
score = 0,
blocknpctop = 0,
blocknpc = 0,
playerblocktop = 0,
playerblock = 0,
nohurt = 0,
nogravity = 1,
noblockcollision = 1,
jumphurt = 0
})
}
npcManager.registerHarmTypes(
v,
{
HARM_TYPE_JUMP,
HARM_TYPE_FROMBELOW,
HARM_TYPE_NPC,
HARM_TYPE_HELD,
HARM_TYPE_TAIL,
HARM_TYPE_SPINJUMP,
HARM_TYPE_SWORD,
HARM_TYPE_LAVA
},
{
[HARM_TYPE_JUMP]=10,
[HARM_TYPE_FROMBELOW]=10,
[HARM_TYPE_NPC]=10,
[HARM_TYPE_HELD]=10,
[HARM_TYPE_TAIL]=10,
[HARM_TYPE_SPINJUMP]=10,
[HARM_TYPE_LAVA]={id=13, xoffset=0.5, xoffsetBack = 0, yoffset=1, yoffsetBack = 1.5}
}
)
end
local function round(val)
local int,frac = math.modf(val)
if frac >= 0.5 then
return math.ceil(val)
else
return math.floor(val)
end
end
local function cor_spawnBlert(args)
local blob = args.parent
local parentData = blob.data._basegame
args.x = round(args.x or 0)
args.y = round(args.y or 0)
local w,h = round(blob.width),round(blob.height)
--windowDebug (tostring(args.x)..", "..tostring(args.y))
local x1,y1,x2,y2 = blob.x+args.x+2, blob.y+args.y+2, blob.x+args.x+w-2, blob.y+args.y+h-2
local npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
local blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree and blob.isValid then
parentData.animFrame = 1
Routine.waitFrames(20)
if blob.isValid then
npcFree = (#NPC.getIntersecting(x1,y1,x2,y2) == 0)
blockFree = (#Block.getIntersecting(x1,y1,x2,y2) == 0)
if npcFree and blockFree then
SFX.play(72)
local child = NPC.spawn (blob.id, blob.x+args.x, blob.y+args.y, player.section, false)
child.data._basegame = {
parent = parentData.parent or blob,
radius = parentData.radius,
growrate = parentData.growrate,
spawned = true
}
end
end
end
end
local function cor_trySpawn(v)
local blob = v
local size = {}
local data = blob.data._basegame
local parent = data.parent or blob
if blob.isValid and parent.isValid then
local x1,x2,y1,y2 = blob.x+0.5*blob.width,parent.x+0.5*parent.width, blob.y+0.5*blob.height,parent.y+0.5*parent.height
--windowDebug(tostring(x1)..","..tostring(x2)..","..tostring(y1)..","..tostring(y2))
local distance = math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1))
data.distance = distance
local surrounding = NPC.getIntersecting(blob.x-0.5*blob.width, blob.y-0.5*blob.height, blob.x+1.5*blob.width, blob.y+1.5*blob.height)
if #surrounding < 9 and distance < data.radius*math.min(blob.width, blob.height) and not data.killChain then
for _,v in ipairs{{x=blob.width},{x=-blob.width},{y=blob.height},{y=-blob.height}} do
v.parent = blob
Routine.run(cor_spawnBlert, v)
end
end
Routine.skip()
if blob.isValid then
if data.animFrame ~= 0 then
if blob.isValid then
data.animFrame = 1
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 2
Routine.waitFrames(16)
end
if blob.isValid then
data.animFrame = 3
Routine.waitFrames(4)
end
if blob.isValid then
data.animFrame = 0
end
end
end
end
end
local function cor_blertDie(args)
SFX.play(38)
local blob = args.npc
local data = blob.data._basegame
data.animFrame = 1
Routine.waitFrames(4)
data.animFrame = 2
if blob.isValid then
local size = {width=round(blob.width), height=round(blob.height), id=blob.id}
blob.speedX = 0
blob.speedY = 0
-- Only go through with the pop effect and ripple kill if the parent reference is a valid normal blert
if data.parent.isValid and size.id == blertID.normal then
-- If killing the core, destroy all others in a ripple
if data.parent == blob then
-- Make all the surrounding blerts look dead
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local x2,y2,x3,y3 = x1-size.width*(data.radius+1), y1-size.height*(data.radius+1), x1+size.width*(data.radius+1), y1+size.height*(data.radius+1)
local surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Make the core invisible
blob.isHidden = true
Routine.waitFrames(32)
-- Double-check (I'm sure there's a much better way to handle this)
surrounding = NPC.getIntersecting(x2,y2,x3,y3)
for k,v in ipairs(surrounding) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.parent == blob then
v.data._basegame.killChain = true
end
end
end
-- Kill the blerts ring by ring
SFX.play(41)
for i=1,data.radius+1,0.25 do
local surroundingB = NPC.getIntersecting(x1-i*size.width, y1-i*size.height, x1+i*size.width, y1+i*size.height)
for k,v in ipairs(surroundingB) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
if v.data._basegame.killChain == true then
v.data._basegame.dead = true
v:kill()
end
end
end
Routine.skip()
end
else
local x1,y1 = blob.x + 0.5*size.width, blob.y + 0.5*size.height
local surroundingA = NPC.getIntersecting(x1-2*size.width, y1-2*size.height, x1+2*size.width, y1+2*size.height)
local surroundingB = NPC.getIntersecting(x1-size.width, y1-1, x1+size.width, y1+1)
local surroundingC = NPC.getIntersecting(x1-1, y1-size.height, x1+1, y1+size.height)
for k,v in ipairs(surroundingA) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) then
v.data._basegame.timer = v.data._basegame.growrate*32 or 32
end
end
for k,v in ipairs(table.append(surroundingB,surroundingC)) do
if v.id == size.id and not v:mem(0x64,FIELD_BOOL) and v ~= args.npc then
if v ~= v.data._basegame.parent then
v.data._basegame.dead = true
end
v:kill()
end
end
end
end
-- Final kill
Routine.waitFrames(4)
if blob.isValid then
data.dead = true
blob:kill()
end
end
end
function dieCheck(v)
end
function blert.onTickNPC(v)
local blob = v
-- Initialize properties
if blob.data._basegame == nil then
blob.data._basegame = {spawned = false}
end
local data = blob.data._basegame
data.growrate = data.growrate or blob.data.growrate or 1
data.radius = data.radius or blob.data.radius or 3
data.parent = data.parent or blob
data.distance = data.distance or 0
-- Never despawn offscreen, but don't start multiplying until onscreen
if blob:mem(0x12A, FIELD_WORD) == 180 then
data.spawned = true
end
if data.spawned == true then
blob:mem(0x12A, FIELD_WORD, 179)
end
-- Manage animation
data.animFrame = data.animFrame or 0
if not data.parent.isValid or data.killChain == true then
data.animFrame = 4
end
blob.animationFrame = data.animFrame
-- Manage multiplication timer
if data.timer == nil then data.timer = data.growrate*65; end;
data.timer = data.timer-1
if data.timer <= 0 and blob.isValid and not data.killChain and data.spawned then
data.timer = data.growrate*65
Routine.run(cor_trySpawn, blob)
dieCheck (blob)
end
-- Force speed to 0
--blob.speedX = 0
--blob.speedY = 0
end
function blert.onNPCKill(eventobj, npc, reason)
if (not npc.isValid) then
return;
end
if npc.id == blertID.normal and not npc:mem(0x64,FIELD_BOOL) and reason ~= HARM_TYPE_OFFSCREEN then
local blob = npc
local data = blob.data._basegame
if data.dead ~= true then
eventobj.cancelled = true
Routine.run(cor_blertDie, {npc=npc})
else
Animation.spawn(killEffect, npc.x, npc.y)
end
end
end
function blert.onInitAPI()
for k,v in pairs(blertID) do
npcManager.registerEvent(v, blert, "onTickNPC")
end
registerEvent(blert, "onNPCKill")
end
return blert
--BASE
-- v.ai1 // v.data.type {
-- /What Type?
-- 0 = !
-- 1 = Up
-- 2 = Left
-- 3 = Right
-- }
-- v.ai2 v.data.life {
-- /How long should the ghost created last?
-- }
--Ghost
-- v.ai1 v.data.type {
-- /Direction?
-- 0 = up
-- 1 = Left
-- 2 = Right
-- }
-- v.ai2 v.data.sp {
-- /Should change direction when jumped?
-- true = Yes
-- false = No
-- }
-- v.ai3 v.data.life {
-- /How long should the ghost last?
-- }
But aren't Golblert just normal ones with no reproduction cap?
According to their .ini description, they would've behaved much like Conway's Game of Life.
Yea here’s the blog post:
https://codehaus.wohlsoft.ru/blog/2017/ ... -500-npcs/
|
|
|
|
|
Return to “LunaLua”
|