diff --git a/img/Newtons 1st law.webp b/img/Newtons 1st law.webp index 82cf970..fb8ae4b 100644 Binary files a/img/Newtons 1st law.webp and b/img/Newtons 1st law.webp differ diff --git a/img/Newtons 2nd law.webp b/img/Newtons 2nd law.webp index eb17dfe..9e17354 100644 Binary files a/img/Newtons 2nd law.webp and b/img/Newtons 2nd law.webp differ diff --git a/img/Pareto efficiency.webp b/img/Pareto efficiency.webp new file mode 100644 index 0000000..e8d661d Binary files /dev/null and b/img/Pareto efficiency.webp differ diff --git a/img/deprecated.webp b/img/deprecated.webp new file mode 100644 index 0000000..8ef1387 Binary files /dev/null and b/img/deprecated.webp differ diff --git a/img/externality.webp b/img/externality.webp new file mode 100644 index 0000000..69fda3a Binary files /dev/null and b/img/externality.webp differ diff --git a/img/interest.webp b/img/interest.webp new file mode 100644 index 0000000..51efb08 Binary files /dev/null and b/img/interest.webp differ diff --git a/img/marginal utility.webp b/img/marginal utility.webp new file mode 100644 index 0000000..92e54bd Binary files /dev/null and b/img/marginal utility.webp differ diff --git a/index.html b/index.html index f4b984a..0ce53a3 100644 --- a/index.html +++ b/index.html @@ -11,6 +11,7 @@ + n-gon diff --git a/js/bullet.js b/js/bullet.js index 7137d87..738a888 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -130,9 +130,9 @@ const b = { // if (b.guns[i].name === name) return b.guns[i].ammo // } // }, - giveGuns(gun = "random", ammoPacks = 10) { - if (tech.ammoCap) ammoPacks = 0.45 * tech.ammoCap - if (tech.isOneGun) b.removeAllGuns(); + giveGuns(gun = "random", ammoPacks = 22) { + if (tech.ammoCap) ammoPacks = tech.ammoCap + if (tech.isOneGun) b.resetAllGuns(); if (gun === "random") { //find what guns player doesn't have options = [] @@ -198,8 +198,8 @@ const b = { } if (gunTechPool.length) { const index = Math.floor(Math.random() * gunTechPool.length) - tech.giveTech(gunTechPool[index]) // choose from the gun pool simulation.makeTextLog(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`) + tech.giveTech(gunTechPool[index]) // choose from the gun pool } else { tech.giveTech() //get normal tech if you can't find any gun tech } @@ -229,11 +229,12 @@ const b = { } b.setFireCD(); }, - removeAllGuns() { + resetAllGuns() { b.inventory = []; //removes guns and ammo for (let i = 0, len = b.guns.length; i < len; ++i) { b.guns[i].count = 0; b.guns[i].have = false; + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0; } tech.buffedGun = 0 @@ -835,10 +836,7 @@ const b = { suck([player], this.explodeRad * 1.3) } - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); //keep bomb in place + Matter.Body.setVelocity(this, { x: 0, y: 0 }); //keep bomb in place //draw suck const radius = 2.75 * this.explodeRad * (this.endCycle - simulation.cycle) / this.suckCycles ctx.fillStyle = "rgba(0,0,0,0.1)"; @@ -1827,7 +1825,7 @@ const b = { friction: 1, frictionAir: 0.4, // thrustMag: 0.1, - drain: tech.isRailEnergy ? 0 : 0.006, + drain: tech.isRailEnergy ? 0.0002 : 0.006, turnRate: isReturn ? 0.1 : 0.03, //0.015 drawStringControlMagnitude: 3000 + 5000 * Math.random(), drawStringFlip: (Math.round(Math.random()) ? 1 : -1), @@ -5816,8 +5814,8 @@ const b = { return `use compressed air to rapidly drive nails
fire rate increases the longer you fire
${this.ammoPack.toFixed(0)} nails per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 60, - defaultAmmoPack: 60, + ammoPack: 27, + defaultAmmoPack: 27, recordedAmmo: 0, have: false, nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count @@ -6131,8 +6129,8 @@ const b = { return `fire a wide burst of short range bullets
has a slow fire rate
${this.ammoPack.toFixed(1)} shots per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 3.5, - defaultAmmoPack: 3.5, + ammoPack: 1.6, + defaultAmmoPack: 1.6, have: false, do() { //fade cross hairs @@ -6422,7 +6420,8 @@ const b = { return `fire 3 balls in a wide arc
balls bounce with no momentum loss
${this.ammoPack.toFixed(0)} balls per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 9, + ammoPack: 4.05, + defaultAmmoPack: 4.05, have: false, // num: 5, do() { }, @@ -6500,8 +6499,8 @@ const b = { return `emit wave packets that propagate through solids
waves slow mobs
${this.ammoPack.toFixed(0)} wave packets per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 115, - defaultAmmoPack: 115, + ammoPack: 52, + defaultAmmoPack: 52, have: false, wavePacketCycle: 0, delay: 40, @@ -6863,7 +6862,8 @@ const b = { return `launch homing missiles that target mobs
missiles explode on contact with mobs
${this.ammoPack.toFixed(1)} missiles per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 5, + ammoPack: 2.3, + defaultAmmoPack: 2.3, have: false, fireCycle: 0, do() { }, @@ -6971,7 +6971,8 @@ const b = { return `lob a single bouncy projectile
explodes on contact or after one second
${this.ammoPack.toFixed(0)} grenades per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 7, + ammoPack: 3.2, + defaultAmmoPack: 3.2, have: false, do() { }, //do is set in b.setGrenadeMode() fire() { @@ -6995,7 +6996,8 @@ const b = { return `toss a sporangium that discharges ${b.guns[6].nameString("s")}
${b.guns[6].nameString("s")} seek out nearby mobs
${this.ammoPack.toFixed(1)} sporangium per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 2.6, + ammoPack: 1.22, + defaultAmmoPack: 1.22, have: false, nameString(suffix = "") { if (tech.isSporeFlea) { @@ -7020,7 +7022,7 @@ const b = { bullet[me].maxRadius = 30; bullet[me].restitution = 0.3; bullet[me].minDmgSpeed = 0; - bullet[me].totalSpores = 8 + 2 * tech.isSporeFreeze + 4 * tech.isSporeColony + bullet[me].totalSpores = 8 + 2 * tech.isSporeFreeze + 5 * tech.isSporeColony bullet[me].stuck = function () { }; bullet[me].beforeDmg = function () { }; bullet[me].do = function () { @@ -7165,7 +7167,7 @@ const b = { ] for (len = this.totalSpores; count < len; count++) { - if (tech.isSporeColony && Math.random() < 0.5) { + if (tech.isSporeColony && Math.random() < 0.33) { things[Math.floor(Math.random() * things.length)]() } else if (tech.isSporeFlea) { things[2]() @@ -7192,8 +7194,8 @@ const b = { return `deploy autonomous drones that smash into mobs
drones collect nearby power ups
${this.ammoPack.toFixed(0)} drones per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 16, - defaultAmmoPack: 16, + ammoPack: 7.3, + defaultAmmoPack: 7.3, have: false, do() { }, fire() { @@ -7234,7 +7236,8 @@ const b = { return `spray bubbly foam that sticks to mobs
slows mobs and does damage over time
${this.ammoPack.toFixed(0)} bubbles per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 28, + ammoPack: 12.6, + defaultAmmoPack: 12.6, have: false, charge: 0, isDischarge: false, @@ -7351,7 +7354,8 @@ const b = { return `throw a self-steering harpoon that uses energy
to retract and refund its ammo cost
${this.ammoPack.toFixed(1)} harpoons per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 1.7, //update this in railgun tech + ammoPack: 0.77, //update this in railgun tech + defaultAmmoPack: 0.77, have: false, fire() { }, do() { }, @@ -7692,7 +7696,8 @@ const b = { return `toss a proximity mine that sticks to walls
refund undetonated mines on exiting a level
${this.ammoPack.toFixed(1)} mines per ${powerUps.orb.ammo()}` }, ammo: 0, - ammoPack: 1.7, + ammoPack: 0.77, + defaultAmmoPack: 0.77, have: false, nameString(suffix = "") { if (tech.isFoamMine) { @@ -7761,12 +7766,12 @@ const b = { }, { name: "laser", //11 - // description: `emit a beam of collimated coherent light
drains energy instead of ammo
drains ${(0.001 + tech.laserDrain) * 100}% energy per second`, descriptionFunction() { - return `emit a beam of collimated coherent light
drains ${((0.001 + tech.laserDrain) * 600).toFixed(2)} energy per second
doesn't use ammo` + return `emit a beam of collimated coherent light
costs ${(tech.laserDrain * 6000).toFixed(1)} energy per second
doesn't use ammo` }, ammo: 0, ammoPack: Infinity, + defaultAmmoPack: Infinity, have: false, charge: 0, isStuckOn: false, @@ -7903,7 +7908,7 @@ const b = { // this.fire = this.firePhoton }, fireLaser() { - const drain = 0.001 + tech.laserDrain / b.fireCDscale + const drain = tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -7921,7 +7926,7 @@ const b = { }, firePulse() { }, fireSplit() { - const drain = 0.001 + tech.laserDrain / b.fireCDscale + const drain = tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -7946,7 +7951,7 @@ const b = { } }, fireWideBeam() { - const drain = 0.001 + tech.laserDrain / b.fireCDscale + const drain = tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -8019,7 +8024,7 @@ const b = { } }, fireHistory() { - drain = 0.001 + tech.laserDrain / b.fireCDscale + drain = tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { diff --git a/js/engine.js b/js/engine.js index 9c79988..eb2aae4 100644 --- a/js/engine.js +++ b/js/engine.js @@ -292,7 +292,7 @@ function collisionChecks(event) { } } - let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1) * ((m.fieldMode === 0 || m.fieldMode === 8) ? 1 + 0.04 * m.coupling : 1); + let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1) * ((m.fieldMode === 0 || m.fieldMode === 8) ? 1 + 0.05 * m.coupling : 1); if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); diff --git a/js/index.js b/js/index.js index 9450c24..a919b26 100644 --- a/js/index.js +++ b/js/index.js @@ -808,14 +808,12 @@ ${simulation.isCheating ? "

lore disabled" : ""} tech.giveTech(index) } else if (!tech.tech[index].isNonRefundable) { // tech.totalCount -= tech.tech[index].count - tech.removeTech(index); document.getElementById("tech-" + index).classList.remove("build-tech-selected"); + tech.removeTech(index); } else { // for non refundable tech this makes it flash off for a second, but return to on to show that it can't be set off document.getElementById("tech-" + index).classList.remove("build-tech-selected") - setTimeout(() => { - document.getElementById("tech-" + index).classList.add("build-tech-selected") - }, 50); + setTimeout(() => { document.getElementById("tech-" + index).classList.add("build-tech-selected") }, 50); } } build.updateExperimentText(isAllowed) @@ -1099,9 +1097,6 @@ ${simulation.isCheating ? "

lore disabled" : ""} } else { //if you have no tech (not cheating) remove all power ups that might have spawned from tech for (let i = 0; i < powerUp.length; ++i) Matter.Composite.remove(engine.world, powerUp[i]); powerUp = []; - // if (build.hasExperimentalMode) { - // for (let i = 0; i < 7; i++) tech.giveTech("undefined") - // } } document.body.style.cursor = "none"; document.body.style.overflow = "hidden" diff --git a/js/level.js b/js/level.js index 150df6d..18e9fa1 100644 --- a/js/level.js +++ b/js/level.js @@ -33,19 +33,22 @@ const level = { // m.energy = 0 // simulation.molecularMode = 2 // m.damage(0.1); - // b.giveGuns("mine") //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("drones") //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.guns[8].ammo = 100000000 - // requestAnimationFrame(() => { tech.giveTech("eternalism") }); - // for (let i = 0; i < 1; ++i) tech.giveTech("beforeunload") - // for (let i = 0; i < 1; ++i) tech.giveTech("Sleipnir") - // for (let i = 0; i < 1; ++i) tech.giveTech("dark patterns") + // requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); + // for (let i = 0; i < 1; ++i) tech.giveTech("mass production") + // tech.giveTech("Pareto efficiency") + // for (let i = 0; i < 1; ++i) tech.giveTech("reduced tolerances") + // for (let i = 0; i < 1; ++i) tech.giveTech("Newtons 1st law") + // for (let i = 0; i < 1; ++i) tech.giveTech("Newtons 2nd law") // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("paradigm shift") }); // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) }); - // m.skin.hexagon(); // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") // m.lastKillCycle = m.cycle - // for (let i = 0; i < 1; ++i) tech.giveTech("what the block?") + // for (let i = 0; i < 1; ++i) tech.giveTech("deprecated") // for (let i = 0; i < 1; ++i) tech.giveTech("unified field theory") // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); @@ -56,7 +59,7 @@ const level = { // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) // Matter.Body.setPosition(player, { x: -200, y: -3330 }); // for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random()) - // for (let i = 0; i < 1; ++i) spawn.laserLayerBoss(1900, -500) + // for (let i = 0; i < 1; ++i) spawn.stinger(1900, -500) // for (let i = 0; i < 1; ++i) spawn.dragonFlyBoss(1900, -500) // spawn.beetleBoss(1900, -500, 25) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) @@ -74,9 +77,9 @@ const level = { // simulation.isAutoZoom = false; //look in close // simulation.zoomScale *= 0.5; // simulation.setZoom(); - // for (let i = 0; i < 10; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); + // for (let i = 0; i < 3; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "boost"); - // for (let i = 0; i < 20; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "heal"); + // for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo"); // for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false); //lore testing // localSettings.isTrainingNotAttempted = true @@ -168,20 +171,49 @@ const level = { powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false); } if (tech.isHealLowHealth) { - if (tech.isEnergyHealth) { - var len = 4 * Math.max(0, m.maxEnergy - m.energy) - } else { - var len = 4 * Math.max(0, m.maxHealth - m.health) - } + const len = tech.isEnergyHealth ? 5 * Math.max(0, m.maxEnergy - m.energy) : 5 * Math.max(0, m.maxHealth - m.health) for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "heal", false); } + if (tech.interestRate > 0) { + const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels + if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].name !== "laser") { + const ammoPerOrb = b.guns[b.activeGun].ammoPack + const a = Math.ceil(rate * b.guns[b.activeGun].ammo / ammoPerOrb) + powerUps.spawnDelay("ammo", a); + simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on ammo = ${a > 20 ? a + powerUps.orb.ammo(1) : powerUps.orb.ammo(a)}`) + } + if (powerUps.research.count > 0) { + const r = Math.ceil(rate * powerUps.research.count) + simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on research = ${r > 20 ? r + powerUps.orb.research(1) : powerUps.orb.research(r)}`) + powerUps.spawnDelay("research", r); + } + if (m.coupling > 0) { + const c = Math.ceil(rate * m.coupling) + powerUps.spawnDelay("coupling", c); + simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on coupling = ${c > 20 ? c + powerUps.orb.coupling(1) : powerUps.orb.coupling(c)}`) + } + + const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2 + const h = Math.ceil(rate * m.health / healPerOrb) + powerUps.spawnDelay("heal", h); + simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on health = ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`) + + // trying to spawn smaller heals + // const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2 + // console.log(healPerOrb) + // let h = tech.interestRate * m.health / healPerOrb + // console.log(tech.interestRate, m.health, healPerOrb, h) + // const overHeal = h - Math.floor(h) + // powerUps.spawn(m.pos.x, m.pos.y, "heal", true, null, Math.max(0.25, overHeal) * 40 * (simulation.healScale ** 0.25)) + // 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)}`) + } }, trainingText(say) { simulation.lastLogTime = 0; //clear previous messages simulation.isTextLogOpen = true simulation.makeTextLog(`supervised.learning(${(Date.now() / 1000).toFixed(0)} s):
${say}
`, Infinity) simulation.isTextLogOpen = false - // lore.trainer.text("Wow. Just a platform.") }, trainingBackgroundColor: "#e1e1e1", custom() { }, @@ -21080,7 +21112,7 @@ const level = { if (m.alive) { // tech.damage *= 2; let text = ""; - if (!tech.isSuperDeterminism) { text += `
${tech.isCancelTech ? "?" : "✕"}
`; }; + if (!tech.isSuperDeterminism) { text += `
${(tech.isCancelTech && tech.cancelTechCount === 0) ? "?" : "✕"}
`; }; text += `

Blessing Of Sal

`; text += `
  Speed Boost
Increase speed by 5%
`; text += `
  Defense Boost
Reduce damage by 5%
`; @@ -24125,64 +24157,6 @@ const level = { ctx.setLineDash([]); } }; - // if(powerUps.pass == undefined) { - // let pass = {pass:true, activated:false}; - // Object.assign(powerUps, pass) - // } - // const loadOut = { - // loadOut: { - // name: "loadOut", - // color: "#000000", //"hsl(248,100%,65%)", - // size() { return 40 }, - // effect() { - // if(m.alive) { - // // tech.damage *= 2; - // let text = ""; - // if (!tech.isSuperDeterminism) { text += `
${tech.isCancelTech ? "?":"✕"}
`; }; - // text += `

Blessing Of Sal

`; - // text += `
  Speed Boost
Increase speed by 5%
`; - // text += `
  Defense Boost
Reduce damage by 5%
`; - // text += `
  Damage Boost
Increase damage by 10%
`; - // if(powerUps.pass == true) { - // text += `
  Blade of Sal
Press Shift to summon the Mythical Las Slayer
Drains Energy
`; - // } - // document.getElementById("choose-grid").innerHTML = text; - // powerUps.showDraft();//no known bugs ig idk, im keep this as it is - // } - // }, - // choose(index) { - // if(index == 1) { - // tech.squirrelFx += 0.25; - // tech.squirrelJump += 0.1; - // m.setMovement(); - // powerUps.endDraft("buff"); - // } else if(index == 2) { - // simulation.dmgScale *= 0.95; - // powerUps.endDraft("buff"); - // } else if(index == 3) { - // m.dmgScale *= 1.1; - // powerUps.endDraft("buff"); - // } else if(index == 4) { //sword! - // powerUps.pass = false; - // addEventListener("keydown", function(event) { - // if(event.key == "Shift" && powerUps.activated == false) { - // sword() - // powerUps.activated = true; - // } else if(event.key == "Shift" && powerUps.activated == true) { - // for(let i = 0; i < mob.length; i++) { - // if(mob[i].isSword) { - // mob[i].death() - // } - // powerUps.activated = false; - // } - // } - // }) - // powerUps.endDraft("buff"); - // } - // } - // } - // } - // Object.assign(powerUps, loadOut) const restoreBoss = function (x, y, radius = 30) { //ATTENTION LANDGREEN: RESTOREBOSS WILL NOT DROP ANY TECH, NOR WILL THERE BE ANY IN THE MAP. DO NOT ADD ANY TECH TO MY MAP mobs.spawn(x, y, 8, radius, 'transparent'); let me = mob[mob.length - 1]; @@ -33022,7 +32996,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("nail gun") b.guns[b.activeGun].ammo = 0 simulation.updateGunHUD(); @@ -33117,7 +33091,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("shotgun") // b.guns[b.activeGun].ammo = 0 // simulation.updateGunHUD(); @@ -33199,7 +33173,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("super balls") // b.guns[b.activeGun].ammo = 0 // simulation.updateGunHUD(); @@ -33283,7 +33257,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("wave") // b.guns[b.activeGun].ammo = 0 // simulation.updateGunHUD(); @@ -33370,7 +33344,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("missiles") // b.guns[b.activeGun].ammo = 0 // simulation.updateGunHUD(); @@ -33459,7 +33433,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); let instruction = 0 level.trainingText(`use your field to stack the blocks`) @@ -33511,7 +33485,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("mine") let instruction = 0 @@ -33595,7 +33569,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("grenades") const elevator1 = level.elevator(550, -100, 180, 25, -840, 0.003, { @@ -33715,7 +33689,7 @@ const level = { level.defaultZoom = 1400 simulation.zoomTransition(level.defaultZoom, 1) document.body.style.backgroundColor = level.trainingBackgroundColor - b.removeAllGuns(); + b.resetAllGuns(); b.giveGuns("harpoon") let instruction = 0 diff --git a/js/player.js b/js/player.js index 2897a0d..bda442f 100644 --- a/js/player.js +++ b/js/player.js @@ -348,7 +348,7 @@ const m = { } if ( !tech.tech[i].isNonRefundable && - !tech.tech[i].isFromAppliedScience && + // !tech.tech[i].isFromAppliedScience && !tech.tech[i].isAltRealityTech ) { totalTech += tech.tech[i].count @@ -366,6 +366,7 @@ const m = { tech.duplication = 0; tech.extraMaxHealth = 0; tech.totalCount = 0; + tech.removeCount = 0; const randomBotCount = b.totalBots() b.zeroBotCount() //remove all bullets, respawn bots @@ -384,14 +385,17 @@ const m = { b.inventoryGun = 0; for (let i = 0, len = b.guns.length; i < len; ++i) { b.guns[i].have = false; - if (b.guns[i].ammo !== Infinity) b.guns[i].ammo = 0; + if (b.guns[i].ammo !== Infinity) { + b.guns[i].ammo = 0; + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; + } } //give random guns for (let i = 0; i < totalGuns; i++) b.giveGuns() //randomize ammo based on ammo/ammoPack count for (let i = 0, len = b.inventory.length; i < len; i++) { - if (b.guns[b.inventory[i]].ammo !== Infinity) b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(ammoCount / b.inventory.length * b.guns[b.inventory[i]].ammoPack * (1.15 + 0.3 * (Math.random() - 0.5)))) + if (b.guns[b.inventory[i]].ammo !== Infinity) b.guns[b.inventory[i]].ammo = Math.max(0, Math.floor(ammoCount / b.inventory.length * b.guns[b.inventory[i]].ammoPack * (2.5 + 0.3 * (Math.random() - 0.5)))) } // console.log(b.activeGun) //randomize tech @@ -553,9 +557,6 @@ const m = { lastCalculatedDefense: 0, //used to decided if defense bar needs to be redrawn (in simulation.checks) defense() { let dmg = 1 - dmg *= m.fieldHarmReduction - // if (!tech.isFlipFlopOn && tech.isFlipFlopHealth) dmg *= 0.5 - // 1.25 + Math.sin(m.cycle * 0.01) if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075); if (tech.isZeno) dmg *= 0.15 if (tech.isFieldHarmReduction) dmg *= 0.6 @@ -566,7 +567,7 @@ const m = { if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.3 if (tech.squirrelFx !== 1) dmg *= 0.8//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4) if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1 - if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min(player.speed * 0.0193, 0.88) //capped at speed of 55 + if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min(player.speed * 0.0193, 0.8) //capped at speed of 55 if (tech.isHarmReduce && input.field) dmg *= 0.1 if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05 if (tech.isBotArmor) dmg *= 0.95 ** b.totalBots() @@ -574,7 +575,9 @@ const m = { if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3 if (tech.isTurret && m.crouch) dmg *= 0.3; if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length - return tech.isEnergyHealth ? Math.pow(dmg, 0.5) : dmg //defense has less effect + // return tech.isEnergyHealth ? Math.pow(dmg, 0.7) : dmg //defense has less effect + // dmg *= m.fieldHarmReduction + return dmg * m.fieldHarmReduction }, rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy))) if (tech.isRewindGrenade) { @@ -1541,7 +1544,7 @@ const m = { m.isAltSkin = true simulation.isAutoZoom = false; m.draw = function () { - const amplitude = 8 + 4 * Math.sin(m.cycle * 0.0075) + const amplitude = 8 + 4 * Math.sin(m.cycle * 0.01) ctx.fillStyle = m.fillColor; m.walk_cycle += m.flipLegs * m.Vx; ctx.save(); @@ -1572,13 +1575,13 @@ const m = { //zoom camera in and out // console.log(simulation.zoomScale) - simulation.setZoom(1800 + 400 * Math.sin(m.cycle * 0.0075)) + simulation.setZoom(1800 + 400 * Math.sin(m.cycle * 0.01)) } }, dilate2() { m.isAltSkin = true m.draw = function () { - const amplitude = Math.sin(m.cycle * 0.0075) + const amplitude = Math.sin(m.cycle * 0.01) ctx.fillStyle = m.fillColor; m.walk_cycle += m.flipLegs * m.Vx; @@ -1595,7 +1598,7 @@ const m = { ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.strokeStyle = "#345"; - ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.0075 + Math.PI); + ctx.lineWidth = 3 + 3 * Math.sin(m.cycle * 0.01 + Math.PI); ctx.stroke(); // ctx.arc(12, 0, 8 + 4 * amplitude, 0, 2 * Math.PI); //big eye ctx.beginPath(); @@ -1608,7 +1611,7 @@ const m = { ctx.restore(); m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal powerUps.boost.draw() - simulation.setZoom(1800 + 400 * Math.sin(m.cycle * 0.0075)) + simulation.setZoom(1800 + 400 * amplitude) } m.drawLeg = function (stroke) { // if (simulation.mouseInGame.x > m.pos.x) { @@ -2860,17 +2863,17 @@ const m = { return `deflecting condenses ${(0.1 * couple).toFixed(2)} ice IX` // return `invulnerable +${2*couple} seconds post collision` case 3: //negative mass - return `${(100 * (1 - 0.973 ** couple)).toFixed(1)}% damage taken` + return `${(0.973 ** couple).toFixed(2)}x damage taken` case 4: //assembler return `+${(0.8 * couple).toFixed(1)} energy per second` case 5: //plasma return `${(1 + 1.5 * couple).toFixed(3)}x damage` case 6: //time dilation - return `+${(5 * couple).toFixed(0)}% longer stopped time` //movement, jumping, and + return `+${(1 + 0.05 * couple).toFixed(2)}x longer stopped time` //movement, jumping, and case 7: //cloaking return `${(1 + 3.3 * couple).toFixed(3)}x ambush damage` case 8: //pilot wave - return `+${(1 + 4 * couple).toFixed(2)}% block collision damage` + return `${(1 + 0.05 * couple).toFixed(2)}x block collision damage` case 9: //wormhole return `after eating blocks +${(2 * couple).toFixed(0)} energy` case 10: //grappling hook diff --git a/js/powerup.js b/js/powerup.js index 09dfc48..469168a 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -320,16 +320,12 @@ const powerUps = { }, endDraft(type, isCanceled = false) { //type should be a gun, tech, or field if (isCanceled) { - if (tech.isCancelTech && Math.random() < 0.85 && type !== "entanglement") { - // powerUps.research.use('tech') - powerUps[type].effect(); - return - } if (tech.isCancelDuplication) { - tech.duplication += 0.05 + const value = 0.05 + tech.duplication += value tech.maxDuplicationEvent() - simulation.makeTextLog(`tech.duplicationChance() += ${0.043}`) - simulation.circleFlare(0.043); + simulation.makeTextLog(`tech.duplicationChance() += ${value}`) + simulation.circleFlare(value); } if (tech.isCancelRerolls) { for (let i = 0, len = 10 + 4 * Math.random(); i < len; i++) { @@ -345,21 +341,14 @@ const powerUps = { } } if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 8) - // if (tech.isCancelTech && Math.random() < 0.3) { - // powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "tech", false); - // simulation.makeTextLog(`options exchange: returns 1 tech`) - // } - // if (tech.isBanish && type === 'tech') { // banish researched tech by adding them to the list of banished tech - // const banishLength = tech.isDeterminism ? 1 : 3 + tech.extraChoices * 2 - // for (let i = 0; i < banishLength; i++) { - // const index = powerUps.tech.choiceLog.length - i - 1 - // if (powerUps.tech.choiceLog[index] && tech.tech[powerUps.tech.choiceLog[index]]) { - // tech.tech[powerUps.tech.choiceLog[index]].isBanished = true - // } - // } - // simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) - // } + if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") { + tech.cancelTechCount++ + // powerUps.research.use('tech') + powerUps[type].effect(); + return + } } + tech.cancelTechCount = 0 if (tech.isAnsatz && powerUps.research.count < 1) { for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); } @@ -386,7 +375,7 @@ const powerUps = { if (this.count < 5) simulation.removeEphemera(this.name) ctx.beginPath(); - ctx.arc(m.pos.x, m.pos.y, this.count, 0, 2 * Math.PI); + ctx.arc(m.pos.x, m.pos.y, Math.max(3, this.count), 0, 2 * Math.PI); ctx.fillStyle = color ctx.fill(); // ctx.strokeStyle = "hsla(200,50%,61%,0.18)"; @@ -504,14 +493,15 @@ const powerUps = { }, currentRerollCount: 0, use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech - if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { tech.addJunkTechToPool(0.01) } else { powerUps.research.changeRerolls(-1) } if (tech.isResearchDamage) { - tech.damage *= 1.04 - simulation.makeTextLog(`1.04x damage from peer review`); + tech.damage *= 1.05 + simulation.makeTextLog(`1.05x damage`); + tech.addJunkTechToPool(0.01) } powerUps.research.currentRerollCount++ // if (tech.isBanish && type === 'tech') { // banish researched tech @@ -610,7 +600,7 @@ const powerUps = { } } if (powerUps.healGiveMaxEnergy) { - tech.healMaxEnergyBonus += 0.11 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1) + tech.healMaxEnergyBonus += 0.14 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1) m.setMaxEnergy(); } }, @@ -636,50 +626,23 @@ const powerUps = { const target = b.guns[b.activeGun] if (target.ammo !== Infinity) { if (tech.ammoCap) { - const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap * 0.8 * couplingExtraAmmo) //0.7 is average - target.ammo = ammoAdded - // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`) + target.ammo = Math.ceil(2 * target.ammoPack * tech.ammoCap * couplingExtraAmmo) } else { - const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack * 0.8 * couplingExtraAmmo) - target.ammo += ammoAdded - // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`) + target.ammo += Math.ceil(2 * (Math.random() + Math.random()) * target.ammoPack * couplingExtraAmmo) } } } else { //give ammo to all guns in inventory - // let textLog = "" for (let i = 0, len = b.inventory.length; i < len; i++) { const target = b.guns[b.inventory[i]] if (target.ammo !== Infinity) { if (tech.ammoCap) { - const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap * couplingExtraAmmo) //0.45 is average - target.ammo = ammoAdded - // textLog += `${target.name}.ammo = ${ammoAdded}
` + target.ammo = Math.ceil(target.ammoPack * tech.ammoCap * couplingExtraAmmo) } else { //default ammo behavior - const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack * couplingExtraAmmo) //Math.ceil(Math.random() * target.ammoPack) - // console.log(ammoAdded, Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack)) - target.ammo += ammoAdded - // textLog += `${target.name}.ammo += ${ammoAdded}
` + target.ammo += Math.ceil((Math.random() + Math.random()) * target.ammoPack * couplingExtraAmmo) } } } - // simulation.makeTextLog(textLog) } - // } else { //give ammo to all guns in inventory - // for (let i = 0, len = b.inventory.length; i < len; i++) { - // const target = b.guns[b.inventory[i]] - // if (target.ammo !== Infinity) { - // if (tech.ammoCap) { - // const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average - // target.ammo = ammoAdded - // simulation.makeTextLog(`${target.name}.ammo = ${ammoAdded}`) - // } else { - // const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack) - // target.ammo += ammoAdded - // simulation.makeTextLog(`${target.name}.ammo += ${ammoAdded}`) - // } - // } - // } - // } simulation.updateGunHUD(); } } @@ -689,7 +652,7 @@ const powerUps = { if (tech.isSuperDeterminism) { return `
` - } else if (tech.isCancelTech) { + } else if (tech.isCancelTech && tech.cancelTechCount === 0) { return `
randomize
` } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { //don't show cancel if on initial level and haven't done tutorial return `` @@ -701,7 +664,7 @@ const powerUps = { let text = "" if (type === "entanglement") { text += `
entanglement
` - } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { text += `
` // style = "margin-left: 192px; margin-right: -192px;" text += `
` text += `
` @@ -720,7 +683,7 @@ const powerUps = { let text = `
` if (type === "entanglement") { text += `entanglement` //‌ - } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { + } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { text += `` // style = "margin-left: 192px; margin-right: -192px;" text += `
` text += `
` @@ -729,7 +692,7 @@ const powerUps = { text += `` // style = "margin-left: 192px; margin-right: -192px;" text += `
` let researchCap = 18 - if (tech.isCancelTech) researchCap -= 2 + if (tech.isCancelTech && tech.cancelTechCount === 0) researchCap -= 2 if (canvas.width < 1951) researchCap -= 3 if (canvas.width < 1711) researchCap -= 4 for (let i = 0, len = Math.min(powerUps.research.count, researchCap); i < len; i++) { @@ -741,7 +704,7 @@ const powerUps = { } if (tech.isSuperDeterminism) { text += `cancel` - } else if (tech.isCancelTech) { + } else if (tech.isCancelTech && tech.cancelTechCount === 0) { text += `randomize` } else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { text += `` //don't show cancel if on initial level and haven't done tutorial @@ -1163,18 +1126,8 @@ const powerUps = { text += powerUps.fieldText(pick, `powerUps.choose('field',${pick})`) } } - // if (tech.isMicroTransactions && powerUps.research.count > 0) { - // const skins = [] //find skins - // for (let i = 0; i < tech.tech.length; i++) { - // if (tech.tech[i].isSkin) skins.push(i) - // } - // const choose = skins[Math.floor(Math.seededRandom(0, skins.length))] //pick an element from the array of options - - // text += `
microtransaction: ${tech.tech[choose].name}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
` - // } if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) { tech.isBrainstormActive = true - let count = 1 let timeStart = performance.now() const cycle = (timestamp) => { @@ -1194,33 +1147,9 @@ const powerUps = { } } requestAnimationFrame(cycle); - - // count++ - // if (count < tech.brainStormDelay * 5 && simulation.isChoosing) { - // if (!(count % tech.brainStormDelay)) { - // powerUps.tech.effect(); - // document.getElementById("choose-grid").style.pointerEvents = "auto"; //turn off the normal 500ms delay - // document.body.style.cursor = "auto"; - // document.getElementById("choose-grid").style.transitionDuration = "0s"; - // } - // requestAnimationFrame(cycle); - // } else { - // tech.isBrainstormActive = false - // } } - // if (localSettings.isHideImages) text += powerUps.researchText('tech') document.getElementById("choose-grid").innerHTML = text powerUps.showDraft(); - - //fade in all circles - // requestAnimationFrame(() => { - // var elements = document.getElementsByClassName('circle-grid'); - // for (var i in elements) { - // if (elements.hasOwnProperty(i)) { - // elements[i].style.opacity = '1'; - // } - // } - // }); } } }, @@ -1287,18 +1216,17 @@ const powerUps = { } }, }, - spawnDelay(type, num) { - let count = num + spawnDelay(type, count) { + count *= 2 let cycle = () => { if (count > 0) { if (m.alive) requestAnimationFrame(cycle); if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2) count-- - const where = { - x: m.pos.x + 50 * (Math.random() - 0.5), - y: m.pos.y + 50 * (Math.random() - 0.5) + if (!(count % 2)) { + const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) } + powerUps.spawn(where.x, where.y, type); } - powerUps.spawn(where.x, where.y, type); } } } @@ -1483,6 +1411,7 @@ const powerUps = { // powerUp[powerUp.length - 1].isDuplicated = true } // remove a random tech from the list of tech you have + tech.removeCount += tech.tech[choose].count tech.tech[choose].remove(); tech.tech[choose].count = 0; tech.tech[choose].isLost = true; @@ -1501,6 +1430,7 @@ const powerUps = { } // remove a random tech from the list of tech you have tech.tech[choose].remove(); + tech.removeCount += tech.tech[choose].count tech.tech[choose].count = 0; tech.tech[choose].isLost = true; simulation.updateTechHUD(); @@ -1513,34 +1443,17 @@ const powerUps = { }, pauseEjectTech(index) { if ((tech.isPauseEjectTech || simulation.testing) && !simulation.isChoosing && !tech.tech[index].isNonRefundable) { - if (Math.random() < 0.03 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) { - tech.removeTech(index) - } else { - powerUps.ejectTech(index) - m.damage(0.04) - } + // if (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count) { + // tech.removeTech(index) + // } else { + // } + powerUps.ejectTech(index) + m.damage(0.04) document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through" document.getElementById(`${index}-pause-tech`).style.animation = "" document.getElementById(`${index}-pause-tech`).onclick = null } }, - // removeRandomTech() { - // const have = [] //find which tech you have - // for (let i = 0; i < tech.tech.length; i++) { - // if (tech.tech[i].count > 0) have.push(i) - // } - // if (have.length) { - // const choose = have[Math.floor(Math.random() * have.length)] - // simulation.makeTextLog(`tech.removeTech("${tech.tech[choose].name}")`) - // const totalRemoved = tech.tech[choose].count - // tech.tech[choose].count = 0; - // tech.tech[choose].remove(); // remove a random tech form the list of tech you have - // tech.tech[choose].isLost = true - // simulation.updateTechHUD(); - // return totalRemoved - // } - // return 0 - // }, randomize(where) { //makes a random power up convert into a random different power up //put 10 power ups close together const len = Math.min(10, powerUp.length) diff --git a/js/simulation.js b/js/simulation.js index 70d5bb4..c362aa2 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -791,7 +791,7 @@ const simulation = { input.endKeySensing(); simulation.ephemera = [] tech.setupAllTech(); //sets tech to default values - b.removeAllGuns(); + b.resetAllGuns(); tech.duplication = 0; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() diff --git a/js/spawn.js b/js/spawn.js index 7f12bf2..02e296d 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -2835,7 +2835,7 @@ const spawn = { for (let i = 0; i < b.inventory.length; i++) { const gun = b.guns[b.inventory[i]] if (gun.ammo > 0 && gun.ammo !== Infinity) { - gun.ammo -= Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * gun.ammoPack) //Math.ceil(Math.random() * target.ammoPack) + gun.ammo -= Math.ceil((Math.random() + Math.random()) * gun.ammoPack) if (gun.ammo < 0) gun.ammo = 0 isRemovedAmmo = true } @@ -3317,7 +3317,7 @@ const spawn = { this.wing(this.angle - 2.1 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius) const seeRange = 550 + 35 * simulation.difficultyMode; - if (this.distanceToPlayer() < seeRange) { + if (this.distanceToPlayer() < 1000) { best = { x: null, y: null, @@ -5938,7 +5938,7 @@ const spawn = { for (let i = 0; i < b.inventory.length; i++) { const gun = b.guns[b.inventory[i]] if (gun.ammo > 0 && gun.ammo !== Infinity) { - gun.ammo -= Math.ceil((0.6 * Math.random() + 0.6 * Math.random()) * gun.ammoPack) //Math.ceil(Math.random() * target.ammoPack) + gun.ammo -= Math.ceil(1.1 * (Math.random() + Math.random()) * gun.ammoPack) if (gun.ammo < 0) gun.ammo = 0 isRemovedAmmo = true } diff --git a/js/tech.js b/js/tech.js index 6d68916..a03faf4 100644 --- a/js/tech.js +++ b/js/tech.js @@ -1,5 +1,6 @@ const tech = { totalCount: null, + removeCount: 0, setupAllTech() { tech.damage = 1 for (let i = 0, len = tech.tech.length; i < len; i++) { @@ -14,9 +15,11 @@ const tech = { } else { tech.tech[i].frequency = 2 } + if (tech.tech[i].name === "heals" || tech.tech[i].name === "ammo" || tech.tech[i].name === "research") tech.tech[i].value = tech.tech[i].defaultValue } //remove lore if it's your first time playing since it's confusing //also remove lore if cheating + tech.removeCount = 0; lore.techCount = 0; if (simulation.isCheating || localSettings.runCount < 1) { //simulation.isCommunityMaps || for (let i = 0, len = tech.tech.length; i < len; i++) { @@ -61,6 +64,7 @@ const tech = { const totalRemoved = tech.tech[index].count simulation.makeTextLog(`tech.removeTech("${tech.tech[index].name}")`, 360) tech.tech[index].remove(); + tech.removeCount += totalRemoved tech.tech[index].count = 0; tech.totalCount -= totalRemoved simulation.updateTechHUD(); @@ -68,21 +72,9 @@ const tech = { simulation.updateTechHUD(); return totalRemoved //return the total number of tech removed }, - // onclick="tech.removeTechPaused(${i}, this)" //add this to tech elements in pause menu - // removeTechPaused(index, who) { - // tech.tech[index].remove(); - // tech.tech[index].count = 0; - // simulation.updateTechHUD(); - // who.innerHTML = "removed" - // // who.style.display = "none" - // }, - // 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) - // } - // }, junkChance: 0, addJunkTechToPool(percent) { //percent is number between 0-1 + simulation.makeTextLog(`+${(100 * percent).toFixed(0)}% JUNKtech chance`) tech.junkChance += (1 - tech.junkChance) * percent return percent //make an array for possible junk tech to add @@ -123,8 +115,8 @@ const tech = { if (tech.tech[i].isJunk) list.push(tech.tech[i].name) } let name = list[Math.floor(Math.random() * list.length)] - tech.giveTech(name) simulation.makeTextLog(`tech.giveTech("${name}")`); + tech.giveTech(name) }, giveTech(index = 'random') { // if (Math.random() < tech.junkChance) { @@ -139,8 +131,8 @@ const tech = { // give a random tech from the tech I don't have if (options.length > 0) { let newTech = options[Math.floor(Math.random() * options.length)] - tech.giveTech(newTech) simulation.makeTextLog(`tech.giveTech("${tech.tech[newTech].name}") //random tech`); + tech.giveTech(newTech) } } else { if (isNaN(index)) { //find index by name @@ -165,18 +157,15 @@ 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.tech[index].cycle = m.cycle - console.log(tech.tech[index].cycle) tech.totalCount++ //used in power up randomization - //move new tech to the top of the tech list - if (index > 0 && !build.isExperimentSelection) { - // Remove the element from the array - const [item] = tech.tech.splice(index, 1); - // Add the element to the front of the array - tech.tech.unshift(item); - } - - simulation.updateTechHUD(); + requestAnimationFrame(() => { + //move new tech to the top of the tech list + if (index > 0 && !build.isExperimentSelection) { + const [item] = tech.tech.splice(index, 1); // Remove the element from the array + tech.tech.unshift(item); // Add the element to the front of the array + } + simulation.updateTechHUD(); + }) } }, setCheating() { @@ -237,7 +226,7 @@ const tech = { if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 2 if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.8 if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 2 - if (tech.isDilate) dmg *= 1.5 + 0.5 * Math.sin(m.cycle * 0.0075) + if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01) if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.015 * m.coupling @@ -257,7 +246,7 @@ const tech = { if (tech.energyDamage) dmg *= 1 + m.energy * 0.23 * tech.energyDamage; if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.01 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 - if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.88, player.speed * 0.0193) + if (tech.isSpeedDamage) dmg *= 1 + Math.min(1, player.speed * 0.0193) if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3; if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit @@ -266,7 +255,7 @@ const tech = { return dmg }, duplicationChance() { - return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.17 : 0) + tech.duplication + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + 0.08 * tech.isDuplicateMobs + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0))) + return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.17 : 0) + tech.duplication + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + 0.08 * tech.isDuplicateMobs + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.6 : 0))) }, isScaleMobsWithDuplication: false, maxDuplicationEvent() { @@ -421,7 +410,7 @@ const tech = { }, { name: "aperture", - description: "every 6 seconds your damage cycles
between 1x and 2x damage", + description: "every 4 seconds your damage cycles
between 0.8x and 3x damage", maxCount: 1, count: 0, frequency: 1, @@ -464,14 +453,14 @@ const tech = { }, { name: "mass-energy equivalence", - description: `energy protects you instead of health
damage taken effects 50% less effective`, + description: `use ${powerUps.orb.research(2)}
energy protects you instead of health`, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, isSkin: true, allowed() { - return !m.isAltSkin && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isAnnihilation //&& !tech.isAmmoFromHealth && !tech.isRewindGun + return (powerUps.research.count > 1 || build.isExperimentSelection) && !m.isAltSkin && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isAnnihilation //&& !tech.isAmmoFromHealth && !tech.isRewindGun }, requires: "not piezoelectricity, CPT, annihilation", effect() { @@ -484,9 +473,13 @@ const tech = { m.displayHealth(); m.lastCalculatedDefense = 0 //this triggers a redraw of the defense bar m.skin.energy(); + for (let i = 0; i < 2; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + } }, remove() { - if (tech.isEnergyHealth) { + if (this.count > 0) { + powerUps.research.changeRerolls(2) tech.isEnergyHealth = false; document.getElementById("health").style.display = "inline" document.getElementById("health-bg").style.display = "inline" @@ -503,10 +496,8 @@ const tech = { { name: "1st ionization energy", link: `1st ionization energy`, - // description: `after you collect ${powerUps.orb.heal()}
+${0.1 * tech.largerHeals} maximum energy`, - // descriptionFunction: `convert current and future ${powerUps.orb.heal()} into

give +${10 * tech.largerHeals} maximum energy`, descriptionFunction() { - return `convert current and future
into

give +${11 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)} maximum energy` + return `convert current and future
into

give +${14 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)} maximum energy` }, maxCount: 1, count: 0, @@ -658,7 +649,7 @@ const tech = { }, { name: "ordnance", - description: "double the frequency of finding guntech
spawn a gun and +6% JUNKtech chance", + description: "2x guntech frequency
spawn a gun and +6% JUNKtech chance", maxCount: 1, count: 0, frequency: 1, @@ -682,121 +673,6 @@ 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` - }, - maxCount: 1, //random power up - count: 0, - frequency: 1, - frequencyDefault: 1, - isNonRefundable: true, - allowed() { - return b.inventory.length > 1 - }, - requires: "at least 2 guns", - effect() { - for (let i = 0; i < b.inventory.length; i++) { - if (Math.random() < 1 / 6) { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun"); - } else if (Math.random() < 1 / 5) { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "tech"); - } else if (Math.random() < 1 / 4) { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "field"); - } else if (Math.random() < 1 / 3) { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "heal"); - } else if (Math.random() < 1 / 2) { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "ammo"); - } else { - powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research"); - } - } - }, - remove() { } - }, - { - name: "supply chain", - descriptionFunction() { - return `double your current ammo for all your guns
triple the frequency of finding applied science` - }, - maxCount: 9, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return true - }, - requires: "", - effect() { - for (let i = 0; i < b.guns.length; i++) { - if (b.guns[i].have) b.guns[i].ammo = Math.floor(2 * b.guns[i].ammo) - } - simulation.makeGunHUD(); - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].name === "applied science") tech.tech[i].frequency *= 3 - } - }, - remove() { - if (this.count) { - for (let j = 0; j < this.count; j++) { - for (let i = 0; i < b.guns.length; i++) { - if (b.guns[i].have) b.guns[i].ammo = Math.floor(0.5 * b.guns[i].ammo) - } - } - simulation.makeGunHUD(); - - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].name === "applied science") tech.tech[i].frequency = 2 - } - } - } - }, - { - name: "applied science", - description: `get a random guntech
for each of your guns`, //spawn ${powerUps.orb.research(1)} and - maxCount: 9, - count: 0, - isNonRefundable: true, - frequency: 2, - frequencyDefault: 2, - allowed() { - return b.inventory.length > 1 - }, - requires: "at least 2 guns", - effect() { - for (let i = b.inventory.length - 1; i > -1; i--) { //backwards because some tech can remove or add guns - const gunTechPool = [] //find gun tech for this gun - for (let j = 0, len = tech.tech.length; j < len; j++) { - // console.log(j, tech.tech[j].isGunTech, tech.tech[j].allowed(), !tech.tech[j].isJunk, !tech.tech[j].isBadRandomOption, tech.tech[j].count < tech.tech[j].maxCount) - const originalActiveGunIndex = b.activeGun //set current gun to active so allowed works - b.activeGun = b.inventory[i] //to make the .allowed work for guns that aren't active - if (tech.tech[j].isGunTech && tech.tech[j].allowed() && !tech.tech[j].isJunk && !tech.tech[j].isBadRandomOption && tech.tech[j].count < tech.tech[j].maxCount) { - const regex = tech.tech[j].requires.search(b.guns[b.inventory[i]].name) //get string index of gun name - const not = tech.tech[j].requires.search(' not ') //get string index of ' not ' - if (regex !== -1 && (not === -1 || not > regex)) gunTechPool.push(j) //look for the gun name in the requirements, but the gun name needs to show up before the word ' not ' - } - b.activeGun = originalActiveGunIndex - if (!b.guns[b.activeGun].have) { - if (b.inventory.length === 0) { - b.activeGun = null - } else { - b.activeGun = b.inventory[0] - } - b.inventoryGun = 0; - } - } - if (gunTechPool.length) { - const index = Math.floor(Math.random() * gunTechPool.length) - tech.giveTech(gunTechPool[index]) // choose from the gun pool - tech.tech[gunTechPool[index]].isFromAppliedScience = true //makes it not remove properly under paradigm shift - simulation.makeTextLog(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`, 360) - } - } - simulation.boldActiveGunHUD(); - }, - remove() { } - }, { name: "arsenal", descriptionFunction() { @@ -880,19 +756,198 @@ const tech = { for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun"); }, remove() { - // if (!this.count) tech.isGunCycle = false; // only set to false if you don't have this tech - // if (tech.isGunCycle) { - // for (let i = 0; i < 8; i++) { - // if (b.inventory.length) b.removeGun(b.guns[b.inventory[b.inventory.length - 1]].name) //remove your last gun - // } - // tech.isGunCycle = false; - // } } }, + { + 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` + }, + maxCount: 1, //random power up + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + allowed() { + return b.inventory.length > 1 + }, + requires: "at least 2 guns", + effect() { + for (let i = 0; i < b.inventory.length; i++) { + if (Math.random() < 1 / 6) { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun"); + } else if (Math.random() < 1 / 5) { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "tech"); + } else if (Math.random() < 1 / 4) { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "field"); + } else if (Math.random() < 1 / 3) { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "heal"); + } else if (Math.random() < 1 / 2) { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "ammo"); + } else { + powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research"); + } + } + }, + remove() { } + }, + { + name: "applied science", + description: `get a random guntech
for each of your guns`, //spawn ${powerUps.orb.research(1)} and + maxCount: 9, + count: 0, + isNonRefundable: true, + frequency: 2, + frequencyDefault: 2, + allowed() { + return b.inventory.length > 1 + }, + requires: "at least 2 guns", + effect() { + for (let i = b.inventory.length - 1; i > -1; i--) { //backwards because some tech can remove or add guns + const gunTechPool = [] //find gun tech for this gun + for (let j = 0, len = tech.tech.length; j < len; j++) { + // console.log(j, tech.tech[j].isGunTech, tech.tech[j].allowed(), !tech.tech[j].isJunk, !tech.tech[j].isBadRandomOption, tech.tech[j].count < tech.tech[j].maxCount) + const originalActiveGunIndex = b.activeGun //set current gun to active so allowed works + b.activeGun = b.inventory[i] //to make the .allowed work for guns that aren't active + if (tech.tech[j].isGunTech && tech.tech[j].allowed() && !tech.tech[j].isJunk && !tech.tech[j].isBadRandomOption && tech.tech[j].count < tech.tech[j].maxCount) { + const regex = tech.tech[j].requires.search(b.guns[b.inventory[i]].name) //get string index of gun name + const not = tech.tech[j].requires.search(' not ') //get string index of ' not ' + if (regex !== -1 && (not === -1 || not > regex)) gunTechPool.push(j) //look for the gun name in the requirements, but the gun name needs to show up before the word ' not ' + } + b.activeGun = originalActiveGunIndex + if (!b.guns[b.activeGun].have) { + if (b.inventory.length === 0) { + b.activeGun = null + } else { + b.activeGun = b.inventory[0] + } + b.inventoryGun = 0; + } + } + if (gunTechPool.length) { + const index = Math.floor(Math.random() * gunTechPool.length) + console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name) + simulation.makeTextLog(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`, 360) + // tech.tech[gunTechPool[index]].isNonRefundable = true //makes it not remove properly under paradigm shift + tech.giveTech(gunTechPool[index]) // choose from the gun pool + // console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name) + // tech.tech[gunTechPool[index]].isFromAppliedScience = true //makes it not remove properly under paradigm shift + } + } + simulation.boldActiveGunHUD(); + }, + remove() { } + }, + { + name: "supply chain", + descriptionFunction() { + return `2x current ammo for all your guns
3x applied science frequency` + }, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return true + }, + requires: "", + effect() { + for (let i = 0; i < b.guns.length; i++) { + if (b.guns[i].have) b.guns[i].ammo = Math.floor(2 * b.guns[i].ammo) + } + simulation.makeGunHUD(); + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].name === "applied science") tech.tech[i].frequency *= 3 + } + }, + remove() { + if (this.count) { + for (let j = 0; j < this.count; j++) { + for (let i = 0; i < b.guns.length; i++) { + if (b.guns[i].have) b.guns[i].ammo = Math.floor(0.5 * b.guns[i].ammo) + } + } + simulation.makeGunHUD(); + + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].name === "applied science") tech.tech[i].frequency = 2 + } + } + } + }, + { + name: "marginal utility", + descriptionFunction() { + if (this.count === 0) this.gun = Math.floor(Math.random() * (b.guns.length - 1)) //don't pick laser + return `2x ammo per ${powerUps.orb.ammo(1)} for ${b.guns[this.gun].name}
spawn ${powerUps.orb.ammo(4)}` + }, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { return true }, + requires: "", + gun: undefined, + effect() { + if (this.gun === undefined) this.gun = Math.floor(Math.random() * (b.guns.length - 1)) //don't pick laser + + simulation.makeTextLog(`${b.guns[this.gun].ammoPack} → ${2 * b.guns[this.gun].ammoPack} average ammo per ${powerUps.orb.ammo(1)} for ${b.guns[this.gun].name}`) + b.guns[this.gun].ammoPack *= 2 + // simulation.makeTextLog(`${(tech.interestRate * 100).toFixed(0)}% interest on health = ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`) + + for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "ammo"); + }, + remove() { + if (this.count) { + b.guns[this.gun].ammoPack /= 2 + } + } + }, + { + name: "Pareto efficiency", + descriptionFunction() { + // return `for each gun randomly
gain 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}` + // return `randomly adjust your guns by
5x or 0.2x ammo per ${powerUps.orb.ammo(1)}` + return `for each of your guns
randomly get 5x or 0.2x ammo per ${powerUps.orb.ammo(1)}` + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isBadRandomOption: true, + allowed() { + return b.inventory.length > 2 + }, + requires: "at least 3 guns", + effect() { + + let options = [] + for (let i = 0; i < b.inventory.length; i++) options.push(b.inventory[i]) + options = shuffle(options) + for (let i = 0; i < options.length; i++) { + const index = options[i] + const scale = (i < options.length / 2) ? 4 : 0.25 + simulation.makeTextLog(`${(b.guns[index].ammoPack).toFixed(1)} ${(b.guns[index].ammoPack * scale).toFixed(1)} average ammo per ${powerUps.orb.ammo(1)} for ${b.guns[index].name}`, Infinity) + b.guns[index].ammoPack *= scale + } + + // let options = [] + // for (let i = 0; i < b.guns.length - 1; i++) options.push(i) + // options = shuffle(options) + // for (let i = 0; i < options.length; i++) { + // const index = options[i] + // const scale = (i < options.length / 2) ? 4 : 0.25 + // simulation.makeTextLog(`${(b.guns[index].ammoPack).toFixed(1)} ${(b.guns[index].ammoPack * scale).toFixed(1)} average ammo per ${powerUps.orb.ammo(1)} for ${b.guns[index].name}`, Infinity) + // b.guns[index].ammoPack *= scale + // } + }, + remove() { } + }, { name: "logistics", - description: `${powerUps.orb.ammo()} give 1.8x ammo, but
it's only added to your current gun`, + description: `2x ammo per ${powerUps.orb.ammo()}, but
ammo is only added to your current gun`, maxCount: 1, count: 0, frequency: 1, @@ -911,10 +966,7 @@ const tech = { { name: "cache", link: `cache`, - description: `${powerUps.orb.ammo()} give 15x ammo, but
you can't store any more ammo than that`, - // ammo powerups always max out your gun, - // but the maximum ammo ti limited - // description: `${powerUps.orb.ammo()} give 13x more ammo, but
you can't store any more ammo than that`, + description: `15x ammo per ${powerUps.orb.ammo()}, but
you can't store any more ammo than that`, maxCount: 1, count: 0, frequency: 1, @@ -1118,7 +1170,10 @@ const tech = { // }, { name: "Newtons 1st law", - description: "damage taken is proportional to your speed
up to 0.2x damage taken at 55 speed", + descriptionFunction() { + return `damage taken is proportional to your speed
up to 0.2x damage taken at 55 speed (${(1 - Math.min(player.speed * 0.0193, 0.8)).toFixed(2)}x)` + }, + description: "", maxCount: 1, count: 0, frequency: 1, @@ -1136,7 +1191,9 @@ const tech = { }, { name: "Newtons 2nd law", - description: "damage is proportional to your speed
up to 2x damage at 55 speed", + descriptionFunction() { + return `damage is proportional to your speed
up to 2x damage at 55 speed (${(1 + Math.min(1, player.speed * 0.0193)).toFixed(2)}x)` + }, maxCount: 1, count: 0, frequency: 1, @@ -1389,7 +1446,7 @@ const tech = { { name: "collider", descriptionFunction() { - return `after mobs die random power ups
collide to form different power ups` + return `after mobs die random power ups
collide to form different 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` }, @@ -2024,7 +2081,17 @@ const tech = { requires: "NOT EXPERIMENT MODE, at least 4 bots", effect() { this.numberOfGunsLost = b.inventory.length - b.removeAllGuns(); + b.inventory = []; //removes guns and ammo + for (let i = 0, len = b.guns.length; i < len; ++i) { + b.guns[i].count = 0; + b.guns[i].have = false; + if (b.guns[i].ammo != Infinity) b.guns[i].ammo = 0; + } + tech.buffedGun = 0 + b.activeGun = null; + b.inventoryGun = 0; + simulation.drawCursor = simulation.drawCursorBasic //set cross hairs + simulation.makeGunHUD(); //double bots for (let i = 0; i < tech.nailBotCount; i++) b.nailBot(); @@ -2067,37 +2134,6 @@ const tech = { } } }, - // { - // name: "robotics", - // description: `spawn 2 random bots
quadruple the frequency of finding bot tech`, - // maxCount: 1, - // count: 0, - // frequency: 1, - // frequencyDefault: 1, - // isBotTech: true, - // allowed() { - // return b.totalBots() > 1 || build.isExperimentSelection - // }, - // requires: "at least 2 bots", - // effect: () => { - // b.randomBot() - // b.randomBot() - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].isBotTech) tech.tech[i].frequency *= 4 - // } - // }, - // remove() { - // if (this.count > 0) { - // b.removeBot() - // b.removeBot() - // b.clearPermanentBots(); - // b.respawnBots(); - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].isBotTech) tech.tech[i].frequency = Math.ceil(tech.tech[i].frequency / 4) - // } - // } - // } - // }, { name: "robotics", description: `spawn 2 random bots
tech, fields, and guns have +1 bot choice`, //tech have an extra bot tech option @@ -2124,8 +2160,8 @@ const tech = { } }, { - name: "open-source", //digital fabricator - description: `spawn 3 random bots
triple the frequency of finding bot tech`, + name: "open-source", + description: `spawn 3 random bots
3x bot tech frequency`, maxCount: 1, count: 0, frequency: 0, @@ -2302,7 +2338,7 @@ const tech = { { name: "shape-memory alloy", descriptionFunction() { - return `if flip-flop is ON
+400 maximum health and +100% ${powerUps.orb.heal()} effect` + return `if flip-flop is ON
+400 maximum health and 2x ${powerUps.orb.heal()} effect` }, maxCount: 1, count: 0, @@ -2703,7 +2739,7 @@ const tech = { }, { name: "Pauli exclusion", - description: `after mob collisions
become invulnerable for +3.5 seconds`, + description: `after mob collisions
become invulnerable for +4 seconds`, maxCount: 9, count: 0, frequency: 1, @@ -2713,7 +2749,7 @@ const tech = { }, requires: "", effect() { - m.collisionImmuneCycles += 210; + m.collisionImmuneCycles += 240; if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage }, remove() { @@ -2741,7 +2777,7 @@ const tech = { { name: "refrigerant", descriptionFunction() { - return `after losing at least 5% ${tech.isEnergyHealth ? "energy" : "health"}
freeze all mobs for 7 seconds` + return `after losing at least 5 ${tech.isEnergyHealth ? "energy" : "health"}
freeze all mobs for 7 seconds` }, maxCount: 1, count: 0, @@ -2919,7 +2955,7 @@ const tech = { }, { name: "inductive charging", - description: "if crouched 7x passive energy generation
if not crouched energy generation is disabled", + description: "if crouched 7x passive energy generation
otherwise passive energy generation is disabled", maxCount: 1, count: 0, frequency: 1, @@ -3311,31 +3347,10 @@ const tech = { tech.isPowerUpDamage = false }, }, - { - name: "self-assembly", - descriptionFunction() { - return `at the start of each level
for every 25 missing ${tech.isEnergyHealth ? "energy" : "health"} spawn ${powerUps.orb.heal()}` - }, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - isHealTech: true, - allowed() { - return true - }, - requires: "", - effect() { - tech.isHealLowHealth = true; - }, - remove() { - tech.isHealLowHealth = false; - } - }, { name: "maintenance", descriptionFunction() { - return `double the frequency of finding healing tech
spawn ${powerUps.orb.heal(13)}` + return `2x healing tech frequency
spawn ${powerUps.orb.heal(13)}` }, maxCount: 1, count: 0, @@ -3355,6 +3370,48 @@ const tech = { }, remove() { } }, + { + name: "self-assembly", + descriptionFunction() { + return `at the start of each level
for every 20 missing ${tech.isEnergyHealth ? "energy" : "health"} spawn ${powerUps.orb.heal()}` + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isHealTech: true, + allowed() { + return true + }, + requires: "", + effect() { + tech.isHealLowHealth = true; + }, + remove() { + tech.isHealLowHealth = false; + } + }, + { + name: "interest", + descriptionFunction() { + return `at the start of each level spawn
${(100 * this.rate).toFixed(0)}% of your ${powerUps.orb.research(1)}, ${powerUps.orb.ammo(1)}, ${powerUps.orb.coupling(1)}, and ${powerUps.orb.heal(1)} (rounded up)` + }, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return true + }, + requires: "", + rate: 0.06, + effect() { + tech.interestRate += this.rate; + }, + remove() { + tech.interestRate = 0; + } + }, { name: "anthropic principle", nameInfo: "", @@ -3388,7 +3445,7 @@ const tech = { }, { name: "weak anthropic principle", - description: "after anthropic principle prevents your death
+50% duplication chance for that level", + description: "after anthropic principle prevents your death
+60% duplication chance for that level", maxCount: 1, count: 0, frequency: 3, @@ -3487,7 +3544,7 @@ const tech = { }, { name: "peer review", - description: `+3% JUNKtech chance
after you research gain 1.04x damage`, + description: `after you research gain 1.05x damage
and +1% JUNKtech chance`, maxCount: 1, count: 0, frequency: 1, @@ -3498,15 +3555,33 @@ const tech = { requires: "at least 2 research, not superdeterminism", effect() { tech.isResearchDamage = true; - this.refundAmount += tech.addJunkTechToPool(0.03) + // this.refundAmount += tech.addJunkTechToPool(0.03) }, - refundAmount: 0, + // refundAmount: 0, remove() { tech.isResearchDamage = false; - if (this.count > 0 && this.refundAmount > 0) { - tech.removeJunkTechFromPool(this.refundAmount) - this.refundAmount = 0 - } + // if (this.count > 0 && this.refundAmount > 0) { + // tech.removeJunkTechFromPool(this.refundAmount) + // this.refundAmount = 0 + // } + } + }, + { + name: "pseudoscience", + description: "research 2 times
for free, but
add 1% JUNKtech chance each time", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isResearchReality && !tech.isSuperDeterminism + }, + requires: "not Ψ(t) collapse, superdeterminism", + effect() { + tech.isJunkResearch = true; + }, + remove() { + tech.isJunkResearch = false; } }, { @@ -3539,7 +3614,7 @@ const tech = { }, { name: "renormalization", - description: `47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}
+5% JUNKtech chance`, + description: `+5% JUNKtech chance
47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}`, maxCount: 1, count: 0, frequency: 2, @@ -3605,7 +3680,7 @@ const tech = { { name: "Bayesian statistics", descriptionFunction() { - return `spawn ${powerUps.orb.research(this.bonusResearch)}
1.03x damage per ${powerUps.orb.research(1)} in your inventory (${(1.03 * powerUps.research.count).toFixed(2)}x)` + return `spawn ${powerUps.orb.research(this.bonusResearch)}
1.03x damage per ${powerUps.orb.research(1)} in your inventory (${(1 + Math.max(0, 0.03 * powerUps.research.count)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3628,103 +3703,50 @@ const tech = { } }, { - name: "mass production", - descriptionFunction() { - return `spawn ${powerUps.orb.ammo(3)}${powerUps.orb.heal(3)}  ${powerUps.orb.research(2)}
tech have extra choices to spawn ${powerUps.orb.ammo(1)},  ${powerUps.orb.heal(1)},  or  ${powerUps.orb.research(1)}` - }, - // description: `< strong class='color-m' > tech always have < strong > +3 choices to spawn < br > ${ powerUps.orb.ammo(8) } ${ powerUps.orb.heal(8) } & nbsp;& nbsp; or ${ powerUps.orb.research(5) } `, - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { return true }, - requires: "", - effect() { - tech.isMassProduction = true - powerUps.spawnDelay("ammo", 4); - powerUps.spawnDelay("heal", 4); - powerUps.spawnDelay("research", 2); - }, - remove() { - tech.isMassProduction = false - } - }, - { - name: "research", - descriptionFunction() { - return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}
next time this effect is improved by ${powerUps.orb.research(5)}` - }, - maxCount: 9, - count: 0, - frequency: 0, - frequencyDefault: 0, - isNonRefundable: true, - isMassProduction: true, - allowed() { return true }, - requires: "", - value: 8, - effect() { - powerUps.spawnDelay("research", this.value); - this.value += 5 - }, - remove() { } - }, - { - name: "ammo", - descriptionFunction() { - return `spawn ${this.value > 33 ? this.value + powerUps.orb.ammo(1) : powerUps.orb.ammo(this.value)}
next time this effect is improved by ${powerUps.orb.ammo(7)}` - }, - maxCount: 9, - count: 0, - frequency: 0, - frequencyDefault: 0, - isNonRefundable: true, - isMassProduction: true, - allowed() { return true }, - requires: "", - value: 10, - effect() { - powerUps.spawnDelay("ammo", this.value); - this.value += 7 - }, - remove() { } - }, - { - name: "heals", - descriptionFunction() { - return `spawn ${this.value > 30 ? this.value + powerUps.orb.heal(1) : powerUps.orb.heal(this.value)}
next time this effect is improved by ${powerUps.orb.heal(7)}` - }, - maxCount: 9, - count: 0, - frequency: 0, - frequencyDefault: 0, - isNonRefundable: true, - isMassProduction: true, - allowed() { return true }, - requires: "", - value: 10, - effect() { - powerUps.spawnDelay("heal", this.value); - this.value += 7 - }, - remove() { } - }, - { - name: "pseudoscience", - description: "research 3 times for free, but
add 1% JUNKtech chance each time", + name: "unified field theory", + description: `when paused you can click to switch fields
2x fieldtech frequency`, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isResearchReality && !tech.isSuperDeterminism + return !tech.isSuperDeterminism && !tech.isNoDraftPause }, - requires: "not Ψ(t) collapse, superdeterminism", + requires: "not superdeterminism, eternalism", effect() { - tech.isJunkResearch = true; + tech.isPauseSwitchField = true; + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].isFieldTech) tech.tech[i].frequency *= 2 + } }, remove() { - tech.isJunkResearch = false; + tech.isPauseSwitchField = false; + if (this.count > 1) { + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].isFieldTech) tech.tech[i].frequency /= 2 + } + } + } + }, + { + name: "eternalism", + description: "1.25x damage
time can't be paused (time can be dilated)", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isPauseSwitchField && !tech.isPauseEjectTech && !tech.isWormHolePause + }, + requires: "not unified field theory, paradigm shift, invariant", + damage: 1.25, + effect() { + tech.damage *= this.damage + tech.isNoDraftPause = true + }, + remove() { + if (this.count) tech.damage /= this.damage + tech.isNoDraftPause = false } }, { @@ -3768,7 +3790,7 @@ const tech = { }, { name: "emergence", - description: "tech, fields, and guns have +1 choice
1.08x damage", + description: "tech, fields, and guns have +1 choice
1.1x damage", maxCount: 9, count: 0, frequency: 1, @@ -3777,18 +3799,16 @@ const tech = { return !tech.isDeterminism }, requires: "not determinism", - damage: 1.08, + damage: 1.1, effect() { tech.extraChoices += 1; tech.damage *= this.damage - // this.refundAmount += tech.addJunkTechToPool(0.03) }, refundAmount: 0, remove() { tech.extraChoices = 0; if (this.count > 0) { tech.damage /= this.damage - // if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount) } } }, @@ -3987,78 +4007,93 @@ const tech = { } }, { - name: "eternalism", - description: "1.25x damage
time can't be paused (time can be dilated)", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return !tech.isPauseSwitchField && !tech.isPauseEjectTech && !tech.isWormHolePause - }, - requires: "not unified field theory, paradigm shift, invariant", - damage: 1.25, - effect() { - tech.damage *= this.damage - tech.isNoDraftPause = true - }, - remove() { - if (this.count) tech.damage /= this.damage - tech.isNoDraftPause = false - } - }, - { - name: "paradigm shift", - // description: `when paused clicking a tech ejects it
with a 20% chance to remove without ejecting`, - // description: `when paused clicking a tech ejects it
and a 20% chance to remove without ejecting`, + name: "mass production", descriptionFunction() { - return `when paused clicking a tech ejects it
–4 ${tech.isEnergyHealth ? "energy" : "health"} each time and a 3% chance to fail` + return `spawn ${powerUps.orb.ammo(3)}${powerUps.orb.heal(3)}  ${powerUps.orb.research(2)}
tech have extra choices to spawn ${powerUps.orb.ammo(1)},  ${powerUps.orb.heal(1)},  or  ${powerUps.orb.research(1)}` }, + // description: `< strong class='color-m' > tech always have < strong > +3 choices to spawn < br > ${ powerUps.orb.ammo(8) } ${ powerUps.orb.heal(8) } & nbsp;& nbsp; or ${ powerUps.orb.research(5) } `, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, - allowed() { - return !tech.isSuperDeterminism && !tech.isNoDraftPause - }, - requires: "not superdeterminism, eternalism", + allowed() { return true }, + requires: "", effect() { - tech.isPauseEjectTech = true; + tech.isMassProduction = true + powerUps.spawnDelay("ammo", 4); + powerUps.spawnDelay("heal", 4); + powerUps.spawnDelay("research", 2); }, remove() { - tech.isPauseEjectTech = false; + tech.isMassProduction = false } }, { - name: "unified field theory", - description: `in the pause menu click to switch fields
double the frequency of finding fieldtech`, - maxCount: 1, + name: "research", + descriptionFunction() { + return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}
next time increase amount spawned by +5${powerUps.orb.research(1)}` + }, + maxCount: 9, count: 0, frequency: 1, frequencyDefault: 1, - allowed() { - return !tech.isSuperDeterminism && !tech.isNoDraftPause - }, - requires: "not superdeterminism, eternalism", + isNonRefundable: true, + isMassProduction: true, + allowed() { return true }, + requires: "", + value: 8, + defaultValue: 8, effect() { - tech.isPauseSwitchField = true; - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].isFieldTech) tech.tech[i].frequency *= 2 - } + powerUps.spawnDelay("research", this.value); + this.value += 5 }, - remove() { - tech.isPauseSwitchField = false; - if (this.count > 1) { - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].isFieldTech) tech.tech[i].frequency /= 2 - } - } - } + remove() { } + }, + { + name: "ammo", + descriptionFunction() { + return `spawn ${this.value > 33 ? this.value + powerUps.orb.ammo(1) : powerUps.orb.ammo(this.value)}
next time increase amount spawned by +7${powerUps.orb.ammo(1)}` + }, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + isMassProduction: true, + allowed() { return true }, + requires: "", + value: 10, + defaultValue: 10, + effect() { + powerUps.spawnDelay("ammo", this.value); + this.value += 7 + }, + remove() { } + }, + { + name: "heals", + descriptionFunction() { + return `spawn ${this.value > 30 ? this.value + powerUps.orb.heal(1) : powerUps.orb.heal(this.value)}
next time increase amount spawned by +7${powerUps.orb.heal(1)}` + }, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + isMassProduction: true, + allowed() { return true }, + requires: "", + value: 10, + defaultValue: 10, + effect() { + powerUps.spawnDelay("heal", this.value); + this.value += 7 + }, + remove() { } }, { name: "field coupling", descriptionFunction() { - // return `spawn ${powerUps.orb.coupling(10)}
that each give +0.1 coupling` //
${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per coupling"} return `spawn ${powerUps.orb.coupling(10)}
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}` }, maxCount: 9, @@ -4228,28 +4263,27 @@ const tech = { { name: "options exchange", link: `options exchange`, - description: `clicking cancel for a field, tech, or gun
has a 85% chance to randomize choices`, + description: `the first time you click cancel it will instead
randomize choices for fields, tech, or guns`, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isSuperDeterminism //&& (tech.isCancelRerolls || tech.isCancelDuplication) + return !tech.isSuperDeterminism //&& (tech.isCancelRerolls || tech.isCancelDuplication || tech.isCancelCouple) }, - requires: "not superdeterminism", //futures exchange, commodities exchange, + requires: "not superdeterminism", //residual dipolar coupling, commodities exchange, futures exchange, effect() { tech.isCancelTech = true + tech.cancelTechCount = 0 }, remove() { tech.isCancelTech = false + tech.cancelTechCount = 0 } }, { name: "futures exchange", description: "clicking cancel for a field, tech, or gun
gives +5% power up duplication chance", - // descriptionFunction() { - // return `clicking × to cancel a field, tech, or gun
gives +${4.9 - 0.15*simulation.difficultyMode}% power up duplication chance` - // }, maxCount: 1, count: 0, frequency: 1, @@ -4294,27 +4328,6 @@ const tech = { } } }, - { - name: "stimulated emission", - description: "+19% chance to duplicate spawned power ups,
but after a collision eject 1 tech", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return tech.duplicationChance() < 1 - }, - requires: "below 1% duplication chance", - effect() { - tech.isStimulatedEmission = true - powerUps.setPowerUpMode(); //needed after adjusting duplication chance - if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15); - }, - remove() { - tech.isStimulatedEmission = false - powerUps.setPowerUpMode(); //needed after adjusting duplication chance - } - }, { name: "metastability", description: "+13% chance to duplicate spawned power ups
duplicates explode with a 4 second half-life", @@ -4338,15 +4351,17 @@ const tech = { }, { name: "correlated damage", - description: "duplication increases damage by the same percent", + descriptionFunction() { + return `duplication increases damage by the same percent
(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)` + }, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return tech.duplicationChance() > 0.15 + return tech.duplicationChance() > 0.03 }, - requires: "duplication chance > 15%", + requires: "duplication chance > 3%", effect() { tech.isDupDamage = true; }, @@ -4375,7 +4390,7 @@ const tech = { }, { name: "apomixis", - description: `when you reach 100% duplication
spawn 11 bosses with 100% more durability`, + description: `when you reach 100% duplication
spawn 11 bosses with 2x durability`, maxCount: 1, count: 0, frequency: 3, @@ -4393,10 +4408,31 @@ const tech = { tech.is100Duplicate = false; } }, + { + name: "stimulated emission", + description: "+19% chance to duplicate spawned power ups,
collisions eject a random tech", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return tech.duplicationChance() < 1 + }, + requires: "below 1% duplication chance", + effect() { + tech.isStimulatedEmission = true + powerUps.setPowerUpMode(); //needed after adjusting duplication chance + if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15); + }, + remove() { + tech.isStimulatedEmission = false + powerUps.setPowerUpMode(); //needed after adjusting duplication chance + } + }, { name: "strange attractor", descriptionFunction() { - return `1.1x damage
removing this increases duplication by +11%` + return `1.1x damage
removing this increases duplication by +11%` }, maxCount: 1, count: 0, @@ -4411,6 +4447,7 @@ const tech = { effect() { tech.damage *= this.damage }, + isRemoveBenefit: true, remove() { if (this.count > 0 && m.alive) { tech.duplication += 0.11 @@ -4422,8 +4459,7 @@ const tech = { }, { name: "strange loop", - // description: `+11% damage
removing this doubles it's damage if you take it again`, - description: `1.1x damage
removing this gives strange attractor and null hypothesis`, + description: `1.1x damage
removing this gives a random removetech`, maxCount: 1, count: 0, frequency: 1, @@ -4437,20 +4473,24 @@ const tech = { effect() { tech.damage *= this.damage }, + isRemoveBenefit: true, remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage this.frequency = 0 + requestAnimationFrame(() => { - tech.giveTech("null hypothesis") - tech.giveTech("strange attractor") + const options = [] + for (let i = 0, len = tech.tech.length; i < len; i++) if (tech.tech[i].isRemoveBenefit && tech.tech[i].count === 0) options.push(i) + const index = options[Math.floor(Math.random() * options.length)] + tech.giveTech(tech.tech[index].name) }); } } }, { name: "null hypothesis", - description: `1.1x damage
removing this spawns ${powerUps.orb.research(15)}`, + description: `1.1x damage
removing this spawns ${powerUps.orb.research(15)}`, maxCount: 1, count: 0, frequency: 1, @@ -4464,6 +4504,7 @@ const tech = { effect() { tech.damage *= this.damage }, + isRemoveBenefit: true, remove() { if (this.count > 0 && m.alive) { tech.damage /= this.damage @@ -4475,7 +4516,7 @@ const tech = { { name: "martingale", descriptionFunction() { - return `${(1 + this.damage).toFixed(2)}x damage. After removing this there is a 50%
chance to get it back with double its damage
` + return `${(1 + this.damage).toFixed(1)}x damage. removing this has a 50%
chance return with 2x its damage (${(1 + this.damage).toFixed(1)}x→${(1 + 2 * this.damage).toFixed(1)}x)
` }, maxCount: 1, count: 0, @@ -4486,24 +4527,99 @@ const tech = { return true }, requires: "", - damage: 0.11, + damage: 0.1, effect() { tech.damage *= 1 + this.damage }, + isRemoveBenefit: true, remove() { if (this.count > 0 && m.alive) { tech.damage /= 1 + this.damage if (Math.random() < 0.5) { this.damage *= 2 - requestAnimationFrame(() => { tech.giveTech("chaos theory") }); + requestAnimationFrame(() => { tech.giveTech("martingale") }); } this.frequency = 0 } } }, + { + name: "externality", + descriptionFunction() { + return `1.1x damage
removing this spawns ${this.ammo} ${powerUps.orb.ammo(1)}` + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isBadRandomOption: true, + allowed() { + return true + }, + requires: "", + damage: 1.1, + ammo: 50, + effect() { + tech.damage *= this.damage + }, + isRemoveBenefit: true, + remove() { + if (this.count > 0 && m.alive) { + tech.damage /= this.damage + powerUps.spawnDelay("ammo", this.ammo) + this.frequency = 0 + } + } + }, + { + name: "deprecated", + scale: 0.05, + descriptionFunction() { + return `after removing this gain
1.05x damage per removed tech(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)` + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isBadRandomOption: true, + allowed() { + return true + }, + requires: "", + damage: 1.1, + effect() { + }, + isRemoveBenefit: true, + remove() { + if (this.count > 0 && m.alive) { + tech.damage *= 1 + this.scale * (1 + tech.removeCount) + this.frequency = 0 + } + } + }, + { + name: "paradigm shift", + descriptionFunction() { + return `when paused clicking a tech ejects it
–4 ${tech.isEnergyHealth ? "energy" : "health"} each time` + }, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return !tech.isSuperDeterminism && !tech.isNoDraftPause + }, + requires: "not superdeterminism, eternalism", + effect() { + tech.isPauseEjectTech = true; + }, + remove() { + tech.isPauseEjectTech = false; + } + }, { name: "Born rule", - description: "remove all current tech
spawn new tech to replace them", + description: "eject all your tech", maxCount: 1, count: 0, frequency: 1, @@ -4524,8 +4640,9 @@ const tech = { } if (tech.isDeterminism) count -= 4 //remove the bonus tech if (tech.isSuperDeterminism) count -= 4 //remove the bonus tech - + const removeCount = tech.removeCount tech.setupAllTech(); // remove all tech + tech.removeCount = removeCount if (simulation.isCheating) tech.setCheating(); lore.techCount = 0; // tech.addLoreTechToPool(); @@ -4538,7 +4655,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 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, @@ -4556,7 +4673,7 @@ const tech = { effect() { let pool = [] for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups - if (tech.tech[i].count && !tech.tech[i].isNonRefundable && !tech.tech[i].isFromAppliedScience) pool.push(i) + if (tech.tech[i].count && !tech.tech[i].isNonRefundable) pool.push(i) } pool = shuffle(pool); //shuffles order of maps let removeCount = 0 @@ -4570,7 +4687,7 @@ const tech = { }, { name: "exchange symmetry", - description: "remove 1 random tech
spawn 2 new guns", + description: "remove 1 random tech
spawn 2 new guns", maxCount: 1, count: 0, frequency: 1, @@ -4587,22 +4704,17 @@ const tech = { if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) have.push(i) } const choose = have[Math.floor(Math.random() * have.length)] - simulation.makeTextLog(`tech.removeTech("${tech.tech[choose].name}")`, 360) for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.spawn(m.pos.x, m.pos.y, "gun"); } powerUps.spawn(m.pos.x, m.pos.y, "gun"); - // powerUps.spawn(m.pos.x, m.pos.y, "gun"); - tech.tech[choose].remove(); // remove a random tech form the list of tech you have - // tech.tech[choose].count = 0; - tech.tech[choose].isLost = true - simulation.updateTechHUD(); + tech.removeTech(choose) }, remove() { } }, { name: "Monte Carlo method", - description: "remove 1 random tech
spawn 2 tech", + description: "remove 1 random tech
spawn 2 tech", maxCount: 1, count: 0, frequency: 1, @@ -4619,50 +4731,6 @@ const tech = { }, remove() { } }, - // { - // name: "backward induction", - // descriptionFunction() { - // if (build.isExperimentSelection || powerUps.tech.choiceLog.length < 10) return `use ${powerUps.orb.research(2)} to choose all the unchosen tech
from your last selection` - - // text = `` - // let num = 3 - // if (tech.extraChoices) num = 5 - // if (tech.isDeterminism) num = 1 - // for (let i = 0; i < num; i++) { - // const index = powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - i - 1] - // if (index !== powerUps.lastTechIndex && tech.tech[index].count < tech.tech[index].maxCount && tech.tech[index].allowed() && tech.tech[index].name !== "backward induction") { - // text += `${tech.tech[index].name}, ` - // } - // } - // text = text.slice(0, -2); - // return `use ${powerUps.orb.research(2)}to choose the unchosen
tech from your previous selection:
${text}` - // }, - // // description: `use ${powerUps.orb.research(2)}to choose all the unchosen
tech from your previous tech selection`, - // maxCount: 1, - // count: 0, - // frequency: 100, - // frequencyDefault: 100, - // isNonRefundable: true, - // isBadRandomOption: true, - // allowed() { - // return powerUps.tech.choiceLog.length > 10 && !tech.isDeterminism && powerUps.research.count > 1 - // }, - // requires: "NOT EXPERIMENT MODE, rejected an option in the last tech selection, at least 2 research, not determinism", - // effect: () => { - // powerUps.research.changeRerolls(-2) - // let num = 3 - // if (tech.extraChoices) num = 5 - // if (tech.isDeterminism) num = 1 - // for (let i = 0; i < num; i++) { - // const index = powerUps.tech.choiceLog[powerUps.tech.choiceLog.length - i - 1] - // if (index !== powerUps.lastTechIndex && tech.tech[index].count < tech.tech[index].maxCount && tech.tech[index].allowed() && tech.tech[index].name !== "backward induction") { - // tech.giveTech(index) - // simulation.makeTextLog(`tech.giveTech("${tech.tech[index].name}") //backward induction`); - // } - // } - // }, - // remove() {} - // }, //************************************************** //************************************************** gun //************************************************** tech @@ -4740,22 +4808,23 @@ const tech = { tech.isNeedles = true for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "nail gun") { - b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 3); - b.guns[i].ammoPack = Math.ceil(b.guns[i].defaultAmmoPack / 3); + b.guns[i].ammo = Math.ceil(b.guns[i].ammo / this.ammoScale); + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack / this.ammoScale; b.guns[i].chooseFireMethod() simulation.updateGunHUD(); break } } }, + ammoScale: 3, remove() { if (tech.isNeedles) { tech.isNeedles = false for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "nail gun") { b.guns[i].chooseFireMethod() - b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 3); - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * this.ammoScale); + b.guns[i].ammoPack = b.guns[i].ammo * this.ammoScale; simulation.updateGunHUD(); break } @@ -4869,7 +4938,6 @@ const tech = { b.guns[0].ammoPack = b.guns[0].defaultAmmoPack; if (b.guns[0].recordedAmmo) b.guns[0].ammo = b.guns[0].recordedAmmo simulation.updateGunHUD(); - if (this.count) requestAnimationFrame(() => { simulation.updateGunHUD(); }); } tech.isIceCrystals = false; @@ -5004,7 +5072,7 @@ const tech = { { name: "spin-statistics", link: `spin-statistics`, - description: "after firing the shotgun you are invulnerable
shotgun has 50% fewer shots", + description: `after firing the shotgun you are invulnerable
shotgun has 0.5x bullets per ${powerUps.orb.ammo(1)}`, isGunTech: true, maxCount: 1, count: 0, @@ -5021,23 +5089,23 @@ const tech = { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "shotgun") { b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.5); - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.5 + b.guns[i].ammoPack *= 0.5 break; } } simulation.updateGunHUD(); }, remove() { - if (tech.isShotgunImmune) { - tech.isShotgunImmune = false; + tech.isShotgunImmune = false; + if (this.count > 0) { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "shotgun") { - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; + b.guns[i].ammoPack = 2 b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 2); + simulation.updateGunHUD(); break; } } - simulation.updateGunHUD(); } } }, @@ -5526,7 +5594,7 @@ const tech = { effect() { tech.isLongitudinal = true; b.guns[3].chooseFireMethod() - b.guns[3].ammoPack = b.guns[3].defaultAmmoPack / this.ammoScale + b.guns[3].ammoPack /= this.ammoScale if (tech.isInfiniteWaveAmmo) { b.guns[3].savedAmmo = Math.ceil(b.guns[3].savedAmmo / this.ammoScale); //used with low frequency } else { @@ -5535,10 +5603,10 @@ const tech = { simulation.updateGunHUD(); }, remove() { - if (tech.isLongitudinal) { - tech.isLongitudinal = false; + tech.isLongitudinal = false; + if (this.count > 0) { b.guns[3].chooseFireMethod() - b.guns[3].ammoPack = b.guns[3].defaultAmmoPack + b.guns[3].ammoPack *= this.ammoScale if (tech.isInfiniteWaveAmmo) { b.guns[3].savedAmmo = Math.ceil(b.guns[3].savedAmmo * this.ammoScale); //used with low frequency } else { @@ -5546,7 +5614,6 @@ const tech = { } simulation.updateGunHUD(); } - tech.isLongitudinal = false; } }, { @@ -5671,11 +5738,11 @@ const tech = { } }, remove() { - if (tech.missileFireCD !== 45) { - tech.missileFireCD = 45; + tech.missileFireCD = 45; + if (this.count > 0) { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "missiles") { - b.guns[i].ammoPack = 5; + b.guns[i].ammoPack /= this.ammoBonus; b.guns[i].ammo = Math.ceil(b.guns[i].ammo / this.ammoBonus); simulation.updateGunHUD(); break @@ -6286,7 +6353,7 @@ const tech = { }, { name: "colony", - description: "1.5x sporangium discharge
40% chance to discharge something different", + description: "1.6x sporangium discharge
33% chance to discharge something different", link: `colony`, isGunTech: true, maxCount: 1, @@ -6469,9 +6536,9 @@ const tech = { { name: "reduced tolerances", link: `reduced tolerances`, - description: `1.7x drones per ${powerUps.orb.ammo()} and energy
0.6x drone duration`, + description: `2x drones per ${powerUps.orb.ammo()} and energy
0.6x drone duration`, isGunTech: true, - maxCount: 3, + maxCount: 1, count: 0, frequency: 2, frequencyDefault: 2, @@ -6480,20 +6547,19 @@ const tech = { }, requires: "drones, not irradiated drones", effect() { - tech.droneCycleReduction = Math.pow(0.6, 1 + this.count) - tech.droneEnergyReduction = Math.pow(0.3, 1 + this.count) + tech.droneCycleReduction = 0.6 + tech.droneEnergyReduction = 0.3 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "drones") { - const scale = Math.pow(3, this.count + 1) - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * scale - } + if (b.guns[i].name === "drones") b.guns[i].ammoPack *= 2 } }, remove() { tech.droneCycleReduction = 1 tech.droneEnergyReduction = 1 - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "drones") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack + if (this.count > 0) { + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "drones") b.guns[i].ammoPack /= 2 + } } } }, @@ -6591,18 +6657,18 @@ const tech = { tech.isDroneRadioactive = true for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "drones") { - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.25 + b.guns[i].ammoPack *= 0.25 b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.25) simulation.makeGunHUD(); } } }, remove() { - if (tech.isDroneRadioactive) { - tech.isDroneRadioactive = false + tech.isDroneRadioactive = false + if (this.count > 0) { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "drones") { - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack + b.guns[i].ammoPack /= 0.25 b.guns[i].ammo = b.guns[i].ammo * 4 simulation.makeGunHUD(); } @@ -6711,7 +6777,8 @@ const tech = { return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.isFoamPressure && (build.isExperimentSelection || powerUps.research.count > 1) }, effect() { - tech.giveTech("foam-bot upgrade") + + requestAnimationFrame(() => { tech.giveTech("foam-bot upgrade") }) for (let i = 0; i < 2; i++) { b.foamBot() tech.foamBotCount++; @@ -6863,14 +6930,14 @@ const tech = { requires: "foam, not non-renewables", ammoLost: 0, effect() { - b.guns[8].ammoPack = b.guns[8].ammoPack * 12; + b.guns[8].ammoPack *= 12; this.ammoLost = b.guns[8].ammo b.guns[8].ammo = 0 simulation.updateGunHUD() }, remove() { - b.guns[8].ammoPack = 24 if (this.count) { + b.guns[8].ammoPack /= 12 b.guns[8].ammo += this.ammoLost simulation.updateGunHUD() } @@ -6960,16 +7027,16 @@ const tech = { tech.isRailGun = true; tech.harpoonDensity = tech.isRailGun ? 0.007 : 0.004 b.guns[9].chooseFireMethod() - b.guns[9].ammoPack = 5; + b.guns[9].ammoPack *= 3; b.guns[9].ammo = b.guns[9].ammo * 6; simulation.updateGunHUD(); }, remove() { - if (tech.isRailGun) { - tech.isRailGun = false; + tech.isRailGun = false; + if (this.count > 0) { tech.harpoonDensity = tech.isRailGun ? 0.007 : 0.004 b.guns[9].chooseFireMethod() - b.guns[9].ammoPack = 1.7; + b.guns[9].ammoPack /= 3; b.guns[9].ammo = Math.ceil(b.guns[9].ammo / 6); simulation.updateGunHUD(); } @@ -6977,7 +7044,7 @@ const tech = { }, { name: "alternator", - description: "harpoon no longer uses any energy", + description: "0.05x harpoon energy cost", isGunTech: true, maxCount: 1, count: 0, @@ -7150,7 +7217,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return ((tech.haveGunCheck("wave") && !tech.isInfiniteWaveAmmo) || tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun)) && !tech.isEnergyNoAmmo + return ((tech.haveGunCheck("wave") && tech.isInfiniteWaveAmmo) || tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun)) && !tech.isEnergyNoAmmo }, requires: "harpoon, laser, wave, frequency, not railgun, non-renewables", effect() { @@ -7182,49 +7249,51 @@ const tech = { }, requires: "laser gun, not pulse", effect() { - let techGiven = 0 - for (let j = 0; j < 3; j++) { - const names = ["quasiparticles", "lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"] - //convert names into indexes - const options = [] - for (let i = 0; i < names.length; i++) { - for (let k = 0; k < tech.tech.length; k++) { - if (tech.tech[k].name === names[i]) { - options.push(k) - break + requestAnimationFrame(() => { + let techGiven = 0 + for (let j = 0; j < 3; j++) { + const names = ["quasiparticles", "lens", "compound lens", "arc length", "infrared diode", "free-electron laser", "dye laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light", "laser-bot", "laser-bot upgrade"] + //convert names into indexes + const options = [] + for (let i = 0; i < names.length; i++) { + for (let k = 0; k < tech.tech.length; k++) { + if (tech.tech[k].name === names[i]) { + options.push(k) + break + } } } - } - //remove options that don't meet requirements - for (let i = options.length - 1; i > -1; i--) { - const index = options[i] - if (!(tech.tech[index].count < tech.tech[index].maxCount) || !tech.tech[index].allowed()) { - options.splice(i, 1); + //remove options that don't meet requirements + for (let i = options.length - 1; i > -1; i--) { + const index = options[i] + if (!(tech.tech[index].count < tech.tech[index].maxCount) || !tech.tech[index].allowed()) { + options.splice(i, 1); + } + } + //pick one option + if (options.length) { + const index = options[Math.floor(Math.random() * options.length)] + simulation.makeTextLog(`tech.giveTech("${tech.tech[index].name}") //optical amplifier`, 360); + tech.giveTech(index) + techGiven++ } } - //pick one option - if (options.length) { - const index = options[Math.floor(Math.random() * options.length)] - simulation.makeTextLog(`tech.giveTech("${tech.tech[index].name}") //optical amplifier`, 360); - tech.giveTech(index) - techGiven++ - } - } - if (techGiven > 0) { - tech.isStuckOn = true - } else { //eject if none found - simulation.makeTextLog(`0 tech found //optical amplifier`); - const loop = () => { - if (!simulation.paused && m.alive) { - for (let i = 0; i < tech.tech.length; i++) { - if (tech.tech[i].name === this.name) powerUps.ejectTech(i) + if (techGiven > 0) { + tech.isStuckOn = true + } else { //eject if none found + simulation.makeTextLog(`0 tech found //optical amplifier`); + const loop = () => { + if (!simulation.paused && m.alive) { + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].name === this.name) powerUps.ejectTech(i) + } + return } - return + requestAnimationFrame(loop); } requestAnimationFrame(loop); } - requestAnimationFrame(loop); - } + }); }, remove() { tech.isStuckOn = false @@ -7440,7 +7509,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.0018 + return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.003 }, requires: "laser, not free-electron, pulse", effect() { @@ -7449,7 +7518,7 @@ const tech = { // tech.laserColorAlpha = "rgba(255,0,20,0.05)" }, remove() { - tech.laserDrain = 0.0018; + tech.laserDrain = 0.003; tech.laserColor = "#f02" tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)" } @@ -7463,7 +7532,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.0018 + return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.003 }, requires: "laser, not pulse, infrared diode", effect() { @@ -7473,7 +7542,7 @@ const tech = { tech.laserColorAlpha = "rgba(0, 11, 255,0.5)" }, remove() { - tech.laserDrain = 0.0018; + tech.laserDrain = 0.003; tech.laserDamage = 0.18; //used in check on pulse and diode: tech.laserDamage === 0.18 tech.laserColor = "#f00" tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)" @@ -7481,24 +7550,24 @@ const tech = { }, { name: "free-electron laser", - description: "3.5x laser energy cost
3x laser damage", + description: "3x laser energy cost
3x laser damage", isGunTech: true, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.0018 + return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade || tech.isLaserField) && !tech.isPulseLaser && tech.laserDrain === 0.003 }, requires: "laser, not pulse, infrared diode", effect() { - tech.laserDrain *= 1 + 2.5 - tech.laserDamage *= 1 + 2 + tech.laserDrain *= 3 + tech.laserDamage *= 3 tech.laserColor = "#83f" tech.laserColorAlpha = "rgba(136, 51, 255,0.5)" }, remove() { - tech.laserDrain = 0.0018; + tech.laserDrain = 0.003; tech.laserDamage = 0.18; //used in check on pulse and diode: tech.laserDamage === 0.18 tech.laserColor = "#f00" tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)" @@ -7513,7 +7582,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDrain === 0.0018 && !tech.isStuckOn + return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDrain === 0.003 && !tech.isStuckOn }, requires: "laser gun, not specular reflection, diffuse, free-electron laser, optical amplifier", effect() { @@ -7806,7 +7875,7 @@ const tech = { }, { name: "neutronium", - description: `move and jump 20% slower
if your field is active 0.05x damage taken`, + description: `0.8x move and jump, but
if your field is active 0.05x damage taken`, isFieldTech: true, maxCount: 1, count: 0, @@ -7948,71 +8017,73 @@ const tech = { }, requires: "molecular assembler, grappling hook, pilot wave", effect() { - for (let i = 0; i < 3; i++) { - if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - } - //fill array of available bots - const notUpgradedBots = [] - const num = 2 - notUpgradedBots.push(() => { - tech.giveTech("nail-bot upgrade") - for (let i = 0; i < num; i++) { - b.nailBot() - tech.nailBotCount++; + requestAnimationFrame(() => { + for (let i = 0; i < 3; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) } - simulation.makeTextLog(`tech.isNailBotUpgrade = true`) - }) - notUpgradedBots.push(() => { - tech.giveTech("foam-bot upgrade") - for (let i = 0; i < num; i++) { - b.foamBot() - tech.foamBotCount++; - } - simulation.makeTextLog(`tech.isFoamBotUpgrade = true`) - }) - notUpgradedBots.push(() => { - tech.giveTech("sound-bot upgrade") - for (let i = 0; i < num; i++) { - b.soundBot() - tech.soundBotCount++; - } - simulation.makeTextLog(`tech.isSoundBotUpgrade = true`) - }) - notUpgradedBots.push(() => { - tech.giveTech("boom-bot upgrade") - for (let i = 0; i < num; i++) { - b.boomBot() - tech.boomBotCount++; - } - simulation.makeTextLog(`tech.isBoomBotUpgrade = true`) - }) - notUpgradedBots.push(() => { - tech.giveTech("laser-bot upgrade") - for (let i = 0; i < num; i++) { - b.laserBot() - tech.laserBotCount++; - } - simulation.makeTextLog(`tech.isLaserBotUpgrade = true`) - }) - notUpgradedBots.push(() => { - tech.giveTech("orbital-bot upgrade") - for (let i = 0; i < num; i++) { - b.orbitBot() - tech.orbitBotCount++; - } - simulation.makeTextLog(`tech.isOrbitalBotUpgrade = true`) - }) - for (let i = 0; i < 2; i++) { //double chance for dynamo-bot, since it's very good for assembler + //fill array of available bots + const notUpgradedBots = [] + const num = 2 notUpgradedBots.push(() => { - tech.giveTech("dynamo-bot upgrade") + tech.giveTech("nail-bot upgrade") for (let i = 0; i < num; i++) { - b.dynamoBot() - tech.dynamoBotCount++; + b.nailBot() + tech.nailBotCount++; } - simulation.makeTextLog(`tech.isDynamoBotUpgrade = true`) + simulation.makeTextLog(`tech.isNailBotUpgrade = true`) }) - } - notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() //choose random function from the array and run it + notUpgradedBots.push(() => { + tech.giveTech("foam-bot upgrade") + for (let i = 0; i < num; i++) { + b.foamBot() + tech.foamBotCount++; + } + simulation.makeTextLog(`tech.isFoamBotUpgrade = true`) + }) + notUpgradedBots.push(() => { + tech.giveTech("sound-bot upgrade") + for (let i = 0; i < num; i++) { + b.soundBot() + tech.soundBotCount++; + } + simulation.makeTextLog(`tech.isSoundBotUpgrade = true`) + }) + notUpgradedBots.push(() => { + tech.giveTech("boom-bot upgrade") + for (let i = 0; i < num; i++) { + b.boomBot() + tech.boomBotCount++; + } + simulation.makeTextLog(`tech.isBoomBotUpgrade = true`) + }) + notUpgradedBots.push(() => { + tech.giveTech("laser-bot upgrade") + for (let i = 0; i < num; i++) { + b.laserBot() + tech.laserBotCount++; + } + simulation.makeTextLog(`tech.isLaserBotUpgrade = true`) + }) + notUpgradedBots.push(() => { + tech.giveTech("orbital-bot upgrade") + for (let i = 0; i < num; i++) { + b.orbitBot() + tech.orbitBotCount++; + } + simulation.makeTextLog(`tech.isOrbitalBotUpgrade = true`) + }) + for (let i = 0; i < 2; i++) { //double chance for dynamo-bot, since it's very good for assembler + notUpgradedBots.push(() => { + tech.giveTech("dynamo-bot upgrade") + for (let i = 0; i < num; i++) { + b.dynamoBot() + tech.dynamoBotCount++; + } + simulation.makeTextLog(`tech.isDynamoBotUpgrade = true`) + }) + } + notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() //choose random function from the array and run it + }) }, remove() { } }, @@ -8555,7 +8626,7 @@ const tech = { { name: "patch", link: `patch`, - description: "after cloaking recover 75%
of your last health lost", + description: "after cloaking recover 0.75x
of your last health lost", isFieldTech: true, maxCount: 1, count: 0, @@ -9187,7 +9258,7 @@ const tech = { count += 4.5 const waves = 2 * Math.sin(count * 0.0133) + Math.sin(count * 0.013) + 0.5 * Math.sin(count * 0.031) + 0.33 * Math.sin(count * 0.03) this.spawnCount = Math.floor(100 * Math.abs(waves)) - this.text = `spawn ${this.spawnCount.toLocaleString(undefined, { minimumIntegerDigits: 3 })} ${powerUps.orb.boost(1)}
that give ${(1 + powerUps.boost.damage).toFixed(2)}% damage for ${(powerUps.boost.duration / 60).toFixed(0)} seconds` + this.text = `spawn ${this.spawnCount.toLocaleString(undefined, { minimumIntegerDigits: 3 })} ${powerUps.orb.boost(1)}
that give ${(1 + powerUps.boost.damage).toFixed(2)}x damage for ${(powerUps.boost.duration / 60).toFixed(0)} seconds` if (document.getElementById(`boost-JUNK-id${this.id}`)) document.getElementById(`boost-JUNK-id${this.id}`).innerHTML = this.text setTimeout(() => { loop() @@ -9344,7 +9415,7 @@ const tech = { }, { name: "reinforcement learning", - description: "+1000% frequency of finding copies of current tech
", + description: "10x current tech frequency", maxCount: 1, count: 0, frequency: 1, @@ -10229,7 +10300,7 @@ const tech = { }, { name: "probability", - description: "increase the frequency
of one random tech by 100", + description: "100x frequency
of one random tech", maxCount: 1, count: 0, frequency: 0, @@ -10400,7 +10471,7 @@ const tech = { }, { name: "repartitioning", - description: "set the frequency of finding normal tech to 0
spawn 5 tech", + description: "set the frequency of finding normal tech to 0
spawn 5 tech", maxCount: 1, count: 0, frequency: 0, @@ -10424,7 +10495,7 @@ const tech = { }, { name: "defragment", - description: "set the frequency of finding JUNKtech to zero", + description: "set the frequency of finding JUNKtech to zero", maxCount: 1, count: 0, frequency: 0, @@ -11841,6 +11912,7 @@ const tech = { duplication: null, isCancelRerolls: null, isCancelTech: null, + cancelTechCount: null, isBotDamage: null, isBanish: null, isMaxEnergyTech: null, @@ -12029,7 +12101,6 @@ const tech = { isHealBrake: null, isMassProduction: null, isPrinter: null, - // isHookWire: null, isHookDefense: null, hookNails: null, isHarpoonDefense: null, @@ -12043,4 +12114,6 @@ const tech = { isPowerUpDamage: null, isExitPrompt: null, isResearchDamage: null, + interestRate: null, + } \ No newline at end of file diff --git a/style.css b/style.css index 216d5f9..0492298 100644 --- a/style.css +++ b/style.css @@ -519,38 +519,6 @@ summary { border-radius: 5px; } -/* keeps 4 columns at 1440px */ -/* @media (1500px <= width < 1950px) { - .experiment-grid-module, .choose-grid-module, .pause-grid-module { - line-height: 150%; - font-size: 0.72em; - } - #experiment-grid, #choose-grid, .pause-grid{ - grid-template-columns: repeat(auto-fit, 360px); - } - .card-background{ - height:315px; - } - .card-text { - min-height: 82px; - } -} -@media (width < 1500px) { - .experiment-grid-module, .choose-grid-module, .pause-grid-module { - line-height: 143%; - font-size: 0.68em; - } - #experiment-grid, #choose-grid, .pause-grid{ - grid-template-columns: repeat(auto-fit, 340px); - } - .card-background{ - height:290px; - } - .card-text { - min-height: 75px; - } -} */ - .experiment-grid-module:hover .card-text { background-color: var(--hover-card-color); } @@ -695,77 +663,6 @@ summary { display: none; } -/* #damage-bar { - position: absolute; - top: 0px; - left: 15px; - height: 6px; - width: 0px; - transition: width 0.3s linear; - opacity: 1; - z-index: 2; - pointer-events: none; - background-color: #f03; - border: 1px solid #701; - display: none; -} - -#defense-bar { - position: absolute; - top: 9px; - left: 15px; - height: 5px; - width: 0px; - transition: width 0.3s linear; - opacity: 1; - z-index: 2; - pointer-events: none; - background-color: #fff; - border: 1px solid #333; - display: none; -} -#health { - position: absolute; - top: 16px; - left: 15px; - height: 20px; - width: 0px; - transition: width 1s ease-out; z-index: 2; - pointer-events: none; - background-color: #0fa; - border: 2px solid rgb(51, 162, 125); - border-radius: 8px; - display: none; -} -#health-bg { - position: absolute; - top: 18px; - left: 15px; - height: 20px; - width: 0px; - transition: width 1s ease-out; - background-color: #000; - opacity: 0.1; - z-index: 1; - pointer-events: none; - border-radius: 8px; - display: none; -} */ - -/* .low-health { - animation: blink 250ms infinite alternate; -} - -@keyframes blink { - from { - opacity: 1; - } - - to { - opacity: 0.6; - } -} */ - /* background on title page */ #fade-out { position: absolute; @@ -926,6 +823,15 @@ summary { text-shadow: 1.5px -1.5px hsla(243, 100%, 38%, 0.2); } +.color-remove { + text-decoration: line-through; + /* letter-spacing: 2px; */ + border-radius: 3px; + padding: 0px 3px; + background-color: hsl(255, 40%, 71%); + color: #fff; +} + .color-cloaked { letter-spacing: 2px; animation: cloak 6s linear infinite alternate; @@ -1090,7 +996,7 @@ summary { background-color: #0d9; border: 0.05em #fff solid; opacity: 0.85; - margin-bottom: -3px; + margin-bottom: -2px; } .heal-circle-energy { @@ -1101,7 +1007,7 @@ summary { background-color: #ff0; border: 0.05em #000 solid; opacity: 0.85; - margin-bottom: -3px; + margin-bottom: -2px; } .coupling-circle { diff --git a/todo.txt b/todo.txt index 234d30a..f17a915 100644 --- a/todo.txt +++ b/todo.txt @@ -1,24 +1,62 @@ ******************************************************** NEXT PATCH ************************************************** -text rework - most numbers converted from "+50%" to "1.5x" - renamed defense -> damage taken - adjusted about 20 tech to round down or up their values to less decimals - for a few I added research cost or JUNK chance to balance rounding +added CSS style for "remove/eject" keyword +tech: deprecated - gain 1.05x damage for each tech removed this game +tech: externality - 1.1x damage, removing this gives 40 ammo power ups +paradigm shift no longer has a 3% failure rate + minus 3->4 health + it can remove applied science tech +removing strange loop gives a random removetech -new community map soft by Richard0820 -tech: peer review - gain +damage each time you research -self-assembly scales with health not health percent -matter.js engine reverted back to 0.18 (to fix an issue with time dilation) +tech: marginal utility - give a specific gun 2x ammo per ammo power up +tech: interest - research, ammo, coupling, health increases by 6% at the start of each level +tech: Pareto efficiency - give each gun randomly 5x or 0.2x ammo per ammo power up + +aperture 6->4s cycles between 1 to 2 -> 0.8 to 3 damage +mass-energy no longer has a reduction in defense effects + but it costs 2 research now +1st ionization energy 11->14 max energy per heal +colony: 1.5->1.6x spores 40->33% chance to spawn something different +laser cost formula changed to be independent of field regen + this makes the effects of cost and fire rate 33% bigger + free-electron laser 3.5->3x energy cost +options exchange - the first time you click cancel it randomizes choices + allows a free trigger from other cancel tech +pseudoscience gets 3->2 free researches +alternator harpoon has 0->0.03x energy cost +coupling for pilot wave gives 1.04->1.05x block damage + +several bugs fixes *********************************************************** TODO ***************************************************** +removeJunkTechFromPool doesn't seem to remove the correct amount + +make search not case sensitive + +wormholes that end inside wall check to see if the space before the wall is safe and end there instead + can use laser code + +tech: - (1 + 0.01)x for each tech, gun, field you've picked up + scales with born rule, duplication, remove tech + +explosions have a chance to spawn spores + infinite feedback loop with spores that explode? + +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 +tech - destroy all but active gun and convert ammo over to main gun + List of ways to break the game CPT + high energy regen research->bot fabrication-> ersatz bots -> various bot upgrades + grappling hook + high fire rate + alternator + time dilation duplication 100% + interest + coupling, research + peer review? electronegativity and high energy? boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires @@ -43,10 +81,6 @@ tech - getting a new gun also gives you 2 random tech for that gun or a field? can these guntech tech be converted into a player choice? -tech: interest - research and ammo increases by 10% at the start of each level? - spawn research and ammo at start of new level - extend to current health? - how to reduce the number of clicks and keypresses auto fire mode player shoots at whatever is nearby @@ -1093,6 +1127,7 @@ possible names for tech sidereal - with respect to the stars (an extra rotation for time keeping) holonomy - parallel transport of a vector leads to movement (applies to curved space) holographic - 2-D surface can predict the 3-D space behind it? I think + conformal - similar rules for small and big scales linked to holographic principle hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other. swarm intelligence - for a drone tech metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity @@ -1141,6 +1176,8 @@ possible names for tech configuration space - holds the position of everything stress–energy tensor radioisotope thermoelectric generator - + retrovirus: these things make JUNK DNA so link it somehow to that tech? + Upon infection with a retrovirus, a cell converts the retroviral RNA into DNA and sometimes the DNA will be passed on to progeny as JUNK DNA ******************************************************** CARS IMAGES ********************************************************