diff --git a/img/MACHO.webp b/img/MACHO.webp
index 8570ee0..0875e67 100644
Binary files a/img/MACHO.webp and b/img/MACHO.webp differ
diff --git a/img/control theory.webp b/img/control theory.webp
new file mode 100644
index 0000000..2843288
Binary files /dev/null and b/img/control theory.webp differ
diff --git a/img/dark energy.webp b/img/dark energy.webp
new file mode 100644
index 0000000..faca967
Binary files /dev/null and b/img/dark energy.webp differ
diff --git a/img/dark matter.webp b/img/dark matter.webp
new file mode 100644
index 0000000..8570ee0
Binary files /dev/null and b/img/dark matter.webp differ
diff --git a/img/slow light.webp b/img/delayed-choice.webp
similarity index 100%
rename from img/slow light.webp
rename to img/delayed-choice.webp
diff --git a/img/inertial confinement.webp b/img/inertial confinement.webp
new file mode 100644
index 0000000..068f0c0
Binary files /dev/null and b/img/inertial confinement.webp differ
diff --git a/img/instability.webp b/img/instability.webp
new file mode 100644
index 0000000..fdcbf8f
Binary files /dev/null and b/img/instability.webp differ
diff --git a/img/stability.webp b/img/stability.webp
new file mode 100644
index 0000000..f9a7dab
Binary files /dev/null and b/img/stability.webp differ
diff --git a/img/stellarator.webp b/img/stellarator.webp
new file mode 100644
index 0000000..49fe2ef
Binary files /dev/null and b/img/stellarator.webp differ
diff --git a/js/level.js b/js/level.js
index 4f5082b..72913db 100644
--- a/js/level.js
+++ b/js/level.js
@@ -26,7 +26,7 @@ const level = {
// tech.tech[297].frequency = 100
// tech.addJunkTechToPool(0.5)
// m.couplingChange(10)
- // m.setField("time dilation") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
+ // m.setField("negative mass") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0
// powerUps.research.count = 3
// tech.isHookWire = true
@@ -43,9 +43,9 @@ const level = {
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// tech.giveTech("1st ionization energy")
- // for (let i = 0; i < 1; ++i) tech.giveTech("negative feedback")
- // for (let i = 0; i < 2; ++i) tech.giveTech("delayed-choice")
- // for (let i = 0; i < 1; ++i) tech.giveTech("pulse")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("tokamak")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("inertial confinement")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("stellarator")
// for (let i = 0; i < 1; ++i) tech.giveTech("mass-energy equivalence")
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("1st ionization energy") });
@@ -54,11 +54,11 @@ const level = {
// for (let i = 0; i < 1; ++i) tech.giveTech("compression engine")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false);
- // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing
- // level.arena();
-
- // for (let i = 0; i < 1; ++i) spawn.snakeSpitBoss(1400, -500)
+ level.testing();
+
+ // for (let i = 0; i < 1; ++i) spawn.snakeBoss(1400, -500)
+ // for (let i = 0; i < 2; i++) powerUps.directSpawn(800, -100, "coupling");
// Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.sucker(1300, -500 + 100 * Math.random())
// spawn.hopper(1900, -500)
@@ -68,11 +68,10 @@ const level = {
// spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
// for (let i = 0; i < 40; ++i) tech.giveTech()
- level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
+ // level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 1; ++i) spawn.laserLayerBoss(1900, -500)
// for (let i = 0; i < 2; i++) spawn.ghoster(level.exit.x, level.exit.y) //ghosters need to spawn after the map loads
- // spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass)
// simulation.isAutoZoom = false; //look in close
// simulation.zoomScale *= 0.5;
@@ -134,7 +133,7 @@ const level = {
}
}
}
- if (tech.isMACHO) spawn.MACHO()
+ if (tech.isDarkMatter) spawn.darkMatter()
for (let i = 0; i < tech.wimpCount; i++) {
spawn.WIMP()
mob[mob.length - 1].isDecoupling = true //so you can find it to remove
@@ -151,6 +150,7 @@ const level = {
newLevelOrPhase() { //runs on each new level but also on final boss phases
//used for generalist and pigeonhole principle
tech.cancelTechCount = 0
+ tech.tokamakHealCount = 0
tech.buffedGun++
if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0;
if (tech.isGunCycle && b.activeGun !== null && b.inventory.length) {
@@ -12651,7 +12651,7 @@ const level = {
Promise.resolve().then(() => {
// Clear all WIMPS and their research
for (let i = 0; i < mob.length; i++) {
- if (mob[i] && !mob[i].isMACHO) {
+ if (mob[i] && !mob[i].isDarkMatter) {
mob[i].isWIMP = true;
}
}
@@ -13302,7 +13302,7 @@ const level = {
if (simulation.cycle % 4 === 0) {
let newMobPositions = [];
for (const i of mob) {
- if (!(i.isMACHO || i.isWIMP || i.isObstacle)) newMobPositions.push({
+ if (!(i.isDarkMatter || i.isWIMP || i.isObstacle)) newMobPositions.push({
x: i.position.x,
y: i.position.y
});
@@ -13572,7 +13572,7 @@ const level = {
level.setPosToSpawn(x, y);
trapPlayer(x, y);
for (let i = 0; i < mob.length; i++) {
- if (mob[i].isMACHO) {
+ if (mob[i].isDarkMatter) {
setPos(mob[i], {
x,
y
diff --git a/js/player.js b/js/player.js
index 2df51df..d650503 100644
--- a/js/player.js
+++ b/js/player.js
@@ -547,10 +547,11 @@ const m = {
lastCalculatedDefense: 0, //used to decided if defense bar needs to be redrawn (in simulation.checks)
defense() {
let dmg = 1
+ if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.3
if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.6
- if (tech.isHarmMACHO) dmg *= tech.isMoveMACHO ? 0.3 : 0.4
+ if (tech.isHarmDarkMatter) dmg *= (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 0.25 : 0.4
if (tech.isImmortal) dmg *= 0.7
if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.973 ** m.coupling
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.3
@@ -2364,6 +2365,30 @@ const m = {
ctx.lineTo(m.holdingTarget.vertices[i + 1].x, m.holdingTarget.vertices[i + 1].y);
ctx.fill();
}
+ if (tech.isTokamakFly && m.throwCharge > 4 && m.energy > 0.01) {
+ player.force.y -= 0.5 * player.mass * simulation.g; //add some reduced gravity
+ // const mass = (player.mass + 10) / 3 * simulation.g //this makes it so you fly slower with larger blocks
+ let isDrain = false
+ const thrust = player.mass * simulation.g * Math.pow(5 / player.mass, 0.1)
+ if (input.down) {
+ isDrain = true
+ player.force.y += 0.9 * thrust;
+ } else if (input.up) {
+ isDrain = true
+ player.force.y -= 0.9 * thrust
+ }
+ if (!m.onGround) {
+ if (input.left) {
+ isDrain = true
+ player.force.x -= 0.4 * thrust
+ } else if (input.right) {
+ isDrain = true
+ player.force.x += 0.4 * thrust
+ }
+ if (isDrain) m.energy -= 0.0017;
+ }
+
+ }
} else {
//draw charge
const x = m.pos.x + 15 * Math.cos(m.angle);
@@ -2425,6 +2450,12 @@ const m = {
}
}
b.pulse(60 * Math.pow(m.holdingTarget.mass, 0.25), m.angle)
+ if (tech.isTokamakHeal && tech.tokamakHealCount < 5) {
+ tech.tokamakHealCount++
+ let massScale = Math.min(65 * Math.sqrt(m.maxHealth), 14 * Math.pow(m.holdingTarget.mass, 0.4))
+ if (powerUps.healGiveMaxEnergy) massScale = powerUps["heal"].size()
+ powerUps.spawn(m.pos.x, m.pos.y, "heal", true, null, massScale * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1))) // spawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
+ }
} else { //normal throw
//bullet-like collisions
m.holdingTarget.collisionFilter.category = cat.bullet
@@ -2962,7 +2993,7 @@ const m = {
drainCD: 0,
effect: () => {
m.fieldBlockCD = 0;
- m.blockingRecoil = 1.5 //4 is normal
+ m.blockingRecoil = 1 //4 is normal
m.fieldRange = 185
m.fieldShieldingScale = 1.6 * Math.pow(0.5, (tech.harmonics - 2))
// m.fieldHarmReduction = 0.66; //33% reduction
diff --git a/js/powerup.js b/js/powerup.js
index 0074835..0e29941 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -668,7 +668,7 @@ const powerUps = {
});
} else if (overHeal > 0.13) { //if leftover heals spawn a new spammer heal power up
requestAnimationFrame(() => {
- powerUps.directSpawn(this.position.x, this.position.y, "heal", true, null, overHeal * 40 * (simulation.healScale ** 0.25))// directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
+ powerUps.directSpawn(this.position.x, this.position.y, "heal", true, null, Math.min(1, overHeal) * 40 * (simulation.healScale ** 0.25))// directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
});
}
if (tech.isHealBrake) {
diff --git a/js/spawn.js b/js/spawn.js
index 1a94832..b771cc4 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -116,13 +116,15 @@ const spawn = {
secondaryBossChance(x, y) {
if (simulation.difficultyMode > 2 && level.levelsCleared > 2) {
spawn.randomLevelBoss(x, y);
+ powerUps.directSpawn(x - 30, y, "ammo");
+ powerUps.directSpawn(x + 30, y, "ammo");
} else {
return false
}
},
//mob templates *********************************************************************************************
//***********************************************************************************************************
- MACHO(x = m.pos.x, y = m.pos.y) { //immortal mob that follows player //if you have the tech it spawns at start of every level at the player
+ darkMatter(x = m.pos.x, y = m.pos.y) { //immortal mob that follows player //if you have the tech it spawns at start of every level at the player
mobs.spawn(x, y, 3, 0.1, "transparent");
let me = mob[mob.length - 1];
me.stroke = "transparent"
@@ -135,13 +137,14 @@ const spawn = {
me.collisionFilter.category = 0;
me.collisionFilter.mask = 0; //cat.player //| cat.body
me.chaseSpeed = 3.3
- me.isMACHO = true;
+ me.isDarkMatter = true;
me.frictionAir = 0.006
me.onDeath = function () {
- tech.isHarmMACHO = false;
+ tech.isHarmDarkMatter = false;
}
me.do = function () {
if (!simulation.isTimeSkipping) {
+ const scale = (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 1.6 : 1
const sine = Math.sin(simulation.cycle * 0.015)
this.radius = 111 * tech.isDarkStar + 370 * (1 + 0.1 * sine)
//chase player
@@ -163,7 +166,7 @@ const spawn = {
// }
// }
- if (tech.isMoveMACHO && m.crouch && input.down) {
+ if (tech.isMoveDarkMatter && m.crouch && input.down) {
Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.97), Vector.mult(player.velocity, 0.03)))
Matter.Body.setPosition(this, Vector.add(Vector.mult(this.position, 0.95), Vector.mult(player.position, 0.05)))
}
@@ -171,18 +174,34 @@ const spawn = {
this.force.x += force.x
this.force.y += force.y
-
- if (mag < this.radius) { //buff to player when inside radius
- tech.isHarmMACHO = true;
- //draw halo
- ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
- ctx.beginPath();
- ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI);
- ctx.lineWidth = 10;
- ctx.stroke();
+ if (tech.isNotDarkMatter) {
+ if (mag < this.radius) { //buff to player when inside radius
+ tech.isHarmDarkMatter = false;
+ } else {
+ tech.isHarmDarkMatter = true;
+ //draw halo
+ ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI);
+ ctx.lineWidth = 10;
+ ctx.stroke();
+ if (tech.isDarkEnergy) m.energy += 0.0017 * scale
+ }
} else {
- tech.isHarmMACHO = false;
+ if (mag < this.radius) { //buff to player when inside radius
+ tech.isHarmDarkMatter = true;
+ //draw halo
+ ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
+ ctx.beginPath();
+ ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI);
+ ctx.lineWidth = 10;
+ ctx.stroke();
+ if (tech.isDarkEnergy) m.energy += 0.0017 * scale
+ } else {
+ tech.isHarmDarkMatter = false;
+ }
}
+
//draw outline
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius + 15, 0, 2 * Math.PI);
@@ -196,7 +215,7 @@ const spawn = {
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded) {
if (Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius < this.radius) {
- const dmg = 0.025 * m.dmgScale * (tech.isMoveMACHO ? 1.5 : 1)
+ const dmg = 0.03 * m.dmgScale * scale
mob[i].damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x,
@@ -1428,7 +1447,7 @@ const spawn = {
me.seeAtDistance2 = 1400000;
me.cellMassMax = 70
me.collisionFilter.mask = cat.player | cat.bullet | cat.body// | cat.map
- Matter.Body.setDensity(me, 0.00012 + 0.00001 * simulation.difficulty) // normal density is 0.001
+ Matter.Body.setDensity(me, 0.00012 + 0.000008 * simulation.difficulty) // normal density is 0.001
me.damageReduction = 0.17
const k = 642 //k=r^2/m
@@ -1691,7 +1710,7 @@ const spawn = {
} else if (!m.isCloak) {
me.foundPlayer();
}
- me.damageReduction = 0.2
+ me.damageReduction = 0.21
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
@@ -1769,7 +1788,7 @@ const spawn = {
me.foundPlayer();
}
- me.damageReduction = 0.22
+ me.damageReduction = 0.23
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
@@ -2146,7 +2165,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.09
+ me.damageReduction = 0.12
me.accelMag = 0.05; //jump height
me.g = 0.003; //required if using this.gravity
me.frictionAir = 0.01;
@@ -2470,7 +2489,7 @@ const spawn = {
// toMe(bullet, this.position, this.eventHorizon))
}
};
- me.damageReduction = 0.25
+ me.damageReduction = 0.27
me.do = function () {
//keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) {
@@ -2662,7 +2681,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.babyList = [] //list of mobs that are apart of this boss
Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
- me.damageReduction = 0.13 //normal is 1, most bosses have 0.25
+ me.damageReduction = 0.14 //normal is 1, most bosses have 0.25
me.isBoss = true;
me.friction = 0;
@@ -2978,7 +2997,7 @@ const spawn = {
me.laserRange = 350;
me.seeAtDistance2 = 2000000;
me.isBoss = true;
- me.damageReduction = 0.35 // me.damageReductionGoal
+ me.damageReduction = 0.38 // me.damageReductionGoal
me.showHealthBar = false; //drawn in this.awake
me.delayLimit = 60 + Math.floor(30 * Math.random());
@@ -3403,7 +3422,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.07
+ me.damageReduction = 0.08
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -3594,7 +3613,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
Matter.Body.setDensity(me, 0.004); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.1
+ me.damageReduction = 0.12
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);
@@ -3686,7 +3705,7 @@ const spawn = {
mobs.spawn(x, y, 3, radius, "rgb(0,235,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
- me.damageReduction = 0.25
+ me.damageReduction = 0.27
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);
@@ -3792,7 +3811,7 @@ const spawn = {
Matter.Body.rotate(me, Math.PI * 0.1);
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
- me.damageReduction = 0.034
+ me.damageReduction = 0.038
me.frictionStatic = 0;
me.friction = 0;
@@ -3850,6 +3869,156 @@ const spawn = {
this.checkStatus();
};
},
+ snakeBoss(x, y) {
+ mobs.spawn(x, y, 0, 30, `rgba(255,0,200)`); //"rgb(221,102,119)"
+ let me = mob[mob.length - 1];
+ me.stroke = "transparent"; //used for drawGhost
+ // Matter.Body.setStatic(me, true); //make static, breaks game on player collision
+ Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
+ me.isBoss = true;
+ me.damageReduction = 0.02
+ me.startingDamageReduction = me.damageReduction
+ me.isInvulnerable = false
+ me.nextHealthThreshold = 0.75
+ me.invulnerableCount = 0
+
+ me.history = []
+ for (let i = 0; i < 15; i++) {
+ me.history.push({ x: me.position.x + i, y: me.position.y })
+ }
+ me.frictionStatic = 0;
+ me.friction = 0;
+ me.memory = 240
+ me.seePlayerFreq = 55
+ me.delay = 6 + 4 * simulation.CDScale;
+ me.nextBlinkCycle = me.delay;
+ me.radius = 30
+ me.JumpDistance = me.radius * 2
+ // spawn.shield(me, x, y, 1);
+ me.collisionFilter.mask = cat.bullet | cat.map //| cat.body //cat.player |
+ me.onDamage = function () {
+ if (this.health < this.nextHealthThreshold) {
+ this.health = this.nextHealthThreshold - 0.01
+ this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
+ this.invulnerableCount = 90
+ this.isInvulnerable = true
+ this.damageReduction = 0
+ this.laserDelay = 130
+ const where = this.history[0]
+ for (let i = 0; i < 10; i++) {
+ this.history.unshift(where)
+ }
+ }
+ };
+ me.onDeath = function () {
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ }
+ me.do = function () {
+ const color = `rgba(255,0,200,${0.3 + 0.07 * Math.random()})`
+
+ //check for player in between each segment
+ for (let i = 0; i < this.history.length - 1; i++) {
+ if (Matter.Query.ray([player], this.history[i], this.history[i + 1], 10).length > 0) {
+ m.damage(0.004 * simulation.dmgScale);
+ simulation.drawList.push({ //add dmg to draw queue
+ x: m.pos.x,
+ y: m.pos.y,
+ radius: 30,
+ color: color,
+ time: 10
+ });
+ break
+ }
+ }
+
+ if (this.nextBlinkCycle < simulation.cycle) { //teleport towards the player
+ this.nextBlinkCycle = simulation.cycle + this.delay;
+ //custom see player by history code
+ let move = (target = this.seePlayer.position) => {
+ const dist = Vector.sub(target, this.position);
+ Matter.Body.translate(this, Vector.mult(Vector.normalise(dist), this.JumpDistance));
+ Matter.Body.setVelocity(this, { x: 0, y: 0 });
+ Matter.Body.setAngle(this, 0);
+ Matter.Body.setAngularVelocity(this, 0)
+ //track previous locations for the tail
+ this.history.push({ x: this.position.x, y: this.position.y }) //add newest to end
+ this.history.shift() //remove first (oldest)
+ }
+ //look for close powers up in line of sight
+ let close = {
+ dist2: Infinity,
+ targetPos: null
+ }
+ for (let i = 0; i < powerUp.length; i++) {
+ if (Matter.Query.ray(map, this.position, powerUp[i].position).length === 0) {
+ const dist = Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position))
+ if (dist < close.dist2) {
+ close = {
+ dist2: dist,
+ // targetPos: { x: powerUp[i].position.x, y: powerUp[i].position.y }
+ target: powerUp[i]
+ }
+ }
+ }
+ }
+ if (close.dist2 < 5000 * 5000) {
+ //chase power ups
+ move(close.target.position)
+ //check if close to power up and eat it
+ if (close.dist2 < 200 * 200) {
+ //eat power up
+ }
+
+ } else if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) {
+ this.seePlayer.yes = true;
+ this.locatePlayer();
+ if (!this.seePlayer.yes) this.seePlayer.yes = true;
+ move()
+ } else if (this.seePlayer.recall) {
+ this.lostPlayer();
+ if (!m.isCloak) {
+ for (let i = 0; i < 50; 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;
+ move()
+ break
+ }
+ }
+ }
+ }
+
+ }
+ this.checkStatus();
+ if (this.isInvulnerable) {
+ this.invulnerableCount--
+ if (this.invulnerableCount < 0) {
+ this.isInvulnerable = false
+ this.damageReduction = this.startingDamageReduction
+ }
+ //draw invulnerable
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 13 + 5 * Math.random();
+ ctx.strokeStyle = `rgba(255,255,255,${0.5 + 0.2 * Math.random()})`;
+ ctx.stroke();
+ }
+ //draw history
+ ctx.beginPath();
+ for (let i = 0, len = this.history.length; i < len; i++) {
+ ctx.lineTo(this.history[i].x, this.history[i].y)
+ }
+ ctx.lineWidth = this.radius * 2;
+ ctx.strokeStyle = color //"rgba(0,235,255,0.5)";
+ ctx.stroke();
+ };
+ },
pulsarBoss(x, y, radius = 90, isNonCollide = false) {
mobs.spawn(x, y, 3, radius, "#a0f");
let me = mob[mob.length - 1];
@@ -3890,7 +4059,7 @@ const spawn = {
me.do = function () {
if (player.speed > 5) this.do = this.fire //don't attack until player moves
}
- me.damageReduction = 0.25
+ me.damageReduction = 0.29
me.fire = function () {
// this.armor();
this.checkStatus();
@@ -4263,7 +4432,7 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.33
+ me.damageReduction = 0.36
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -4725,7 +4894,7 @@ const spawn = {
// spawn.shield(me, x, y, 1);
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.12
+ me.damageReduction = 0.13
me.isBoss = true;
me.onDamage = function () { };
me.onDeath = function () {
@@ -4820,8 +4989,8 @@ const spawn = {
me.frictionAir = 0;
me.restitution = 1
// spawn.spawnOrbitals(me, radius + 50 + 125 * Math.random(), 1)
- Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.09
+ Matter.Body.setDensity(me, 0.002 + 0.00005 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.11
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -5274,7 +5443,7 @@ const spawn = {
let me = mob[mob.length - 1];
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
me.isBoss = true;
- me.damageReduction = 0.1
+ me.damageReduction = 0.11
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.02
@@ -5722,7 +5891,7 @@ const spawn = {
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
- me.damageReduction = 0.15
+ me.damageReduction = 0.17
me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01;
@@ -6030,7 +6199,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
- Matter.Body.setDensity(me, 0.0025 + 0.00013 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.0025 + 0.00009 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "transparent"; //used for drawGhost
me.seeAtDistance2 = 1500000;
@@ -6057,7 +6226,7 @@ const spawn = {
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
- me.damageReduction = 0.2
+ me.damageReduction = 0.22
me.do = function () {
// this.armor();
this.seePlayerCheckByDistance();
@@ -6114,8 +6283,8 @@ const spawn = {
}, 2000); //add in a delay in case the level gets flipped left right
me.isBoss = true;
- Matter.Body.setDensity(me, 0.01 + 0.0004 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.2
+ Matter.Body.setDensity(me, 0.01 + 0.0003 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.22
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true
@@ -6472,8 +6641,8 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
me.isBoss = true;
- Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.2
+ Matter.Body.setDensity(me, 0.0022 + 0.00015 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.22
me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(330 * simulation.CDScale)
@@ -6684,7 +6853,7 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 50, 1);
spawn.spawnOrbitals(me, radius + 125, 1);
spawn.spawnOrbitals(me, radius + 200, 1);
- Matter.Body.setDensity(me, 0.004 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ Matter.Body.setDensity(me, 0.004 + 0.00015 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function () { //helps collisions functions work better after vertex have been changed
setTimeout(() => { //fix mob in place, but allow rotation
for (let i = 0, len = 6; i < len; i++) {
@@ -6713,7 +6882,7 @@ const spawn = {
});
}
};
- me.damageReduction = 0.25
+ me.damageReduction = 0.27
me.do = function () {
// this.armor();
if (this.grenadeLimiter > 1) this.grenadeLimiter--
@@ -6875,7 +7044,7 @@ const spawn = {
me.onDamage = function () {
this.cycle = 0
};
- me.damageReduction = 0.35
+ me.damageReduction = 0.39
me.do = function () {
Matter.Body.rotate(this, 0.003) //gently spin around
this.checkStatus();
@@ -7011,7 +7180,7 @@ const spawn = {
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
};
me.onDamage = function () { };
- me.damageReduction = 0.25
+ me.damageReduction = 0.28
me.do = function () {
// this.armor();
this.seePlayerCheck();
@@ -7393,7 +7562,7 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
let me = mob[mob.length - 1];
me.collisionFilter.mask = cat.bullet | cat.player | cat.body //| cat.mob
- me.damageReduction = 0.028
+ me.damageReduction = 0.031
Matter.Body.setDensity(me, 0.0001); //normal is 0.001
// me.accelMag = 0.0007 * simulation.accelScale;
@@ -7432,8 +7601,8 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1];
me.isBoss = true;
- Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.25
+ Matter.Body.setDensity(me, 0.0006 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.27
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -7682,8 +7851,8 @@ const spawn = {
mobs.spawn(x, y, nodes, radius, "rgb(255,0,150)");
let me = mob[mob.length - 1];
me.isBoss = true;
- Matter.Body.setDensity(me, 0.0017 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- me.damageReduction = 0.1
+ Matter.Body.setDensity(me, 0.0018 + 0.00015 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.11
me.stroke = "transparent"; //used for drawGhost
me.seeAtDistance2 = 2000000;
diff --git a/js/tech.js b/js/tech.js
index d10f69e..0879a0b 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -73,7 +73,7 @@ const tech = {
},
junkChance: 0,
addJunkTechToPool(percent) { //percent is number between 0-1
- simulation.makeTextLog(`+${(100 * percent).toFixed(0)}% JUNKtech chance (${100 * tech.junkChance.toFixed(0)} total chance)`)
+ simulation.makeTextLog(`+${(100 * percent).toFixed(0)}% JUNKtech chance (${(100 * tech.junkChance).toFixed(0)} total chance)`)
// tech.junkChance += (1 - tech.junkChance) * percent
tech.junkChance += percent
if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0
@@ -207,12 +207,14 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
let dmg = tech.damage * m.fieldDamage
+ if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 1.5
+ if (tech.isNoDefenseDamage && m.defense() === 1) dmg *= 2
if (tech.isImmunityDamage && m.immuneCycle > m.cycle) dmg *= 4
if (tech.isPowerUpDamage) dmg *= 1 + 0.05 * powerUp.length
if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.5 : 4
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 2
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.8
- if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 2
+ if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.9 : 2
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
@@ -227,12 +229,12 @@ const tech = {
if (tech.isRerollDamage) dmg *= 1 + Math.max(0, 0.05 * powerUps.research.count)
if (tech.isBotDamage) dmg *= 1 + 0.04 * b.totalBots()
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
- if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy)
+ if (tech.isLowEnergyDamage) dmg *= 1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)
if (tech.energyDamage) dmg *= 1 + m.energy * 0.23 * tech.energyDamage;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.01
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
if (tech.isSpeedDamage) dmg *= 1 + Math.min(1, (tech.speedAdded + player.speed) * 0.0193)
- if (tech.isAxion && tech.isHarmMACHO) dmg *= (tech.isMoveMACHO ? 3 : 2)
+ if (tech.isAxion && tech.isHarmDarkMatter) dmg *= ((tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 3.2 : 2)
if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3;
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit
// if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, 1 - (tech.isEnergyHealth ? m.energy : m.health))
@@ -874,8 +876,6 @@ const tech = {
{
name: "Pareto efficiency",
descriptionFunction() {
- // return `for each gun randomly
gain 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}`
- // return `randomly adjust your guns by
5x or 0.2x ammo per ${powerUps.orb.ammo(1)}`
return `for each of your guns
randomly get 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}`
},
maxCount: 1,
@@ -898,16 +898,6 @@ const tech = {
simulation.makeTextLog(`${(b.guns[index].ammoPack).toFixed(1)} → ${(b.guns[index].ammoPack * scale).toFixed(1)} average ammo per ${powerUps.orb.ammo(1)} for ${b.guns[index].name}`, Infinity)
b.guns[index].ammoPack *= scale
}
-
- // let options = []
- // for (let i = 0; i < b.guns.length - 1; i++) options.push(i)
- // options = shuffle(options)
- // for (let i = 0; i < options.length; i++) {
- // const index = options[i]
- // const scale = (i < options.length / 2) ? 4 : 0.25
- // simulation.makeTextLog(`${(b.guns[index].ammoPack).toFixed(1)} → ${(b.guns[index].ammoPack * scale).toFixed(1)} average ammo per ${powerUps.orb.ammo(1)} for ${b.guns[index].name}`, Infinity)
- // b.guns[index].ammoPack *= scale
- // }
},
remove() { }
},
@@ -932,7 +922,7 @@ const tech = {
{
name: "cache",
link: `cache`,
- description: `15x ammo per ${powerUps.orb.ammo()}, but
you can't store any more ammo than that`,
+ description: `17x ammo per ${powerUps.orb.ammo()}, but
you can't store additional ammo`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -942,7 +932,7 @@ const tech = {
},
requires: "not non-renewables",
effect() {
- tech.ammoCap = 15;
+ tech.ammoCap = 17;
powerUps.ammo.effect()
},
remove() {
@@ -1115,12 +1105,13 @@ const tech = {
},
requires: "",
effect() {
- tech.isFarAwayDmg = true; //used in mob.damage()
+ tech.isFarAwayDmg = true;
},
remove() {
tech.isFarAwayDmg = false;
}
},
+
{
name: "microstates",
link: `microstates`,
@@ -2416,8 +2407,11 @@ const tech = {
}
},
{
- name: "MACHO",
- description: "a massive compact halo object follows you
0.4x damage taken inside the MACHO",
+ name: "dark matter",
+ //a MAssive Compact Halo Object follows you
+ descriptionFunction() {
+ return `dark matter slowly gravitates towards you
0.4x damage taken ${tech.isNotDarkMatter ? "outside" : "inside"} dark matter`
+ },
maxCount: 1,
count: 0,
frequency: 1,
@@ -2427,46 +2421,30 @@ const tech = {
},
requires: "",
effect() {
- tech.isMACHO = true; //this harm reduction comes from the particle toggling tech.isHarmMACHO
- spawn.MACHO()
+ tech.isDarkMatter = true; //this harm reduction comes from the particle toggling tech.isHarmDarkMatter
+ spawn.darkMatter()
},
remove() {
- tech.isMACHO = false;
- tech.isHarmMACHO = false;
+ tech.isDarkMatter = false;
+ tech.isHarmDarkMatter = false;
for (let i = 0, len = mob.length; i < len; i++) {
- if (mob[i].isMACHO) mob[i].alive = false;
+ if (mob[i].isDarkMatter) mob[i].alive = false;
}
}
},
- {
- name: "entropic gravity",
- description: "crouching pulls the MACHO towards you
1.5x for all MACHO effects",
- maxCount: 1,
- count: 0,
- frequency: 2,
- frequencyDefault: 2,
- allowed() {
- return tech.isMACHO
- },
- requires: "MACHO",
- effect() {
- tech.isMoveMACHO = true
- },
- remove() {
- tech.isMoveMACHO = false
- }
- },
{
name: "axion",
- description: "while inside the MACHO
2x damage",
+ descriptionFunction() {
+ return `while ${tech.isNotDarkMatter ? "outside" : "inside"} dark matter
2x damage`
+ },
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isMACHO
+ return tech.isDarkMatter
},
- requires: "MACHO",
+ requires: "dark matter",
effect() {
tech.isAxion = true
},
@@ -2475,16 +2453,72 @@ const tech = {
}
},
{
- name: "dark star",
- description: `mobs inside the MACHO are damaged
1.3x MACHO radius`,
+ name: "dark energy",
+ descriptionFunction() {
+ return `while ${tech.isNotDarkMatter ? "outside" : "inside"} dark matter
generate 10 energy per second`
+ },
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isMACHO
+ return tech.isDarkMatter
},
- requires: "MACHO",
+ requires: "dark matter",
+ effect() {
+ tech.isDarkEnergy = true
+ },
+ remove() {
+ tech.isDarkEnergy = false
+ }
+ },
+ {
+ name: "MACHO",
+ description: "dark matter's effects are only active outside it's range
1.6x to all dark matter effects",
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.isDarkMatter && !tech.isMoveDarkMatter && !tech.isDarkStar
+ },
+ requires: "dark matter, not entropic gravity, dark star",
+ effect() {
+ tech.isNotDarkMatter = true
+ },
+ remove() {
+ tech.isNotDarkMatter = false
+ }
+ },
+ {
+ name: "entropic gravity",
+ description: "crouching pulls dark matter towards you
1.6x to all dark matter effects",
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.isDarkMatter && !tech.isNotDarkMatter
+ },
+ requires: "dark matter, not MACHO",
+ effect() {
+ tech.isMoveDarkMatter = true
+ },
+ remove() {
+ tech.isMoveDarkMatter = false
+ }
+ },
+ {
+ name: "dark star",
+ description: `mobs inside dark matter are damaged
1.3x dark matter radius`,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.isDarkMatter && !tech.isNotDarkMatter
+ },
+ requires: "dark matter, not MACHO",
effect() {
tech.isDarkStar = true
},
@@ -2552,7 +2586,7 @@ const tech = {
},
{
name: "Pauli exclusion",
- description: `for 6 seconds after mob collisions
become invulnerable and inhibit energy regen`,
+ description: `for 8 seconds after mob collisions
become invulnerable and inhibit energy regen`,
maxCount: 9,
count: 0,
frequency: 1,
@@ -2562,7 +2596,7 @@ const tech = {
},
requires: "",
effect() {
- m.collisionImmuneCycles += 360;
+ m.collisionImmuneCycles += 480;
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
},
remove() {
@@ -2729,27 +2763,21 @@ const tech = {
{
name: "Gibbs free energy",
descriptionFunction() {
- return `use ${powerUps.orb.research(2)}
1.01x damage per energy below 100 (${(1 + Math.max(0, 1 - m.energy)).toFixed(2)}x)`
+ return `1.005x damage for each missing energy
(${(1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
- return powerUps.research.count > 1 || build.isExperimentSelection
+ return true
},
requires: "",
effect() {
tech.isLowEnergyDamage = true;
- for (let i = 0; i < 2; i++) {
- if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
- }
},
remove() {
tech.isLowEnergyDamage = false;
- if (this.count > 0) {
- powerUps.research.changeRerolls(2)
- }
}
},
{
@@ -2780,7 +2808,7 @@ const tech = {
},
{
name: "Maxwells demon",
- description: "energy above max decays 30x slower
+5% JUNKtech chance",
+ description: "energy above maximum decays 30x slower
+5% JUNKtech chance",
maxCount: 1,
count: 0,
frequency: 2,
@@ -2868,7 +2896,7 @@ const tech = {
},
{
name: "waste heat recovery",
- description: "if a mob has died in the last 5 seconds
generate 0.05x max energy every second",
+ description: "if a mob has died in the last 5 seconds
generate 0.05x maximum energy every second",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2887,7 +2915,7 @@ const tech = {
{
name: "recycling",
descriptionFunction() {
- return `if a mob has died in the last 5 seconds
recover 0.005x max ${tech.isEnergyHealth ? "energy" : "health"} every second`
+ return `if a mob has died in the last 5 seconds
recover 0.005x maximum ${tech.isEnergyHealth ? "energy" : "health"} every second`
},
description: "",
maxCount: 1,
@@ -2924,6 +2952,66 @@ const tech = {
tech.isHarmReduceNoKill = false;
}
},
+ {
+ name: "stability",
+ descriptionFunction() {
+ return `0.3x damage taken
while your health is at maximum`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.isMaxHealthDefense = true;
+ },
+ remove() {
+ tech.isMaxHealthDefense = false;
+ }
+ },
+ {
+ name: "instability",
+ descriptionFunction() {
+ return `2x damage while your damage taken is 1.00x
(damage taken = ${(m.defense()).toFixed(2)}x)`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.isNoDefenseDamage = true;
+ },
+ remove() {
+ tech.isNoDefenseDamage = false;
+ }
+ },
+ {
+ name: "control theory",
+ descriptionFunction() {
+ return `1.5x damage
while your health is at maximum`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.isMaxHealthDamage = true;
+ },
+ remove() {
+ tech.isMaxHealthDamage = false;
+ }
+ },
{
name: "homeostasis",
descriptionFunction() {
@@ -3059,7 +3147,7 @@ const tech = {
allowed() {
return m.maxHealth > 1;
},
- requires: "max health above 100",
+ requires: "maximum health above 100",
effect() {
tech.isAcidDmg = true;
},
@@ -3070,7 +3158,7 @@ const tech = {
{
name: "induction brake",
descriptionFunction() {
- return `after using ${powerUps.orb.heal()} slow nearby mobs for 17 seconds`
+ return `after using ${powerUps.orb.heal()}
slow nearby mobs for 17 seconds`
},
maxCount: 1,
count: 0,
@@ -3133,7 +3221,7 @@ const tech = {
{
name: "quenching",
descriptionFunction() {
- return `${powerUps.orb.heal()} overhealing results in 2x health loss
and 2x max health increase`
+ return `${powerUps.orb.heal()} overhealing results in 2x health loss
and 2x maximum health increase`
},
maxCount: 1,
count: 0,
@@ -5029,7 +5117,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
+ return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0))
},
requires: "a freeze effect",
effect() {
@@ -5067,7 +5155,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
+ return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
},
requires: "a localized freeze effect, no other mob death tech",
effect() {
@@ -5086,7 +5174,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
+ return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
},
requires: "ice IX",
effect() {
@@ -5105,7 +5193,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
+ return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
},
requires: "a localized freeze effect",
effect() {
@@ -5130,7 +5218,7 @@ const tech = {
// },
// requires: "perfect diamagnetism",
allowed() {
- return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)))
+ return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0)))
},
requires: "a localized freeze effect",
effect() {
@@ -7423,7 +7511,7 @@ const tech = {
//**************************************************
{
name: "spherical harmonics",
- description: "1.5x standing wave deflection energy efficiency
shield deflection radius holds it's max range", //standing wave oscillates in a 3rd dimension
+ description: "1.5x standing wave deflection energy efficiency
shield deflection radius is stable", //standing wave oscillates in a 3rd dimension
isFieldTech: true,
maxCount: 9,
count: 0,
@@ -7513,9 +7601,13 @@ const tech = {
}
},
{
+
+ // descriptionFunction() {
+ // return `use ${powerUps.orb.research(2)}
1.01x damage per energy below maximum (${(1 + Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)`
+ // },
name: "electronegativity",
descriptionFunction() {
- return `1.0023x damage per energy
(${(1 + 0.23 * m.maxEnergy).toFixed(2)}x damage at max energy)`
+ return `1.0023x damage per energy
(${(1 + 0.23 * m.energy).toFixed(2)} at current energy, ${(1 + 0.23 * m.maxEnergy).toFixed(2)}x at maximum energy)`
},
// description: "+1% damage per 8 stored energy",
isFieldTech: true,
@@ -7653,7 +7745,7 @@ const tech = {
{
name: "dynamic equilibrium",
descriptionFunction() {
- return `increase damage by your last ${tech.isEnergyHealth ? "energy" : "health"} loss
style ="float: right;">(${(1 + tech.lastHitDamage * m.lastHit).toFixed(2)}x damage)`
+ return `increase damage by your last ${tech.isEnergyHealth ? "energy" : "health"} loss
(${(1 + tech.lastHitDamage * m.lastHit).toFixed(2)}x damage)`
},
isFieldTech: true,
maxCount: 9,
@@ -7701,7 +7793,7 @@ const tech = {
},
{
name: "aerostat",
- description: `2x damage while off the ground
0.85x damage while on the ground`,
+ description: `2x damage while off the ground
0.9x damage while on the ground`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8022,7 +8114,7 @@ const tech = {
},
{
name: "tokamak",
- description: "throwing a block converts it into energy
and a pulsed fusion explosion",
+ description: "tokamak converts thrown blocks into energy
and a pulsed fusion explosion",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8039,6 +8131,47 @@ const tech = {
tech.isTokamak = false;
}
},
+ {
+ name: "stellarator",
+ descriptionFunction() {
+ return `the first 5 blocks detonated by tokamak
spawn ${powerUps.orb.heal(1)} proportional to block size`
+ },
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 3,
+ frequencyDefault: 3,
+ allowed() {
+ return tech.isTokamak && (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10)
+ },
+ requires: "tokamak",
+ effect() {
+ tech.isTokamakHeal = true;
+ tech.tokamakHealCount = 0
+ },
+ remove() {
+ tech.isTokamakHeal = false;
+ }
+ },
+ {
+ name: "inertial confinement",
+ description: "while holding a block charged with tokamak
you can use energy to fly", //and invulnerable?
+ isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 3,
+ frequencyDefault: 3,
+ allowed() {
+ return tech.isTokamak && (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10)
+ },
+ requires: "tokamak",
+ effect() {
+ tech.isTokamakFly = true;
+ },
+ remove() {
+ tech.isTokamakFly = false;
+ }
+ },
{
name: "degenerate matter",
description: "if your field is active
0.1x damage taken",
@@ -11764,7 +11897,6 @@ const tech = {
isDroneRespawn: null,
deathSpawns: null,
isMobBlockFling: null,
- // blockingIce: null,
isPhaseVelocity: null,
waveBeamSpeed: null,
wavePacketAmplitude: null,
@@ -11772,14 +11904,18 @@ const tech = {
iceIXOnDeath: null,
wimpCount: null,
isAddBlockMass: null,
- isMACHO: null,
- isHarmMACHO: null,
- isMoveMACHO: null,
+ isDarkMatter: null,
+ isHarmDarkMatter: null,
+ isMoveDarkMatter: null,
+ isNotDarkMatter: null,
isSneakAttack: null,
isFallingDamage: null,
harmonics: null,
isStandingWaveExpand: null,
isTokamak: null,
+ isTokamakHeal: null,
+ tokamakHealCount: null,
+ isTokamakFly: null,
deflectEnergy: null,
superBallDelay: null,
isBlockExplode: null,
@@ -11829,6 +11965,7 @@ const tech = {
isRewindField: null,
isCrouchRegen: null,
isAxion: null,
+ isDarkEnergy: null,
isDarkStar: null,
isWormholeMapIgnore: null,
isLessDamageReduction: null,
@@ -11909,4 +12046,7 @@ const tech = {
interestRate: null,
isImmunityDamage: null,
isMobDeathImmunity: null,
+ isMaxHealthDefense: null,
+ isNoDefenseDamage: null,
+ isMaxHealthDamage: null,
}
\ No newline at end of file
diff --git a/style.css b/style.css
index e63679f..347b57b 100644
--- a/style.css
+++ b/style.css
@@ -311,7 +311,7 @@ summary {
.sort-button {
border: 1px #333 solid;
- border-radius: 0.5em;
+ border-radius: 0.4em;
background-color: #fff;
font-size: 0.5em;
/* padding: 0.3em; */
@@ -872,11 +872,17 @@ summary {
text-shadow: 0px 0px 7px #000;
}
-.color-MACHO {
+.color-dark-matter {
color: #246;
text-shadow: 0px 0px 7px #246;
}
+.color-tokamak {
+ color: #5c3ab8;
+ font-weight: 100;
+ text-shadow: 0px -5px 9px rgb(255, 0, 204);
+}
+
.color-dup {
font-variant: small-caps;
letter-spacing: 1px;
diff --git a/todo.txt b/todo.txt
index 947e8a8..bf37b72 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,37 +1,22 @@
******************************************************** NEXT PATCH **************************************************
-new community levels: (you can enable community maps in the settings)
- rings by thatLittleFrog
- flappyGon by Digin
- trial by Cirryn and Tarantula Hawk
- arena level updated by Whyisthisnotavalable
+renamed MACHO -> dark matter
+tech: MACHO - dark matter is active when you are outside not inside it's range, 1.5 to dark matter effects
+tech: dark energy - inside dark matter regen 10 energy
+tech: stability - 0.3x damage taken if health equals maxHealth
+tech: instability - 2x damage if damage taken is 1x
+tech: control theory - 1.5x damage if health equals maxHealth
+tech: inertial confinement - while charging tokamak you can fly, but energy drains
+tech: stellarator - after firing a block with tokamak, spawn up to 5 heals
-difficulty scaling: 0.84->0.85x player damage per level
-research spawn per level is no longer in the difficulty settings
- instead players get 1 research for only the first few levels
-cell boss has less health at high difficulty
+boss health nerf: almost every boss has ~0.8x less health
+ secondary bosses also spawn 2 ammo
+aerostat 0.85->0.9 damage on the ground
+Pauli exclusion 6->8 seconds of invulnerable after getting hit
+Gibbs free energy 2->0 research cost, 1.01->1.05 damage scales with energy below 100->maxEnergy
+cache 15->17x ammo
-converted JUNK tech to additive, instead of the multiplicative
- makes the first JUNK you take do the same, but if you take too much you can get to 100%
-right aligned some text in tech descriptions
-added some circles to the in-game console messages
-
-renamed slow light -> delayed-choice - a single 0.4 second delayed 0.7x damage laser beam
- also now works with reflection
-plasma torch field gets 1.5x damage by default
-molecular assembler coupling 0.8->0.6 energy per second
-nail-bot upgrade 5->4x fire rate
-foam-bot upgrade 3->2.5x size and fire rate
-sound-bot upgrade 2.5->2x fire rate, damage, 1->2x wave packet length
-boom-bot upgrade reduced range, bot acceleration
-orbital-bot upgrade 1.5->2x radius
-perimeter defense 0.95->0.96x damage taken per bot
-network effect 1.05->1.04x damage per bot
-tech: working mass - cleaned up physics and logic a bit
-negative feedback scales with health below maxHealth, not health below 100
- 1.007->1.006x damage per missing health
-homeostasis scales with missing health, not health below 100
- limit of 0.2x at 0 health
+several bug fixes
******************************************************* DESIGN ******************************************************
@@ -59,57 +44,19 @@ list of powerful synergies
*********************************************************** TODO *****************************************************
-figure out how to put controls in background on initial level
- mouse smooth makes the text position jitter when it moves sub pixels
- hide the jitter with artificial jitter to make it seem intentional
- make it look like the instructions are on a fuzzy TV screen
- when player presses move buttons highlight the box/letter for those buttons
-
-a few bosses have too much health
- probably the ones that scale with simulation.difficulty
- Matter.Body.setDensity(me, 0.00012 + 0.00001 * simulation.difficulty) // normal density is 0.001
-
-
-make player mass an adjustable var in the skin
- does this mess with jump height or air control?
-increase mass and movement speed at the same time
- increase jump differently because it scales extra with mass
- m.defaultMass = 4.5
- m.definePlayerMass()
- possible player.mass bad interactions
- grapple
-
-tech: - if health === maxHealth take 0.6x damage
- do 1.5x damage?
-
-JUNK tech - player takes damage from block collisions
- is this gonna contribute to lag?
-
-tech: anthropic principle - cost 1 research to let you not die once per level
- another tech that allows it to trigger multiple times
-
-tokamak synergy tech
- tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?)
- tech: inertial confinement - while charging tokamak you can fly, and invulnerable
- but energy drains
-
-bullets should trigger shrinking platforms level element?
-
-level element - player activated elevators
- could be fast and throw player
- could just rise up slow (slow might have a bad jerky animation)
-
-tech: super balls split after 3 seconds
- but they lost 50% less time
-
-buff plasma torch
- buff plasma tech?
- buff plasma field defense?
- buff plasma damage?
-
-rework energy and health HUD
- make both diegetic?
- should health be red or green?
+snakeBoss - boss with a tail that grows longer
+ improve behavior for when it can't see player
+ wander around looking for power ups
+ what if it gets lost?
+ eat power ups
+ eject them after you die
+ get longer after eating
+ eat mobs?
+ eat blocks?
+ modes: recolor tail based on modes
+ hunting power ups -> small + fast : blue cyan
+ hunting player -> attack? : red/pink
+ slow high defense : white
white laser
what to name? not much in wikipedia
@@ -119,23 +66,42 @@ white laser
tech.laserColor = "#fff"
tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
-bug Newton's 1st law image not showing up on github server
- shows up on n-gon, and landgreen github, but webp file isn't loading onto server?
- try name change,
- wait and see if next patch fixes it
-
tech: atomic pile - lose 1 health if you are above the maximum energy
generate energy for each nearby mob?
do damage?
plasma torch tech?
-boss mob - several squares that move like the snake in the game snake/light cycles
- moves towards player (is smell history pathing good enough?)
- doesn't have inertia/force? or it obeys normal physics kinda?
- gets longer when
- you hit it with bullets?
- it gets near a power up?
- it gets near mobs
+make some explosions have less knock back?
+ annoying with flame test, boom bot?
+
+figure out how to put instructions for controls in background on initial level
+ mouse smooth makes the text position jitter when it moves sub pixels
+ hide the jitter with artificial jitter to make it seem intentional
+ make it look like the instructions are on a fuzzy TV screen
+ when player presses move buttons highlight the box/letter for those buttons
+
+make player mass an adjustable var in the skin
+ does this mess with jump height or air control?
+increase mass and movement speed at the same time
+ increase jump differently because it scales extra with mass
+ m.defaultMass = 4.5
+ m.definePlayerMass()
+ possible player.mass bad interactions
+ grapple
+
+JUNK tech - player takes damage from block collisions
+ is this gonna contribute to lag?
+
+bullets should trigger shrinking platforms level element?
+
+level element - player activated elevators
+ could be fast and throw player
+ could just rise up slow (slow might have a bad jerky animation)
+
+rework energy and health HUD
+ make both diegetic?
+ how? not sure there is a good way to do this...
+ should health be red or green?
Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots.
after snap shot is stored draw outline of body positions for a second to show the change
@@ -1328,6 +1294,8 @@ possible names for tech
Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer
cyanoacrylate - superglue use for a slowing effect?
+ hysteresis - the dependence of the state of a system on its history
+ superposition - something with waves overlapping
******************************************************** IMAGES ********************************************************