From fc70dfee2f1eb559bcec61ae58b0c84b3eb617b7 Mon Sep 17 00:00:00 2001 From: landgreen Date: Fri, 12 Jul 2024 21:41:27 -0700 Subject: [PATCH] more orbs in text replaced tech, field, and gun text with orbs orbs length scale with px->em cleaned up simulation variables text in pause menu some minor tech description changes total tech count no longer includes instant tech or removed tech tech: planned obsolescence - at the start of each level eject your oldest tech and gain 1.1 damage heuristics 1.3 -> between 1 and 1.5 fire rate combinatorial optimization 1.35->1.4 damage difficulty reduction per level 0.85->0.87x damage done 1.23->1.22 damage taken --- img/planned obsolescence.webp | Bin 0 -> 72358 bytes index.html | 164 +---------- js/bullet.js | 11 +- js/engine.js | 2 +- js/index.js | 163 +++++------ js/level.js | 73 +++-- js/player.js | 24 +- js/powerup.js | 98 +++---- js/simulation.js | 1 + js/spawn.js | 24 +- js/tech.js | 499 ++++++++++++++-------------------- style.css | 57 ++-- todo.txt | 286 ++++++++----------- 13 files changed, 529 insertions(+), 873 deletions(-) create mode 100644 img/planned obsolescence.webp diff --git a/img/planned obsolescence.webp b/img/planned obsolescence.webp new file mode 100644 index 0000000000000000000000000000000000000000..b47d9284bc78e3a4b3947c8bd6dfd4970c8a40cb GIT binary patch literal 72358 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 E0Pqtraining -
- - -
+
+
settings
-
@@ -182,54 +70,9 @@
- - -
-
- -
`; + + + + + + + + +
`; const ejectClass = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'pause-eject' : '' for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].count > 0) { @@ -924,43 +935,43 @@ ${tech.junkChance ? `
JUNK: ${(100 * tech // populateGrid() { //background-color:var(--build-bg-color); let text = ` -
-
- - - - - - - - -
-
-
-
- - - start - - -
-
- - - reset - - -
-
- - - share - - -
-
-
-
` +
+
+ + + + + + + + +
+
+
+
+ + + start + + +
+
+ + + reset + + +
+
+ + + share + + +
+
+
+
` const hideStyle = `style="height:auto; border: none; background-color: transparent;"` for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) { const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` diff --git a/js/level.js b/js/level.js index cfdbfe7..4bc8273 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("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.setField("plasma torch") //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 @@ -36,29 +36,28 @@ const level = { // b.giveGuns("super balls") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser - // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser + // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // tech.laserColor = "#fff" // tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)" // b.guns[8].ammo = 100000000 - // requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); + // requestAnimationFrame(() => { tech.giveTech("stimulated emission") }); // tech.giveTech("1st ionization energy") - // 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") }); - // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") + // for (let i = 0; i < 1; ++i) tech.giveTech("booby trap") + // for (let i = 0; i < 1; ++i) tech.giveTech("obsolescence") + // for (let i = 0; i < 1; ++i) tech.giveTech("arsenal") + // requestAnimationFrame(() => { for (let i = 0; i < 3; i++) tech.giveTech("mechatronics") }); + // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("paradigm shift") }); + // for (let i = 0; i < 2; i++) tech.giveTech("nail-bot") // m.lastKillCycle = m.cycle - // for (let i = 0; i < 1; ++i) tech.giveTech("compression engine") + // for (let i = 0; i < 1; ++i) tech.giveTech("cross-disciplinary") // 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); // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing // 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"); + // for (let i = 0; i < 20; i++) powerUps.directSpawn(0, 0, "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) @@ -112,7 +111,10 @@ const level = { if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage } } - if (!simulation.isTraining) level.levelAnnounce(); + if (!simulation.isTraining) { + document.title = "n-gon: " + level.levelAnnounce(); + simulation.makeTextLog(`level.onLevel = "${level.levels[level.onLevel]}"`); + } simulation.setupCamera(player.position); simulation.setZoom(); level.addToWorld(); //add bodies to game engine @@ -204,6 +206,19 @@ const level = { // if (h > healPerOrb) powerUps.spawnDelay("heal", h); // simulation.makeTextLog(`${(Math.ceil(tech.interestRate * 100)).toFixed(0)}% interest on health = ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`) } + if (tech.ejectOld > 0) { + let index = null //find oldest tech that you have + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].count > 0) index = i + } + if (index) { //eject it + const effect = Math.pow(1.1, tech.tech[index].count) + simulation.makeTextLog(`${(effect).toFixed(2)}x damage //from obsolescence`, 360) + tech.damage *= effect + tech.ejectOld *= effect + powerUps.ejectTech(index) + } + } }, trainingText(say) { simulation.lastLogTime = 0; //clear previous messages @@ -241,8 +256,8 @@ const level = { } else if (simulation.difficultyMode > 1) { scale = 2 } - m.dmgScale = Math.pow(0.85, level.levelsCleared * scale) - simulation.dmgScale = Math.max(0.1, 0.23 * level.levelsCleared * scale) //damage done by mobs scales with total levels + m.dmgScale = Math.pow(0.87, level.levelsCleared * scale) + simulation.dmgScale = Math.max(0.1, 0.22 * level.levelsCleared * scale) //damage done by mobs scales with total levels // simulation.healScale = 1 / (1 + simulation.difficulty * 0.043) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; @@ -268,10 +283,9 @@ const level = { levelAnnounce() { const cheating = simulation.isCheating ? "(testing)" : "" if (level.levelsCleared === 0) { - document.title = `n-gon: initial ${cheating}`; + return `initial ${cheating}`; } else { - document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} ${cheating}` - simulation.makeTextLog(`level.onLevel = "${level.levels[level.onLevel]}"`); + return `${level.levelsCleared} ${level.levels[level.onLevel]} ${cheating}` } }, announceMobTypes() { @@ -624,13 +638,12 @@ const level = { let text = `

training

- Begin the guided tutorial that shows you how to use your field and gun. + Begin the guided tutorial that shows you how to use your ${powerUps.field.gun()} and ${powerUps.orb.gun()}.

play

Begin the standard game where you progress through 13 random levels and beat the final boss.
` - //use you use your gun, field, and tech document.getElementById("choose-grid").innerHTML = text //show level info document.getElementById("choose-grid").style.opacity = "1" @@ -4089,9 +4102,10 @@ const level = { } else { isSpawnedBoss = true isDoorsLocked = true - for (let i = 0; i < 9; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "ammo") - for (let i = 0; i < 3; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "heal"); - const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54 + for (let i = 0; i < 12; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1800, "ammo") + for (let i = 0; i < 5; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "heal"); + for (let i = 0; i < 1; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1750, "research"); + const scale = Math.pow(simulation.difficulty, 0.7) if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) { for (let i = 0; i < 250; i++) spawn.starter(-2700 + 2400 * Math.random(), -1300 - 500 * Math.random()) } else { @@ -4112,7 +4126,6 @@ const level = { } } } - // spawn.secondaryBossChance(-2300, -800) } } else { doorIn.isClosing = false @@ -31938,7 +31951,7 @@ const level = { } if (tech.isPiezo) g.energy += 20.48; if (tech.isCouplingNoHit && g.coupling > 0) { - g.couplingChange(-5) + g.couplingChange(-3) const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random()) let where = Vector.add(g.pos, Vector.mult(unit, 17)) @@ -34513,27 +34526,27 @@ const level = { const buttonDoor = level.button(400, 0) let instruction = 0 - level.trainingText(`use your field to pick up the gun power up`) + level.trainingText(`use your field to pick up ${powerUps.orb.gun()}`) level.custom = () => { if (instruction === 0 && simulation.isChoosing) { instruction++ - level.trainingText(`use your field to pick up the gun power up + level.trainingText(`use your field to pick up ${powerUps.orb.gun()}
choose a gun`) } else if (instruction === 1 && !simulation.isChoosing) { instruction++ - level.trainingText(`use your field to pick up the gun power up + level.trainingText(`use your field to pick up ${powerUps.orb.gun()}
choose a gun

use the left mouse button to shoot the mobs`) } else if (instruction === 2 && mob.length === 0) { instruction++ - level.trainingText(`use your field to pick up the gun power up + level.trainingText(`use your field to pick up ${powerUps.orb.gun()}
choose a gun
use the left mouse button to shoot the mobs

drop a block on the red button to open the door`) } else if (instruction === 3 && !door.isClosing) { instruction++ - level.trainingText(`use your field to pick up the gun power up + level.trainingText(`use your field to pick up ${powerUps.orb.gun()}
choose a gun
use the left mouse button to shoot the mobs
put a block on the red button to open the door
`) diff --git a/js/player.js b/js/player.js index d650503..7402cbb 100644 --- a/js/player.js +++ b/js/player.js @@ -699,7 +699,7 @@ const m = { tech.isDeathAvoidedThisLevel = true powerUps.research.changeRerolls(-1) simulation.makeTextLog(`m.research--
${powerUps.research.count}`) - for (let i = 0; i < 16; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false); + for (let i = 0; i < 22; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false); m.energy = m.maxEnergy + 0.1 if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds simulation.wipe = function () { //set wipe to have trails @@ -2156,7 +2156,6 @@ const m = { m.fieldBlockCD = 10; m.fieldDamage = 1 m.fieldHarmReduction = 1; - m.lastHit = 0 m.isSneakAttack = false m.duplicateChance = 0 m.grabPowerUpRange2 = 200000; @@ -2890,7 +2889,7 @@ const m = { couplingDescription(couple = m.coupling) { switch (m.fieldMode) { case 0: //field emitter - return `all other field effects` + return `all effects` case 1: //standing wave // return `deflecting condenses +${couple.toFixed(1)} ice IX` return `+${(couple * 5).toFixed(0)} maximum energy` @@ -3091,7 +3090,7 @@ const m = { }, { name: "perfect diamagnetism", - description: "deflecting does not drain energy
shield maintains functionality while inactive
5 energy per second", + description: `deflecting does not drain energy
shield maintains functionality while inactive
5 energy per second`, effect: () => { m.fieldMeterColor = "#48f" //"#0c5" m.eyeFillColor = m.fieldMeterColor @@ -3326,7 +3325,7 @@ const m = { { name: "negative mass", //
hold blocks as if they have a lower mass - description: "use energy to nullify  gravity
0.4x damage taken
6 energy per second", + description: `use energy to nullify  gravity
0.4x damage taken
6 energy per second`, fieldDrawRadius: 0, effect: () => { m.fieldFire = true; @@ -3572,7 +3571,7 @@ const m = { 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.045; + m.energy -= 0.044; b.iceIX(1) } else if (simulation.molecularMode === 3) { if (tech.isDroneRadioactive) { @@ -4091,7 +4090,7 @@ const m = { }, { name: "time dilation", - description: "use energy to stop time
1.2x movement and fire rate
12 energy per second", + description: `use energy to stop time
1.2x movement and fire rate
12 energy per second`, set() { // m.fieldMeterColor = "#0fc" // m.fieldMeterColor = "#ff0" @@ -4290,7 +4289,7 @@ const m = { }, { name: "metamaterial cloaking", - description: "0.3x damage taken while cloaked
after decloaking 4.5x damage for 2 s
6 energy per second", + description: `0.3x damage taken while cloaked
after decloaking 4.5x damage for 2 s
6 energy per second`, effect: () => { m.fieldFire = true; m.fieldMeterColor = "#333"; @@ -4451,10 +4450,7 @@ const m = { }, { name: "pilot wave", - //
blocks can't collide with intangible mobs - //field radius decreases out of line of sight - //unlock tech from other fields - description: "use energy to guide blocks
tech, fields, and guns have +3 choices
10 energy per second", + description: `use energy to guide blocks
,
, and
have +3 choices
10 energy per second`, effect: () => { m.fieldMeterColor = "#333" m.eyeFillColor = m.fieldMeterColor @@ -5231,13 +5227,13 @@ const m = { }, { name: "grappling hook", - description: `use energy to fire a hook that pulls you
0.6x damage taken
9 energy per second`, + description: `use energy to fire a hook that pulls you
0.5x damage taken
9 energy per second`, effect: () => { m.fieldFire = true; // m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping // m.fieldMeterColor = "#789"//"#456" m.eyeFillColor = m.fieldMeterColor - m.fieldHarmReduction = 0.6; //40% reduction + m.fieldHarmReduction = 0.5; //40% reduction m.grabPowerUpRange2 = 300000 //m.grabPowerUpRange2 = 200000; m.hold = function () { diff --git a/js/powerup.js b/js/powerup.js index 0e29941..229ec6e 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -34,48 +34,10 @@ const powerUps = { healGiveMaxEnergy: false, //for tech 1st ionization energy orb: { research(num = 1) { - switch (num) { - case 1: - return `
` - case 2: - return ` -
-
-
       ` - case 3: - return ` -
-
-
-
          ` - case 4: - return ` -
-
-
-
-
            ` - case 5: - return ` -
-
-
-
-
-
              ` - case 6: - return ` -
-
-
-
-
-
-
                ` - } + if (num === 1) return `
` let text = '' for (let i = 0; i < num; i++) { - text += `
` + text += `
` } text += '
    ' for (let i = 0; i < num; i++) { @@ -90,7 +52,7 @@ const powerUps = { } let text = '' for (let i = 0; i < num; i++) { - text += `
` + text += `
` } text += '
    ' for (let i = 0; i < num; i++) { @@ -100,37 +62,43 @@ const powerUps = { }, heal(num = 1) { if (powerUps.healGiveMaxEnergy) { - switch (num) { - case 1: - return `
` - } + if (num === 1) return `
` + let text = '' for (let i = 0; i < num; i++) { - text += `
` + text += `
` } text += '
    ' - for (let i = 0; i < num; i++) { - text += '  ' - } + for (let i = 0; i < num; i++) text += '  ' return text } else { - switch (num) { - case 1: - return `
` - } + if (num === 1) return `
` + let text = '' for (let i = 0; i < num; i++) { - text += `
` + text += `
` } text += '
    ' - for (let i = 0; i < num; i++) { - text += '  ' - } + for (let i = 0; i < num; i++) text += '  ' return text } }, tech(num = 1) { - return `
` + return `
` + }, + field(num = 1) { + return `
` + }, + gun(num = 1) { + return `
` + }, + gunTech(num = 1) { + return `
+
` + }, + fieldTech(num = 1) { + return `
+
` }, coupling(num = 1) { switch (num) { @@ -139,7 +107,7 @@ const powerUps = { } let text = '' for (let i = 0; i < num; i++) { - text += `
` + text += `
` } text += '
   ' for (let i = 0; i < num; i++) { @@ -421,11 +389,11 @@ const powerUps = {
-
0.85x damage done per level
1.23x damage taken per level
-
-5 initial power ups
faster and more mobs per level
-
0.85x damage done per level
1.23x damage taken per level
-
+1 boss per level
-1 tech per boss
-
0.85x damage done per level
1.23x damage taken per level
+
0.87x damage done per level
1.22x damage taken per level
+
-5 initial power ups
faster mobs and more mobs
+
0.87x damage done per level
1.22x damage taken per level
+
+1 boss per level
-1 ${powerUps.orb.tech()} per boss
+
0.87x damage done per level
1.22x damage taken per level
3x chance for shielded mobs
-3 initial power ups
@@ -1602,6 +1570,7 @@ const powerUps = { // remove a random tech from the list of tech you have tech.removeCount += tech.tech[choose].count tech.tech[choose].remove(); + tech.totalCount -= tech.tech[choose].count tech.tech[choose].count = 0; tech.tech[choose].isLost = true; simulation.updateTechHUD(); @@ -1619,6 +1588,7 @@ const powerUps = { } // remove a random tech from the list of tech you have tech.tech[choose].remove(); + tech.totalCount -= tech.tech[choose].count tech.removeCount += tech.tech[choose].count tech.tech[choose].count = 0; tech.tech[choose].isLost = true; diff --git a/js/simulation.js b/js/simulation.js index 0ae161f..f5298b2 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -830,6 +830,7 @@ const simulation = { simulation.wipe = function () { //set wipe to normal ctx.clearRect(0, 0, canvas.width, canvas.height); } + m.lastHit = 0 m.hole.isOn = false simulation.paused = false; engine.timing.timeScale = 1; diff --git a/js/spawn.js b/js/spawn.js index 6706fb1..850fec9 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -5530,7 +5530,7 @@ const spawn = { me.torqueMagnitude = 0.00024 * me.inertia * (Math.random() > 0.5 ? -1 : 1); me.delay = 70 + 70 * simulation.CDScale; me.cd = 0; - me.swordRadius = 0; + me.swordRadius = 50; me.swordVertex = 1 me.swordRadiusMax = 1100 + 20 * simulation.difficulty; me.swordRadiusGrowRate = me.swordRadiusMax * (0.005 + 0.0003 * simulation.difficulty) @@ -5564,15 +5564,16 @@ const spawn = { Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 ) { //find vertex farthest away from player - let dist = 0 - for (let i = 0, len = this.vertices.length; i < len; i++) { - const D = Vector.magnitudeSquared(Vector.sub({ x: this.vertices[i].x, y: this.vertices[i].y }, m.pos)) - if (D > dist) { - dist = D - this.swordVertex = i - } - } - this.laserAngle = this.swordVertex / 5 * 2 * Math.PI + 0.6283 + // let dist = 0 + // for (let i = 0, len = this.vertices.length; i < len; i++) { + // const D = Vector.magnitudeSquared(Vector.sub({ x: this.vertices[i].x, y: this.vertices[i].y }, m.pos)) + // if (D > dist) { + // dist = D + // this.swordVertex = i + // } + // } + // this.laserAngle = this.swordVertex / 5 * 2 * Math.PI + 0.6283 + this.sword = this.swordGrow Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setAngularVelocity(this, 0) @@ -5581,6 +5582,7 @@ const spawn = { this.isInvulnerable = true this.frictionAir = 1 } + this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle); //always see the tip of the sword } me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing me.swordGrow = function () { @@ -5606,7 +5608,7 @@ const spawn = { this.spinCount++ if (this.spinCount > 80) { this.sword = this.swordWaiting - this.swordRadius = 0 + this.swordRadius = 50 this.accelMag = 0.001 * simulation.accelScale; this.cd = simulation.cycle + this.delay; this.damageReduction = this.startingDamageReduction diff --git a/js/tech.js b/js/tech.js index 3f2953c..6ad991b 100644 --- a/js/tech.js +++ b/js/tech.js @@ -151,7 +151,7 @@ const tech = { if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false //stops the bug where you can't gets stacks of tech you take with decoherence, I think tech.tech[index].effect(); //give specific tech tech.tech[index].count++ - tech.totalCount++ //used in power up randomization + if (!tech.tech[index].isInstant) tech.totalCount++ //used in power up randomization requestAnimationFrame(() => { //move new tech to the top of the tech list if (index > 0 && !build.isExperimentSelection) { @@ -165,7 +165,7 @@ const tech = { setCheating() { if (!simulation.isCheating) { simulation.isCheating = true; - level.levelAnnounce(); + document.title = "n-gon:" + level.levelAnnounce(); lore.techCount = 0; for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].isLore) { @@ -210,10 +210,10 @@ const tech = { 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.isPowerUpDamage) dmg *= 1 + 0.07 * 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.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9 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 @@ -593,7 +593,7 @@ const tech = { { name: "ternary", //"divisor", descriptionFunction() { - return `1.8x damage while your current gun
has ammo divisible by 3` + return `1.9x damage while your ammo
is evenly divisible by 3(${((b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) ? "1.9" : "1")}x)` //if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9 }, maxCount: 1, count: 0, @@ -612,7 +612,7 @@ const tech = { { name: "integrated armament", link: `integrated armament`, - description: `1.3x damage, but new guns replace
your current gun and convert guntech
`, + description: `1.3x damage, but new ${powerUps.orb.gun()} replace
current ${powerUps.orb.gun()} and convert your ${powerUps.orb.gunTech()}
`, maxCount: 1, count: 0, frequency: 1, @@ -630,7 +630,7 @@ const tech = { }, { name: "ordnance", - description: "spawn a gun, gain 2x guntech frequency
+6% JUNKtech chance", + description: `spawn ${powerUps.orb.gun()} and gain 2x ${powerUps.orb.gunTech()} frequency
+6% JUNK chance`, maxCount: 1, count: 0, frequency: 1, @@ -657,7 +657,7 @@ const tech = { { name: "arsenal", descriptionFunction() { - return `1.25x damage per unequipped gun
(${(1 + 0.25 * Math.max(0, b.inventory.length - 1)).toFixed(2)}x)` + return `for each unused ${powerUps.orb.gun()} in your inventory
1.25x damage (${(1 + 0.25 * Math.max(0, b.inventory.length - 1)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -675,8 +675,8 @@ const tech = { { name: "active cooling", descriptionFunction() { - return `1.25x fire rate per unequipped gun
(${(1 / Math.pow(0.8, Math.max(0, b.inventory.length - 1))).toFixed(2)}x)` - }, //
but not including your equipped gun` }, + return `for each unused ${powerUps.orb.gun()} in your inventory
1.25x fire rate (${(1 / Math.pow(0.8, Math.max(0, b.inventory.length - 1))).toFixed(2)}x)` + }, maxCount: 1, count: 0, frequency: 1, @@ -700,7 +700,7 @@ const tech = { let gun = b.guns[b.inventory[tech.buffedGun]].name info = `
this level: ${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x damage for ${gun}` } - return `a new gun is chosen to be improved each level
1.3x damage per gun for the chosen gun${info}` + return `a new ${powerUps.orb.gun()} in your inventory is chosen each level
if it's equipped, 1.3x damage per ${powerUps.orb.gun()} in your inventory${info}
` }, maxCount: 1, count: 0, @@ -721,7 +721,7 @@ const tech = { }, { name: "generalist", - description: "spawn 7 guns, but you can't switch guns
your equipped gun cycles after each level", + description: `spawn 7 ${powerUps.orb.gun()}, but you can't switch ${powerUps.orb.gun()}
your equipped ${powerUps.orb.gun()} cycles after each level`, maxCount: 1, count: 0, frequency: 1, @@ -729,7 +729,7 @@ const tech = { isInstant: true, isBadRandomOption: true, allowed() { - return b.inventory.length < b.guns.length - 5 && b.inventory.length > 1 + return (b.inventory.length < b.guns.length - 5) && (b.inventory.length > 1) }, requires: "at least 2 guns, at least 5 unclaimed guns", effect() { @@ -743,7 +743,7 @@ const tech = { { name: "ad hoc", descriptionFunction() { - return `spawn a ${powerUps.orb.heal()}, ${powerUps.orb.research(1)}, ${powerUps.orb.ammo(1)}, field, gun, or tech
for each of your guns` + return `spawn a ${powerUps.orb.heal()}, ${powerUps.orb.research()}, ${powerUps.orb.ammo()}, ${powerUps.orb.tech()}, ${powerUps.orb.gun()}, or ${powerUps.orb.field()}
for each ${powerUps.orb.gun()} in your inventory` }, maxCount: 1, //random power up count: 0, @@ -775,7 +775,7 @@ const tech = { }, { name: "applied science", - description: `get a random guntech
for each of your guns`, //spawn ${powerUps.orb.research(1)} and + description: `get a random ${powerUps.orb.gunTech()}
for each ${powerUps.orb.gun()} in your inventory`, //spawn ${powerUps.orb.research(1)} and maxCount: 1, count: 0, isInstant: true, @@ -824,7 +824,7 @@ const tech = { { name: "supply chain", descriptionFunction() { - return `spawn a gun
spawn ${powerUps.orb.ammo(1)} that will 2x your gun's ammo` + return `spawn ${powerUps.orb.gun()}
spawn ${powerUps.orb.ammo()} to match your current ammo` }, maxCount: 9, count: 0, @@ -876,7 +876,7 @@ const tech = { { name: "Pareto efficiency", descriptionFunction() { - return `for each of your guns
randomly get 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}` + return `for each ${powerUps.orb.gun()} in your inventory
randomly get 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}` }, maxCount: 1, count: 0, @@ -903,7 +903,7 @@ const tech = { }, { name: "logistics", - description: `2x ammo per ${powerUps.orb.ammo()}, but
ammo is only added to your current gun`, + description: `2x ammo per ${powerUps.orb.ammo()}, but
ammo is only added to your current ${powerUps.orb.gun()}`, maxCount: 1, count: 0, frequency: 1, @@ -1111,12 +1111,11 @@ const tech = { tech.isFarAwayDmg = false; } }, - { name: "microstates", link: `microstates`, descriptionFunction() { - return `use ${powerUps.orb.research(3)}
1.01x damage per bullet or bot` + return `use ${powerUps.orb.research(3)}
1.01x damage per bullet or bot (${(1 + bullet.length * 0.01).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -1181,7 +1180,13 @@ const tech = { }, { name: "heuristics", - description: "1.3x fire rate", + descriptionFunction() { + let totalRate = 1 + for (let i = 0; i < this.totalRate.length; i++) totalRate *= this.totalRate[i] + let currentRate = "" + if (this.count) currentRate = `
(${(totalRate).toFixed(2)}x)` + return `randomly gain between 1x and 1.5x fire rate` + currentRate + }, maxCount: 9, count: 0, frequency: 1, @@ -1190,12 +1195,19 @@ const tech = { return true }, requires: "", + totalRate: [], //tracks the random damage upgrades so it can be removed and in descriptionFunction effect() { - tech.fireRate *= 0.77 + const rate = (Math.floor((Math.random() * 0.5 + 1) * 100)) / 100 + tech.fireRate /= rate + this.totalRate.push(rate) b.setFireCD(); + simulation.makeTextLog(`tech.fireRate *= ${rate} //heuristics`); }, remove() { - tech.fireRate = 1; + if (this.count && m.alive) { + for (let i = 0; i < this.totalRate.length; i++) tech.fireRate *= this.totalRate[i] + } + this.totalRate.length = 0 b.setFireCD(); } }, @@ -1214,12 +1226,12 @@ const tech = { frequencyDefault: 1, allowed() { return true }, requires: "", - damage: 1.1, damageSoFar: [], //tracks the random damage upgrades so it can be removed and in descriptionFunction effect() { const damage = (Math.floor((Math.random() * 0.3 + 1) * 100)) / 100 tech.damage *= damage this.damageSoFar.push(damage) + simulation.makeTextLog(`tech.damage *= ${damage} //mechatronics`); }, remove() { if (this.count && m.alive) for (let i = 0; i < this.damageSoFar.length; i++) tech.damage /= this.damageSoFar[i] @@ -1416,7 +1428,6 @@ const tech = { name: "collider", descriptionFunction() { return `after mobs die existing power ups
collide to form new power ups` - // return `after mobs die there is a +33% chance to convert
${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, ${powerUps.orb.research(1)}, tech, field, gun into other types` }, maxCount: 1, @@ -1970,7 +1981,9 @@ const tech = { }, { name: "perimeter defense", - description: "for each permanent bot
0.96x damage taken", + descriptionFunction() { + return `for each permanent bot
0.96x damage taken(${(0.96 ** b.totalBots()).toFixed(2)}x)` + }, maxCount: 1, count: 0, frequency: 2, @@ -1989,7 +2002,9 @@ const tech = { }, { name: "network effect", - description: "for each permanent bot
1.04x damage", + descriptionFunction() { + return `for each permanent bot
1.04x damage(${(1 + 0.04 * b.totalBots()).toFixed(2)}x)` + }, maxCount: 1, count: 0, frequency: 2, @@ -2010,7 +2025,7 @@ const tech = { name: "bot fabrication", link: `bot fabrication`, descriptionFunction() { - return `after you collect ${powerUps.orb.research(2 + Math.floor(0.1666 * b.totalBots()))}use them to build a
random bot (+1 cost every 5 bots)` + return `after you collect ${powerUps.orb.research(2 + Math.floor(0.1666 * b.totalBots()))}use them
to build a random bot (+1 cost every 5 bots)` }, // description: `if you collect ${powerUps.orb.research(2)}use them to build a
random bot (+1 cost every 5 bots)`, maxCount: 1, @@ -2034,7 +2049,7 @@ const tech = { }, { name: "open-source", - description: `tech, fields, and guns have +1 bot choice
3x bottech frequency`, + description: `${powerUps.orb.tech()}, ${powerUps.orb.field()}, and ${powerUps.orb.gun()} have +1 bot choice
3x bot-${powerUps.orb.tech()} frequency`, maxCount: 1, count: 0, frequency: 1, @@ -2062,7 +2077,7 @@ const tech = { { name: "ersatz bots", link: `ersatz bots`, - description: "double your current permanent bots
remove all guns in your inventory", + description: `double your current permanent bots
remove all ${powerUps.orb.gun()} in your inventory`, maxCount: 1, count: 0, frequency: 2, @@ -2258,7 +2273,7 @@ const tech = { }, { name: "decorrelation", - description: "if your gun and field are unused for 2 seconds
0.3x damage taken", + description: `if your ${powerUps.orb.gun()} and ${powerUps.orb.field()} keys are unused for 2 seconds
0.3x damage taken`, maxCount: 1, count: 0, frequency: 1, @@ -2276,7 +2291,7 @@ const tech = { }, { name: "anticorrelation", - description: "if your gun and field are unused for 2 seconds
2x damage", + description: `if your ${powerUps.orb.gun()} and ${powerUps.orb.field()} keys are unused for 2 seconds
2x damage`, maxCount: 1, count: 0, frequency: 1, @@ -2389,7 +2404,7 @@ const tech = { { name: "first derivative", descriptionFunction() { - return `while your first gun is equipped
0.85x damage taken per gun (${(0.85 ** b.inventory.length).toFixed(2)}x)` + return `0.85x damage taken per ${powerUps.orb.gun()} in your inventory
while the 1st ${powerUps.orb.gun()} in your inventory is equipped(${(0.85 ** b.inventory.length).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -2546,7 +2561,7 @@ const tech = { { name: "non-Newtonian armor", link: `non-Newtonian armor`, - description: "after mob collisions
0.3x damage taken for 10 seconds", + description: "after mob collisions
0.3x damage taken for 10 seconds", maxCount: 1, count: 0, frequency: 1, @@ -2782,7 +2797,7 @@ const tech = { }, { name: "overcharge", - description: "+88 maximum energy
+4% JUNKtech chance", + description: "+88 maximum energy
+4% JUNK chance", maxCount: 9, count: 0, frequency: 1, @@ -2808,7 +2823,7 @@ const tech = { }, { name: "Maxwells demon", - description: "energy above maximum decays 30x slower
+5% JUNKtech chance", + description: "energy above maximum decays 30x slower
+5% JUNK chance", maxCount: 1, count: 0, frequency: 2, @@ -2975,7 +2990,7 @@ const tech = { { name: "instability", descriptionFunction() { - return `2x damage while your damage taken is 1.00x
(damage taken = ${(m.defense()).toFixed(2)}x)` + return `2x damage while your damage taken is 1.00x
(current damage taken = ${(m.defense()).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3017,7 +3032,7 @@ const tech = { descriptionFunction() { // return `0.9x damage taken for each ${name} missing
(${(Math.pow(0.1 * max, Math.max(0, max - h))).toFixed(2)}x)` const scale = 0.2 //adjust this to control the strength of this effect - return `reduce damage taken for each missing ${tech.isEnergyHealth ? "energy" : "health"}
down to a limit of ${scale}x at 0 ${tech.isEnergyHealth ? "energy" : "health"}(${(Math.pow(scale, Math.max(0, 1 - (tech.isEnergyHealth ? m.energy / m.maxEnergy : m.health / m.maxHealth)))).toFixed(2)}x)` + return `missing ${tech.isEnergyHealth ? "energy" : "health"} reduces damage taken
down to a limit of ${scale}x at 0 ${tech.isEnergyHealth ? "energy" : "health"}(${(Math.pow(scale, Math.max(0, 1 - (tech.isEnergyHealth ? m.energy / m.maxEnergy : m.health / m.maxHealth)))).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3077,7 +3092,7 @@ const tech = { { name: "antiscience", descriptionFunction() { - return `–10 ${tech.isEnergyHealth ? "energy" : "health"} after picking up a tech
1.7x damage` + return `–10 ${tech.isEnergyHealth ? "energy" : "health"} after picking up ${powerUps.orb.tech()}
1.7x damage` }, maxCount: 1, count: 0, @@ -3178,7 +3193,7 @@ const tech = { { name: "adiabatic healing", descriptionFunction() { - return `2x healing from ${powerUps.orb.heal()}
+4% JUNKtech chance` + return `2x healing from ${powerUps.orb.heal()}
+4% JUNK chance` }, maxCount: 3, count: 0, @@ -3266,7 +3281,7 @@ const tech = { { name: "accretion disk", descriptionFunction() { - return `1.05x damage for each power up on this level
(${(1 + 0.05 * powerUp.length).toFixed(2)}x)` + return `1.07x damage for each power up on this level
+5% JUNK chance (${(1 + 0.07 * powerUp.length).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3279,15 +3294,21 @@ const tech = { requires: "accretion", effect() { tech.isPowerUpDamage = true + this.refundAmount += tech.addJunkTechToPool(0.05) }, + refundAmount: 0, remove() { tech.isPowerUpDamage = false + if (this.count > 0 && this.refundAmount > 0) { + tech.removeJunkTechFromPool(this.refundAmount) + this.refundAmount = 0 + } }, }, { name: "maintenance", descriptionFunction() { - return `2x healtech frequency
spawn ${powerUps.orb.heal(13)}` + return `2x healing-${powerUps.orb.tech()} frequency
spawn ${powerUps.orb.heal(13)}` }, maxCount: 1, count: 0, @@ -3358,7 +3379,7 @@ const tech = { // }, 1000); // }, descriptionFunction() { - return `once per level, instead of dying
use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}` + return `once per level, instead of dying use ${powerUps.orb.research(1)} and
spawn ${powerUps.orb.heal(22)}` }, maxCount: 1, count: 0, @@ -3438,8 +3459,7 @@ const tech = { }, { name: "many-worlds", - // description: "each level is an alternate reality, where you
find a tech at the start of each level", - description: `at the start of each level spawn a tech
and enter an alternate reality`, + description: `at the start of each level spawn ${powerUps.orb.tech()}
and enter an alternate reality`, maxCount: 1, count: 0, frequency: 1, @@ -3481,7 +3501,7 @@ const tech = { }, { name: "decoherence", - description: `after a boss dies spawn ${powerUps.orb.research(2)}
tech options you don't choose won't reoccur`, + description: `after a boss dies spawn ${powerUps.orb.research(2)}
${powerUps.orb.tech()} options you don't choose won't reoccur`, maxCount: 1, count: 0, frequency: 1, @@ -3507,7 +3527,7 @@ const tech = { }, { name: "peer review", - description: `after you research gain 1.05x damage
and +1% JUNKtech chance`, + description: `after you research gain 1.05x damage
and +1% JUNK chance`, maxCount: 1, count: 0, frequency: 1, @@ -3525,7 +3545,7 @@ const tech = { }, { name: "pseudoscience", - description: "research 2 times for free, but
add 1% JUNKtech chance each time", + description: "research 2 times for free, but
add 1% JUNK chance each time", maxCount: 1, count: 0, frequency: 1, @@ -3543,7 +3563,7 @@ const tech = { }, { name: "renormalization", - description: `47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}
+5% JUNKtech chance`, + description: `47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}
+5% JUNK chance`, maxCount: 1, count: 0, frequency: 2, @@ -3610,7 +3630,7 @@ const tech = { }, { name: "ansatz", - description: `after choosing a field, tech, or gun
if you have no ${powerUps.orb.research(1)} in your inventory spawn ${powerUps.orb.research(3)}`, + description: `after choosing ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
if you have no ${powerUps.orb.research(1)} in your inventory spawn ${powerUps.orb.research(3)}`, maxCount: 1, count: 0, frequency: 1, @@ -3628,7 +3648,7 @@ const tech = { }, { name: "unified field theory", - description: `when paused you can click to switch fields
2x fieldtech frequency`, + description: `when paused you can switch ${powerUps.orb.field()} by clicking
2x ${powerUps.orb.fieldTech()} frequency`, maxCount: 1, count: 0, frequency: 1, @@ -3654,7 +3674,7 @@ const tech = { }, { name: "eternalism", - description: "1.25x damage
time can't be paused (time can be dilated)", + description: `1.25x damage
time can't be paused (time can still be dilated)`, maxCount: 1, count: 0, frequency: 1, @@ -3675,7 +3695,7 @@ const tech = { }, { name: "brainstorming", - description: "tech choices randomize
every 1.5 seconds for 10 seconds", + description: `${powerUps.orb.tech()} choices randomize
every 1.5 seconds for 10 seconds`, maxCount: 1, count: 0, frequency: 1, @@ -3696,7 +3716,7 @@ const tech = { }, { name: "cross-disciplinary", - description: "tech have an extra field or gun choice
+5% chance to duplicate spawned power ups", + description: `${powerUps.orb.tech()} have an extra ${powerUps.orb.field()} or ${powerUps.orb.gun()} choice
+5% chance to duplicate spawned power ups`, maxCount: 1, count: 0, frequency: 1, @@ -3717,7 +3737,7 @@ const tech = { }, { name: "emergence", - description: "tech, fields, and guns have +1 choice
1.1x damage", + description: `${powerUps.orb.field()}, ${powerUps.orb.tech()}, and ${powerUps.orb.gun()} have +1 choice
1.1x damage`, maxCount: 9, count: 0, frequency: 1, @@ -3740,7 +3760,7 @@ const tech = { { name: "path integral", link: `path integral`, - description: "your next tech choice has all possible options
+4% JUNKtech chance", + description: `your next ${powerUps.orb.tech()} has all possible choices
+4% JUNK chance`, maxCount: 1, count: 0, frequency: 1, @@ -3767,7 +3787,7 @@ const tech = { }, { name: "determinism", - description: "spawn 5 tech
only 1 choice for tech, fields, and guns", + description: `spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}
only 1 choice for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, and ${powerUps.orb.gun()}`, maxCount: 1, count: 0, frequency: 1, @@ -3789,7 +3809,7 @@ const tech = { }, { name: "superdeterminism", - description: `spawn 5 tech
you can't cancel and ${powerUps.orb.research(1)} no longer spawn`, + description: `spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}
you can't cancel and ${powerUps.orb.research(1)} no longer spawn`, maxCount: 1, count: 0, frequency: 3, @@ -3812,7 +3832,7 @@ const tech = { { name: "technical debt", descriptionFunction() { - return `4x damage but lose 0.15x damage
for each tech you have learned (${(tech.totalCount > 20 ? (Math.pow(0.85, tech.totalCount - 20)) : (4 - 0.15 * tech.totalCount)).toFixed(2)}x)` + return `4x damage but lose 0.15x damage
for each ${powerUps.orb.tech()} you have (${(tech.totalCount > 20 ? (Math.pow(0.85, tech.totalCount - 20)) : (4 - 0.15 * tech.totalCount)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3832,13 +3852,13 @@ const tech = { }, { name: "meta-analysis", - description: `if you choose a JUNKtech you instead get a
random normal tech and spawn ${powerUps.orb.research(2)}`, + description: `if you choose a JUNK you instead get a
random nonJUNK ${powerUps.orb.tech()} and ${powerUps.orb.research(2)}`, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return tech.junkChance > 0 + return tech.junkChance > 0.1 }, requires: "some JUNK tech", effect() { @@ -3850,7 +3870,7 @@ const tech = { }, { name: "dark patterns", - description: "1.3x damage
+15% JUNKtech chance", + description: "1.3x damage
+15% JUNK chance", maxCount: 9, count: 0, frequency: 1, @@ -3875,7 +3895,7 @@ const tech = { { name: "junk DNA", descriptionFunction() { - return `increase damage by twice the
JUNKtech chance (${(1 + 2 * tech.junkChance).toFixed(2)}x)` + return `increase damage by twice the
JUNK chance (${(1 + 2 * tech.junkChance).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3895,7 +3915,7 @@ const tech = { { name: "mass production", descriptionFunction() { - return `tech have extra choices to spawn ${powerUps.orb.ammo(1)},  ${powerUps.orb.heal(1)},  or  ${powerUps.orb.research(1)}
+3% chance to duplicate spawned power ups` + return `${powerUps.orb.tech()} have extra choices to spawn ${powerUps.orb.ammo(1)},  ${powerUps.orb.heal(1)},  or  ${powerUps.orb.research(1)}
+3% chance to duplicate spawned power ups` }, maxCount: 1, count: 0, @@ -4085,7 +4105,7 @@ const tech = { name: "fine-structure constant", descriptionFunction() { // return `spawn ${this.value} ${powerUps.orb.coupling(1)} that each give +0.1 coupling
-0.5 coupling after mob collisions`//
${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per coupling"} - return `after a boss dies spawn ${powerUps.orb.coupling(9)}
lose ${powerUps.orb.coupling(4)} after mob collisions`//
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)} + return `after a boss dies spawn ${powerUps.orb.coupling(9)}
lose ${powerUps.orb.coupling(3)} after mob collisions`//
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)} }, maxCount: 1, count: 0, @@ -4107,7 +4127,6 @@ const tech = { { name: "residual dipolar coupling", descriptionFunction() { - // return `clicking cancel for a field, tech, or gun
spawns ${powerUps.orb.coupling(5)}that each give +0.1 coupling`//
${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per coupling"} return `clicking cancel spawns ${powerUps.orb.coupling(8)}
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}` }, maxCount: 1, @@ -4128,7 +4147,7 @@ const tech = { { name: "commodities exchange", descriptionFunction() { - return `clicking cancel for a field, tech, or gun
spawns 8-12 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` + return `clicking cancel for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
spawns 8-12 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` }, maxCount: 1, count: 0, @@ -4148,8 +4167,7 @@ const tech = { { name: "options exchange", link: `options exchange`, - // description: `once per level clicking cancel will randomize
with 2x choices for fields, tech, or guns
`, - description: `clicking cancel for fields, tech, or guns
will randomize with 3x choices, once a level`, + description: `clicking cancel for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
will randomize with 3x choices, once a level`, maxCount: 1, count: 0, frequency: 1, @@ -4169,7 +4187,7 @@ const tech = { }, { name: "futures exchange", - description: "clicking cancel for a field, tech, or gun
gives +5% power up duplication chance", + description: `clicking cancel for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
gives +5% power up duplication chance`, maxCount: 1, count: 0, frequency: 1, @@ -4189,7 +4207,7 @@ const tech = { }, { name: "replication", - description: "+10% chance to duplicate spawned power ups
+15% JUNKtech chance", + description: "+10% chance to duplicate spawned power ups
+15% JUNK chance", maxCount: 9, count: 0, frequency: 1, @@ -4278,7 +4296,7 @@ const tech = { }, { name: "stimulated emission", - description: "+20% chance to duplicate spawned power ups,
collisions eject a random tech", + description: `+20% chance to duplicate spawned power ups,
collisions eject a random ${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 1, @@ -4328,7 +4346,7 @@ const tech = { }, { name: "strange loop", - description: `1.1x damage
removing this gives a random removetech`, + description: `1.1x damage
removing this gives a random remove-${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 1, @@ -4415,7 +4433,7 @@ const tech = { { name: "externality", descriptionFunction() { - return `1.1x damage
removing this spawns ${this.ammo} ${powerUps.orb.ammo(1)}` + return `1.1x damage
removing this spawns ${this.ammo} ${powerUps.orb.ammo()}` }, maxCount: 1, count: 0, @@ -4444,7 +4462,7 @@ const tech = { name: "deprecated", scale: 0.07, descriptionFunction() { - return `after removing this gain
${1 + this.scale}x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` + return `after removing this gain
${1 + this.scale}x damage per removed ${powerUps.orb.tech()}(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -4466,10 +4484,31 @@ const tech = { } } }, + { + name: "planned obsolescence", + descriptionFunction() { + return `at the start of each level eject your oldest ${powerUps.orb.tech()}
and gain 1.1x damage each time` //(${(tech.ejectOld).toFixed(2)}x) + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isBadRandomOption: true, + allowed() { + return true + }, + requires: "", + effect() { + tech.ejectOld = 1 //this grows + }, + remove() { + tech.ejectOld = 0 + } + }, { name: "paradigm shift", descriptionFunction() { - return `when paused clicking a tech ejects it
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.3x cost each use)` + return `when paused clicking your ${powerUps.orb.tech()} ejects them
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.3x cost each use)` }, maxCount: 1, count: 0, @@ -4489,7 +4528,7 @@ const tech = { }, { name: "Born rule", - description: "eject all your tech", + description: `eject all your ${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 1, @@ -4537,7 +4576,7 @@ const tech = { { name: "Occams razor", descriptionFunction() { - return `randomly remove half your tech
for each removed ${(1 + this.damagePerRemoved).toFixed(2)}x damage (~${((this.count === 0) ? 1 + this.damagePerRemoved * 0.5 * tech.totalCount : this.damage).toFixed(2)}x)` + return `randomly remove half your ${powerUps.orb.tech()}
for each removed ${(1 + this.damagePerRemoved).toFixed(2)}x damage (~${((this.count === 0) ? 1 + this.damagePerRemoved * 0.5 * tech.totalCount : this.damage).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -4561,6 +4600,7 @@ const tech = { for (let i = 0, len = pool.length * 0.5; i < len; i++) removeCount += tech.removeTech(pool[i]) this.damage = this.damagePerRemoved * removeCount tech.damage *= (1 + this.damage) + simulation.makeTextLog(`${(1 + this.damage).toFixed(2)}x damage //from Occam's razor`, 360) }, remove() { if (this.count && m.alive) tech.damage /= (1 + this.damage) @@ -4568,7 +4608,7 @@ const tech = { }, { name: "exchange symmetry", - description: "remove 1 random tech
spawn 2 new guns", + description: `remove a random ${powerUps.orb.tech()}
spawn ${powerUps.orb.gun()}${powerUps.orb.gun()}`, maxCount: 1, count: 0, frequency: 1, @@ -4595,7 +4635,7 @@ const tech = { }, { name: "Monte Carlo method", - description: "remove 1 random tech
spawn 2 tech", + description: `remove a random ${powerUps.orb.tech()}
spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 1, @@ -4796,7 +4836,7 @@ const tech = { { name: "ice crystal nucleation", link: `ice crystal nucleation`, - description: "nail gun uses energy to condense
unlimited freezing ice shards", + description: "nail gun uses energy instead of ammo
to condense freezing ice nails", isGunTech: true, maxCount: 1, count: 0, @@ -4873,7 +4913,7 @@ const tech = { }, { name: "supercritical fission", - description: "if nails, needles, or rivets strike mobs
near their center they can explode", + description: "if nails, needles, or rivets strike mobs
near their center they trigger an explosion", isGunTech: true, maxCount: 1, count: 0, @@ -5012,7 +5052,7 @@ const tech = { { name: "Noether violation", link: `Noether violation`, - description: "1.5x shotgun damage
shotgun recoil is reversed", + description: "1.5x shotgun damage
shotgun recoil is reversed", isGunTech: true, maxCount: 1, count: 0, @@ -5091,7 +5131,7 @@ const tech = { { name: "ice-shot", link: `ice-shot`, - description: "shotgun grows freezing ice IX crystals", + description: "shotgun condenses ice IX crystals
that freeze mobs", isGunTech: true, maxCount: 1, count: 0, @@ -5186,7 +5226,7 @@ const tech = { }, { name: "superfluidity", - description: "freeze effects are applied
to a small area around the target", + description: "freeze effects are applied
to a small area around the target", isGunTech: true, maxCount: 1, count: 0, @@ -5270,7 +5310,7 @@ const tech = { }, { name: "Zectron", - description: `2x super ball damage, but
after colliding with super balls -4 energy`, + description: `2x super ball damage, but
-4 energy after you collide with super balls`, isGunTech: true, maxCount: 1, count: 0, @@ -5586,7 +5626,7 @@ const tech = { { name: "missile-bot", link: `missile-bot`, - description: `use ${powerUps.orb.research(1)}to trade your missile gun
for a bot that fires missiles`, + description: `use ${powerUps.orb.research(1)}to trade your missile ${powerUps.orb.gun()}
for a bot that fires missiles`, // isGunTech: true, isRemoveGun: true, maxCount: 1, @@ -5658,7 +5698,7 @@ const tech = { }, { name: "launch system", - description: `5x missile gun fire rate
1.2x missile ammo per ${powerUps.orb.ammo(1)}`, + description: `5x missile fire rate
1.2x missile ammo per ${powerUps.orb.ammo(1)}`, isGunTech: true, maxCount: 1, count: 0, @@ -5916,7 +5956,7 @@ const tech = { }, { name: "flame test", - description: "after grenades detonate they release
a colorful cluster of small explosions", + description: "after grenades detonate they trigger
a colorful cluster of small explosions", isGunTech: true, maxCount: 1, count: 0, @@ -5935,7 +5975,7 @@ const tech = { }, { name: "pyrotechnics", - description: "after grenades detonate they release
a colorful circle of explosions", + description: "after grenades detonate they trigger
a colorful circle of explosions", isGunTech: true, maxCount: 1, count: 0, @@ -5954,7 +5994,7 @@ const tech = { }, { name: "fireworks", - description: "after grenades detonate they release
colorful petals of explosions", + description: "after grenades detonate they trigger
colorful petals of explosions", isGunTech: true, maxCount: 1, count: 0, @@ -6092,7 +6132,7 @@ const tech = { }, { name: "booby trap", - description: "50% chance to drop a mine from power ups
+15% JUNKtech chance", + description: "50% chance to drop a mine from power ups
+15% JUNK chance", isGunTech: true, maxCount: 1, count: 0, @@ -6138,7 +6178,7 @@ const tech = { { name: "blast ball", descriptionFunction() { - return `instead of nails mines fire bouncy balls` + return `mines fire bouncy balls instead of nails` }, isGunTech: true, maxCount: 1, @@ -6444,7 +6484,7 @@ const tech = { }, { name: "fault tolerance", - description: `use ${powerUps.orb.research(2)}to trade your drone gun
for 5 drones that last forever`, + description: `use ${powerUps.orb.research(2)}to trade your drone ${powerUps.orb.gun()}
for 5 drones that last forever`, // isGunTech: true, isRemoveGun: true, maxCount: 1, @@ -6540,7 +6580,6 @@ const tech = { { name: "von Neumann probe", //"drone repair", description: "after a drone expires it will use -4 energy
and a nearby block to replicate itself", - // description: "broken drones repair if the drone gun is active
repairing has a 25% chance to use 1 drone", isGunTech: true, maxCount: 1, count: 0, @@ -6710,7 +6749,7 @@ const tech = { }, { name: "surfactant", - description: `use ${powerUps.orb.research(2)}to trade your foam gun
for 2 foam-bots and foam-bot upgrade`, + description: `use ${powerUps.orb.research(2)}to trade your foam ${powerUps.orb.gun()}
for 2 foam-bots and foam-bot upgrade`, // isGunTech: true, isRemoveGun: true, maxCount: 1, @@ -6809,7 +6848,7 @@ const tech = { }, { name: "foam fractionation", - description: "if you have below 300 ammo
2x foam gun bubble size", + description: "if you have below 300 ammo
2x foam bubble size", isGunTech: true, maxCount: 1, count: 0, @@ -6855,7 +6894,7 @@ const tech = { }, { name: "pressure vessel", - description: "build up charge while firing foam gun
after firing discharge foam bubbles", + description: "build up charge while firing foam
after firing discharge foam bubbles", isGunTech: true, maxCount: 1, count: 0, @@ -6921,7 +6960,7 @@ const tech = { }, { name: "railgun", - description: `hold fire to charge harpoon and release to launch
harpoons can't retract`, + description: `hold and release fire key to launch harpoons
but, harpoons can't retract`, // description: `+900% harpoon ammo, but it can't retract
+50% harpoon density and damage`, isGunTech: true, maxCount: 1, @@ -7147,7 +7186,7 @@ const tech = { }, { name: "optical amplifier", - description: "gain 3 random laser guntech
laser only turns off if you have no energy", + description: `gain 3 random laser ${powerUps.orb.tech()}
laser only turns off if you have no energy`, // isGunTech: true, maxCount: 1, count: 0, @@ -7249,7 +7288,7 @@ const tech = { }, { name: "lens", - description: "2.5x laser gun damage if it passes
through a revolving 90° arc circular lens", //π / 2 + description: "2.5x laser damage if it passes
through a revolving 90° arc circular lens", //π / 2 isGunTech: true, maxCount: 1, count: 0, @@ -7314,7 +7353,7 @@ const tech = { }, { name: "diffraction grating", - description: `+1 diverging laser gun beam`, + description: `+1 diverging laser beam`, isGunTech: true, maxCount: 9, count: 0, @@ -7338,7 +7377,7 @@ const tech = { { name: "diffuse beam", link: `diffuse beam`, - description: "laser gun beam is wider and doesn't reflect
3.2x laser damage", + description: "your laser beam is wider, but it doesn't reflect
3.2x laser damage", isGunTech: true, maxCount: 1, count: 0, @@ -7363,7 +7402,7 @@ const tech = { }, { name: "output coupler", - description: "1.3x laser gun beam width
1.3x laser damage", + description: "1.3x laser beam width
1.3x laser damage", isGunTech: true, maxCount: 9, count: 0, @@ -7388,7 +7427,7 @@ const tech = { }, { name: "delayed-choice", - description: "laser gun fires a 0.4 second delayed beam
delayed beams do 0.7x damage", + description: "your laser fires a 0.4 second delayed beam
that does 0.7x damage", isGunTech: true, maxCount: 9, count: 0, @@ -7578,7 +7617,7 @@ const tech = { }, { name: "expansion", - description: "using standing wave field expands its radius
+77 maximum energy", + description: "using standing wave expands its radius
+77 maximum energy", isFieldTech: true, maxCount: 1, count: 0, @@ -7745,13 +7784,13 @@ const tech = { { name: "dynamic equilibrium", descriptionFunction() { - return `increase damage by your last ${tech.isEnergyHealth ? "energy" : "health"} loss
(${(1 + tech.lastHitDamage * m.lastHit).toFixed(2)}x damage)` + return `increase damage by your most recent ${tech.isEnergyHealth ? "energy" : "health"} loss
(${(1 + (tech.lastHitDamage === 0 ? 5 : tech.lastHitDamage) * m.lastHit).toFixed(2)}x)` }, isFieldTech: true, maxCount: 9, count: 0, frequency: 2, - frequencyDefault: 2, + frequencyDefault: 200, allowed() { return m.fieldMode === 8 || m.fieldMode === 3 }, @@ -7765,7 +7804,7 @@ const tech = { }, { name: "neutronium", - description: `0.8x move and jump, but
if your field is active 0.05x damage taken`, + description: `0.8x move and jump, but
while your ${powerUps.orb.field()} is active 0.05x damage taken`, isFieldTech: true, maxCount: 1, count: 0, @@ -7793,7 +7832,9 @@ const tech = { }, { name: "aerostat", - description: `2x damage while off the ground
0.9x damage while on the ground`, + descriptionFunction() { + return `2x damage while off the ground
0.9x damage while on the ground(${(m.onGround ? 0.9 : 2).toFixed(1)}x)` + }, isFieldTech: true, maxCount: 1, count: 0, @@ -7848,110 +7889,9 @@ const tech = { tech.isFlyFaster = false; } }, - // { - // name: "Bose Einstein condensate", - // description: "use energy to freeze mobs in your field
pilot wave, negative mass, time dilation", - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 2, - // frequencyDefault: 2, - // allowed() { - // return m.fieldMode === 8 || m.fieldMode === 3 || (m.fieldMode === 6 && !tech.isRewindField) - // }, - // requires: "pilot wave, negative mass, time dilation, not retrocausality", - // effect() { - // tech.isFreezeMobs = true - // }, - // remove() { - // tech.isFreezeMobs = false - // } - // }, - - // { - // name: "mycelium manufacturing", - // link: `mycelium manufacturing`, - // // description: `use ${powerUps.orb.research(1)}to repurpose molecular assembler
excess energy used to grow spores`, - // descriptionFunction() { return `use ${powerUps.orb.research(1)}to repurpose molecular assembler
excess energy used to grow ${b.guns[6].nameString('s')}` }, - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 3, - // frequencyDefault: 3, - // allowed() { - // return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldMode === 4 && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport) - // }, - // requires: "molecular assembler, no other manufacturing, no drone tech", - // effect() { - // if (!build.isExperimentSelection) { - // for (let i = 0; i < 1; i++) { - // if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - // } - // } - // tech.isSporeField = true; - // }, - // remove() { - // tech.isSporeField = false; - // if (this.count > 0) powerUps.research.changeRerolls(1) - // } - // }, - // { - // name: "missile manufacturing", - // link: `missile manufacturing`, - // description: `use ${powerUps.orb.research(1)}to repurpose molecular assembler
excess energy used to construct missiles`, - // // description: "use 3 research to repurpose assembler
excess energy used to construct missiles", - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 3, - // frequencyDefault: 3, - // allowed() { - // return (build.isExperimentSelection || powerUps.research.count > 0) && m.maxEnergy > 0.5 && m.fieldMode === 4 && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel) - // }, - // requires: "molecular assembler, no other manufacturing, no drone tech", - // effect() { - // if (!build.isExperimentSelection) { - // for (let i = 0; i < 1; i++) { - // if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - // } - // } - // tech.isMissileField = true; - // }, - // remove() { - // tech.isMissileField = false; - // if (this.count > 0) powerUps.research.changeRerolls(1) - // } - // }, - // { - // name: "ice IX manufacturing", - // link: `ice IX manufacturing`, - // description: `use ${powerUps.orb.research(1)}to repurpose molecular assembler
excess energy used to condense ice IX`, - // // description: "use 3 research to repurpose assembler
excess energy used to condense ice IX", - // isFieldTech: true, - // maxCount: 1, - // count: 0, - // frequency: 3, - // frequencyDefault: 3, - // allowed() { - // return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldMode === 4 && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel) - // }, - // requires: "molecular assembler, no other manufacturing, no drone tech", - // effect() { - // if (!build.isExperimentSelection) { - // for (let i = 0; i < 1; i++) { - // if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - // } - // } - // tech.isIceField = true; - // }, - // remove() { - // tech.isIceField = false; - // if (this.count > 0) powerUps.research.changeRerolls(1) - // } - // }, { name: "additive manufacturing", - description: "hold crouch and use your field to print a block
with 1.8x density, damage, and launch speed", + description: `hold crouch and use ${powerUps.orb.field()} to print a block
with 1.8x density, damage, and launch speed`, isFieldTech: true, maxCount: 1, count: 0, @@ -7974,7 +7914,7 @@ const tech = { // description: "molecular assembler prints one block
to jump off while midair", descriptionFunction() { const fieldName = m.fieldMode === 8 ? "pilot wave" : "molecular assembler" - return `a second jump in midair
will print a block to jump off` + return `pressing the jump key in midair
will print a block to jump off` // return `${fieldName} prints a block
to jump off while midair` }, isFieldTech: true, @@ -8090,7 +8030,7 @@ const tech = { }, { name: "combinatorial optimization", - description: "1.35x damage
0.7x fire rate", + description: "1.4x damage
0.7x fire rate", isFieldTech: true, maxCount: 1, count: 0, @@ -8100,7 +8040,7 @@ const tech = { return m.fieldMode === 6 || m.fieldMode === 7 || m.fieldMode === 8 }, requires: "time dilation, cloaking, pilot wave", - damage: 1.35, + damage: 1.4, effect() { tech.damage *= this.damage tech.aimDamage = 1.42 @@ -8174,7 +8114,7 @@ const tech = { }, { name: "degenerate matter", - description: "if your field is active
0.1x damage taken", + description: `if your ${powerUps.orb.field()} key is active
0.1x damage taken`, isFieldTech: true, maxCount: 1, count: 0, @@ -8194,7 +8134,7 @@ const tech = { { name: "plasma-bot", link: `plasma-bot`, - description: `use ${powerUps.orb.research(2)}to trade your field
for a bot that uses energy to emit plasma`, + description: `use ${powerUps.orb.research(2)}to trade your ${powerUps.orb.field()}
for a bot that uses energy to emit plasma`, // isFieldTech: true, isInstant: true, maxCount: 1, @@ -8259,6 +8199,30 @@ const tech = { if (this.count > 0) powerUps.research.changeRerolls(this.count * 2) } }, + { + name: "plasma jet", + link: `plasma jet`, + description: `use ${powerUps.orb.research(2)}
1.5x plasma torch range`, + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (tech.plasmaBotCount || m.fieldMode === 5) && (build.isExperimentSelection || powerUps.research.count > 1) && !tech.isPlasmaBall + }, + requires: "plasma torch, not plasma ball", + effect() { + tech.isPlasmaRange += 0.5; + for (let i = 0; i < 2; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + } + }, + remove() { + tech.isPlasmaRange = 1; + if (this.count > 0) powerUps.research.changeRerolls(this.count * 2) + } + }, { name: "extruder", description: "extrude a thin hot wire of plasma
increases damage and energy cost", @@ -8484,7 +8448,7 @@ const tech = { { name: "symbiosis", descriptionFunction() { - return `after a boss dies spawn ${powerUps.orb.research(4)}${powerUps.orb.heal(3)} and a tech
after a mob dies –0.25 maximum ${tech.isEnergyHealth ? "energy" : "health"}` + return `after a boss dies spawn ${powerUps.orb.research(4)}${powerUps.orb.heal(3)}${powerUps.orb.tech()}
after a mob dies –0.25 maximum ${tech.isEnergyHealth ? "energy" : "health"}` }, isFieldTech: true, maxCount: 1, @@ -8548,7 +8512,7 @@ const tech = { { name: "dazzler", link: `dazzler`, - description: "after decloaking
stun nearby mobs for 2 second", + description: "after decloaking
stun nearby mobs for 2 seconds", isFieldTech: true, maxCount: 1, count: 0, @@ -8586,7 +8550,7 @@ const tech = { }, { name: "WIMPs", - description: `at the end of each level spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly chases you`, + description: `at each level's exit, spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly chases you`, isFieldTech: true, maxCount: 9, count: 0, @@ -9062,7 +9026,7 @@ const tech = { // }, { name: "swap meet", - description: "normal tech become JUNK
and JUNK become normal tech", + description: `normal ${powerUps.orb.tech()} become JUNK
and JUNK become normal`, maxCount: 1, count: 0, frequency: 0, @@ -9211,7 +9175,7 @@ const tech = { remove() { } }, { - name: "planned obsolescence", + name: "defunct", description: "build 100 scrap bots
bots might last for 30 seconds", maxCount: 1, count: 0, @@ -9324,7 +9288,7 @@ const tech = { }, { name: "reinforcement learning", - description: "10x current tech frequency", + description: `10x current ${powerUps.orb.tech()} frequency`, maxCount: 1, count: 0, frequency: 1, @@ -9374,7 +9338,7 @@ const tech = { }, { name: "closed timelike curve", - description: "spawn 5 field power ups, but every 12 seconds
teleport a second into your future or past", + description: `spawn ${powerUps.orb.field()}${powerUps.orb.field()}${powerUps.orb.field()}${powerUps.orb.field()}${powerUps.orb.field()}, but every 12 seconds
teleport a second into your future or past`, maxCount: 1, count: 0, frequency: 0, @@ -9451,7 +9415,7 @@ const tech = { // }, { name: "discount", - description: "get 3 random JUNKtech for the price of 1!", + description: `get 3 random JUNK${powerUps.orb.tech()} for the price of 1!`, maxCount: 1, count: 0, frequency: 0, @@ -9492,7 +9456,7 @@ const tech = { // }, { name: "Higgs phase transition", - description: "instantly spawn 5 tech, but add a chance to
remove everything with a 5 minute half-life", + description: `instantly spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}, but add a chance to
remove everything with a 5 minute half-life`, maxCount: 1, count: 0, frequency: 0, @@ -9553,7 +9517,7 @@ const tech = { }, { name: "brainstorm", - description: "the tech choice menu randomizes
every 0.5 seconds for 10 seconds", + description: `${powerUps.orb.tech()} choices randomize
every 0.5 seconds for 10 seconds`, maxCount: 1, count: 0, frequency: 0, @@ -10196,7 +10160,7 @@ const tech = { }, { name: "disintegrated armament", - description: "spawn a gun
remove your active gun", + description: `spawn ${powerUps.orb.gun()}
remove your active ${powerUps.orb.gun()}`, maxCount: 1, count: 0, frequency: 0, @@ -10215,7 +10179,7 @@ const tech = { }, { name: "probability", - description: "100x frequency
of one random tech", + description: `100x frequency
of a random ${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 0, @@ -10246,7 +10210,7 @@ const tech = { }, { name: "encryption", - description: "secure tech information", + description: `secure information`, maxCount: 1, count: 0, frequency: 0, @@ -10386,7 +10350,7 @@ const tech = { }, { name: "repartitioning", - description: "set the frequency of finding normal tech to 0
spawn 5 tech", + description: `set the frequency of finding nonJUNK-${powerUps.orb.tech()} to 0
spawn ${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}${powerUps.orb.tech()}`, maxCount: 1, count: 0, frequency: 0, @@ -10410,7 +10374,7 @@ const tech = { }, { name: "defragment", - description: "set the frequency of finding JUNKtech to zero", + description: "set the frequency of finding JUNK to zero", maxCount: 1, count: 0, frequency: 0, @@ -10676,7 +10640,7 @@ const tech = { }, { name: "expert system", - description: "spawn a tech power up
+50% JUNKtech chance", + description: "spawn JUNK
+50% JUNK chance", maxCount: 9, count: 0, frequency: 0, @@ -10946,24 +10910,6 @@ const tech = { }, remove() { } }, - // { - // name: "microtransactions", - // description: `when you choose a tech you can
use ${powerUps.orb.research(1)} to buy a free in game skin`, - // maxCount: 1, - // count: 0, - // frequency: 0, - // isJunk: true, - // allowed() { - // return true - // }, - // requires: "", - // effect() { - // tech.isMicroTransactions = true - // }, - // remove() { - // tech.isMicroTransactions = false - // } - // }, { name: "ship", description: "fly around with no legs", @@ -11098,7 +11044,7 @@ const tech = { }, { name: "translucent", - description: "spawn 3 gun power ups
your bullets and bots are transparent", + description: `spawn ${powerUps.orb.gun()}${powerUps.orb.gun()}${powerUps.orb.gun()}
your bullets and bots are transparent`, maxCount: 1, count: 0, frequency: 0, @@ -11459,7 +11405,7 @@ const tech = { }, { name: "planetesimals", - description: `play planetesimals (an asteroids-like game)
clear levels in planetesimals to spawn tech
if you die in planetesimals you die in n-gon`, + description: `play planetesimals (an asteroids-like game)
clear levels in planetesimals to spawn ${powerUps.orb.tech()}
if you die in planetesimals you die in n-gon`, maxCount: 1, count: 0, frequency: 0, @@ -11494,7 +11440,7 @@ const tech = { }, { name: "tinker", - description: "permanently unlock JUNKtech in experiment mode
this effect is stored for future visits", + description: `permanently unlock JUNK${powerUps.orb.tech()} in experiment mode
this effect is stored for future visits`, maxCount: 1, count: 0, frequency: 0, @@ -11643,10 +11589,6 @@ const tech = { this.description = `null is open at level.final()
 ` } else { this.frequency += lore.techGoal * 2 - // for (let i = 0; i < tech.tech.length; i++) { //set name for all unchosen copies of this tech - // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech[i].description = `${lore.techCount+1}/${lore.techGoal}
add copies of this to the potential tech pool` - // } - // for (let i = 0, len = 10; i < len; i++) tech.addLoreTechToPool() this.description = `uncaught error:
${Math.max(0, lore.techGoal - lore.techCount)} more required for access to null` } }, 1); @@ -11658,46 +11600,8 @@ const tech = { } } ], - // addLoreTechToPool() { //adds lore tech to tech pool - // if (!simulation.isCheating) { - // tech.tech.push({ - // name: `undefined`, - // description: `${lore.techCount+1}/${lore.techGoal}
add copies of this to the potential tech pool`, - // maxCount: 1, - // count: 0, - // frequency: 2, - // isLore: true, - // isInstant: true, - // isExperimentHide: true, - // allowed() { - // return true - // }, - // requires: "", - // effect() { - // setTimeout(() => { //a short delay, I can't remember why - // lore.techCount++ - // if (lore.techCount > lore.techGoal - 1) { - // // tech.removeLoreTechFromPool(); - // for (let i = tech.tech.length - 1; i > 0; i--) { - // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1) - // } - // } else { - // for (let i = 0; i < tech.tech.length; i++) { //set name for all unchosen copies of this tech - // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech[i].description = `${lore.techCount+1}/${lore.techGoal}
add copies of this to the potential tech pool` - // } - // for (let i = 0, len = 10; i < len; i++) tech.addLoreTechToPool() - // } - // }, 1); - // }, - // remove() {} - // }) - // } - // }, - // junk: [ - - // ], //variables use for gun tech upgrades - fireRate: null, + fireRate: 1, //initializes to 1 bulletSize: null, energySiphon: null, healSpawn: null, @@ -12049,4 +11953,5 @@ const tech = { isMaxHealthDefense: null, isNoDefenseDamage: null, isMaxHealthDamage: null, + ejectOld: null, } \ No newline at end of file diff --git a/style.css b/style.css index 347b57b..5ccb90b 100644 --- a/style.css +++ b/style.css @@ -184,15 +184,11 @@ summary { scrollbar-width: none; } - - - .choose-grid-no-images { border-radius: 8px; border: 10px solid #444; gap: 10px; background-color: #444; - /* padding: 10px 1px; */ position: absolute; top: 50%; left: 50%; @@ -222,9 +218,6 @@ summary { line-height: 160%; background-color: var(--card-color); font-size: 0.75em; - /* transform-style: preserve-3d; - transition: transform 2s; - transform: rotateX(180deg); */ } .choose-grid-module:hover { @@ -259,9 +252,7 @@ summary { overflow: auto; max-height: 100vh; -ms-overflow-style: none; - /* IE and Edge */ scrollbar-width: none; - /* Firefox */ padding: 1px; } @@ -276,21 +267,9 @@ summary { overflow: auto; max-height: 100vh; -ms-overflow-style: none; - /* IE and Edge */ scrollbar-width: none; - /* Firefox */ } -/* .pause-console { */ -/* padding: 10px; */ -/* margin: 10px; */ -/* border-radius: 10px; */ -/* line-height: 140%; */ -/* font-size: 1em; */ -/* padding: 10px; */ -/* margin: -5px 0; */ -/* } */ - #pause-grid-left::-webkit-scrollbar { display: none; } @@ -581,6 +560,10 @@ summary { z-index: 12; font-size: 1.5em; transition: opacity 5s ease-in; + + /* border: 1.5px #333 solid; */ + /* border-radius: 8px; */ + /* background-color: #fff; */ } .details-div { @@ -588,20 +571,9 @@ summary { border-radius: 8px; border: 2px #333 solid; background-color: #fff; - /* box-shadow: 8px 8px 6px rgba(0, 0, 60, 0.11); */ } - - - - - - - - - - #dmg { position: absolute; z-index: 2; @@ -757,6 +729,7 @@ summary { /* transition: opacity 0.15s; */ pointer-events: none; user-select: none; + /* font-family: monospace; */ } .color-text { @@ -998,13 +971,27 @@ summary { } .circle-grid { - width: 1.35em; - height: 1.35em; + width: 1.32em; + height: 1.32em; border-radius: 50%; display: inline-block; margin-bottom: -0.3em; } +.circle-grid-big { + /* width: 1.7em; + height: 1.7em; + border-radius: 50%; + display: inline-block; + margin-bottom: -0.5em -0.5em -0.5em -0.5em; */ + width: 1.32em; + height: 1.32em; + border-radius: 50%; + display: inline-block; + margin-bottom: -0.3em; + transform: scale(1.5); +} + .circle-grid-instant { width: 1.1em; height: 1.1em; @@ -1660,7 +1647,7 @@ summary { } .pause-details { - background-color: hsl(240, 18%, 93%); + background-color: #e2e9ec; border: 1px solid #333; border-radius: 5px; padding: 7px; diff --git a/todo.txt b/todo.txt index 34a2108..974162a 100644 --- a/todo.txt +++ b/todo.txt @@ -1,53 +1,40 @@ ******************************************************** NEXT PATCH ************************************************** -snakeBoss - boss with a tail that grows longer after damage or eating power ups - maybe have it eat blocks too? +replaced tech, field, and gun text with orbs + orbs length scale with px->em +cleaned up simulation variables text in pause menu +some minor tech description changes +total tech count no longer includes instant tech or removed tech -trying out putting actual system error messages directly into the in-game console +tech: planned obsolescence - at the start of each level eject your oldest tech and gain 1.1 damage -charmed baryons: 0.66->0.8x movement -grappling hook field: 0.6->0.5 damage taken +heuristics 1.3 -> between 1 and 1.5 fire rate +combinatorial optimization 1.35->1.4 damage -******************************************************* DESIGN ****************************************************** +difficulty reduction per level + 0.85->0.87x damage done + 1.23->1.22 damage taken -priorities - synergies between tech - difficult to achieve synergies that feel so powerful they are game breaking / changing - randomized content that adds repeatability - bosses, mobs, levels, tech - graphical indicators of tech effects and quantity - subtle lore woven into unexpected places +******************************************************** BUGS ******************************************************** -add more randomize sub level map content - left/right sides of lock - small lab rooms +ants marching outline on splash screen doesn't sync right on safari -list of powerful synergies - CPT + high energy regen - research + bot fabrication + ersatz bots + various bot upgrades - harpoon + high fire rate + alternator + time dilation - duplication 100% - interest + coupling, research + (peer review? or Bayesian statistics) - electronegativity and high energy? - electronegativity + anyon + duplication + Maxwells demon + interest + pair production - chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level +player can become crouched while not touching the ground if they exit the ground while crouched + +fix door.isClosing actually meaning isClosed? *********************************************************** TODO ***************************************************** +tech - at the start of each new level eject the oldest tech you have and gain 10% damage + + + merge multiple power ups of the same type if nearby 5-10 ammo, research, coupling can merge to form a slightly larger power up version check for merger possibility every 60 seconds? adjust mass spawns to just spawn larger power ups versions and change? spawnDelay -white laser - what to name? not much in wikipedia - goes through shields? - damage, energy cost - 3+ closely overlapping beams (but reflecting, not like diffusion) - tech.laserColor = "#fff" - tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)" - tech: atomic pile - lose 1 health if you are above the maximum energy generate energy for each nearby mob? do damage? @@ -56,9 +43,6 @@ tech: atomic pile - lose 1 health if you are above the maximum energy field tech: molecular assembler - every time you spawn a drone/spore/... become immune to damage for time scales with how much energy was used to spawn drone/... -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 @@ -154,8 +138,6 @@ make sure healing isn't effected by simulation.healScale instead heal orb size should be scaled but the ratio between size and heal shouldn't be effected -tech - destroys a random tech each new level and gains +damage each time - boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires reactor only? will rewind time @@ -992,77 +974,6 @@ n-gon outreach ideas hacker news - show hacker news post twitch - lets play -******************************************************** BUGS ******************************************************** - -bug: maybe I can put in an event listener to reset inputs to false when you tab out to prevent key sticking - -bug - url sharing still broken sometimes - -tech upgrade to anthropic principle to make it trigger at 50% life and 0% once per map - -bug? cloaking field doesn't show energy over max - -run more profiles of n-gon to fix performance issues - -bug - death while paused crashes game? - -bug: possibly clearing away all bullets causes a problem - bullet.js 255 (.do() is missing) - I died and quantum immortality triggered (I had needles and ice-IX) - game crashed but recovered - -vanish element bug, crashes on touching element, happens for 1 person maybe with junk tech? - -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 - (this might be fixed...) - -blocks on buttons teleport into the button endlessly if they are being slowly floated away - maybe add a cooldown? - can't reproduce - -ants marching outline doesn't sync right on safari anymore. - -door to exit in level: vats does nothing - did I do that? - -death while in power up selection menu doesn't reset properly - of course it's not possible to die in this menu unless you use testing and shift+X - -player can become crouched while not touching the ground if they exit the ground while crouched - -a couple times people have reported the final boss dropping extra bodies on death - -blue triangle boss can move backwards and aim away from you if set up properly - issues with dot product probably, but might not be worth fixing - -mouse event e.which is deprecated - -fix door.isClosing actually meaning isClosed? - -make it so that when you are immune to harm you can either jump on mobs or you pass through them - -is there a way to check if the player is stuck inside the map or block - trigger a short term non-collide if that occurs - -(intermittent, but almost every time) bug - capping the fps causes random slow downs, that can be fixed with pause - ******************************************************** LEVELS ******************************************************** map: observatory @@ -1210,6 +1121,72 @@ add sounds // tone(445.50) // tone(495) +******************************************************** IMAGES ******************************************************** + +process: discord midjourney prompts -> "pixelmator pro" adjust color, repair, scale to 384x256, export PNG -> webP? -> place in /img folder +make n-gon a progressive web app to manage image downloads, cache +wave function collapse opens the pause menu after it triggers alternate reality + this is actually good, maybe reuse this code to get pause menu to open at any time +if pause is pressed while selecting power ups, display pause menu on top of selection menu +***styles*** + try --- Pastel drawing, Psychedelic art, Arabesque (cool patterns), knolling (everything spread out and placed on a flat mat) + try taking screen shots of fields graphics and feeding them into midJourney V4 + technology stuff --- Dan Matutina (cute complex technology), + Katsuhiro Otomo (intricate space technology), Tsutomu Nihei (black and white detailed future tech) + infographics of all know multiverses. 1980s Japanese graphic design, dimensional astrolabe, + Japanese poster graphics, Ralph McQuarrie (looks like star wars), Simon Stålenhag (retro-futuristic), Yoshiyuki Tomino (detailed anime future technology) + isometric: low-poly, box cutout, made in blender, Materials: matte clay + subtractive sculpture + kinetic sculpture + quantum stuff -- Hypertorus, Glowing Opal Pearlescent, Physics, Hydro-Dipping Hydrodipped, Vija Celmins, Matt Molloy (photo of golden waves in the sky) +***maybe redo*** + laser + supercritical fission +***past style themes*** + base prompt for player on 5.2: clean white robot spherical turret on bird legs test chamber + standing wave - a 3-D cyan transparent nested concentric aligned centered sphere with rings + by Philippe Starck + perfect diamagnetism - physics magnetic field chalk diagram + time dilation - graphic of a hyperbolic equation Luminogram + negative mass - Blacklight painting by Moebius + plasma torch - by Dan Mumford + + metamaterial cloaking - Scientific photography by Miki Asai, by Bruce Munro + molecular assembler - by Laurie Greasley 16-bit Isometric + wormhole - by Tim White + pilot wave - none + + nail gun - Screenprint + shotgun - blueprint by Dan McPharlin + grenades, missiles, explosions - vibrant fireball explosion sonic shockwave ring art by Victo Ngai --ar 3:2 --v 5 --s 750 + spores - turquoise black spores on a white background full color scientific anatomy by Ernst Haeckel + drones - insect quadcopter tilt-shift photography + super balls - By Akari Toriyama + wave - sound wave oscilloscope by Paul Catherall, concentric circles by Paul Catherall + Barbara Takenaga's painting depicting a clean sound wave on aoscilloscope device --ar 3:2 --v 5 + foam - black blobs Ink doodle + harpoon - iron harpoon on a rope weapon art white background by Eiichiro Oda --no fish --ar 3:2 --v 5 --s 750 + mine - by Dan McPharlin + laser - complex optical scientific equipment + knolling photography + + guns, ammo - isometric clean pixel art image cutaway of , style of tekkonkinkreet + defensive - Paper cutout + bots - hovering drone by Laurie Greasley 16-bit Isometric + generic energy tech - by Laurie Greasley + duplication, cancel - by Kazumasa Nagai + anti-shear topology, fracture analysis, shear stress - Chemigram + ON/OFF - ASCII art + block throwing - Bauhaus style + tech that adds JUNK - by Choi Jeong-hwa + ice IX - microscope images of ice crystals + tech that spawns health - glowing green balls by Enki Bilal + invulnerable - by Nick Veasey (photos that look like x-rays) + alternate reality - Fractal art + tech choice - mandala tile Mosaic + time, CPT, pause - by Lee Bontecou + boost, coupling power ups tech - cyan electron orbiting a black nucleus electric field as bas-relief //(by Kazumasa Nagai) + radioactive - volumetric atomic nucleus diagram by Paul Catherall ******************************************************** LORE ******************************************************** @@ -1279,75 +1256,32 @@ 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 + math terms - integral, derivative, Laplace transform, inflection point + quasicrystals - something with low friction, maybe defense? + Coalescence - things merging together like clouds. maybe mergin power ups? + trihydrogen cation - common molecule in space, dark matter tech? -******************************************************** IMAGES ******************************************************** - -process: discord midjourney prompts -> "pixelmator pro" adjust color, repair, scale to 384x256, export PNG -> webP? -> place in /img folder -make n-gon a progressive web app to manage image downloads, cache -wave function collapse opens the pause menu after it triggers alternate reality - this is actually good, maybe reuse this code to get pause menu to open at any time -if pause is pressed while selecting power ups, display pause menu on top of selection menu -***styles*** - try --- Pastel drawing, Psychedelic art, Arabesque (cool patterns), knolling (everything spread out and placed on a flat mat) - try taking screen shots of fields graphics and feeding them into midJourney V4 - technology stuff --- Dan Matutina (cute complex technology), - Katsuhiro Otomo (intricate space technology), Tsutomu Nihei (black and white detailed future tech) - infographics of all know multiverses. 1980s Japanese graphic design, dimensional astrolabe, - Japanese poster graphics, Ralph McQuarrie (looks like star wars), Simon Stålenhag (retro-futuristic), Yoshiyuki Tomino (detailed anime future technology) - isometric: low-poly, box cutout, made in blender, Materials: matte clay - subtractive sculpture - kinetic sculpture - quantum stuff -- Hypertorus, Glowing Opal Pearlescent, Physics, Hydro-Dipping Hydrodipped, Vija Celmins, Matt Molloy (photo of golden waves in the sky) -***maybe redo*** - laser - supercritical fission -***past style themes*** - base prompt for player on 5.2: clean white robot spherical turret on bird legs test chamber - standing wave - a 3-D cyan transparent nested concentric aligned centered sphere with rings - by Philippe Starck - perfect diamagnetism - physics magnetic field chalk diagram - time dilation - graphic of a hyperbolic equation Luminogram - negative mass - Blacklight painting by Moebius - plasma torch - by Dan Mumford - - metamaterial cloaking - Scientific photography by Miki Asai, by Bruce Munro - molecular assembler - by Laurie Greasley 16-bit Isometric - wormhole - by Tim White - pilot wave - none - - nail gun - Screenprint - shotgun - blueprint by Dan McPharlin - grenades, missiles, explosions - vibrant fireball explosion sonic shockwave ring art by Victo Ngai --ar 3:2 --v 5 --s 750 - spores - turquoise black spores on a white background full color scientific anatomy by Ernst Haeckel - drones - insect quadcopter tilt-shift photography - super balls - By Akari Toriyama - wave - sound wave oscilloscope by Paul Catherall, concentric circles by Paul Catherall - Barbara Takenaga's painting depicting a clean sound wave on aoscilloscope device --ar 3:2 --v 5 - foam - black blobs Ink doodle - harpoon - iron harpoon on a rope weapon art white background by Eiichiro Oda --no fish --ar 3:2 --v 5 --s 750 - mine - by Dan McPharlin - laser - complex optical scientific equipment - knolling photography - - guns, ammo - isometric clean pixel art image cutaway of , style of tekkonkinkreet - defensive - Paper cutout - bots - hovering drone by Laurie Greasley 16-bit Isometric - generic energy tech - by Laurie Greasley - duplication, cancel - by Kazumasa Nagai - anti-shear topology, fracture analysis, shear stress - Chemigram - ON/OFF - ASCII art - block throwing - Bauhaus style - tech that adds JUNK - by Choi Jeong-hwa - ice IX - microscope images of ice crystals - tech that spawns health - glowing green balls by Enki Bilal - invulnerable - by Nick Veasey (photos that look like x-rays) - alternate reality - Fractal art - tech choice - mandala tile Mosaic - time, CPT, pause - by Lee Bontecou - boost, coupling power ups tech - cyan electron orbiting a black nucleus electric field as bas-relief //(by Kazumasa Nagai) - radioactive - volumetric atomic nucleus diagram by Paul Catherall +******************************************************* DESIGN ****************************************************** +priorities + synergies between tech + difficult to achieve synergies that feel so powerful they are game breaking / changing + randomized content that adds repeatability + bosses, mobs, levels, tech + graphical indicators of tech effects and quantity + subtle lore woven into unexpected places +add more randomize sub level map content + left/right sides of lock + small lab rooms +list of powerful synergies + CPT + high energy regen + research + bot fabrication + ersatz bots + various bot upgrades + harpoon + high fire rate + alternator + time dilation + duplication 100% + interest + coupling, research + (peer review? or Bayesian statistics) + electronegativity and high energy? + electronegativity + anyon + duplication + Maxwells demon + interest + pair production + chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level