diff --git a/.DS_Store b/.DS_Store
index e0de150..714a293 100644
Binary files a/.DS_Store and b/.DS_Store differ
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?