diff --git a/js/bullet.js b/js/bullet.js
index 8ace739..bb826bc 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -1439,7 +1439,7 @@ const b = {
minDmgSpeed: 4,
lookFrequency: Math.floor(7 + Math.random() * 3),
density: tech.harpoonDensity, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
- drain: tech.isRailEnergyGain ? 0.002 : 0.006,
+ drain: tech.isRailEnergy ? 0.002 : 0.006,
beforeDmg(who) {
if (tech.isShieldPierce && who.isShielded) { //disable shields
who.isShielded = false
@@ -1695,7 +1695,7 @@ const b = {
friction: 1,
frictionAir: 0.4,
thrustMag: 0.1,
- drain: tech.isRailEnergyGain ? 0.002 : 0.006,
+ drain: tech.isRailEnergy ? 0.002 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
@@ -2247,7 +2247,7 @@ const b = {
x: where.x + 3000 * Math.cos(m.angle),
y: where.y + 3000 * Math.sin(m.angle)
}, dmg = tech.laserDamage, reflections = tech.laserReflections, isThickBeam = false, push = 1) {
- const reflectivity = 1 - 1 / (reflections * 1.5)
+ const reflectivity = 1 - 1 / (reflections * 3)
let damage = m.dmgScale * dmg
let best = {
x: 1,
@@ -2528,10 +2528,56 @@ const b = {
isArmed: false,
endCycle: Infinity,
lookFrequency: 0,
- range: 700,
+ range: 700 - 300 * tech.isFoamMine,
beforeDmg() {},
onEnd() {
- if (this.isArmed) b.targetedNail(this.position, tech.isMineSentry ? 7 : 22, 40 + 10 * Math.random(), 1200, true, 2.2) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
+ if (tech.isFoamMine) {
+ for (let i = 0; i < 14; i++) {
+ const radius = 13 + 8 * Math.random()
+ const velocity = { x: 5.5 * Math.random(), y: 0 }
+ b.foam(this.position, Vector.rotate(velocity, this.angle + 1.57 + 3 * (Math.random() - 0.5)), radius) //6.28 * Math.random()
+ }
+
+ let count = 0
+ let cycle = () => {
+ if (count < 40) {
+ if (!simulation.paused && !simulation.isChoosing) { //!(simulation.cycle % 1) &&
+ count++
+
+ const targets = [] //target nearby mobs
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (
+ Vector.magnitude(Vector.sub(this.position, mob[i].position)) < this.range + mob[i].radius + 300 &&
+ !mob[i].isBadTarget && //|| mob[i].isMobBullet
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ !mob[i].isInvulnerable
+ ) {
+ // targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, dist / 50))) //predict where the mob will be in a few cycles
+ targets.push(mob[i]) //predict where the mob will be in a few cycles
+ }
+ }
+ if (targets.length > 0) { // aim near a random target in array
+ const index = Math.floor(Math.random() * targets.length) //pick random target from list
+ const radius = 7 + 10 * Math.random()
+ const SPEED = 23 + 6 * Math.random() - radius * 0.3 + 0.5 * targets[index].speed
+ const predict = Vector.mult(targets[index].velocity, Vector.magnitude(Vector.sub(this.position, targets[index].position)) / 60)
+ const where = Vector.add(targets[index].position, predict)
+ const velocity = Vector.mult(Vector.normalise(Vector.sub(where, this.position)), SPEED)
+ b.foam(this.position, Vector.rotate(velocity, 0.2 * (Math.random() - 0.5)), radius)
+ } else {
+ const radius = 7 + 10 * Math.random()
+ const velocity = { x: 10 + 8 * Math.random(), y: 0 }
+ b.foam(this.position, Vector.rotate(velocity, this.angle + 1.57 + 2.8 * (Math.random() - 0.5)), radius) //6.28 * Math.random()
+ }
+ }
+ requestAnimationFrame(cycle);
+ }
+ }
+ requestAnimationFrame(cycle)
+
+ } else if (this.isArmed && !tech.isMineSentry) {
+ b.targetedNail(this.position, tech.isMineSentry ? 7 : 22, 40 + 10 * Math.random(), 1200, true, 2.2) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
+ }
},
do() {
this.force.y += this.mass * 0.002; //extra gravity
@@ -2556,14 +2602,13 @@ const b = {
this.arm();
//sometimes the mine can't attach to map and it just needs to be reset
- const that = this
- setTimeout(function() {
- if (Matter.Query.collides(that, map).length === 0 || Matter.Query.point(map, that.position).length > 0) {
- that.endCycle = 0 // if not touching map explode
- that.isArmed = false
- b.mine(that.position, that.velocity, that.angle)
+ setTimeout(() => {
+ if (Matter.Query.collides(this, map).length === 0 || Matter.Query.point(map, this.position).length > 0) {
+ this.endCycle = 0 // if not touching map explode
+ this.isArmed = false
+ b.mine(this.position, this.velocity, this.angle)
}
- }, 100, that);
+ }, 100);
break
}
//move until you are touching the wall
@@ -2599,17 +2644,18 @@ const b = {
for (let i = 0, len = mob.length; i < len; ++i) {
if (
!mob[i].isBadTarget &&
- Vector.magnitude(Vector.sub(this.position, mob[i].position)) < 700 + mob[i].radius + random &&
+ Vector.magnitude(Vector.sub(this.position, mob[i].position)) < this.range + mob[i].radius + random &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0
) {
- if (tech.isStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random); //AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
+ if (tech.isStun) b.AoEStunEffect(this.position, this.range + mob[i].radius + random); //AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
if (tech.isMineSentry) {
- this.lookFrequency = 8 + Math.floor(3 * Math.random())
+ this.lookFrequency = 6
this.endCycle = simulation.cycle + 1020
this.do = function() { //overwrite the do method for this bullet
this.force.y += this.mass * 0.002; //extra gravity
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
+ this.endCycle -= 5
b.targetedNail(this.position, 1, 45 + 5 * Math.random(), 1100, false, 2.3) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
if (!(simulation.cycle % (this.lookFrequency * 6))) {
simulation.drawList.push({
@@ -3734,9 +3780,9 @@ const b = {
Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.target.velocity), this.target.position))
}
if (this.target.isBoss) {
- if (this.target.speed > 7.5) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.98))
+ if (this.target.speed > 6.5) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.975))
} else {
- if (this.target.speed > 3.5) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.95))
+ if (this.target.speed > 2.5) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.94))
}
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9);
@@ -3746,35 +3792,6 @@ const b = {
const SCALE = 1 - 0.004 / tech.isBulletsLastLonger //shrink if mob is shielded
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
-
- // if (true && !(simulation.cycle % 20)) {
- // let electricity = (who) => {
- // who.damage(2 * m.dmgScale, true)
- // const unit = Vector.normalise(Vector.sub(this.position, who.position))
- // //draw electricity
- // const step = 80
- // ctx.beginPath();
- // let x = this.position.x - 20 * unit.x;
- // let y = this.position.y - 20 * unit.y;
- // ctx.moveTo(x, y);
- // for (let i = 0; i < 3; i++) {
- // x += step * (-unit.x + 1.5 * (Math.random() - 0.5))
- // y += step * (-unit.y + 1.5 * (Math.random() - 0.5))
- // ctx.lineTo(x, y);
- // }
- // ctx.lineWidth = 3;
- // ctx.strokeStyle = "#f0f";
- // ctx.stroke();
- // }
-
- // //find mobs that are close
- // for (let i = 0, len = mob.length; i < len; ++i) {
- // if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) - mob[i].radius < 5000 && !mob[i].isBadTarget) {
- // electricity(mob[0])
- // }
- // }
- // }
-
} else {
this.target.damage(m.dmgScale * this.damage);
}
@@ -3808,23 +3825,23 @@ const b = {
}
}
this.target = null
- } else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map or blocks
- const slow = 0.85
+ } else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map
+ const slow = 0.87
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
- const SCALE = 0.96
+ const SCALE = 0.97
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
// } else if (Matter.Query.collides(this, body).length > 0) {
- } else if (Matter.Query.point(body, this.position).length > 0) {
- const slow = 0.9
+ } else if (Matter.Query.point(body, this.position).length > 0) { //slow when touching blocks
+ const slow = 0.94
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
- const SCALE = 0.96
+ const SCALE = 0.99
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
} else {
@@ -6617,7 +6634,7 @@ const b = {
charge: 0,
railDo() {
if (this.charge > 0) {
- const DRAIN = (tech.isRailEnergyGain ? 0.0005 : 0.002)
+ const DRAIN = (tech.isRailEnergy ? 0.0005 : 0.002)
//exit railgun charging without firing
if (m.energy < DRAIN) {
// m.energy += 0.025 + this.charge * 22 * this.drain
@@ -6756,7 +6773,7 @@ const b = {
this.charge = this.charge * smoothRate + 1 - smoothRate
if (m.energy > DRAIN) m.energy -= DRAIN
- // m.energy += (this.charge - previousCharge) * ((tech.isRailEnergyGain ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
+ // m.energy += (this.charge - previousCharge) * ((tech.isRailEnergy ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
//draw magnetic field
const X = m.pos.x
diff --git a/js/level.js b/js/level.js
index dd46a4b..246c79d 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,20 +16,20 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(2 * 4) //30 is near max on hard //60 is near max on why
+ // level.difficultyIncrease(9 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
// m.maxHealth = m.health = 100
+ // tech.isRerollDamage = true
// powerUps.research.changeRerolls(100000)
// m.immuneCycle = Infinity //you can't take damage
- // powerUps.research.changeRerolls(100)
// tech.tech[297].frequency = 100
// b.guns[0].ammo = 10000
- // m.setField("time dilation") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
- // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
- // tech.giveTech("infrared diode");
- // tech.giveTech("active cooling");
- // tech.giveTech("pulse")
+ // m.setField("perfect diamagnetism") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
+ // b.giveGuns("mine") //0 nail gun 1 shotgun 2 super balls 3 matter wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
+ // tech.giveTech("sentry");
+ // tech.giveTech("laser-mines");
+ // tech.giveTech("elephant's toothpaste")
// for (let i = 0; i < 1; ++i) tech.giveTech("slow light")
// for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser")
// m.damage(0.1);
@@ -37,8 +37,8 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research");
+ // spawn.flutter(1900, -500, 10)
// spawn.starter(1900, -500, 200)
- // spawn.starter(1900, -500, 50)
// spawn.dragonFlyBoss(1900, -400)
// spawn.beetleBoss(1900, -400)
// for (let i = 0; i < 2; ++i) spawn.flutter(1900 + 300 * Math.random(), -500 + 300 * Math.random())
@@ -4586,7 +4586,7 @@ const level = {
spawn.randomMob(3600, 1725, 0.9);
spawn.randomMob(4100, 1225, 0.9);
spawn.randomMob(2825, 400, 0.9);
- if (simulation.difficulty > 1) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "blinkBoss", "streamBoss", "historyBoss", "orbitalBoss", "grenadierBoss", "blockBoss", "revolutionBoss", "slashBoss"]);
+ if (simulation.difficulty > 1) spawn.randomLevelBoss(6000, 2300, ["dragonFlyBoss", "beetleBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "blinkBoss", "streamBoss", "historyBoss", "orbitalBoss", "grenadierBoss", "blockBoss", "revolutionBoss", "slashBoss"]);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(7725, 2275)
@@ -5144,7 +5144,7 @@ const level = {
spawn.randomMob(3975, -3900, 0.5);
spawn.randomMob(1725, 125, 0.5);
if (simulation.difficulty > 1) {
- if (Math.random() < 0.33) {
+ if (Math.random() < 0.5) {
spawn.randomLevelBoss(4250, -250);
spawn.debris(-250, 50, 1650, 2); //16 debris per level
spawn.debris(2475, 0, 750, 2); //16 debris per level
diff --git a/js/mob.js b/js/mob.js
index 3e6a57e..aa51a78 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -589,7 +589,7 @@ const mobs = {
ctx.setLineDash([]);
}
},
- wing(a, radius = 250, ellipticity = 0.4, dmg = 0.0004) {
+ wing(a, radius = 250, ellipticity = 0.4, dmg = 0.0006) {
const minorRadius = radius * ellipticity
const perp = { x: Math.cos(a), y: Math.sin(a) } //
const where = Vector.add(this.position, Vector.mult(perp, radius + 0.8 * this.radius))
diff --git a/js/player.js b/js/player.js
index 63a4665..fd05fc8 100644
--- a/js/player.js
+++ b/js/player.js
@@ -1124,9 +1124,9 @@ const m = {
if (m.energy > 0.001) {
if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle
if (tech.isCapacitor && m.throwCharge < 4) m.throwCharge = 4
- m.throwCharge += 0.5 / m.holdingTarget.mass
+ m.throwCharge += 0.5 / m.holdingTarget.mass / b.fireCDscale
- if (m.throwCharge < 6) m.energy -= 0.001; // m.throwCharge caps at 5
+ if (m.throwCharge < 6) m.energy -= 0.001 / b.fireCDscale; // m.throwCharge caps at 5
//trajectory path prediction
if (tech.isTokamak) {
@@ -2073,10 +2073,19 @@ const m = {
}
}
} else if (simulation.molecularMode === 1) {
- m.energy -= 0.35;
- b.missile({ x: m.pos.x, y: m.pos.y - 40 }, -Math.PI / 2 + 0.5 * (Math.random() - 0.5), 0, 1)
+ m.energy -= 0.33;
+ const direction = {
+ x: Math.cos(m.angle),
+ y: Math.sin(m.angle)
+ }
+ const push = Vector.mult(Vector.perp(direction), 0.08)
+ b.missile({ x: m.pos.x + 30 * direction.x, y: m.pos.y + 30 * direction.y }, m.angle, -15)
+ bullet[bullet.length - 1].force.x += push.x * (Math.random() - 0.5)
+ bullet[bullet.length - 1].force.y += 0.005 + push.y * (Math.random() - 0.5)
+
+ // b.missile({ x: m.pos.x, y: m.pos.y - 40 }, -Math.PI / 2 + 0.5 * (Math.random() - 0.5), 0, 1)
} else if (simulation.molecularMode === 2) {
- m.energy -= 0.05;
+ m.energy -= 0.045;
b.iceIX(1)
} else if (simulation.molecularMode === 3) {
if (tech.isDroneRadioactive) {
diff --git a/js/spawn.js b/js/spawn.js
index e7a2572..ecfa377 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1614,7 +1614,7 @@ const spawn = {
// me.isBadTarget = true;
me.isMobBullet = true;
me.showHealthBar = false;
- me.timeLeft = 1500 + Math.floor(600 * Math.random());
+ me.timeLeft = 1200 + Math.floor(600 * Math.random());
me.isRandomMove = Math.random() < 0.3 //most chase player, some don't
me.accelMag = 0.01; //jump height
@@ -1649,7 +1649,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1];
me.isBoss = true;
- me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0.06 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.accelMag = 0.05; //jump height
me.g = 0.003; //required if using this.gravity
me.frictionAir = 0.01;
@@ -2696,12 +2696,12 @@ const spawn = {
mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1];
me.isBoss = true;
- Matter.Body.setDensity(me, 0.0016); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
- me.accelMag = 0.0006 + 0.0006 * Math.sqrt(simulation.accelScale);
+ me.accelMag = 0.0006 + 0.0007 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.05;
// me.seePlayerFreq = 40 + Math.floor(13 * Math.random())
me.memory = 240;
@@ -2714,7 +2714,7 @@ const spawn = {
// me.onDeath = function() {};
me.flapRate = 0.3 + Math.floor(3 * Math.random()) / 10 + 100 * me.accelMag
- me.flapRadius = 75 + 50 * Math.random() + radius * 2
+ me.flapRadius = 75 + radius * 3
me.do = function() {
this.seePlayerByHistory()
this.checkStatus();
@@ -2753,7 +2753,7 @@ const spawn = {
}
};
},
- beetleBoss(x, y, radius = 60) {
+ beetleBoss(x, y, radius = 50) {
mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1];
me.isBoss = true;
@@ -2764,14 +2764,14 @@ const spawn = {
me.nextHealthThreshold = 0.75
me.invulnerableCount = 0
- me.flapRate = 0.25
+ me.flapRate = 0.2
me.wingSize = 0
- me.wingGoal = 250
+ me.wingGoal = 250 + simulation.difficulty
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
- me.accelMag = 0.0005 + 0.0005 * Math.sqrt(simulation.accelScale);
+ me.accelMag = 0.00045 + 0.0005 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.05;
- me.seePlayerFreq = 30
+ me.seePlayerFreq = 20
me.memory = 420;
me.restitution = 1;
me.frictionStatic = 0;
@@ -2789,58 +2789,94 @@ const spawn = {
// }
// }
- if (Math.random() < 0.3) {
- const len = 0.1 * simulation.difficulty //spawn some baby flutters
+ // if (Math.random() < 0.3) {
+ // const len = 0.1 * simulation.difficulty //spawn some baby flutters
+ // let i = 0
+ // let spawnFlutters = () => {
+ // if (i < len) {
+ // if (!(simulation.cycle % 30) && !simulation.paused && !simulation.isChoosing) {
+ // const phase = i / len * 2 * Math.PI
+ // const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
+ // spawn.flutter(where.x, where.y)
+ // i++
+ // }
+ // requestAnimationFrame(spawnFlutters);
+ // }
+ // }
+ // requestAnimationFrame(spawnFlutters);
+ // me.isAlreadyHadBabies = true
+ // }
+
+ me.pushAway = function(magX = 0.13, magY = 0.05) {
+ for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally
+ if (Vector.magnitudeSquared(Vector.sub(body[i].position, this.position)) < 4000000) { //2000
+ body[i].force.x += magX * body[i].mass * (body[i].position.x > this.position.x ? 1 : -1)
+ body[i].force.y -= magY * body[i].mass
+ }
+ }
+ for (let i = 0, len = bullet.length; i < len; ++i) { //push blocks away horizontally
+ if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, this.position)) < 4000000) { //2000
+ bullet[i].force.x += magX * bullet[i].mass * (bullet[i].position.x > this.position.x ? 1 : -1)
+ bullet[i].force.y -= magY * bullet[i].mass
+ }
+ }
+ for (let i = 0, len = powerUp.length; i < len; ++i) { //push blocks away horizontally
+ if (Vector.magnitudeSquared(Vector.sub(powerUp[i].position, this.position)) < 4000000) { //2000
+ powerUp[i].force.x += magX * powerUp[i].mass * (powerUp[i].position.x > this.position.x ? 1 : -1)
+ powerUp[i].force.y -= magY * powerUp[i].mass
+ }
+ }
+ if (Vector.magnitudeSquared(Vector.sub(player.position, this.position)) < 4000000) { //2000
+ player.force.x += magX * player.mass * (player.position.x > this.position.x ? 1 : -1)
+ player.force.y -= magY * player.mass
+ }
+ }
+
+ me.babies = function(len) {
+ const delay = Math.max(3, Math.floor(15 - len / 2))
let i = 0
let spawnFlutters = () => {
if (i < len) {
- if (!(simulation.cycle % 30) && !simulation.paused && !simulation.isChoosing) {
- const phase = i / len * 2 * Math.PI
- const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
- spawn.flutter(where.x, where.y)
+ if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing) {
+ // const phase = i / len * 2 * Math.PI
+ // const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
+ const unit = Vector.normalise(Vector.sub(player.position, this.position))
+ const velocity = Vector.mult(unit, 10 + 10 * Math.random())
+ const where = Vector.add(this.position, Vector.mult(unit, radius * 1.2))
+ spawn.allowShields = false
+ spawn.flutter(where.x, where.y, Math.floor(7 + 8 * Math.random()))
+ const who = mob[mob.length - 1]
+ Matter.Body.setDensity(who, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setVelocity(who, velocity);
+ Matter.Body.setAngle(who, Math.atan2(velocity.y, velocity.x))
+
+ this.alertNearByMobs();
+ spawn.allowShields = true
i++
}
requestAnimationFrame(spawnFlutters);
}
}
requestAnimationFrame(spawnFlutters);
- me.isAlreadyHadBabies = true
}
-
-
+ // me.babies(0.05 * simulation.difficulty + 1)
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
-
- const len = 0.1 * simulation.difficulty //spawn some baby flutters
- if (len > 3 && !this.isAlreadyHadBabies) {
- let i = 0
- let spawnFlutters = () => {
- if (i < len) {
- if (!(simulation.cycle % 20) && !simulation.paused && !simulation.isChoosing) {
- const phase = i / len * 2 * Math.PI
- const where = Vector.add(me.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
- spawn.flutter(where.x, where.y)
- i++
- }
- requestAnimationFrame(spawnFlutters);
- }
- }
- requestAnimationFrame(spawnFlutters);
- }
+ me.babies(0.05 * simulation.difficulty + 1)
};
me.onDamage = function() {
- if (this.health < this.nextHealthThreshold) {
+ if (this.health < this.nextHealthThreshold && this.alive) {
this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4
- this.invulnerableCount = 180 + Math.floor(60 * Math.random())
+ this.invulnerableCount = 90 + Math.floor(30 * Math.random())
this.isInvulnerable = true
this.damageReduction = 0
this.frictionAir = 0
this.wingGoal = 0
this.wingSize = 0
- this.flapRate += 0.1
- this.accelMag *= 1.25
+ this.flapRate += 0.13
+ this.accelMag *= 1.4
}
};
me.do = function() {
@@ -2853,6 +2889,8 @@ const spawn = {
this.damageReduction = this.startingDamageReduction
this.frictionAir = 0.05
this.wingGoal = 250
+ this.pushAway(Math.sqrt(this.flapRate) * 0.13, Math.sqrt(this.flapRate) * 0.06) //this.flapRate = 0.2, +0.13x3 -> 0.6
+ me.babies(0.05 * simulation.difficulty + 1)
}
// //draw wings as if they are protecting
// const wingShield = (a, size) => {
@@ -2908,10 +2946,10 @@ const spawn = {
this.torque -= turn;
}
const flapArc = 0.7 //don't go past 1.57 for normal flaps
- this.wingSize = 0.98 * this.wingSize + 0.02 * this.wingGoal
+ this.wingSize = 0.97 * this.wingSize + 0.03 * this.wingGoal
ctx.fillStyle = this.fill = `hsla(${160+40*Math.random()}, 100%, ${25 + 25*Math.random()*Math.random()}%, 0.9)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
- this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0008)
- this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0008)
+ this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0012)
+ this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingSize, 0.5, 0.0012)
} else {
this.wingSize = 0.96 * this.wingSize + 0 //shrink while stunned
}
@@ -4175,7 +4213,7 @@ const spawn = {
me.isMobBullet = true;
me.isUnstable = true; //dies when blocked
me.showHealthBar = false;
- me.explodeRange = 200 + 150 * Math.random()
+ me.explodeRange = 210 + 140 * Math.random()
me.isExploding = false
me.countDown = Math.ceil(4 * Math.random())
me.isInvulnerable = true //not actually invulnerable, just prevents block + ice-9 interaction
@@ -4199,7 +4237,7 @@ const spawn = {
this.death();
//hit player
if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.explodeRange && m.immuneCycle < m.cycle) {
- m.damage(0.01 * simulation.dmgScale * (tech.isRadioactiveResistance ? 0.25 : 1));
+ m.damage(0.015 * simulation.dmgScale * (tech.isRadioactiveResistance ? 0.25 : 1));
m.energy -= 0.15 * (tech.isRadioactiveResistance ? 0.25 : 1)
if (m.energy < 0) m.energy = 0
}
diff --git a/js/tech.js b/js/tech.js
index f55feb3..afaf4c9 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -498,7 +498,7 @@ const tech = {
for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
},
remove() {
- tech.isGunCycle = false;
+ if (!this.count) tech.isGunCycle = false; // only set to false if you don't have this tech
// if (tech.isGunCycle) {
// for (let i = 0; i < 8; i++) {
// if (b.inventory.length) b.removeGun(b.guns[b.inventory[b.inventory.length - 1]].name) //remove your last gun
@@ -3880,7 +3880,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
+ return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
},
requires: "nails, nail gun, rivets, shotgun",
effect() {
@@ -3900,7 +3900,7 @@ const tech = {
frequencyDefault: 2,
allowed() {
// return (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("mines"))
- return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
+ return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
},
//
requires: "nail gun, not rotary cannon, rivets, or needles",
@@ -4052,7 +4052,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
+ return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine)) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
},
requires: "nail gun, nails, rivets, mine, not ceramic needles",
effect() {
@@ -4065,7 +4065,7 @@ const tech = {
{
name: "6s half-life",
link: `6s half-life`,
- description: "nails are made of plutonium-238
+100% damage over 6 seconds",
+ description: "nails, needles, rivets are made of plutonium-238
radioactive damage lasts +3 seconds",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4085,7 +4085,7 @@ const tech = {
{
name: "1s half-life",
link: `1s half-life`,
- description: "nails are made of lithium-8
damage occurs after 1 second",
+ description: "nails, needles, rivets are made of lithium-8
+300% radioactive damage for 1 second",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5144,6 +5144,25 @@ const tech = {
}
}
},
+ {
+ name: "elephant's toothpaste",
+ description: "mines catalyze a reaction
that yields foam bubbles",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.haveGunCheck("mine") && !tech.isMineSentry
+ },
+ requires: "mines, not sentry",
+ effect() {
+ tech.isFoamMine = true;
+ },
+ remove() {
+ tech.isFoamMine = false;
+ }
+ },
{
name: "laser-mines",
link: `laser-mines`,
@@ -5173,9 +5192,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("mine")
+ return tech.haveGunCheck("mine") && !tech.isFoamMine
},
- requires: "mines",
+ requires: "mines, not elephant's toothpaste",
effect() {
tech.isMineSentry = true;
},
@@ -5285,7 +5304,7 @@ const tech = {
},
{
name: "siphonaptera",
- description: "shotgun and sporangium hatch fleas", //
spore tech applies to fleas
+ description: "sporangium and shotgun hatch fleas", //
spore tech applies to fleas
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5621,7 +5640,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall)
+ return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine)
},
requires: "foam, not uncertainty",
effect() {
@@ -5640,7 +5659,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal)
+ return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal)
},
requires: "foam, matter wave, not electrostatic induction, not phonon",
effect() {
@@ -5659,7 +5678,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm || tech.isSporeFlea
+ return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm || tech.isSporeFlea || tech.isFoamMine
},
requires: "foam, worms",
effect() {
@@ -5678,7 +5697,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall
+ return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine
},
requires: "foam",
effect() {
@@ -5699,7 +5718,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall
+ return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall || tech.isFoamMine
},
requires: "foam",
effect() {
@@ -5882,7 +5901,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isGrapple && !tech.isRailEnergyGain
+ return tech.haveGunCheck("harpoon") && tech.isGrapple && !tech.isRailEnergy
},
requires: "grappling hook, not alternator",
effect() {
@@ -5905,10 +5924,10 @@ const tech = {
},
requires: "harpoon, not bulk modulus",
effect() {
- tech.isRailEnergyGain = true;
+ tech.isRailEnergy = true;
},
remove() {
- tech.isRailEnergyGain = false;
+ tech.isRailEnergy = false;
}
},
{
@@ -6170,7 +6189,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isLaserLens
+ return tech.haveGunCheck("laser") && tech.isLaserLens
},
requires: "lens",
effect() {
@@ -6259,7 +6278,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isWideLaser
+ return tech.haveGunCheck("laser") && tech.isWideLaser
},
requires: "laser gun, diffuse beam",
effect() {
@@ -6648,7 +6667,7 @@ const tech = {
},
{
name: "dynamic equilibrium",
- descriptionFunction() { return `increase damage by your defense times
5% of your last ${tech.isEnergyHealth ? "energy" : "health"} loss (+${(100*tech.lastHitDamage * m.lastHit * (2 - m.harmReduction())).toFixed(0)}% damage)` }, // = +${10*m.harmReduction()}%
+ descriptionFunction() { return `increase damage by your defense and
5% of your last ${tech.isEnergyHealth ? "energy" : "health"} loss (+${(100*tech.lastHitDamage * m.lastHit * (2 - m.harmReduction())).toFixed(0)}% damage)` }, // = +${10*m.harmReduction()}%
// descriptionFunction() { return `increase damage by your last ${tech.isEnergyHealth ? "energy" : "health"} loss
(${(tech.lastHitDamage).toFixed(0)}%)(${(100*m.lastHit).toFixed(0)} ${tech.isEnergyHealth ? "energy" : "health"})(${2 - m.harmReduction()} defense) = ${(100*tech.lastHitDamage * m.lastHit * (2 - m.harmReduction())).toFixed(0)}% damage ` }, // = +${10*m.harmReduction()}%
isFieldTech: true,
maxCount: 9,
@@ -10335,7 +10354,7 @@ const tech = {
isPulseLaser: null,
isRadioactive: null,
radioactiveDamage: null,
- isRailEnergyGain: null,
+ isRailEnergy: null,
isMineSentry: null,
isIncendiary: null,
overfillDrain: null,
@@ -10360,6 +10379,7 @@ const tech = {
isMissileBig: null,
isMissileBiggest: null,
isLaserMine: null,
+ isFoamMine: null,
isAmmoFoamSize: null,
isIceIX: null,
isDupDamage: null,
diff --git a/todo.txt b/todo.txt
index 1d32582..e719017 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,14 +1,27 @@
******************************************************** NEXT PATCH **************************************************
-snakeBoss is now dragonFlyBoss
- snakeSpitBoss till exists, don't worry
+elephant's toothpaste: mines make foam
-flutter and beetle mobs changes
+sentry fires about 40% faster
+ but each shot slightly reduces the total duration
+ (duration = 17s - 1/10 s per shot)
-Noether violation has 50% less forward recoil for shotgun
+foam can move through blocks a bit faster
+laser reflection damage is increased
+ about 15% -> 8% damage loss per reflection
+beetleBoss pushes player away and spawns baby flutter mobs
+fire rate affects block throwing charge rate
*********************************************************** TODO *****************************************************
+bug blocks and power ups falling through map
+ always foam gun (4-5 times)
+ might be about tech pressure vessel
+ happens rarely, doesn't repeat
+ normally after level 6
+
+seed isn't working right from shared URL
+
mob mechanics
bullets hit player and stay attached for 4-5 seconds, slowing player
hopperBullets?