From 2e406c526400980889ef2bbb6bd6065fb2003e84 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 11 Aug 2021 20:40:17 -0700 Subject: [PATCH] orthocyclic winding tech: brushless motor - drones rush more often and do 44% more damage requires torque bursts tech: orthocyclic winding - irradiated drones are faster and do more damage requires irradiated drones automatic aiming systems (bots, drones, missiles) will ignore the pink seeking mob bullets safari is super buggy, I'm guessing no one that reports bugs uses it. fixed scroll bar covering up pause right side text on safari and firefox fixed issue with ctx.setLineDash sometimes making the player dashed on safari various other bug fixes --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 31 +++++++++++--------- js/engine.js | 1 + js/index.js | 15 ++-------- js/level.js | 8 ++---- js/mob.js | 34 +++++++++++----------- js/player.js | 3 +- js/spawn.js | 17 +++++------ js/tech.js | 78 ++++++++++++++++++++++++++++++++------------------- style.css | 2 -- todo.txt | 44 ++++++++++++++++++++++++----- 11 files changed, 139 insertions(+), 94 deletions(-) diff --git a/.DS_Store b/.DS_Store index e0de15057b7d50fab5f43b334825be108bd68521..714a293238c696f340c89f1624f0402b5d2da40d 100644 GIT binary patch delta 21 ccmZoMXffEJ#mw||%48j8KgI`}tC>4R08~T=kN^Mx delta 21 ccmZoMXffEJ#mw}vbFvPzALE40)y$nD08y+5F#rGn diff --git a/js/bullet.js b/js/bullet.js index 10b0bbb..815b230 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1589,7 +1589,7 @@ const b = { ctx.stroke(); ctx.globalAlpha *= reflectivity; //reflections are less intense } - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); ctx.globalAlpha = 1; } }, @@ -2052,7 +2052,7 @@ const b = { Composite.add(engine.world, bullet[bIndex]); //add bullet to world if (tech.isMutualism && m.health > 0.01) { - m.health -= 0.005 + m.health -= 0.005 m.displayHealth(); bullet[bIndex].isMutualismActive = true } @@ -2132,7 +2132,7 @@ const b = { }, drone(where = { x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) }, speed = 1) { const me = bullet.length; - const THRUST = tech.isFastDrones ? 0.0023 : 0.0015 + const THRUST = 0.0015 // const FRICTION = tech.isFastDrones ? 0.008 : 0.0005 const dir = m.angle + 0.4 * (Math.random() - 0.5); const RADIUS = (4.5 + 3 * Math.random()) @@ -2142,8 +2142,10 @@ const b = { friction: 0.05, frictionAir: 0, restitution: 1, - dmg: 0.24 + 0.12 * tech.isDroneTeleport, //damage done in addition to the damage from momentum - lookFrequency: 70 + Math.floor(17 * Math.random()), + density: 0.0005, // 0.001 is normal density + //total 0.24 + 0.3 average + dmg: 0.34 + 0.12 * tech.isDroneTeleport + 0.15 * tech.isDroneFastLook, //damage done in addition to the damage from momentum + lookFrequency: (tech.isDroneFastLook ? 20 : 70) + Math.floor(17 * Math.random()), endCycle: simulation.cycle + Math.floor((950 + 420 * Math.random()) * tech.isBulletsLastLonger * tech.droneCycleReduction) + 140 + RADIUS * 5, classType: "bullet", collisionFilter: { @@ -2331,7 +2333,7 @@ const b = { }, droneRadioactive(where = { x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) }, speed = 1) { const me = bullet.length; - const THRUST = tech.isFastDrones ? 0.002 : 0.0012 + 0.0004 * (Math.random() - 0.5) + const THRUST = (tech.isFastDrones ? 0.003 : 0.0012) + 0.0005 * (Math.random() - 0.5) const dir = m.angle + 0.4 * (Math.random() - 0.5); const RADIUS = 3 bullet[me] = Bodies.polygon(where.x, where.y, 8, RADIUS, { @@ -2357,12 +2359,13 @@ const b = { radioRadius: 0, maxRadioRadius: 300 + Math.floor(100 * Math.random()), beforeDmg(who) { - const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting - Matter.Body.setVelocity(this, { - x: unit.x, - y: unit.y - }); - this.lockedOn = null + // const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting + // Matter.Body.setVelocity(this, { + // x: unit.x, + // y: unit.y + // }); + // this.lockedOn = null + // if (this.endCycle > simulation.cycle + this.deathCycles) { // this.endCycle -= 60 // if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles @@ -2396,7 +2399,7 @@ const b = { //aoe damage to mobs for (let i = 0, len = mob.length; i < len; i++) { if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.radioRadius + mob[i].radius) { - let dmg = 0.11 * b.dmgScale * tech.droneRadioDamage //neutron bombs dmg = 0.09 + let dmg = (0.12 + 0.04 * tech.isFastDrones) * b.dmgScale * tech.droneRadioDamage //neutron bombs dmg = 0.09 if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way if (mob[i].shield) dmg *= 3 // to make up for the /5 that shields normally take mob[i].damage(dmg); @@ -5165,7 +5168,7 @@ const b = { ctx.lineWidth = this.charge * 1 ctx.setLineDash([10, 20]); ctx.stroke(); - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); //draw magnetic field const X = m.pos.x diff --git a/js/engine.js b/js/engine.js index 0266fc5..fdfa9d1 100644 --- a/js/engine.js +++ b/js/engine.js @@ -175,6 +175,7 @@ function collisionChecks(event) { if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) + // console.log(obj.dmg, 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) if (tech.isCrit && mob[k].isStunned) dmg *= 4 mob[k].damage(dmg); if (mob[k].alive) mob[k].foundPlayer(); diff --git a/js/index.js b/js/index.js index bd737d6..6a0b70b 100644 --- a/js/index.js +++ b/js/index.js @@ -202,6 +202,7 @@ const build = { // } // }, pauseGrid() { + //right side let botText = "" if (tech.nailBotCount) botText += `
nail-bots: ${tech.nailBotCount}` if (tech.orbitBotCount) botText += `
orbital-bots: ${tech.orbitBotCount}` @@ -243,13 +244,13 @@ const build = { for (let i = 0, len = b.inventory.length; i < len; i++) { text += `
  ${b.guns[b.inventory[i]].name} - ${b.guns[b.inventory[i]].ammo}
${b.guns[b.inventory[i]].description}
` } - let el = document.getElementById("pause-grid-left") el.style.display = "grid" el.innerHTML = text + + //left side text = ""; text += `
  ${m.fieldUpgrades[m.fieldMode].name}
${m.fieldUpgrades[m.fieldMode].description}
` - let countTech = 0 for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) { const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; @@ -274,23 +275,13 @@ const build = { } else { text += `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
` } - countTech++ } else if (tech.tech[i].isLost) { text += `
${tech.tech[i].name}
${tech.tech[i].description}
` } } - - //show in game console with scroll bar? - // text +=`` - - el = document.getElementById("pause-grid-right") el.style.display = "grid" el.innerHTML = text - // if (countTech > 5 || b.inventory.length > 6) { - // document.body.style.overflowY = "scroll"; - // document.body.style.overflowX = "hidden"; - // } }, unPauseGrid() { // document.body.style.overflow = "hidden" diff --git a/js/level.js b/js/level.js index 5276bc4..2400af7 100644 --- a/js/level.js +++ b/js/level.js @@ -12,19 +12,17 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // localSettings.levelsClearedLastGame = 10 - // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // tech.isFieldFree = true // m.setField("perfect diamagnetism") - // b.giveGuns("rail gun") + // b.giveGuns("drones") // tech.missileBotCount++; // b.missileBot(); // tech.giveTech("half-wave rectifier") // b.giveGuns("nail gun") // tech.giveTech("Lenz's law") // for (let i = 0; i < 9; i++) tech.giveTech("MIRV") - // for (let i = 0; i < 4; i++) tech.giveTech() level.intro(); //starting level // level.testing(); //not in rotation, used for testing @@ -2271,8 +2269,8 @@ const level = { spawn.mapRect(5050, -100, 50, 150); spawn.mapRect(4850, -275, 50, 175); // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why - // spawn.starter(1900, -500, 200) //big boy - spawn.growBossCulture(1900, -500) + spawn.starter(1900, -500, 200) //big boy + // spawn.growBossCulture(1900, -500) // spawn.blinkBoss(1900, -500) // spawn.snakeSpitBoss(1900, -500) // spawn.growBossCulture(1900, -500) diff --git a/js/mob.js b/js/mob.js index ede5414..bbe763b 100644 --- a/js/mob.js +++ b/js/mob.js @@ -314,21 +314,23 @@ const mobs = { this.foundPlayer(); } else if (this.seePlayer.recall) { this.lostPlayer(); - for (let i = 0; i < depth; i++) { //if lost player lock onto a player location in history - let history = m.history[(m.cycle - 10 * i) % 600] - if (Matter.Query.ray(map, this.position, history.position).length === 0) { - this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep - this.seePlayer.position.x = history.position.x; - this.seePlayer.position.y = history.position.y; - this.seePlayer.yes = true; - //draw the history location found for testing purposes - // ctx.beginPath(); - // ctx.moveTo(this.position.x, this.position.y); - // ctx.lineTo(history.position.x, history.position.y); - // ctx.lineWidth = 5; - // ctx.strokeStyle = "#000"; - // ctx.stroke(); - break + if (!m.isCloak) { + for (let i = 0; i < depth; i++) { //if lost player lock onto a player location in history + let history = m.history[(m.cycle - 10 * i) % 600] + if (Matter.Query.ray(map, this.position, history.position).length === 0) { + this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep + this.seePlayer.position.x = history.position.x; + this.seePlayer.position.y = history.position.y; + this.seePlayer.yes = true; + //draw the history location found for testing purposes + // ctx.beginPath(); + // ctx.moveTo(this.position.x, this.position.y); + // ctx.lineTo(history.position.x, history.position.y); + // ctx.lineWidth = 5; + // ctx.strokeStyle = "#000"; + // ctx.stroke(); + break + } } } } @@ -552,7 +554,7 @@ const mobs = { ctx.lineWidth = 1; ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); ctx.stroke(); // Draw it - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); } }, searchSpring() { diff --git a/js/player.js b/js/player.js index 40b8cb6..345bf52 100644 --- a/js/player.js +++ b/js/player.js @@ -670,6 +670,7 @@ const m = { if (tech.isDeathAvoid && powerUps.research.count > 0 && !tech.isDeathAvoidedThisLevel) { //&& Math.random() < 0.5 tech.isDeathAvoidedThisLevel = true m.health = 0.05 + m.displayHealth(); powerUps.research.changeRerolls(-1) simulation.makeTextLog(`m.research--
${powerUps.research.count}`) @@ -687,11 +688,11 @@ const m = { }, 3000); } else { m.health = 0; + m.displayHealth(); m.death(); return; } } - m.displayHealth(); document.getElementById("dmg").style.transition = "opacity 0s"; document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4); } diff --git a/js/spawn.js b/js/spawn.js index b390bc7..271a814 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -563,7 +563,7 @@ const spawn = { ctx.lineWidth = 1.5 * scale; ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); ctx.stroke(); // Draw it - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); ctx.lineWidth = 20; ctx.strokeStyle = `rgba(80,0,255,${0.07*scale})`; ctx.stroke(); // Draw it @@ -579,7 +579,7 @@ const spawn = { ctx.lineWidth = 1.5; ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); ctx.stroke(); // Draw it - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); ctx.lineWidth = 20; ctx.strokeStyle = "rgba(80,0,255,0.07)"; ctx.stroke(); // Draw it @@ -1319,7 +1319,7 @@ const spawn = { } // this.seePlayerCheckByDistance() if (!(simulation.cycle % this.seePlayerFreq)) { - if (this.distanceToPlayer2() < this.seeAtDistance2) { //&& !m.isCloak ignore cloak for black holes + if (this.distanceToPlayer2() < this.seeAtDistance2) { // ignore cloak for black holes this.locatePlayer(); if (!this.seePlayer.yes) this.seePlayer.yes = true; } else if (this.seePlayer.recall) { @@ -1987,7 +1987,7 @@ const spawn = { ctx.lineWidth = 3; ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); ctx.stroke(); - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); } }; }, @@ -2143,7 +2143,7 @@ const spawn = { ctx.lineWidth = 2; ctx.strokeStyle = "rgba(120,0,255,0.3)"; ctx.stroke(); - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); } } else { //aim at player this.fireCycle++ @@ -2266,7 +2266,7 @@ const spawn = { ctx.lineWidth = 2; ctx.strokeStyle = "rgba(255,0,100,0.3)"; ctx.stroke(); - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); } } else { //aim at player this.fireCycle++ @@ -2382,7 +2382,7 @@ const spawn = { ctx.lineWidth = 1.5; ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); ctx.stroke(); // Draw it - ctx.setLineDash([0, 0]); + ctx.setLineDash([]); ctx.lineWidth = 20; ctx.strokeStyle = "rgba(80,0,255,0.07)"; ctx.stroke(); // Draw it @@ -3524,6 +3524,7 @@ const spawn = { me.restitution = 0.5; me.leaveBody = false; me.isDropPowerUp = false; + me.isBadTarget = true; me.showHealthBar = false; me.collisionFilter.category = cat.mobBullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; @@ -3648,7 +3649,7 @@ const spawn = { let angle = Math.PI let mag = 300 - const color1 = "rgb(245,180,255)" + const color1 = "rgb(235,180,255)" mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; diff --git a/js/tech.js b/js/tech.js index 0cd7eeb..80df842 100644 --- a/js/tech.js +++ b/js/tech.js @@ -871,9 +871,9 @@ frequency: 1, frequencyDefault: 1, allowed() { - return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot + return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot }, - requires: "super balls, basic or slug shotgun, drones, not irradiated drones", + requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", effect() { tech.isIncendiary = true }, @@ -3448,7 +3448,7 @@ level.difficultyDecrease(simulation.difficultyMode) // simulation.difficulty-= simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`) - tech.addJunkTechToPool(21) + tech.addJunkTechToPool(31) // for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i]) }, remove() { @@ -4614,8 +4614,8 @@ isGunTech: true, maxCount: 1, count: 0, - frequency: 3, - frequencyDefault: 3, + frequency: 2, + frequencyDefault: 2, allowed() { return tech.isSporeWorm || tech.isWormShot }, @@ -4657,25 +4657,6 @@ } } }, - { - name: "brushless motor", - description: "drones accelerate 50% faster", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) - }, - requires: "drones", - effect() { - tech.isFastDrones = true - }, - remove() { - tech.isFastDrones = false - } - }, { name: "delivery drone", description: "if a drone picks up a power up,
it becomes larger, faster, and more durable", @@ -4723,9 +4704,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("drones") && !tech.isDroneRadioactive + return tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isIncendiary }, - requires: "drone gun, not irradiated drones", + requires: "drone gun, not irradiated drones, incendiary", effect() { tech.isDroneTeleport = true }, @@ -4733,6 +4714,25 @@ tech.isDroneTeleport = false } }, + { + name: "brushless motor", + description: "drones can rush 66% more often
increase drone collision damage by 44%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.isDroneTeleport + }, + requires: "torque bursts", + effect() { + tech.isDroneFastLook = true + }, + remove() { + tech.isDroneFastLook = false + } + }, { name: "irradiated drones", description: "the space around drones is irradiated
reduce ammo/efficiency by 75%", @@ -4785,6 +4785,25 @@ tech.droneRadioDamage = 1 } }, + { + name: "orthocyclic winding", + description: "drones accelerate 66% faster
increase radiation damage by 33%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.isDroneRadioactive + }, + requires: "irradiated drones", + effect() { + tech.isFastDrones = true + }, + remove() { + tech.isFastDrones = false + } + }, { name: "electrostatic induction", description: "foam bubbles are electrically charged
causing attraction to nearby mobs", @@ -5881,7 +5900,7 @@ }, { name: "ambush", - description: "metamaterial cloaking field damage effect
is increased from 300% to 500%", + description: "metamaterial cloaking field damage effect
is increased from 300% to 600%", isFieldTech: true, maxCount: 1, count: 0, @@ -5892,7 +5911,7 @@ }, requires: "metamaterial cloaking", effect() { - tech.sneakAttackDmg = 6 + tech.sneakAttackDmg = 7 }, remove() { tech.sneakAttackDmg = 4 @@ -7819,6 +7838,8 @@ isOverHeal: null, isDroneRadioactive: null, droneRadioDamage: null, + isDroneTeleport: null, + isDroneFastLook: null, isFoamTeleport: null, isResearchBoss: null, isJunkResearch: null, @@ -7833,7 +7854,6 @@ harmonicEnergy: null, isFieldHarmReduction: null, isFastTime: null, - isDroneTeleport: null, isAnthropicTech: null, isSporeWorm: null, isWormShot: null, diff --git a/style.css b/style.css index 58d60d5..49b57c8 100644 --- a/style.css +++ b/style.css @@ -218,14 +218,12 @@ summary { } #pause-grid-right { - justify-content: end; position: relative; overflow: auto; max-height: 100vh; } #pause-grid-left { - justify-content: start; position: relative; overflow: auto; max-height: 100vh; diff --git a/todo.txt b/todo.txt index 6e54a90..8bd0079 100644 --- a/todo.txt +++ b/todo.txt @@ -1,15 +1,35 @@ ******************************************************** NEXT PATCH ******************************************************** -tech: ambush - cloaking damage effect is increase from 300% to 500% +tech: brushless motor - drones rush more often and do 44% more damage + requires torque bursts +tech: orthocyclic winding - irradiated drones are faster and do more damage + requires irradiated drones -several bug fixes +automatic aiming systems (bots, drones, missiles) will ignore the pink seeking mob bullets +safari is super buggy, I'm guessing no one that reports bugs uses it. + fixed scroll bar covering up pause right side text on safari and firefox + fixed issue with ctx.setLineDash sometimes making the player dashed on safari + +various other bug fixes ******************************************************** TODO ******************************************************** +mob: spawning seekers on death + +"Lazer pulser Boss" +Basically the blue lazer boss, but it has another color +Instead of shooting one current stream of lasers, the laser is completely harmless +If the boss focused the Lazer on the player for a certain amount of time, it'll glow brightly and send a fast, explosive pulse down the Lazer beam +The harmless lazer beam serves like a sniper's lazer scope + laser damage seems low based on 2 runs history is low damage +buff laser push tech + push like plasma? + push harder + drones can combine with other drones to get bigger? drones that grab powers ups can grab more then one and get even bigger each time @@ -188,15 +208,25 @@ n-gon outreach ideas ******************************************************** BUGS ******************************************************** -Matter.World module has now been replaced by Matter.Composite (is this a possible fix?) - // for (let i = 0; i < array.length; ++i) Matter.World.remove(engine.world, array[i]); - for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]); - +safari issues + once: can't pick up blocks + fixed on new map + cloaking field + once: after damage, locked into slow time mode + fixed on damage + 3 times player head graphics not rotating + left/right leg flip broke + walk leg direction, legs are walking backwards + happened maybe after power up selection menu?? + cloaking field(at least once) + aiming still works + fixed on new map, although flip still broken (is flip a separate issue?) + flip fixed on new game sharing builds as html doesn't work for long lists... it shouldn't be sharing undefined at all probably some other problems too - (might be fixed...) + (this might be fixed...) blocks on buttons teleport into the button endlessly if they are being slowly floated away maybe add a cooldown?