Skip to content

Instantly share code, notes, and snippets.

@Dregu
Last active March 14, 2024 14:23
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Dregu/c42da3ac903342891b55f1208a4523c7 to your computer and use it in GitHub Desktop.
Save Dregu/c42da3ac903342891b55f1208a4523c7 to your computer and use it in GitHub Desktop.
Spelunky 2 custom tile codes

Spelunky 2 custom tile codes

Random custom tile codes and other crap for custom levels. Free for all!

-- this one is a bit more complicated than the other example here,
-- but these chains will also attach to blocks in the middle
-- piece of chain, attached to what's on top
define_tile_code("chain")
set_pre_tile_code_callback(function(x, y, layer)
local ceiling = get_grid_entity_at(x, y+1, layer)
if ceiling == -1 then
local block = get_entities_at(ENT_TYPE.ACTIVEFLOOR_CHAINEDPUSHBLOCK, MASK.ACTIVEFLOOR, x, y+1, layer, 0.5)
if #block > 0 then
ceiling = block[1]
end
end
spawn_over(ENT_TYPE.FLOOR_CHAINANDBLOCKS_CHAIN, ceiling, 0, -1)
return true
end, "chain")
-- piece of chain with a firebug on it
define_tile_code("chain_firebug")
set_pre_tile_code_callback(function(x, y, layer)
local ceiling = get_grid_entity_at(x, y+1, layer)
if ceiling == -1 then
local block = get_entities_at(ENT_TYPE.ACTIVEFLOOR_CHAINEDPUSHBLOCK, MASK.ACTIVEFLOOR, x, y+1, layer, 0.5)
if #block > 0 then
ceiling = block[1]
end
end
local chain = spawn_over(ENT_TYPE.FLOOR_CHAINANDBLOCKS_CHAIN, ceiling, 0, -1)
spawn_over(ENT_TYPE.MONS_FIREBUG, chain, 0, 0)
return true
end, "chain_firebug")
-- block, attached to what's on top
define_tile_code("chain_block")
set_pre_tile_code_callback(function(x, y, layer)
local ceiling = get_grid_entity_at(x, y+1, layer)
spawn_over(ENT_TYPE.ACTIVEFLOOR_CHAINEDPUSHBLOCK, ceiling, 0, -1)
return true
end, "chain_block")
-- queen bee who breaks tiles
define_tile_code("brute_bee")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_critical(ENT_TYPE.MONS_QUEENBEE, x, y, layer, 0, 0)
set_post_statemachine(uid, function(ent)
local x, y, l = get_position(ent.uid)
local dx = math.random(-1, 1)
local dy = math.random(-1, 1)
local floor = get_grid_entity_at(x+dx, y+dy, l)
if floor ~= -1 then
local ent = get_entity(floor)
if test_flag(ent.flags, ENT_FLAG.SOLID) and not test_flag(ent.flags, ENT_FLAG.INDESTRUCTIBLE_OR_SPECIAL_FLOOR) then
kill_entity(floor)
end
end
end)
return true
end, "brute_bee")
-- spawn bubbles from any water surface like tiamat's
set_post_entity_spawn(function(e)
e:set_post_update_state_machine(function(e)
if prng:random() < 0.0002 then
spawn_critical(ENT_TYPE.ACTIVEFLOOR_BUBBLE_PLATFORM, e.abs_x, e.abs_y, e.layer, 0, 0)
end
end)
end, SPAWN_TYPE.ANY, MASK.FX, ENT_TYPE.FX_WATER_SURFACE)
-- this guy is riding a turkey, roaming around like the vanilla one
define_tile_code("caveman_turkey")
set_pre_tile_code_callback(function(x, y, layer)
local rider = get_entity(spawn_critical(ENT_TYPE.MONS_CAVEMAN, x, y, layer, 0, 0))
local mount = get_entity(spawn_critical(ENT_TYPE.MOUNT_TURKEY, x, y, layer, 0, 0))
mount:tame(true)
carry(mount.uid, rider.uid)
rider.move_state = 0
end, "caveman_turkey")
-- this guy just sits on the ground unless you stomp him, won't even get up when touched but will bite
define_tile_code("caveman_sitting")
set_pre_tile_code_callback(function(x, y, layer)
local rider = get_entity(spawn_critical(ENT_TYPE.MONS_CAVEMAN, x, y, layer, 0, 0))
rider:set_behavior(2)
end, "caveman_sitting")
-- this guy just stands still unless you touch him, won't attack on sight
define_tile_code("caveman_standing")
set_pre_tile_code_callback(function(x, y, layer)
local rider = get_entity(spawn_critical(ENT_TYPE.MONS_CAVEMAN, x, y, layer, 0, 0))
rider.move_state = 17
end, "caveman_standing")
-- this guy is sleeping and will wake up if you disturb him, like vanilla
define_tile_code("caveman_sleeping")
set_pre_tile_code_callback(function(x, y, layer)
local rider = get_entity(spawn_critical(ENT_TYPE.MONS_CAVEMAN, x, y, layer, 0, 0))
rider.move_state = 11
end, "caveman_sleeping")
-- piece of chain, attached to what's on top
define_tile_code("chain")
set_pre_tile_code_callback(function(x, y, layer)
local ceiling = get_grid_entity_at(x, y+1, layer)
spawn_over(ENT_TYPE.FLOOR_CHAINANDBLOCKS_CHAIN, ceiling, 0, -1)
return true
end, "chain")
-- piece of chain with a firebug on it
define_tile_code("chain_firebug")
set_pre_tile_code_callback(function(x, y, layer)
local ceiling = get_grid_entity_at(x, y+1, layer)
local chain = spawn_over(ENT_TYPE.FLOOR_CHAINANDBLOCKS_CHAIN, ceiling, 0, -1)
spawn_over(ENT_TYPE.MONS_FIREBUG, chain, 0, 0)
return true
end, "chain_firebug")
-- just sets the level spawn, no background, platforms, pots or torches
define_tile_code("entrance_nocrap")
set_pre_tile_code_callback(function(x, y, layer)
spawn_grid_entity(ENT_TYPE.FLOOR_DOOR_ENTRANCE, x, y, layer)
state.level_gen.spawn_x = x
state.level_gen.spawn_y = y
local rx, ry = get_room_index(x, y)
state.level_gen.spawn_room_x = rx
state.level_gen.spawn_room_y = ry
return true
end, "entrance_nocrap")
-- example for extra spawns to spawn two extra dogs in natural hidey-holes like vanilla
-- replaces any useless treasure already there if necessary
function has(arr, item)
for _, v in pairs(arr) do
if v == item then
return true
end
end
return false
end
keep_items = {ENT_TYPE.ITEM_CURSEDPOT, ENT_TYPE.ITEM_CRATE, ENT_TYPE.ITEM_LOCKEDCHEST_KEY}
function only_useless_items_at(x, y, l)
if #get_entities_at(0, MASK.MONSTER | MASK.ACTIVEFLOOR, x, y, l, 0.4) > 0 then return false end
for i,v in pairs(get_entities_at(0, MASK.ITEM, x, y, l, 0.4)) do
local ent = get_entity(v)
if has(keep_items, ent.type.id) then return false end
end
return true
end
function clear_useless_items_at(x, y, l)
for i,v in pairs(get_entities_at(0, MASK.ITEM, x, y, l, 0.4)) do
local ent = get_entity(v)
if has(keep_items, ent.type.id) then return end
ent:destroy()
end
end
function is_solid_floor(x, y, l)
local ent = get_entity(get_grid_entity_at(x, y, l))
if not ent then return false end
return test_flag(ent.flags, ENT_FLAG.SOLID)
end
function hidey_hole_is_valid(x, y, l)
if not default_spawn_is_valid(x, y, l) then return false end
if is_solid_floor(x, y-1, l) and is_solid_floor(x, y+1, l) and (is_solid_floor(x-1, y, l) or is_solid_floor(x+1, y, l)) then
return only_useless_items_at(x, y, l)
end
return false
end
spawn_extra_dog = define_extra_spawn(function(x, y, l)
clear_useless_items_at(x, y, l)
spawn_entity_snapped_to_floor(ENT_TYPE.MONS_PET_DOG, x, y, l)
end, hidey_hole_is_valid, 0, 0)
set_callback(function(room_gen_ctx)
room_gen_ctx:set_num_extra_spawns(spawn_extra_dog, 2, 0)
end, ON.POST_ROOM_GENERATION)
-- horizontal elevator that activates when you step on it
define_tile_code("elevator_horizontal")
set_pre_tile_code_callback(function(x, y, layer)
local ent = get_entity(spawn(ENT_TYPE.ACTIVEFLOOR_CRUSH_TRAP, x, y, layer, 0, 0))
ent.angle = math.pi/2
ent.animation_frame = 26
for _,t in ipairs(entity_get_items_by(ent.uid, 0, MASK.LOGICAL)) do
get_entity(t):destroy()
end
set_post_statemachine(ent.uid, function(ent)
for _,p in ipairs(entity_get_items_by(ent.uid, 0, MASK.PLAYER)) do
local player = get_entity(p)
if player.idle_counter >= 30 and ent.move_state == 0 then
local ex, ey, l = get_position(ent.uid)
local right = get_grid_entity_at(ex+1, ey, l)
if right == -1 then
ent.dirx = 1
else
ent.dirx = -1
end
ent.move_state = 6
end
end
if ent.dirx < 0 and ent.move_state == 6 then
ent.animation_frame = 27
elseif ent.dirx > 0 and ent.move_state == 6 then
ent.animation_frame = 28
else
ent.animation_frame = 26
end
end)
return true
end, "elevator_horizontal")
-- horizontal forcefields that are actually pointing in the right direction
-- left is off when right is on, like in tiamat
define_tile_code("forcefield_right")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_HORIZONTAL_FORCEFIELD, x, y, layer)
local ent = get_entity(uid)
ent.angle = 3*math.pi/2
end, "forcefield_right")
define_tile_code("forcefield_right_top")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_HORIZONTAL_FORCEFIELD_TOP, x, y, layer)
local ent = get_entity(uid)
ent.angle = 3*math.pi/2
end, "forcefield_right_top")
define_tile_code("forcefield_left")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_HORIZONTAL_FORCEFIELD, x, y, layer)
local ent = get_entity(uid)
ent.angle = math.pi/2
ent.flags = set_flag(ent.flags, ENT_FLAG.FACING_LEFT)
ent.timer = 60
end, "forcefield_left")
define_tile_code("forcefield_left_top")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_HORIZONTAL_FORCEFIELD_TOP, x, y, layer)
local ent = get_entity(uid)
ent.angle = math.pi/2
ent.flags = set_flag(ent.flags, ENT_FLAG.FACING_LEFT)
end, "forcefield_left_top")
-- horizontal forcefield facing right, that's always on
define_tile_code("forcefield_right_on")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_HORIZONTAL_FORCEFIELD, x, y, layer)
local ent = get_entity(uid)
ent.angle = 3*math.pi/2
ent:set_post_update_state_machine(function(e)
e.timer = 1
end)
end, "forcefield_right_on")
-- quillback who rolls forever after seen the player
define_tile_code("infinite_quillback")
set_pre_tile_code_callback(function(x, y, layer)
local quill = spawn(ENT_TYPE.MONS_CAVEMAN_BOSS, x, y, layer, 0, 0)
set_post_statemachine(quill, function(ent)
if ent.seen_player then
ent.move_state = 10
end
end)
return true
end, "infinite_quillback")
-- the one and only kaizo block
define_tile_code("kaizo_block")
set_pre_tile_code_callback(function(x, y, layer)
local ent = get_entity(spawn(ENT_TYPE.ACTIVEFLOOR_PUSHBLOCK, x, y, layer, 0, 0))
ent.flags = set_flag(ent.flags, ENT_FLAG.NO_GRAVITY)
ent.more_flags = set_flag(ent.more_flags, ENT_MORE_FLAG.DISABLE_INPUT)
ent.flags = set_flag(ent.flags, ENT_FLAG.INVISIBLE)
ent.flags = clr_flag(ent.flags, ENT_FLAG.SOLID)
local trigger = get_entity(spawn_over(ENT_TYPE.LOGICAL_TENTACLE_TRIGGER, ent.uid, 0, 0))
trigger.x = 0
trigger.y = -0.5
trigger.hitboxx = 0.22
trigger.hitboxy = 0.05
trigger.offsetx = 0
trigger.offsety = 0
set_pre_collision2(trigger.uid, function(self, collidee)
local bx, by, bl = get_position(ent.uid)
local cx, cy, cl = get_position(collidee.uid)
if test_flag(ent.flags, ENT_FLAG.INVISIBLE) and collidee.velocityy > 0 and cy < y-0.3 then
ent.flags = clr_flag(ent.flags, ENT_FLAG.INVISIBLE)
ent.flags = set_flag(ent.flags, ENT_FLAG.SOLID)
collidee.velocityy = -0.1
spawn(ENT_TYPE.ITEM_GOLDCOIN, bx, by+0.6, bl, 0, 0.2)
self:destroy()
end
return true
end)
return true
end, "kaizo_block")
-- use main exit in a regular level, functioning as a real exit
define_tile_code("main_exit")
set_pre_tile_code_callback(function(x, y, layer)
local exitdoor = get_entity(spawn(ENT_TYPE.FLOOR_DOOR_MAIN_EXIT, x, y, layer, 0, 0))
-- uncomment if you just want it for decoration
--exitdoor.flags = clr_flag(exitdoor.flags, ENT_FLAG.ENABLE_BUTTON_PROMPT)
spawn(ENT_TYPE.BG_OUROBORO, x, y+6, layer, 0, 0)
return true
end, "main_exit")
set_post_entity_spawn(function(ent)
set_timeout(function()
-- manually load transition so we don't get stuck chasing our tail
state.screen_next = SCREEN.TRANSITION
state.loading = 1
end, 360)
end, SPAWN_TYPE.SYSTEMIC, 0, ENT_TYPE.FX_OUROBORO_HEAD)
-- they aggro automatically
define_tile_code("mosquito_aggro")
set_pre_tile_code_callback(function(x, y, layer)
local fly = get_entity(spawn(ENT_TYPE.MONS_MOSQUITO, x, y, layer, 0, 0))
fly.move_state = 6
return true
end, "mosquito_aggro")
-- olmec pillars that grow up until they hit a ceiling or level ends
define_tile_code("pillar_grow")
set_pre_tile_code_callback(function(x, y, layer)
local bottom = get_entity(spawn_critical(ENT_TYPE.BG_OLMEC_PILLAR, x, y, layer, 0, 0))
bottom.animation_frame = 10
y = y + 1
local top
while #get_entities_at(0, MASK.FLOOR, x, y, layer, 1) == 0 and y < 123 do
top = get_entity(spawn_critical(ENT_TYPE.BG_OLMEC_PILLAR, x, y, layer, 0, 0))
top.animation_frame = 5
y = y + 1
end
top.animation_frame = 0
end, "pillar_grow")
-- oneway dustwalls that push you in whatever direction. doesn't affect movement if already moving in the right way
define_tile_code("dustwall_right")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn(ENT_TYPE.FLOOR_DUSTWALL, x, y, layer, 0, 0)
local ent = get_entity(uid)
ent.flags = clr_flag(ent.flags, ENT_FLAG.SOLID)
ent.hitboxx = 0.45
ent.hitboxy = 0.45
set_pre_collision2(uid, function(self, collidee)
if collidee.velocityx < 0.1 then collidee.velocityx = 0.1 end
return true
end)
return true
end, "dustwall_right")
define_tile_code("dustwall_left")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn(ENT_TYPE.FLOOR_DUSTWALL, x, y, layer, 0, 0)
local ent = get_entity(uid)
ent.flags = clr_flag(ent.flags, ENT_FLAG.SOLID)
ent.hitboxx = 0.45
ent.hitboxy = 0.45
set_pre_collision2(uid, function(self, collidee)
if collidee.velocityx > -0.1 then collidee.velocityx = -0.1 end
return true
end)
return true
end, "dustwall_left")
define_tile_code("dustwall_down")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn(ENT_TYPE.FLOOR_DUSTWALL, x, y, layer, 0, 0)
local ent = get_entity(uid)
ent.flags = clr_flag(ent.flags, ENT_FLAG.SOLID)
ent.hitboxx = 0.45
ent.hitboxy = 0.45
set_pre_collision2(uid, function(self, collidee)
if collidee.velocityy > -0.1 then collidee.velocityy = -0.1 end
return true
end)
return true
end, "dustwall_down")
define_tile_code("dustwall_up")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn(ENT_TYPE.FLOOR_DUSTWALL, x, y, layer, 0, 0)
local ent = get_entity(uid)
ent.flags = clr_flag(ent.flags, ENT_FLAG.SOLID)
ent.hitboxx = 0.45
ent.hitboxy = 0.45
set_pre_collision2(uid, function(self, collidee)
if collidee.velocityy < 0.1 then collidee.velocityy = 0.1 end
return true
end)
return true
end, "dustwall_up")
-- These scripts remove all powerups, items, companions, mounts and status effects
-- from all players before, during or after level transition.
-- Great for self contained kaizo/puzzle levels in level sequence mods
-- clear 'carry through exit' flag from all spawned items so they are forced to drop at the exit
-- if you remove this part, held item will removed during the transition by tripping and forced on level load anyway
set_post_entity_spawn(function(ent)
if state.screen == SCREEN.LEVEL then
ent.flags = clr_flag(ent.flags, 22)
end
end, SPAWN_TYPE.ANY, MASK.ITEM, nil)
-- drop all items when entering a portal
set_post_entity_spawn(function(ent)
set_pre_collision2(ent.uid, function(portal, collider)
if getmetatable(collider).__type.name == "Player" then
unequip_backitem(collider.uid)
for i,v in ipairs(entity_get_items_by(collider.uid, 0, MASK.ITEM)) do
drop(collider.uid, v)
end
end
end)
end, SPAWN_TYPE.ANY, 0, ENT_TYPE.LOGICAL_PORTAL)
-- remove all powerups and companions when exiting
set_callback(function()
if state.loading == 1 and state.screen_next == SCREEN.TRANSITION then
-- remove all companions before transition so they don't appear in it
state.items.player_inventory[1].companion_count = 0
-- remove powerups and drop backitems before entering the door
for _,p in ipairs(players) do
for _,v in ipairs(p:get_powerups()) do
p:remove_powerup(v)
unequip_backitem(p.uid)
end
end
end
end, ON.LOADING)
-- remove mount by tripping in the transition (just for the funnies, callback below forces this anyway)
set_callback(function()
set_global_timeout(function()
if state.screen ~= SCREEN.TRANSITION then return end
-- no floor, this would end up horribly
if state.theme == THEME.COSMIC_OCEAN or state.theme == THEME.DUAT then return end
-- stun you for a bit, doesn't hurt though
for i=1,state.items.player_count do
local p = get_player(i)
if p and (p.overlay or p.holding_uid ~= -1) then
p:damage(p.uid, 0, 30, 0.15, 0.1, 1)
end
end
end, 30)
end, ON.TRANSITION)
-- actually make sure mount and a bunch of stuff is removed on next level
set_callback(function()
for i=1,state.items.player_count do
state.items.player_inventory[i].mount_type = 0
state.items.player_inventory[i].companion_count = 0
state.items.player_inventory[i].held_item = 0
state.items.player_inventory[i].poison_tick_timer = -1
state.items.player_inventory[i].cursed = false
state.items.player_inventory[i].elixir_buff = false
end
end, ON.PRE_LEVEL_GENERATION)
-- single tile pipes, don't put these next to other pipe tiles
define_tile_code("pipe_horizontal")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_PIPE, x, y, layer)
set_timeout(function()
local pipe = get_entity(uid)
pipe.animation_frame = 140
pipe.direction_type = 3
pipe.end_pipe = true
local deco_uid = spawn_entity_over(ENT_TYPE.DECORATION_PIPE, pipe.uid, -0.5,
0)
local deco = get_entity(deco_uid)
deco.animation_frame = 143
deco.width = -1
deco.height = 1
deco_uid = spawn_entity_over(ENT_TYPE.DECORATION_PIPE, pipe.uid, 0.5,
0)
deco = get_entity(deco_uid)
deco.animation_frame = 143
deco.width = 1
deco.height = 1
end, 1)
end, "pipe_horizontal")
define_tile_code("pipe_vertical")
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.FLOOR_PIPE, x, y, layer)
set_timeout(function()
local pipe = get_entity(uid)
pipe.animation_frame = 128
pipe.direction_type = 12
pipe.end_pipe = true
local deco_uid = spawn_entity_over(ENT_TYPE.DECORATION_PIPE, pipe.uid, 0,
-0.5)
local deco = get_entity(deco_uid)
deco.animation_frame = 131
deco.width = 1
deco.height = -1
deco_uid = spawn_entity_over(ENT_TYPE.DECORATION_PIPE, pipe.uid, 0,
0.5)
deco = get_entity(deco_uid)
deco.animation_frame = 131
deco.width = 1
deco.height = 1
end, 1)
end, "pipe_vertical")
-- slidingwall in up or down position, toggled with a normal switch in the same room
-- or a special switch_N to toggle the Nth slidingwall in the level
local num_switches = 5 -- how many switch tilecodes to define
local slidingwalls = {} -- store entity uids for the walls here to keep track in case they're destroyed
set_callback(function()
slidingwalls = get_entities_by_type(ENT_TYPE.FLOOR_SLIDINGWALL_CEILING)
end, ON.POST_LEVEL_GENERATION)
local function spawn_slidingwall(x, y, layer, up)
local ceiling = get_entity(spawn_grid_entity(ENT_TYPE.FLOOR_SLIDINGWALL_CEILING, x, y, layer))
local chain = get_entity(spawn_over(ENT_TYPE.ITEM_SLIDINGWALL_CHAIN_LASTPIECE, ceiling.uid, 0, 0))
chain.attached_to_uid = -1
ceiling.attached_piece = chain
local wall = get_entity(spawn_over(ENT_TYPE.ACTIVEFLOOR_SLIDINGWALL, chain.uid, 0, -1.5))
wall.ceiling = ceiling
ceiling.active_floor_part_uid = wall.uid
if up then ceiling.state = 1 end
end
-- this spawns in the up position
define_tile_code("slidingwall_up")
set_pre_tile_code_callback(function(x, y, layer)
spawn_slidingwall(x, y, layer, true)
end, "slidingwall_up")
-- this also spawns in the up position, but drops down immediately
define_tile_code("slidingwall_down")
set_pre_tile_code_callback(function(x, y, layer)
spawn_slidingwall(x, y, layer, false)
end, "slidingwall_down")
local function define_switch(n)
local tilecode = "switch_"..tostring(n)
define_tile_code(tilecode)
set_pre_tile_code_callback(function(x, y, layer)
local uid = spawn_grid_entity(ENT_TYPE.ITEM_SLIDINGWALL_SWITCH_REWARD, x, y, layer)
-- added switch specific colors for testing
math.randomseed(n)
local r, g, b = math.random(), math.random(), math.random()
local ent = get_entity(uid)
ent.color.r, ent.color.g, ent.color.b = r, g, b
set_on_damage(uid, function(self)
if self.timer > 0 then return end
self.timer = 30
self.animation_frame = self.animation_frame == 86 and 96 or 86
local ceiling = get_entity(slidingwalls[n])
if not ceiling then return end
ceiling.state = ceiling.state == 1 and 0 or 1
end)
end, tilecode)
end
for i=1,num_switches do
define_switch(i)
end
-- function to grow vine, poles or anything else, up from floor or down from ceiling
-- includes script to test with mouse or replace spikes with poles
function grow(type, x, y, l)
local last = spawn_grid_entity(type, x, y, l)
local dir = 0
if get_grid_entity_at(x, y-1, l) ~= -1 then
dir = 1
elseif get_grid_entity_at(x, y+1, l) ~= -1 then
dir = -1
else
return
end
local dy = dir
while true do
local next = get_grid_entity_at(x, y+dy, l)
local next2 = get_grid_entity_at(x, y+dy+dir, l)
if next == -1 and next2 == -1 then
last = spawn_grid_entity(type, x, y+dy, l)
else
local ent = get_entity(last)
if type == ENT_TYPE.FLOOR_VINE then
ent.animation_frame = 28
elseif type == ENT_TYPE.FLOOR_CLIMBING_POLE then
ent.animation_frame = 4
elseif type == ENT_TYPE.FLOOR_CHAINANDBLOCKS_CHAIN then
ent.animation_frame = 40
end
return
end
dy = dy + dir
end
end
function spawn_growable(type, x, y, l)
if state.time_level == 0 then
set_callback(function()
grow(type, x, y, l)
clear_callback()
end, ON.POST_LEVEL_GENERATION)
else
grow(type, x, y, l)
end
end
set_pre_tile_code_callback(function(x, y, l)
spawn_growable(ENT_TYPE.FLOOR_CLIMBING_POLE, x, y, l)
return true
end, "spikes")
iio = get_io()
set_callback(function()
if iio.mouseclicked[1] then
local mx, my = mouse_position()
local x, y = game_position(mx, my)
spawn_growable(ENT_TYPE.FLOOR_CLIMBING_POLE, x, y, state.camera_layer)
end
if iio.mouseclicked[2] then
local mx, my = mouse_position()
local x, y = game_position(mx, my)
spawn_growable(ENT_TYPE.FLOOR_VINE, x, y, state.camera_layer)
end
end, ON.GUIFRAME)
-- unpushable pushblock, still falls and moves on conveyors normally
define_tile_code("unpush_block")
set_pre_tile_code_callback(function(x, y, layer)
local block_id = spawn(ENT_TYPE.ACTIVEFLOOR_PUSHBLOCK, x, y, layer, 0, 0)
local block = get_entity(block_id)
block.more_flags = set_flag(block.more_flags, ENT_MORE_FLAG.DISABLE_INPUT)
return true
end, "unpush_block")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment