-- Floating Item Spawner by Ashnal -- This script is designed to be repacked with map pk3s/wads, but otherwise not modified. If you need it modified (for example if the map thing number conflicts with something else), please let me know. -- Literally just spits out floating papersprite items (the ones that you drop when exploded) at the location of its spawnpoint, similar to an item box -- Thing number is 1777. Parameter in ZoneBuilder +1 is the item type, corresponding to the kartdebugitem list, or a list below for reference -- Angle is the amount to give, anything over 255 will cap the amount to 255, 0 will result in 1. Otherwise, angle shown in ZB = amount. -- Setting the AMBUSH flag will cause the spawned floating item to have no gravity and stay in place -- Setting the SPECIAL flag will cause the spawner to only ever spawn one item, creating a one time pickup -- Setting the EXTRA flag will ensure that a player can never pick up more than the amount designated from the pickup. -- For example, if you put 3 spawners near each other that give a player 2 sneakers and set EXTRA on them, they will gain 2 sneaker on the first one they drive over, but then if they drive over another, they will be unable to collect them -- If a player has some of the given item, but not as many as you've set on the spawner, they will be given -- Floating items behave as the normal in game one, including sliding down physics slopes and gravity (if you dont set Ambush flag) /* Sneaker 0 Rocket Sneaker 1 Invincibility 2 Banana 3 Eggman 4 Orbinaut 5 Jawz 6 Mine 7 Ballhog 8 Self-Propelled Bomb 9 Grow 10 Shrink 11 Lightning Shield 12 Hyudoro 13 Pogo Spring 14 Kitchen Sink 15 */ if not floatingitemspawner then rawset(_G, "floatingitemspawner", true) else return end local MT_FLOATINGITEM = MT_FLOATINGITEM local MF_NOGRAVITY = MF_NOGRAVITY local MTF_AMBUSH = MTF_AMBUSH local MTF_OBJECTSPECIAL = MTF_OBJECTSPECIAL local MF_NOCLIPTHING = MF_NOCLIPTHING local MF2_NIGHTSPULL = MF2_NIGHTSPULL local INT32_MAX = INT32_MAX local ANG1 = ANG1 local MTF_EXTRA = 1 -- Doesnt exist as a real flag in source code, but exists in ZB freeslot("MT_FLOATINGITEMSPAWNER") mobjinfo[MT_FLOATINGITEMSPAWNER] = { doomednum = 1777, spawnstate = S_INVISIBLE, flags = MF_NOCLIP|MF_NOGRAVITY|MF_DONTENCOREMAP|MF_NOBLOCKMAP|MF_NOCLIPTHING } addHook("MobjSpawn", function(mo) mo.cooldown = 0 end, MT_FLOATINGITEMSPAWNER) local function touched(special, toucher) if not (special.spawnedbyspawner and special.spawner and special.spawner.spawnpoint.options & MTF_EXTRA and toucher.player and not toucher.player.kartstuff[k_itemheld] and toucher.player.kartstuff[k_itemtype] == special.threshold and toucher.player.kartstuff[k_itemamount] > 0) then return end if toucher.player.kartstuff[k_itemamount] >= special.movecount then return true end -- prevent collection, the player has as many or more than this would give special.movecount = $ - toucher.player.kartstuff[k_itemamount] -- they have less, adjust amount to bring player up to the amount desired end addHook("TouchSpecial", touched, MT_FLOATINGITEM) local xitemhooked = false local basecooldown = 5*TICRATE/2 addHook("MobjThinker", function(mo) if (mo.spawneditem and mo.spawneditem.valid) then -- If the reference goes invalid, we know that a player picked up the floating item -- Nothing elseif mo.cooldown then mo.cooldown = max(0, $-1) else local typetospawn = MT_FLOATINGITEM if xItemLib then if not xitemhooked then addHook("TouchSpecial", touched, MT_FLOATINGXITEM) xitemhooked = true end typetospawn = MT_FLOATINGXITEM end mo.spawneditem = P_SpawnMobj(mo.x, mo.y, mo.z+P_MobjFlip(mo), typetospawn) if mo.spawneditem and mo.spawneditem.valid then if mo.spawnpoint.options & MTF_AMBUSH then mo.spawneditem.flags = $|MF_NOGRAVITY mo.spawneditem.flags2 = $|MF2_NIGHTSPULL -- This and the next line are some options I picked up from hardcode to allow the item to float while still animating and behaving properly mo.spawneditem.tracer = mo.spawneditem -- Has to be set to something or hardcode calls P_RemoveMobj on it else mo.spawneditem.momz = P_MobjFlip(mo)*1*mapobjectscale mo.spawneditem.flags = $|MF_NOCLIPTHING -- Vanilla does this, and removes it when it touches the ground end mo.spawneditem.spawnedbyspawner = true -- In case a thinker elsewhere wants to check it or something mo.spawneditem.spawner = mo mo.spawneditem.fuse = INT32_MAX -- Prevents kmp itemfuse from removing it, an effectively infinite timer -- Cheap spawn animation, it starts really small and scales up into visibility mo.spawneditem.scale = mo.spawneditem.scale/12 mo.spawneditem.destscale = mapobjectscale mo.spawneditem.scalespeed = (mapobjectscale-mo.spawneditem.scale)/20 -- This sets the type and amount mo.spawneditem.threshold = mo.spawnpoint.extrainfo+1 -- Parameter in ZB goes from 0-15, and items (excepting SAD and NONE) range from 1-16, so +1 to align them mo.spawneditem.movecount = max(min(mo.angle/ANG1, 255), 1) mo.cooldown = basecooldown if mo.spawnpoint.options & MTF_OBJECTSPECIAL then P_RemoveMobj(mo) -- If flagged with special, then just remove yourself to create a one time spawn end end end return true end, MT_FLOATINGITEMSPAWNER)