hangblocks.lua - Hang in there, baby! (v1.1)

Share and discuss custom LunaLua code and content packs for SMBX2.

Moderator: Userbase Moderators

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

hangblocks.lua - Hang in there, baby! (v1.1)

Postby cold soup » Thu Mar 30, 2023 9:07 pm

Blocks you can grab and hang on to, sorta like horizontal ropes. They're similar to the horizontal ropes from the Donkey Kong Country games. You grab them automatically if you're falling. While grabbing one, you can move left and right, jump from them, or let go of them by pressing down.

Since I only made and configured graphics for Mario, he's the only character you can use on them by default (other characters cause an error). However, once you have graphics configured for them, the other classic characters (Luigi, Peach, Toad, Link) should work with them too. X2 characters probably won't work.

Check the readme for guides on how to register blocks or create character graphics!

EXAMPLE:
Spoiler: show
Image
Spoiler: show
Image
DOWNLOAD:
Last edited by cold soup on Tue Aug 20, 2024 11:37 pm, edited 4 times in total.

ditditdit
Buster Beetle
Buster Beetle
Posts: 92
Joined: Sun Jan 02, 2022 4:25 pm
Flair: e
Pronouns: she/they
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby ditditdit » Fri Mar 31, 2023 1:48 pm

i love this!

although to me, the climbing sprites for mario in the gif look cursed.

DRACalgar Law
Tweeter
Tweeter
Posts: 137
Joined: Sun Oct 16, 2022 3:59 pm
Flair: King of the Boss Makers
Pronouns: he/him
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby DRACalgar Law » Fri Mar 31, 2023 2:20 pm

Will those players be able to attack while hanging?

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby cold soup » Sat Apr 01, 2023 4:41 pm

ditditdit wrote:
Fri Mar 31, 2023 1:48 pm
i love this!

although to me, the climbing sprites for mario in the gif look cursed.
i'm gonna be honest, the sprites were just kinda thrown together. plus i'm not really well-versed in the SMB3 style
DRACalgar Law wrote:
Fri Mar 31, 2023 2:20 pm
Will those players be able to attack while hanging?
nope

ChunkyChimp
Spiny
Spiny
Posts: 26
Joined: Tue Sep 01, 2020 9:02 pm
Flair: I TAKE GFX FOR MY OWN LEVELS

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby ChunkyChimp » Fri Apr 07, 2023 11:39 pm

Looks like a great addition, but I think Mario should face away while hanging. Or be rendered behind the rope. RN looks wacky

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9891
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby Emral » Mon Apr 10, 2023 3:46 am

Hey there! Great script, just one thing you ought to change!
Your script seems to add new variables to the player. The player does not have a data table, so this could come into conflict with other code, or accidentally override basegame variables.
Infact, the variable p.isOnGround overwrites the basegame method p:isOnGround(). This causes scripts to error when your script is loaded, if they perform grounded checks for the player.
My recommendation is to not store this value in the player, but make your own table storing the value for each player.
local isOnGround = {false, false}

isOnGround[p.idx] = true

Gaming.

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby cold soup » Mon May 08, 2023 11:00 pm

Emral wrote:
Mon Apr 10, 2023 3:46 am
Hey there! Great script, just one thing you ought to change!
Your script seems to add new variables to the player. The player does not have a data table, so this could come into conflict with other code, or accidentally override basegame variables.
Infact, the variable p.isOnGround overwrites the basegame method p:isOnGround(). This causes scripts to error when your script is loaded, if they perform grounded checks for the player.
My recommendation is to not store this value in the player, but make your own table storing the value for each player.
local isOnGround = {false, false}

isOnGround[p.idx] = true

Gaming.
thanks for the advice! i thought that was a variable that players had since it was in the SMBX2 documentation, and i assumed i needed it set to "true" so players have ground friction while grabbing a hangblock. turns out it's neither, so i removed the line of code that sets it in the latest update. thanks for pointing out it can cause errors, hopefully that should be fixed now

Emral
Cute Yoshi Egg
Cute Yoshi Egg
Posts: 9891
Joined: Mon Jan 20, 2014 12:58 pm
Flair: Phoenix

Re: hangblocks.lua - Hang in there, baby! (v1.0.2)

Postby Emral » Tue May 09, 2023 8:50 am

cold soup wrote:
Mon May 08, 2023 11:00 pm

thanks for the advice! i thought that was a variable that players had since it was in the SMBX2 documentation, and i assumed i needed it set to "true" so players have ground friction while grabbing a hangblock. turns out it's neither, so i removed the line of code that sets it in the latest update. thanks for pointing out it can cause errors, hopefully that should be fixed now
Ahh, I understand the misunderstanding there. This function is actually only used by SMBX2 user code, so it wouldn't affect friction. I believe one of the memory offsets that handles bottom block collision is responsible for that, but that also controls jumping ability, so it might be best to not mess too much with the guts of the system.
I looked over the update and it looks good now (thumbsup).

FutureNyanCat
Foo
Foo
Posts: 805
Joined: Fri Dec 20, 2013 8:39 pm
Flair: Species: Felis robotus
Pronouns: He/Him
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.3)

Postby FutureNyanCat » Fri Sep 22, 2023 6:54 am

I've reported a bug where if the script is loaded in a level, players won't be able to grab NPCs that have the grabtop flag enabled, including SMB2 grass and Shy Guys. I'm not sure how to fix that.

Master of Disaster
Swooper
Swooper
Posts: 67
Joined: Sun Nov 28, 2021 9:29 am
Flair: Average Koopa Fan
Pronouns: he/him

Re: hangblocks.lua - Hang in there, baby! (v1.0.3)

Postby Master of Disaster » Fri Sep 22, 2023 7:38 am

FutureNyanCat wrote:
Fri Sep 22, 2023 6:54 am
I've reported a bug where if the script is loaded in a level, players won't be able to grab NPCs that have the grabtop flag enabled, including SMB2 grass and Shy Guys. I'm not sure how to fix that.
Fixed it. The Cause was that the grabDelay was always set when ducking, even if the player is not hanging on a rope. I just moved the part that sets the grabDelay so it only executes when holding a rope.

Here's the code:

Code: Select all

--[[
	hangblocks.lua v1.0.3 (v.1.0.4 now hehehe)

	A library that adds blocks that function as Donkey Kong Country 2-esque horizontal ropes.
	This script handles player behavior when hanging from a block, as well as collision detection
	for hangblocks.

	by cold soup
]]

local blockManager = require("blockManager")

local hangblocks = {}

local blockIDs = {}

hangblocks.playerData = {}

---------------------- CUSTOMIZABLE PROPERTIES ----------------------
--[[
	This script by default is only configured properly for Mario, as he's the only one I made 
	graphics for. However, you can set the graphics and properties of other characters by adding 
	their constants to the tables of individual properties.
	
	Example: 
	hangblocks.grabframes = {
	 	[CHARACTER_MARIO] = Graphics.loadImageResolved("grabframes-mario.png"),
		[CHARACTER_LUIGI] = Graphics.loadImageResolved("grabframes-luigi.png")
	}

	List of character constants: https://docs.codehaus.moe/#/constants/characters
]]

-- grab graphics
hangblocks.grabframes = {
	[CHARACTER_MARIO] = Graphics.loadImageResolved("grabframes-mario.png")
}

-- width and height of an individual frame
hangblocks.framewidth = {
	[CHARACTER_MARIO] = 36
}
hangblocks.frameheight = {
	[CHARACTER_MARIO] = 60
}

-- x and y offsets of a single frame
hangblocks.frameXoffset = {
	[CHARACTER_MARIO] = -4
}
hangblocks.frameYoffset = {
	[CHARACTER_MARIO] = -6
}

-- number of frames for moving while on a hangblock
hangblocks.numframes = {
	[CHARACTER_MARIO] = 2
}

-- render priority of the climbing animation
-- mainly here if you want a character to be behind the blocks
hangblocks.framepriority = {
	[CHARACTER_MARIO] = -25
}

-- speed of the animation
hangblocks.animSpeed = 12

---------------------------------------------------------------------

function hangblocks.register(id)
	blockManager.registerEvent(id, hangblocks, "onTickEndBlock")
	blockIDs[id] = true
end

function hangblocks.onInitAPI()
	registerEvent(hangblocks, "onTick")
	registerEvent(hangblocks, "onDraw")
end

local function initializePlayerData(index)
	if hangblocks.playerData[index] then return end
	hangblocks.playerData[index] = {
		grabbing = false,
		currentBlock = nil,
		grabDelay = 0, -- player can't grab blocks if this value is above 0, used so small players can drop 
		currentFrame = 0,
		animationTimer = hangblocks.animSpeed;
	}
end

function hangblocks.onTick()
	for _,p in ipairs(Player.get()) do
		initializePlayerData(p.idx)

		if (hangblocks.playerData[p.idx].grabDelay > 0) then
			hangblocks.playerData[p.idx].grabDelay = hangblocks.playerData[p.idx].grabDelay - 1
			p:mem(0x172,FIELD_BOOL,false) -- added so the player doesn't shoot a projectile/tail swipe when they jump off
		end

		--[[if (player:mem(0x12E, FIELD_BOOL)) then -- prevents players from grabbing ropes while crouching		-- THIS IS MOVED SINCE IT BREAKS GRABBING NPCS FROM ABOVE.
			hangblocks.playerData[p.idx].grabDelay = 10 -- set to 10 because link gets stuck otherwise
		end--]]--

		-- behavior for grabbing a rope
		if (hangblocks.playerData[p.idx].grabbing) then
			p.y = hangblocks.playerData[p.idx].currentBlock.y
			p.speedY = 0

			-- prevents the player from running or using projectiles while grabbing a rope
			p.keys.run = false
			p.keys.altRun = false

			if (player:mem(0x12E, FIELD_BOOL)) then -- prevents players from grabbing ropes while crouching	-- NOW ONLY EXECUTED WHEN THE PLAYER GRABS THE ROPE; Breaks grabbing from above otherwise
				hangblocks.playerData[p.idx].grabDelay = 10 -- set to 10 because link gets stuck otherwise
			end
			
			-- animation-related code
			if (p.speedX == 0) then
				hangblocks.playerData[p.idx].currentFrame = 0
				hangblocks.playerData[p.idx].animationTimer = hangblocks.animSpeed + 1
			else
				hangblocks.playerData[p.idx].animationTimer = hangblocks.playerData[p.idx].animationTimer + 1

				if (hangblocks.playerData[p.idx].animationTimer > hangblocks.animSpeed) then
					hangblocks.playerData[p.idx].currentFrame = (1 + (hangblocks.playerData[p.idx].currentFrame % hangblocks.numframes[p.character]))
					if (p.direction == -1) then hangblocks.playerData[p.idx].currentFrame = hangblocks.playerData[p.idx].currentFrame + hangblocks.numframes[p.character] end
					
					hangblocks.playerData[p.idx].animationTimer = 0
				end
			end

			-- lets go of the rope if the player jumped or pressed down
			if(p.keys.jump == KEYS_PRESSED or p.keys.altJump == KEYS_PRESSED or p.keys.down == KEYS_DOWN) then
				hangblocks.playerData[p.idx].grabbing = false
				hangblocks.playerData[p.idx].grabDelay = 10
			end
		end

		hangblocks.playerData[p.idx].grabbing = false
	end
end

function hangblocks.onDraw()
  	for _,p in ipairs(Player.get()) do
  		if (hangblocks.playerData[p.idx].grabbing and p.deathTimer <= 0) then
  			p:setFrame(-50)

			if (not p:mem(0x142, FIELD_BOOL)) then -- don't draw the player if they're blinking
  				Graphics.draw{
  					type = RTYPE_IMAGE,
  					image = hangblocks.grabframes[p.character],
  					sceneCoords = true,
  					x = p.x + hangblocks.frameXoffset[p.character],
  					y = p.y + hangblocks.frameYoffset[p.character],
  					priority = hangblocks.framepriority[p.character],
  					sourceX = hangblocks.playerData[p.idx].currentFrame * hangblocks.framewidth[p.character],
  					sourceY = (hangblocks.frameheight[p.character] * (p.powerup)) - hangblocks.frameheight[p.character],
  					sourceWidth = hangblocks.framewidth[p.character],
  					sourceHeight = hangblocks.frameheight[p.character]
  				}
  			end
		end
  	end
end

function hangblocks.onTickEndBlock(v)
    -- Don't run code for invisible entities
	if v.isHidden or v:mem(0x5A, FIELD_BOOL) then return end
	
	local data = v.data
	
	-- checks for players touching the block
	for _,p in ipairs(Player.getIntersecting(v.x,v.y,v.x+v.width,v.y+v.height)) do
		if (p.speedY >= 0 and -- player is falling
			p.y > v.y-6 and -- top of player is touching the block
			hangblocks.playerData[p.idx].grabDelay <= 0 and -- doesn't have grab delay
			not p:mem(0x36,FIELD_BOOL) and -- not underwater/in quicksand
			p.forcedState <= 0
		) then
			hangblocks.playerData[p.idx].grabbing = true
			hangblocks.playerData[p.idx].currentBlock = v
		end
	end
end

return hangblocks

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.3)

Postby cold soup » Fri Sep 22, 2023 12:39 pm

Master of Disaster wrote:
Fri Sep 22, 2023 7:38 am
FutureNyanCat wrote:
Fri Sep 22, 2023 6:54 am
I've reported a bug where if the script is loaded in a level, players won't be able to grab NPCs that have the grabtop flag enabled, including SMB2 grass and Shy Guys. I'm not sure how to fix that.
Fixed it. The Cause was that the grabDelay was always set when ducking, even if the player is not hanging on a rope. I just moved the part that sets the grabDelay so it only executes when holding a rope.
thanks for pointing this out! the bit of code you moved was there originally since otherwise big characters couldn't let go of ropes properly when pressing down. turns out that had some bad side effects. the latest version should let you pick up grabtop enemies now while still allowing big characters to let go of ropes properly. if anyone still finds any issues though let me know

The Thwomp King
Boss Bass
Boss Bass
Posts: 1272
Joined: Tue Feb 17, 2015 12:09 pm

Re: hangblocks.lua - Hang in there, baby! (v1.0.4)

Postby The Thwomp King » Tue Feb 06, 2024 7:11 pm

Wow this is really cool, and I love how smooth everything runs. Definitely using this for my project, and I'm hoping someone makes more hanging graphics for other characters in the near future!

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.0.5)

Postby cold soup » Wed Feb 14, 2024 8:44 pm

cold soup wrote:
Thu Mar 30, 2023 9:07 pm
Blocks you can grab and hang on to, sorta like horizontal ropes. They're similar to the horizontal ropes from the Donkey Kong Country games. You grab them automatically if you're falling. While grabbing one, you can move left and right, jump from them, or let go of them by pressing down.

Since I only made and configured graphics for Mario, he's the only character you can use on them by default (other characters cause an error). However, once you have graphics configured for them, the other classic characters (Luigi, Peach, Toad, Link) should work with them too. X2 characters probably won't work.

Check the readme for guides on how to register blocks or create character graphics!

EXAMPLE:
Spoiler: show
Image
Spoiler: show
Image
DOWNLOAD:
pushed another bugfix. this fixes an issue where the library occasionally threw an error upon the level loading, which i think only really started happening in beta 5 (though it stemmed from a programming error on my part Oops). i'd suggest updating the library if one of your levels uses it

cold soup
Swooper
Swooper
Posts: 73
Joined: Wed May 13, 2020 8:29 pm
Flair: yeah
Pronouns: they/she
Contact:

Re: hangblocks.lua - Hang in there, baby! (v1.1)

Postby cold soup » Tue Aug 20, 2024 11:46 pm

new update! this makes it so you can no longer fall off of hangblocks from the side, which makes a lot more sense visually. this change is enabled by default but it's toggleable. aside from a few QoL features there's a pretty significant optimization change so i'd update the script asap if you're using it in your episode

full changelog
Spoiler: show
- Added an parameter that prevents players from falling off the sides of hangblocks that's active by default. To go back to the original behavior, set hangblocks.canFallOffSide to true.
- Default block's ID has been changed because the reserved blocks range doesn't start at 750. Oops!

- Hangblock-related data now use the player's data table, meaning it's easier to check said data from other scripts. Data is stored under Player.data.hangblocks.
- Collisions with hangblocks are now better optimized because the original way they checked for collisions was really stupid and bad


Return to “LunaLua”

Who is online

Users browsing this forum: No registered users and 6 guests

SMWCentralTalkhausMario Fan Games GalaxyKafukaMarioWikiSMBXEquipoEstelari