What's the best way to make a multi-hit killbrick that works with CanCollide set to true and false?

The game Jupiter’s Towers of Hell has these killbricks that hit multiple times every second. I tried to replicate this, but my killbricks(in the form of spikes) still only hit when the player moves. Does anyone know how to solve this?

Resources:

players = []
When a player touches the spikes
players[player] = tick()
When a player stops touching a spike
players[player]=nil

create a function that fires every heartbeat (or however often you want it to fire) iterating through the values in the map and damaging them by (tick()-players[player]) * damage_per_second. Then set players[player] to tick again.

2 Likes

Region 3 is pretty useful for this. Just have a loop that checks every second if there is something in the region (or technically the hitbox) that has a humanoid and then just damage it.

2 Likes

You could also attach this to Heartbeat so that it’s checked every frame

All you would really need to do is have a short wait() paried with a debounce and TakeDamage()

That’ll give you the exact effect though it will also allow you to change how long you want the player to take damage right after so if you do a normal wait() then it will be super short however, if you do wait(1) it will take 1 second afterwards to cause more damage.

(Similar to tlr22 but without tick())

local PartsTouching = {}

part.Touched:Connect(function(part)
–add it to PartsTouching
end)

parts.TouchEnded:Connect(function(part)
–remove it from PartsTouching
end)

while wait(1) do
– get players from PartsTouching and do damage
end

Ok, I tried doing this. I’m not much of a coder, unfortunately, so I was wondering why this wasn’t working.

Something like this. I don’t expect this to work completely as I haven’t tested it, but you can atleast start from here I guess.

local partsTouching = {}

local function ObjectExistsInTable(tableToCheck, object)
	for iteration, objectIteration in ipairs(tableToCheck) do
		if object == objectIteration then
			return true, iteration
		end
	end
	return false
end

part.Touched:connect(function(hit)
	local exists, iteration = ObjectExistsInTable(partsTouching, hit)
	if not exists then
		table.insert(partsTouching, hit)
	end
end)

part.TouchEnded:connect(function(hit)
	local exists, iteration = ObjectExistsInTable(partsTouching, hit)
	if exists then
		print("removing "..hit.Name)
		table.remove(partsTouching, iteration)
	end
end)

while wait(1) do
	local players = {}
	for iteration, partTouching in ipairs(partsTouching) do
		local player = game.Players:GetPlayerFromCharacter(partTouching.Parent)
		if player then
			local exists, iteration = ObjectExistsInTable(players, player)
			if not exists then
				table.insert(players, player)
			end
		end
	end 
	
	for iteration, player in ipairs(players) do
		player.Character.Humanoid:TakeDamage(10)
	end
end
4 Likes

You might as well use BasePart.GetTouchingParts for this kind of a system instead of reinventing the wheel with both a Touched and TouchEnded event outside of your while wait loop. The way you’re handling it is also fairly expensive and it only gets worse should there be more entries in the table.

Some pointers, although not that relevant:

  • Lowercase methods are deprecated in favour of PasalCase methods, so it’d be Connect. It’s often recommended that you don’t use deprecated items.

    • Unless you don’t care, which some developers don’t. ex
  • GetService is the canonical way to fetch a service. It should be used over indexing services with dot syntax. This is especially so when it comes to consistency.

    • Again, unless you don’t care. No problem with direct indexing.
1 Like

Wasn’t aware of the GetTouchingParts. Good call on that. With the other two, I don’t really care lol. Players is created by default anyways. I use GetService for anything that’s not created by default. and I’m too used to lowercase connect, feelsbad.

Good looks though.

1 Like