const tech = { totalCount: null, setupAllTech() { for (let i = 0, len = tech.tech.length; i < len; i++) { tech.tech[i].remove(); tech.tech[i].isLost = false tech.tech[i].count = 0 } // tech.nailBotCount = 0; // tech.foamBotCount = 0; // tech.boomBotCount = 0; // tech.laserBotCount = 0; // tech.orbitalBotCount = 0; // tech.plasmaBotCount = 0; tech.armorFromPowerUps = 0; tech.totalCount = 0; simulation.updateTechHUD(); }, removeTech(index) { tech.tech[index].remove(); tech.tech[index].count = 0; simulation.updateTechHUD(); }, giveTech(index = 'random') { if (index === 'random') { let options = []; for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed()) options.push(i); } // 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) } } else { if (isNaN(index)) { //find index by name let found = false; for (let i = 0; i < tech.tech.length; i++) { if (index === tech.tech[i].name) { index = i; found = true; break; } } if (!found) return //if name not found don't give any tech } if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech tech.tech[index].effect(); //give specific tech tech.tech[index].count++ tech.totalCount++ //used in power up randomization simulation.updateTechHUD(); } }, setTechoNonRefundable(name) { for (let i = 0; i < tech.tech.length; i++) { if (tech.tech.name === name) { tech.tech[i].isNonRefundable = true; return } } }, haveGunCheck(name) { if ( !build.isCustomSelection && b.inventory.length > 2 && name !== b.guns[b.activeGun].name && Math.random() > 2 / (b.inventory.length + tech.isGunCycle * 3) //lower chance of tech specific to a gun if you have lots of guns ) { return false } for (i = 0, len = b.inventory.length; i < len; i++) { if (b.guns[b.inventory[i]].name === name) return true } return false }, damageFromTech() { let dmg = mech.fieldDamage // if (tech.aimDamage>1) if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - mech.energy) * 0.5 if (tech.isMaxEnergyTech) dmg *= 1.4 if (tech.isEnergyNoAmmo) dmg *= 1.5 if (tech.isDamageForGuns) dmg *= 1 + 0.07 * b.inventory.length if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, 1 - mech.health) if (tech.isHarmDamage && mech.lastHarmCycle + 600 > mech.cycle) dmg *= 3; if (tech.isEnergyLoss) dmg *= 1.5; if (tech.isAcidDmg && mech.health > 1) dmg *= 1.4; if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.isEnergyDamage) dmg *= 1 + mech.energy / 9; if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038 if (tech.isRerollDamage) dmg *= 1 + 0.04 * powerUps.reroll.rerolls if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (tech.isNoFireDamage && mech.cycle > mech.fireCDcycle + 120) dmg *= 1.66 if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.4, player.speed * 0.013) if (tech.isBotDamage) dmg *= 1 + 0.02 * tech.totalBots() return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.04 + tech.duplicateChance + mech.duplicateChance }, totalBots() { return tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount }, tech: [{ name: "electrolytes", description: "increase damage by 1%
for every 9 stored energy", maxCount: 1, count: 0, allowed() { return mech.maxEnergy > 1 || tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 }, requires: "increased energy regen or max energy", effect: () => { tech.isEnergyDamage = true }, remove() { tech.isEnergyDamage = false; } }, { name: "exciton-lattice", description: `increase damage by 50%, but
ammo will no longer spawn`, maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("nail gun") && tech.isIceCrystals) || tech.haveGunCheck("laser") || mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" }, requires: "energy based damage", effect() { tech.isEnergyNoAmmo = true; }, remove() { tech.isEnergyNoAmmo = false; } }, { name: "exothermic process", description: "increase damage by 50%
if a mob dies drain energy by 25%", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.isEnergyLoss = true; }, remove() { tech.isEnergyLoss = false; } }, { name: "heat engine", description: `increase damage by 40%, but
reduce maximum energy by 50`, maxCount: 1, count: 0, allowed() { return tech.isEnergyLoss && mech.maxEnergy === 1 && !tech.isMissileField && !tech.isSporeField && !tech.isRewindAvoidDeath }, requires: "exothermic process, not max energy increase, CPT, missile or spore nano-scale", effect() { tech.isMaxEnergyTech = true; mech.setMaxEnergy() }, remove() { tech.isMaxEnergyTech = false; mech.setMaxEnergy() } }, { name: "Gibbs free energy", description: `increase damage by 5%
for every 10 energy below 100`, maxCount: 1, count: 0, allowed() { return tech.isEnergyLoss && mech.maxEnergy < 1.1 }, requires: "exothermic process", effect() { tech.isLowEnergyDamage = true; }, remove() { tech.isLowEnergyDamage = false; } }, { name: "rest frame", description: "increase damage by 25%
when not moving", maxCount: 6, count: 0, allowed() { return mech.Fx === 0.016 }, requires: "base movement speed", effect: () => { tech.restDamage += 0.25 }, remove() { tech.restDamage = 1; } }, { name: "kinetic bombardment", description: "increase damage by up to 33%
at a distance of 40 steps from the target", maxCount: 1, count: 0, allowed() { return true }, requires: "", effect() { tech.isFarAwayDmg = true; //used in mob.damage() }, remove() { tech.isFarAwayDmg = false; } }, { name: "fluoroantimonic acid", description: "increase damage by 40%
when your health is above 100", maxCount: 1, count: 0, allowed() { return mech.maxHealth > 1; }, requires: "health above 100", effect() { tech.isAcidDmg = true; }, remove() { tech.isAcidDmg = false; } }, { name: "integrated armament", description: "increase damage by 25%
your inventory can only hold 1 gun", maxCount: 1, count: 0, allowed() { return b.inventory.length < 2 }, requires: "no more than 1 gun", effect() { tech.isOneGun = true; }, remove() { tech.isOneGun = false; } }, { name: "negative feedback", description: "increase damage by 6%
for every 10 health below 100", maxCount: 1, count: 0, allowed() { return mech.health < 0.6 || build.isCustomSelection }, requires: "health below 60", effect() { tech.isLowHealthDmg = true; //used in mob.damage() }, remove() { tech.isLowHealthDmg = false; } }, { name: "radiative equilibrium", description: "for 10 seconds after receiving harm
increase damage by 200%", maxCount: 1, count: 0, allowed() { return mech.harmReduction() < 1 }, requires: "some harm reduction", effect() { tech.isHarmDamage = true; }, remove() { tech.isHarmDamage = false; } }, { name: "perturbation theory", description: "increase damage by 4%
for each of your rerolls", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls > 3 || build.isCustomSelection }, requires: "at least 4 rerolls", effect() { tech.isRerollDamage = true; }, remove() { tech.isRerollDamage = false; } }, { name: "electrostatic discharge", description: "increase damage by 20%
20% increased delay after firing", maxCount: 1, count: 0, allowed() { return true }, effect() { tech.slowFire = 1.2 b.setFireCD(); }, remove() { tech.slowFire = 1; b.setFireCD(); } }, { name: "Ψ(t) collapse", description: "66% decreased delay after firing
when you have no rerolls", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls === 0 && !tech.manyWorlds }, requires: "no rerolls", effect() { tech.isRerollHaste = true; tech.rerollHaste = 0.33; b.setFireCD(); }, remove() { tech.isRerollHaste = false; tech.rerollHaste = 1; b.setFireCD(); } }, { name: "auto-loading heuristics", description: "30% decreased delay after firing", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { tech.fireRate *= 0.7 b.setFireCD(); }, remove() { tech.fireRate = 1; b.setFireCD(); } }, { name: "mass driver", description: "increase block collision damage by 100%
charge throws more quickly for less energy", maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name !== "wormhole" }, requires: "not wormhole", effect() { tech.throwChargeRate = 2 }, remove() { tech.throwChargeRate = 1 } }, { name: "ammonium nitrate", description: "increase explosive damage by 20%
increase explosive radius by 20%", maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { tech.explosiveRadius += 0.2; }, remove() { tech.explosiveRadius = 1; } }, { name: "nitroglycerin", description: "increase explosive damage by 60%
decrease explosive radius by 20%", maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { tech.isSmallExplosion = true; }, remove() { tech.isSmallExplosion = false; } }, { name: "acetone peroxide", description: "increase explosive radius by 80%, but
you take 400% more harm from explosions", maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { tech.isExplosionHarm = true; }, remove() { tech.isExplosionHarm = false; } }, { name: "electric reactive armor", // description: "explosions do no harm
while your energy is above 98%", description: "harm from explosions is passively reduced
by 7% for every 10 stored energy", maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isFlechetteExplode || tech.isPulseLaser }, requires: "an explosive damage source", effect: () => { tech.isImmuneExplosion = true; }, remove() { tech.isImmuneExplosion = false; } }, { name: "thermal runaway", description: "mobs explode when they die
be careful", maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isFlechetteExplode) && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isBotSpawner }, requires: "an explosive damage source, no other mob death tech", effect: () => { tech.isExplodeMob = true; }, remove() { tech.isExplodeMob = false; } }, { name: "reaction inhibitor", description: "mobs spawn with 11% less health", maxCount: 3, count: 0, allowed() { return tech.nailsDeathMob || tech.sporesOnDeath || tech.isExplodeMob || tech.isBotSpawner }, requires: "any mob death tech", effect: () => { tech.mobSpawnWithHealth *= 0.89 //set all mobs at full health to 0.85 for (let i = 0; i < mob.length; i++) { if (mob.health > tech.mobSpawnWithHealth) mob.health = tech.mobSpawnWithHealth } }, remove() { tech.mobSpawnWithHealth = 1; } }, { name: "zoospore vector", description: "mobs produce spores when they die
9% chance", maxCount: 9, count: 0, allowed() { return !tech.nailsDeathMob && !tech.isExplodeMob && !tech.isBotSpawner }, requires: "no other mob death tech", effect() { tech.sporesOnDeath += 0.09; for (let i = 0; i < 8; i++) { b.spore(mech.pos) } }, remove() { tech.sporesOnDeath = 0; } }, { name: "impact shear", description: "mobs release a nail when they die
nails target nearby mobs", maxCount: 9, count: 0, allowed() { return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.isBotSpawner }, requires: "no other mob death tech", effect: () => { tech.nailsDeathMob++ }, remove() { tech.nailsDeathMob = 0; } }, { name: "scrap bots", description: "20% chance to build a bot after killing a mob
the bot lasts for about 20 seconds", maxCount: 3, count: 0, allowed() { return tech.totalBots() > 0 && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isExplodeMob }, requires: "a bot and no other mob death tech", effect() { tech.isBotSpawner += 0.20; }, remove() { tech.isBotSpawner = 0; } }, { name: "nail-bot", description: "a bot fires nails at targets in line of sight", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { tech.nailBotCount++; b.nailBot(); }, remove() { tech.nailBotCount -= this.count; } }, { name: "nail-bot upgrade", description: "500% increased fire rate
applies to all current and future nail-bots", maxCount: 1, count: 0, allowed() { return tech.nailBotCount > 1 }, requires: "2 or more nail bots", effect() { tech.isNailBotUpgrade = true for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'nail') bullet[i].isUpgraded = true } }, remove() { tech.isNailBotUpgrade = false for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'nail') bullet[i].isUpgraded = false } } }, { name: "foam-bot", description: "a bot fires foam at nearby targets", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { tech.foamBotCount++; b.foamBot(); }, remove() { tech.foamBotCount -= this.count; } }, { name: "foam-bot upgrade", description: "200% increased foam size and fire rate
applies to all current and future foam-bots", maxCount: 1, count: 0, allowed() { return tech.foamBotCount > 1 }, requires: "2 or more foam bots", effect() { tech.isFoamBotUpgrade = true for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'foam') bullet[i].isUpgraded = true } }, remove() { tech.isFoamBotUpgrade = false for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'foam') bullet[i].isUpgraded = false } } }, { name: "boom-bot", description: "a bot defends the space around you
ignites an explosion after hitting a mob", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { tech.boomBotCount++; b.boomBot(); }, remove() { tech.boomBotCount -= this.count; } }, { name: "boom-bot upgrade", description: "250% increased explosion damage and size
applies to all current and future boom-bots", maxCount: 1, count: 0, allowed() { return tech.boomBotCount > 1 }, requires: "2 or more boom bots", effect() { tech.isBoomBotUpgrade = true for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'boom') bullet[i].isUpgraded = true } }, remove() { tech.isBoomBotUpgrade = false for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'boom') bullet[i].isUpgraded = false } } }, { name: "laser-bot", description: "a bot uses energy to emit a laser
targeting nearby mobs", maxCount: 9, count: 0, allowed() { return mech.maxEnergy > 0.5 }, requires: "maximum energy above 50%", effect() { tech.laserBotCount++; b.laserBot(); }, remove() { tech.laserBotCount -= this.count; } }, { name: "laser-bot upgrade", description: "350% increased laser damage
applies to all current and future laser-bots", maxCount: 1, count: 0, allowed() { return tech.laserBotCount > 1 }, requires: "2 or more laser bots", effect() { tech.isLaserBotUpgrade = true for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'laser') bullet[i].isUpgraded = true } }, remove() { tech.isLaserBotUpgrade = false for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'laser') bullet[i].isUpgraded = false } } }, { name: "orbital-bot", description: "a bot is locked in orbit around you
stuns and damages mobs on contact", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { b.orbitBot(); tech.orbitBotCount++; }, remove() { tech.orbitBotCount -= this.count; } }, { name: "orbital-bot upgrade", description: "increase damage by 150% and radius by 30%
applies to all current and future orbit-bots", maxCount: 1, count: 0, allowed() { return tech.orbitBotCount > 1 }, requires: "2 or more orbital bots", effect() { tech.isOrbitBotUpgrade = true const range = 190 + 60 * tech.isOrbitBotUpgrade for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'orbit') { bullet[i].isUpgraded = true bullet[i].range = range bullet[i].orbitalSpeed = Math.sqrt(0.25 / range) } } }, remove() { tech.isOrbitBotUpgrade = false const range = 190 + 60 * tech.isOrbitBotUpgrade for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType === 'orbit') { bullet[i].range = range bullet[i].orbitalSpeed = Math.sqrt(0.25 / range) } } } }, { name: "bot fabrication", description: "anytime you collect 5 rerolls
use them to build a random bot", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls > 5 || build.isCustomSelection }, requires: "at least 6 rerolls", effect() { tech.isRerollBots = true; powerUps.reroll.changeRerolls(0) simulation.makeTextLog(`mech.rerolls = 0`) }, remove() { tech.isRerollBots = false; } }, { name: "perimeter defense", description: "reduce harm by 3%
for each of your permanent bots", maxCount: 1, count: 0, allowed() { return tech.totalBots() > 5 && !tech.isEnergyHealth }, requires: "5 or more bots", effect() { tech.isBotArmor = true }, remove() { tech.isBotArmor = false } }, { name: "network effect", description: "increase damage by 2%
for each of your permanent bots", maxCount: 1, count: 0, allowed() { return tech.totalBots() > 6 }, requires: "6 or more bots", effect() { tech.isBotDamage = true }, remove() { tech.isBotDamage = false } }, { name: "bot replication", description: "duplicate your permanent bots
remove all of your guns", maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return tech.totalBots() > 3 }, requires: "at least 3 bots", effect() { b.removeAllGuns(); simulation.makeGunHUD(); //double bots for (let i = 0; i < tech.nailBotCount; i++) { b.nailBot(); } tech.nailBotCount *= 2 for (let i = 0; i < tech.laserBotCount; i++) { b.laserBot(); } tech.laserBotCount *= 2 for (let i = 0; i < tech.foamBotCount; i++) { b.foamBot(); } tech.foamBotCount *= 2 for (let i = 0; i < tech.boomBotCount; i++) { b.boomBot(); } tech.boomBotCount *= 2 for (let i = 0; i < tech.orbitBotCount; i++) { b.orbitBot(); } tech.orbitBotCount *= 2 for (let i = 0; i < tech.plasmaBotCount; i++) { b.plasmaBot(); } tech.plasmaBotCount *= 2 for (let i = 0; i < tech.missileBotCount; i++) { b.missileBot(); } tech.missileBotCount *= 2 }, remove() {} }, { name: "ablative drones", description: "rebuild your broken parts as drones
chance to occur after receiving harm", maxCount: 1, count: 0, allowed() { return mech.harmReduction() < 1 }, requires: "some harm reduction", effect() { tech.isDroneOnDamage = true; for (let i = 0; i < 4; i++) { b.drone() //spawn drone } }, remove() { tech.isDroneOnDamage = false; } }, { name: "mine synthesis", description: "drop a mine after picking up a power up", maxCount: 1, count: 0, allowed() { return tech.duplicationChance() > 0 }, requires: "some power up duplication", effect() { tech.isMineDrop = true; if (tech.isMineDrop) b.mine(mech.pos, { x: 0, y: 0 }, 0, tech.isMineAmmoBack) }, remove() { tech.isMineDrop = false; } }, { name: "squirrel-cage rotor", description: "move and jump about 25% faster", maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { // good with melee builds, content skipping builds tech.squirrelFx += 0.2; tech.squirrelJump += 0.09; mech.setMovement() }, remove() { tech.squirrelFx = 1; tech.squirrelJump = 1; mech.setMovement() } }, { name: "Newton's 1st law", description: "moving at high speeds reduces harm
by up to 50%", maxCount: 1, count: 0, allowed() { return mech.Fx > 0.016 && !tech.isEnergyHealth }, requires: "speed increase, not mass-energy equivalence", effect() { tech.isSpeedHarm = true }, remove() { tech.isSpeedHarm = false } }, { name: "Newton's 2nd law", description: "moving at high speeds increases damage
by up to 33%", maxCount: 1, count: 0, allowed() { return mech.Fx > 0.016 }, requires: "speed increase", effect() { tech.isSpeedDamage = true }, remove() { tech.isSpeedDamage = false } }, { name: "Pauli exclusion", description: `immune to harm for an extra 0.75 seconds
after receiving harm from a collision`, maxCount: 9, count: 0, allowed() { return true }, requires: "", effect() { tech.collisionImmuneCycles += 45; mech.immuneCycle = mech.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles }, remove() { tech.collisionImmuneCycles = 25; } }, { name: "decorrelation", description: "reduce harm by 40%
after not using your gun or field for 2 seconds", maxCount: 1, count: 0, allowed() { return (tech.totalBots() > 1 || tech.haveGunCheck("drones") || tech.haveGunCheck("mine") || tech.haveGunCheck("spores") || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing") && !tech.isEnergyHealth }, requires: "drones, spores, mines, or bots", effect() { tech.isNoFireDefense = true }, remove() { tech.isNoFireDefense = false } }, { name: "anticorrelation", description: "increase damage by 66%
after not using your gun or field for 2 seconds", maxCount: 1, count: 0, allowed() { return tech.isNoFireDefense }, requires: "decorrelation", effect() { tech.isNoFireDamage = true }, remove() { tech.isNoFireDamage = false } }, { name: "non-Newtonian armor", description: "for 10 seconds after receiving harm
reduce harm by 66%", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth && mech.harmReduction() < 1 }, requires: "some harm reduction", effect() { tech.isHarmArmor = true; }, remove() { tech.isHarmArmor = false; } }, { name: "clock gating", description: `slow time by 50% after receiving harm
reduce harm by 15%`, maxCount: 1, count: 0, allowed() { return simulation.fpsCapDefault > 45 && !tech.isRailTimeSlow }, requires: "FPS above 45", effect() { tech.isSlowFPS = true; }, remove() { tech.isSlowFPS = false; } }, { name: "liquid cooling", description: `freeze all mobs for 5 seconds
after receiving harm`, maxCount: 1, count: 0, allowed() { return tech.isSlowFPS }, requires: "clock gating", effect() { tech.isHarmFreeze = true; }, remove() { tech.isHarmFreeze = false; } }, { name: "osmoprotectant", description: `collisions with stunned or frozen mobs
cause you no harm`, maxCount: 1, count: 0, allowed() { return tech.isStunField || tech.isPulseStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.haveGunCheck("ice IX") || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage }, requires: "a freezing or stunning effect", effect() { tech.isFreezeHarmImmune = true; }, remove() { tech.isFreezeHarmImmune = false; } }, { name: "supercapacitor", description: "energy above your max decays 60% slower", maxCount: 1, count: 0, allowed() { return tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isRailEnergyGain || tech.isWormholeEnergy || tech.iceEnergy > 0 }, requires: "a source of overfilled energy", effect() { tech.overfillDrain = 0.85 }, remove() { tech.overfillDrain = 0.75 } }, { name: "CPT reversal", description: "charge, parity, and time invert to undo harm
rewind (1.5—5) seconds for (66—220) energy", maxCount: 1, count: 0, allowed() { //&& (mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" || mech.maxEnergy > 1) return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !tech.isEnergyHealth && !tech.isRewindGun }, requires: "not standing wave, mass-energy, piezo, max energy reduction, CPT gun", effect() { tech.isRewindAvoidDeath = true; }, remove() { tech.isRewindAvoidDeath = false; } }, { name: "causality bots", description: "when you rewind, build some bots
that protect you for about 7 seconds", maxCount: 3, count: 0, allowed() { return tech.isRewindAvoidDeath || tech.isRewindEnergy }, requires: "CPT", effect() { tech.isRewindBot++; }, remove() { tech.isRewindBot = 0; } }, { name: "causality bombs", description: "before you rewind drop some grenades", maxCount: 1, count: 0, allowed() { return tech.isRewindAvoidDeath }, requires: "CPT", effect() { tech.isRewindGrenade = true; }, remove() { tech.isRewindGrenade = false; } }, { name: "piezoelectricity", description: "colliding with mobs gives you 400 energy
reduce harm by 15%", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.isPiezo = true; mech.energy += 4; }, remove() { tech.isPiezo = false; } }, { name: "ground state", description: "reduce harm by 60%
you no longer passively regenerate energy", maxCount: 1, count: 0, allowed() { return (tech.iceEnergy || tech.isWormholeEnergy || tech.isPiezo || tech.isRailEnergyGain) && tech.energyRegen !== 0.004 }, requires: "piezoelectricity, Penrose, half-wave, or thermoelectric, but not time crystals", effect: () => { tech.energyRegen = 0; mech.fieldRegen = tech.energyRegen; }, remove() { tech.energyRegen = 0.001; mech.fieldRegen = tech.energyRegen; } }, { name: "mass-energy equivalence", description: "energy protects you instead of health
harm reduction effects provide no benefit", maxCount: 1, count: 0, allowed() { return !tech.isEnergyLoss && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field" }, requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass", effect: () => { mech.health = 0 // mech.displayHealth(); document.getElementById("health").style.display = "none" document.getElementById("health-bg").style.display = "none" document.getElementById("dmg").style.backgroundColor = "#0cf"; tech.isEnergyHealth = true; mech.displayHealth(); }, remove() { tech.isEnergyHealth = false; document.getElementById("health").style.display = "inline" document.getElementById("health-bg").style.display = "inline" document.getElementById("dmg").style.backgroundColor = "#f67"; mech.health = Math.min(mech.maxHealth, mech.energy); mech.displayHealth(); } }, { name: "1st ionization energy", description: "each heal power up you collect
increases your maximum energy by 4", maxCount: 1, count: 0, allowed() { return tech.isEnergyHealth }, requires: "mass-energy equivalence", effect() { tech.healGiveMaxEnergy = true; //tech.healMaxEnergyBonus given from heal power up powerUps.heal.color = "#0ae" for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color } }, remove() { tech.healGiveMaxEnergy = false; tech.healMaxEnergyBonus = 0 powerUps.heal.color = "#0eb" for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color } } }, { name: "overcharge", description: "increase your maximum energy by 50", maxCount: 9, count: 0, allowed() { return mech.maxEnergy > 0.99 }, requires: "max energy >= 1", effect() { // mech.maxEnergy += 0.5 // mech.energy += 0.5 tech.bonusEnergy += 0.5 mech.setMaxEnergy() }, remove() { tech.bonusEnergy = 0; mech.setMaxEnergy() } }, { name: "energy conservation", description: "6% of damage done recovered as energy", maxCount: 9, count: 0, allowed() { return tech.damageFromTech() > 1 }, requires: "some increased damage", effect() { tech.energySiphon += 0.06; }, remove() { tech.energySiphon = 0; } }, { name: "waste energy recovery", description: "if a mob has died in the last 5 seconds
regen 5% of max energy every second", maxCount: 1, count: 0, allowed() { return mech.maxEnergy > 0.99 }, requires: "max energy >= 1", effect() { tech.isEnergyRecovery = true; }, remove() { tech.isEnergyRecovery = false; } }, { name: "scrap recycling", description: "if a mob has died in the last 5 seconds
regain 1% of max health every second", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.isHealthRecovery = true; }, remove() { tech.isHealthRecovery = false; } }, { name: "entropy exchange", description: "heal for 1% of damage done", maxCount: 9, count: 0, allowed() { return !tech.isEnergyHealth && tech.damageFromTech() > 1 }, requires: "some increased damage, not mass-energy equivalence", effect() { tech.healthDrain += 0.01; }, remove() { tech.healthDrain = 0; } }, { name: "supersaturation", description: "increase your maximum health by 50", maxCount: 9, count: 0, allowed() { return !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.bonusHealth += 0.5 mech.addHealth(0.50) mech.setMaxHealth(); }, remove() { tech.bonusHealth = 0 mech.setMaxHealth(); } }, { name: "inductive coupling", description: "for each unused power up at the end of a level
add 4 max health (up to 44 health per level)", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.isArmorFromPowerUps = true; //tracked by tech.armorFromPowerUps }, remove() { tech.isArmorFromPowerUps = false; // tech.armorFromPowerUps = 0; //this is now reset in tech.setupAllTech(); mech.setMaxHealth(); } }, { name: "transceiver chip", description: "unused power ups at the end of each level
are still activated (selections are random)", maxCount: 1, count: 0, allowed() { return tech.isArmorFromPowerUps }, requires: "inductive coupling", effect() { tech.isEndLevelPowerUp = true; }, remove() { tech.isEndLevelPowerUp = false; } }, { name: "negentropy", description: `at the start of each level
spawn a heal for every 50 missing health`, maxCount: 1, count: 0, allowed() { return mech.maxHealth > 1 || tech.isArmorFromPowerUps }, requires: "increased max health", effect() { tech.isHealLowHealth = true; }, remove() { tech.isHealLowHealth = false; } }, { name: "adiabatic healing", description: "heal power ups are 100% more effective", maxCount: 3, count: 0, allowed() { return (mech.health < 0.7 || build.isCustomSelection) && !tech.isEnergyHealth }, requires: "not mass-energy equivalence", effect() { tech.largerHeals++; }, remove() { tech.largerHeals = 1; } }, { name: "anthropic principle", nameInfo: "", addNameInfo() { setTimeout(function() { powerUps.reroll.changeRerolls(0) }, 1000); }, description: "consume a reroll to avoid dying once a level
and spawn 6 heal power ups", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls > 0 || build.isCustomSelection }, requires: "at least 1 reroll", effect() { tech.isDeathAvoid = true; tech.isDeathAvoidedThisLevel = false; setTimeout(function() { powerUps.reroll.changeRerolls(0) }, 1000); }, remove() { tech.isDeathAvoid = false; } }, { name: "bubble fusion", description: "after destroying a mob's shield
spawn 1-2 heals, ammo, or rerolls", maxCount: 1, count: 0, allowed() { return true }, requires: "", effect() { tech.isShieldAmmo = true; }, remove() { tech.isShieldAmmo = false; } }, { name: "Bayesian statistics", description: "20% chance to duplicate spawned power ups
after a collision, eject 1 tech", maxCount: 1, count: 0, allowed() { return tech.duplicationChance() < 1 }, requires: "below 100% duplication chance", effect: () => { tech.isBayesian = true simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw }, remove() { tech.isBayesian = false if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal } }, { name: "stimulated emission", description: "6% chance to duplicate spawned power ups", maxCount: 9, count: 0, allowed() { return tech.duplicationChance() < 1 }, requires: "below 100% duplication chance", effect() { tech.duplicateChance += 0.06 simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw }, remove() { tech.duplicateChance = 0 if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal } }, { name: "futures exchange", description: "clicking × to cancel a field, tech, or gun
increases power up duplication chance by 4%", maxCount: 1, count: 0, allowed() { return tech.duplicationChance() < 1 && !tech.isDeterminism }, requires: "below 100% duplication chance, not determinism", effect() { tech.isCancelDuplication = true tech.cancelCount = 0 simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw }, remove() { tech.isCancelDuplication = false tech.cancelCount = 0 if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal } }, { name: "commodities exchange", description: "clicking × to cancel a field, tech, or gun
spawns 6 heals, ammo, or rerolls", maxCount: 1, count: 0, allowed() { return tech.duplicationChance() > 0 && !tech.isDeterminism }, requires: "a chance to duplicate power ups, not determinism", effect() { tech.isCancelRerolls = true }, remove() { tech.isCancelRerolls = false } }, { name: "exchange symmetry", description: "convert 1 a random tech into 3 new guns
recursive tech lose all stacks", maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return (tech.totalCount > 3) && !tech.isSuperDeterminism }, requires: "at least 1 tech, a chance to duplicate power ups", effect: () => { 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) } const choose = have[Math.floor(Math.random() * have.length)] simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); } powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); 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(); }, remove() {} }, { name: "monte carlo experiment", description: "spawn 2 tech
remove 1 random tech", maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return (tech.totalCount > 3) && !tech.isSuperDeterminism && tech.duplicationChance() > 0 }, requires: "at least 1 tech, a chance to duplicate power ups", effect: () => { 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) } const choose = have[Math.floor(Math.random() * have.length)] simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`) for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); } powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); 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(); }, remove() {} }, { name: "strange attractor", description: `use 2 rerolls to spawn 1 tech
with double your duplication chance`, maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return !tech.isSuperDeterminism && tech.duplicationChance() > 0 && powerUps.reroll.rerolls > 1 }, requires: "at least 1 tech and 1 reroll, a chance to duplicate power ups", effect: () => { powerUps.reroll.changeRerolls(-2) simulation.makeTextLog(`mech.rerolls -= 2
${powerUps.reroll.rerolls}`) const chanceStore = tech.duplicateChance tech.duplicateChance = (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.04 + mech.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); tech.duplicateChance = chanceStore }, remove() {} }, { name: "entanglement", nameInfo: "", addNameInfo() { setTimeout(function() { simulation.boldActiveGunHUD(); }, 1000); }, description: "while your first gun is equipped
reduce harm by 13% for each of your guns", maxCount: 1, count: 0, allowed() { return b.inventory.length > 1 && !tech.isEnergyHealth }, requires: "at least 2 guns", effect() { tech.isEntanglement = true setTimeout(function() { simulation.boldActiveGunHUD(); }, 1000); }, remove() { tech.isEntanglement = false; } }, { name: "arsenal", description: "increase damage by 7%
for each gun in your inventory", maxCount: 1, count: 0, allowed() { return b.inventory.length > 1 }, requires: "at least 2 guns", effect() { tech.isDamageForGuns = true; }, remove() { tech.isDamageForGuns = false; } }, { name: "generalist", description: "spawn 5 guns, but you can't switch guns
guns cycle automatically with each new level", maxCount: 1, count: 0, isNonRefundable: true, allowed() { return tech.isDamageForGuns }, requires: "arsenal", effect() { tech.isGunCycle = true; for (let i = 0; i < 5; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); } }, remove() { tech.isGunCycle = false; } }, { name: "logistics", description: "ammo power ups give 200% ammo
but ammo is only added to your current gun", maxCount: 1, count: 0, allowed() { return !tech.isEnergyNoAmmo }, requires: "not exciton-lattice", effect() { tech.isAmmoForGun = true; }, remove() { tech.isAmmoForGun = false; } }, { name: "supply chain", description: "double your current ammo for all guns", maxCount: 9, count: 0, isNonRefundable: true, allowed() { return tech.isAmmoForGun }, requires: "logistics", 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(); }, remove() {} }, { name: "catabolism", description: "when you fire while out of ammo
gain 3 ammo, but lose 5 health", maxCount: 1, count: 0, allowed() { return !tech.isEnergyHealth && !tech.isEnergyNoAmmo }, requires: "not mass-energy equivalence
not exciton-lattice", effect: () => { tech.isAmmoFromHealth = true; }, remove() { tech.isAmmoFromHealth = false; } }, { name: "desublimated ammunition", description: "use 50% less ammo when crouching", maxCount: 1, count: 0, allowed() { return true }, requires: "", effect() { tech.isCrouchAmmo = true }, remove() { tech.isCrouchAmmo = false; } }, { name: "gun turret", description: "reduce harm by 50% when crouching", maxCount: 1, count: 0, allowed() { return tech.isCrouchAmmo && !tech.isEnergyHealth }, requires: "desublimated ammunition
not mass-energy equivalence", effect() { tech.isTurret = true }, remove() { tech.isTurret = false; } }, { name: "cardinality", description: "tech, fields, and guns have 5 choices", maxCount: 1, count: 0, allowed() { return !tech.isDeterminism }, requires: "not determinism", effect: () => { tech.isExtraChoice = true; }, remove() { tech.isExtraChoice = false; } }, { name: "determinism", description: "spawn 5 tech
tech, fields, and guns have only 1 choice", maxCount: 1, count: 0, isNonRefundable: true, allowed() { return !tech.isExtraChoice && !tech.isCancelDuplication && !tech.isCancelRerolls }, requires: "not cardinality, not futures or commodities exchanges", effect: () => { tech.isDeterminism = true; for (let i = 0; i < 5; i++) { //if you change the six also change it in Born rule powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); } }, remove() { tech.isDeterminism = false; } }, { name: "superdeterminism", description: "spawn 7 tech
rerolls, guns, and fields no longer spawn", maxCount: 1, count: 0, isNonRefundable: true, allowed() { return tech.isDeterminism && !tech.manyWorlds }, requires: "determinism", effect: () => { tech.isSuperDeterminism = true; for (let i = 0; i < 7; i++) { //if you change the six also change it in Born rule powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); } }, remove() { tech.isSuperDeterminism = false; } }, { name: "many-worlds", description: "after choosing a field, tech, or gun
if you have no rerolls spawn 2", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls === 0 && !tech.isSuperDeterminism && !tech.isRerollHaste }, requires: "not superdeterminism or Ψ(t) collapse
no rerolls", effect: () => { tech.manyWorlds = true; }, remove() { tech.manyWorlds = false; } }, { name: "renormalization", description: "consuming a reroll for any purpose
has a 37% chance to spawn a reroll", maxCount: 1, count: 0, allowed() { return (powerUps.reroll.rerolls > 1 || build.isCustomSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste }, requires: "not superdeterminism or Ψ(t) collapse
at least 2 rerolls", effect() { tech.renormalization = true; }, remove() { tech.renormalization = false; } }, { name: "erase", description: "rerolled or canceled tech will not reoccur
spawn 4 rerolls", maxCount: 1, count: 0, allowed() { return (powerUps.reroll.rerolls > 2 || build.isCustomSelection) && !tech.isDeterminism }, requires: "not determinism, at least 3 rerolls", effect() { tech.isBanish = true for (let i = 0; i < 4; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false); } }, remove() { tech.isBanish = false powerUps.tech.banishLog = [] //reset banish log } }, { name: "quantum immortality", description: "after dying, continue in an alternate reality
spawn 4 rerolls", maxCount: 1, count: 0, allowed() { return powerUps.reroll.rerolls > 1 || build.isCustomSelection }, requires: "at least 2 rerolls", effect() { tech.isImmortal = true; for (let i = 0; i < 4; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false); } }, remove() { tech.isImmortal = false; } }, { name: "Born rule", description: "remove all current tech
spawn new tech to replace them", maxCount: 1, count: 0, // isNonRefundable: true, isCustomHide: true, allowed() { return (tech.totalCount > 6) }, requires: "more than 6 tech", effect: () => { //remove active bullets //to get rid of bots for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); bullet = []; let count = 0 //count tech for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups if (!tech.tech[i].isNonRefundable) count += tech.tech[i].count } if (tech.isDeterminism) count -= 3 //remove the bonus tech if (tech.isSuperDeterminism) count -= 2 //remove the bonus tech tech.setupAllTech(); // remove all tech for (let i = 0; i < count; i++) { // spawn new tech power ups powerUps.spawn(mech.pos.x, mech.pos.y, "tech"); } //have state is checked in mech.death() }, remove() {} }, { name: "perpetual rerolls", description: "find 1 reroll at the start of each level", maxCount: 1, count: 0, allowed() { return !tech.isSuperDeterminism && !tech.isPerpetualHeal && !tech.isPerpetualAmmo && !tech.isPerpetualStun }, requires: "only 1 perpetual effect, not superdeterminism", effect() { tech.isPerpetualReroll = true }, remove() { tech.isPerpetualReroll = false } }, { name: "perpetual heals", description: "find 2 heals at the start of each level", maxCount: 1, count: 0, allowed() { return !tech.isPerpetualReroll && !tech.isPerpetualAmmo && !tech.isPerpetualStun }, requires: "only 1 perpetual effect", effect() { tech.isPerpetualHeal = true }, remove() { tech.isPerpetualHeal = false } }, { name: "perpetual ammo", description: "find 2 ammo at the start of each level", maxCount: 1, count: 0, allowed() { return !tech.isPerpetualReroll && !tech.isPerpetualHeal && !tech.isPerpetualReroll && !tech.isPerpetualStun && !tech.isEnergyNoAmmo }, requires: "only 1 perpetual effect, not exciton lattice", effect() { tech.isPerpetualAmmo = true }, remove() { tech.isPerpetualAmmo = false } }, { name: "perpetual stun", description: "stun all mobs for up to 8 seconds
at the start of each level", maxCount: 1, count: 0, allowed() { return !tech.isPerpetualReroll && !tech.isPerpetualHeal && !tech.isPerpetualAmmo }, requires: "only 1 perpetual effect", effect() { tech.isPerpetualStun = true }, remove() { tech.isPerpetualStun = false } }, //************************************************** //************************************************** gun //************************************************** tech //************************************************** { name: "CPT gun", description: "adds the CPT gun to your inventory
it rewinds your health, velocity, and position", isGunTech: true, maxCount: 1, count: 0, allowed() { return (tech.totalBots() > 5 || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave") && !tech.isEnergyHealth && !tech.isRewindAvoidDeath //build.isCustomSelection || }, requires: "bots > 5, plasma torch, nano-scale, pilot wave, not mass-energy equivalence, CPT", effect() { tech.isRewindGun = true b.guns.push(b.gunRewind) b.giveGuns("CPT gun"); }, remove() { if (tech.isRewindGun) { b.removeGun("CPT gun", true) // for (let i = 0; i < b.guns.length; i++) { // if (b.guns[i].name === "CPT gun") { // b.guns[i].have = false // for (let j = 0; j < b.inventory.length; j++) { // if (b.inventory[j] === i) { // b.inventory.splice(j, 1) // break // } // } // if (b.inventory.length) { // b.activeGun = b.inventory[0]; // } else { // b.activeGun = null; // } // simulation.makeGunHUD(); // b.guns.splice(i, 1) //also remove CPT gun from gun pool array // break // } // } tech.isRewindGun = false } } }, { name: "incendiary ammunition", description: "some bullets are loaded with explosives
nail gun, shotgun, super balls, drones", isGunTech: true, maxCount: 1, count: 0, allowed() { return ((mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) || tech.haveGunCheck("drones") || tech.haveGunCheck("super balls") || tech.haveGunCheck("nail gun") || tech.haveGunCheck("shotgun")) && !tech.isIceCrystals && !tech.isNailCrit && !tech.isNailShot && !tech.isNailPoison }, requires: "drones, super balls, nail gun, shotgun", effect() { tech.isIncendiary = true }, remove() { tech.isIncendiary = false; } }, { name: "fragmentation", description: "some detonations and collisions eject nails
blocks, rail gun, grenades, missiles, shotgun slugs", isGunTech: true, maxCount: 9, count: 0, allowed() { return (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.haveGunCheck("rail gun") || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.throwChargeRate > 1 }, requires: "grenades, missiles, rail gun, shotgun slugs, or mass driver", effect() { tech.fragments++ }, remove() { tech.fragments = 0 } }, { name: "anti-shear topology", description: "some bullets last 30% longer
drones, spores, missiles, foam, wave, ice IX, neutron", isGunTech: true, maxCount: 3, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("wave beam") || tech.haveGunCheck("ice IX") || tech.isNeutronBomb }, requires: "drones, spores, missiles, foam
wave beam, ice IX, neutron bomb", effect() { tech.isBulletsLastLonger += 0.3 }, remove() { tech.isBulletsLastLonger = 1; } }, { name: "microstates", description: "increase damage by 4%
for every 10 active bullets", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isBulletsLastLonger > 1 }, requires: "Lorentzian topology", effect() { tech.isDamageFromBulletCount = true }, remove() { tech.isDamageFromBulletCount = false } }, { name: "ice crystal nucleation", description: "the nail gun uses energy to condense
unlimited freezing ice shards", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIncendiary }, requires: "nail gun, not incendiary, not powder-actuated", effect() { tech.isIceCrystals = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "nail gun") { b.guns[i].ammoPack = Infinity b.guns[i].recordedAmmo = b.guns[i].ammo b.guns[i].ammo = Infinity simulation.updateGunHUD(); break; } } }, remove() { if (tech.isIceCrystals) { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "nail gun") { b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; if (b.guns[i].recordedAmmo) b.guns[i].ammo = b.guns[i].recordedAmmo simulation.updateGunHUD(); break; } } } tech.isIceCrystals = false; } }, { name: "critical bifurcation", description: "nail gun nails do 400% more damage
when they strike near the center of a mob", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("nail gun") && !tech.isIncendiary }, requires: "nail gun, not incendiary", effect() { tech.isNailCrit = true }, remove() { tech.isNailCrit = false } }, { name: "pneumatic actuator", description: "nail gun takes 45% less time to ramp up
to it's shortest delay after firing", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("nail gun") }, requires: "nail gun", effect() { tech.nailFireRate = true }, remove() { tech.nailFireRate = false } }, { name: "powder-actuated", description: "nail gun takes no time to ramp up
nails have a 30% faster muzzle speed", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("nail gun") && tech.nailFireRate && !tech.isIceCrystals }, requires: "nail gun and pneumatic actuator", effect() { tech.nailInstantFireRate = true }, remove() { tech.nailInstantFireRate = false } }, { name: "shotgun spin-statistics", description: "immune to harm while firing the shotgun
ammo costs are doubled", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("shotgun") }, requires: "shotgun", effect() { tech.isShotgunImmune = true; //cut current ammo by 1/2 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); break; } } simulation.updateGunHUD(); 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 * 0.5 break; } } }, remove() { tech.isShotgunImmune = false; 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; break; } } } }, { name: "nailshot", description: "the shotgun fires a burst of nails", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot }, requires: "shotgun", effect() { tech.isNailShot = true; }, remove() { tech.isNailShot = false; } }, { name: "shotgun slug", description: "the shotgun fires 1 large bullet", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("shotgun") && !tech.isNailShot }, requires: "shotgun", effect() { tech.isSlugShot = true; }, remove() { tech.isSlugShot = false; } }, { name: "Newton's 3rd law", description: "the shotgun fire delay is 66% faster
recoil is greatly increased", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("shotgun") }, requires: "shotgun", effect() { tech.isShotgunRecoil = true; }, remove() { tech.isShotgunRecoil = false; } }, { name: "super duper", description: "fire 1 additional super ball", isGunTech: true, maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("super balls") && !tech.oneSuperBall }, requires: "super balls, but not the tech super ball", effect() { tech.superBallNumber++ }, remove() { tech.superBallNumber = 4; } }, { name: "super ball", description: "fire just 1 large super ball
that stuns mobs for 3 second", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("super balls") && tech.superBallNumber === 4 }, requires: "super balls, but not super duper", effect() { tech.oneSuperBall = true; }, remove() { tech.oneSuperBall = false; } }, { name: "super sized", description: `your super balls are 20% larger
increases mass and physical damage`, isGunTech: true, maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("super balls") }, requires: "super balls", effect() { tech.bulletSize += 0.15 }, remove() { tech.bulletSize = 1; } }, { name: "flechettes cartridges", description: "flechettes release three needles in each shot
ammo costs are tripled", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") }, requires: "flechettes", effect() { tech.isFlechetteMultiShot = true; //cut current ammo by 1/3 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "flechettes") { b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 3); break } } //cut ammo packs by 1/3 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "flechettes") { b.guns[i].ammoPack = Math.ceil(b.guns[i].defaultAmmoPack / 3); break } } simulation.updateGunHUD(); }, remove() { if (tech.isFlechetteMultiShot) { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "flechettes") { b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 3); break } } for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "flechettes") { b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; break } simulation.updateGunHUD(); } } tech.isFlechetteMultiShot = false; } }, { name: "6s half-life", description: "flechette needles made of plutonium-238
increase damage by 100% over 6 seconds", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") && !tech.isFastDot }, requires: "flechettes", effect() { tech.isSlowDot = true; }, remove() { tech.isSlowDot = false; } }, { name: "1/2s half-life", description: "flechette needles made of lithium-8
flechette damage occurs after 1/2 a second", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") && !tech.isSlowDot }, requires: "flechettes", effect() { tech.isFastDot = true; }, remove() { tech.isFastDot = false; } }, { name: "supercritical fission", description: "flechettes can explode
if they strike mobs near their center", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") && !tech.pierce }, requires: "flechettes and not piercing needles", effect() { tech.isFlechetteExplode = true }, remove() { tech.isFlechetteExplode = false } }, { name: "radioactive contamination", description: "after a mob or shield dies,
leftover radiation spreads to a nearby mob", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") || tech.isNailPoison || tech.isHeavyWater || tech.isWormholeDamage || tech.isNeutronBomb }, requires: "radiation damage source", effect() { tech.isRadioactive = true }, remove() { tech.isRadioactive = false } }, { name: "piercing needles", description: "needles penetrate mobs and blocks
potentially hitting multiple targets", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("flechettes") && !tech.isFlechetteExplode }, requires: "flechettes and not supercritical fission", effect() { tech.pierce = true; }, remove() { tech.pierce = false; } }, { name: "wave packet", description: "wave beam emits two oscillating particles
decrease wave damage by 20%", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("wave beam") && !tech.isExtruder }, requires: "wave beam", effect() { tech.waveHelix = 2 }, remove() { tech.waveHelix = 1 } }, { name: "phase velocity", description: "the wave beam propagates faster in solids", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("wave beam") && !tech.isWaveReflect && !tech.isExtruder }, requires: "wave beam", effect() { tech.waveSpeedMap = 3 //needs to be 3 to stop bound state require check tech.waveSpeedBody = 1.9 }, remove() { tech.waveSpeedMap = 0.08 tech.waveSpeedBody = 0.25 } }, { name: "bound state", description: "wave beam bullets last 5x longer
bullets are bound to a region around player", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("wave beam") && tech.waveSpeedMap !== 3 && !tech.isExtruder }, requires: "wave beam", effect() { tech.isWaveReflect = true }, remove() { tech.isWaveReflect = false } }, { name: "cruise missile", description: "missiles travel 50% slower,
but have a 50% larger explosive payload", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("missiles") || tech.isMissileField }, requires: "missiles", effect() { tech.missileSize = true }, remove() { tech.missileSize = false } }, { name: "MIRV", description: "launch +1 missile at a time
decrease size and fire rate by 10%", isGunTech: true, maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("missiles") }, requires: "missiles", effect() { tech.missileCount++; }, remove() { tech.missileCount = 1; } }, { name: "missile-bot", description: "a bot fires missiles at far away targets", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("missiles") }, requires: "missiles", effect() { tech.missileBotCount++; b.missileBot(); }, remove() { tech.missileBotCount = 0; } }, { name: "rocket-propelled grenade", description: "grenades rapidly accelerate forward
map collisions trigger an explosion", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("grenades") }, requires: "grenades", effect() { tech.isRPG = true; b.setGrenadeMode() }, remove() { tech.isRPG = false; b.setGrenadeMode() } }, { name: "vacuum bomb", description: "grenades fire slower, explode bigger
and, suck everything towards them", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("grenades") && !tech.isNeutronBomb }, requires: "grenades, not neutron bomb", effect() { tech.isVacuumBomb = true; b.setGrenadeMode() }, remove() { tech.isVacuumBomb = false; b.setGrenadeMode() } }, { name: "neutron bomb", description: "grenades are irradiated with Cf-252
does damage, harm, and drains energy", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("grenades") && !tech.fragments && !tech.isVacuumBomb }, requires: "grenades, not fragmentation", effect() { tech.isNeutronBomb = true; b.setGrenadeMode() }, remove() { tech.isNeutronBomb = false; b.setGrenadeMode() } }, { name: "water shielding", description: "increase neutron bomb's range by 20%
player is immune to its harmful effects", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isNeutronBomb }, requires: "neutron bomb", effect() { tech.isNeutronImmune = true }, remove() { tech.isNeutronImmune = false } }, { name: "vacuum permittivity", description: "increase neutron bomb's range by 20%
objects in range of the bomb are slowed", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isNeutronBomb }, requires: "neutron bomb", effect() { tech.isNeutronSlow = true }, remove() { tech.isNeutronSlow = false } }, { name: "laser-mines", description: "mines hover in place until mobs get in range
mines use energy to emit 3 unaimed lasers", isGunTech: true, maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("mine") || tech.isMineDrop) && !tech.isMineSentry }, requires: "mines, not sentry", effect() { tech.isLaserMine = true; }, remove() { tech.isLaserMine = false; } }, { name: "mine reclamation", description: "retrieve ammo from all undetonated mines
and 20% of mines after detonation", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("mine") && !tech.isMineSentry }, requires: "mine, not sentry", effect() { tech.isMineAmmoBack = true; }, remove() { tech.isMineAmmoBack = false; } }, { name: "sentry", description: "mines target mobs with nails over time
mines last about 12 seconds", isGunTech: true, maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("mine") && !tech.isMineAmmoBack && !tech.isLaserMine) || tech.isMineDrop }, requires: "mine, not mine reclamation, not laser-mines", effect() { tech.isMineSentry = true; }, remove() { tech.isMineSentry = false; } }, { name: "irradiated nails", description: "nails are made with a cobalt-60 alloy
85% radioactive damage over 2 seconds", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + (tech.haveGunCheck("nail gun") && !tech.isIncendiary)) * 2 > 1 }, requires: "nails", effect() { tech.isNailPoison = true; }, remove() { tech.isNailPoison = false; } }, { name: "railroad ties", description: "nails are 40% larger
increases physical damage by about 20%", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + (tech.haveGunCheck("nail gun") && !tech.isIncendiary)) * 2 > 1 }, requires: "nails", effect() { tech.biggerNails += 0.33 }, remove() { tech.biggerNails = 1 } }, { name: "mycelial fragmentation", description: "sporangium release an extra spore
once a second during their growth phase", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("spores") }, requires: "spores", effect() { tech.isSporeGrowth = true }, remove() { tech.isSporeGrowth = false } }, { name: "tinsellated flagella", description: "sporangium release 2 more spores
spores accelerate 50% faster", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField }, requires: "spores", effect() { tech.isFastSpores = true }, remove() { tech.isFastSpores = false } }, { name: "cryodesiccation", description: "sporangium release 2 more spores
spores freeze mobs for 1 second", //
spores do 1/3 damage isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField }, requires: "spores", effect() { tech.isSporeFreeze = true }, remove() { tech.isSporeFreeze = false } }, { name: "diplochory", description: "spores use the player for dispersal
until they locate a viable host", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField }, requires: "spores", effect() { tech.isSporeFollow = true }, remove() { tech.isSporeFollow = false } }, { name: "mutualism", description: "increase spore damage by 100%
spores borrow 0.5 health until they die", isGunTech: true, maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth }, requires: "spores", effect() { tech.isMutualism = true }, remove() { tech.isMutualism = false } }, { name: "brushless motor", description: "drones accelerate 50% faster", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("drones") || (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) }, requires: "drones", effect() { tech.isFastDrones = true }, remove() { tech.isFastDrones = false } }, { name: "harvester", description: "after a drone picks up a power up,
it's larger, faster, and very durable", isGunTech: true, maxCount: 1, count: 0, allowed() { return !tech.isArmorFromPowerUps && (tech.haveGunCheck("drones") || (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) }, requires: "drones", effect() { tech.isDroneGrab = true }, remove() { tech.isDroneGrab = false } }, { name: "superfluidity", description: "freeze effects apply to mobs near it's target", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("ice IX") || tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField }, requires: "a freeze effect", effect() { tech.isAoESlow = true }, remove() { tech.isAoESlow = false } }, { name: "heavy water", description: "ice IX is synthesized with an extra neutron
does radioactive damage over 5 seconds", isGunTech: true, maxCount: 1, count: 0, allowed() { return (tech.haveGunCheck("ice IX") || tech.isIceField) && !tech.iceEnergy }, requires: "ice IX", effect() { tech.isHeavyWater = true }, remove() { tech.isHeavyWater = false; } }, { name: "thermoelectric effect", description: "killing mobs with ice IX gives 4 health
and 80 energy", isGunTech: true, maxCount: 9, count: 0, allowed() { return (tech.haveGunCheck("ice IX") || tech.isIceField) && !tech.isHeavyWater }, requires: "ice IX", effect() { tech.iceEnergy++ }, remove() { tech.iceEnergy = 0; } }, { name: "necrophoresis", description: "foam bubbles grow and split into 3 copies
when the mob they are stuck to dies", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("foam") || tech.foamBotCount > 1 }, requires: "foam", effect() { tech.isFoamGrowOnDeath = true }, remove() { tech.isFoamGrowOnDeath = false; } }, { name: "colloidal foam", description: "foam bubbles dissipate 40% faster
increase foam damage per second by 300%", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("foam") || tech.foamBotCount > 2 }, requires: "foam", effect() { tech.isFastFoam = true }, remove() { tech.isFastFoam = false; } }, { name: "foam fractionation", description: "foam gun bubbles are 100% larger
when you have below 200 ammo", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("foam") || tech.foamBotCount > 2 }, requires: "foam", effect() { tech.isAmmoFoamSize = true }, remove() { tech.isAmmoFoamSize = false; } }, // { // name: "foam size", // description: "increase foam damage by 200%
foam dissipates 50% faster", // maxCount: 1, // count: 0, // allowed() { // return tech.haveGunCheck("foam") || tech.foamBotCount > 2 // }, // requires: "foam", // effect() { // tech.isLargeFoam = true // }, // remove() { // tech.isLargeFoam = false; // } // }, // { // name: "frame-dragging", // description: "slow time while charging the rail gun
charging no longer drains energy", // maxCount: 1, // count: 0, // allowed() { // return simulation.fpsCapDefault > 45 && tech.haveGunCheck("rail gun") && !tech.isSlowFPS && !tech.isCapacitor // }, // requires: "rail gun and FPS above 45", // effect() { // tech.isRailTimeSlow = true; // }, // remove() { // tech.isRailTimeSlow = false; // simulation.fpsCap = simulation.fpsCapDefault // simulation.fpsInterval = 1000 / simulation.fpsCap; // } // }, { name: "half-wave rectifier", description: "charging the rail gun gives you energy
instead of draining it", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("rail gun") }, requires: "rail gun", effect() { tech.isRailEnergyGain = true; }, remove() { tech.isRailEnergyGain = false; } }, { name: "dielectric polarization", description: "firing the rail gun damages nearby mobs", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("rail gun") }, requires: "rail gun", effect() { tech.isRailAreaDamage = true; }, remove() { tech.isRailAreaDamage = false; } }, { name: "capacitor bank", description: "the rail gun no longer takes time to charge
rail gun rods are 66% less massive", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("rail gun") }, requires: "rail gun", effect() { tech.isCapacitor = true; }, remove() { tech.isCapacitor = false; } }, { name: "laser diodes", description: "all lasers drain 37% less energy
effects laser-gun, laser-bot, and laser-mines", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("laser") || tech.laserBotCount > 1 || tech.isLaserMine }, requires: "laser", effect() { tech.isLaserDiode = 0.63; //100%-37% }, remove() { tech.isLaserDiode = 1; } }, { name: "specular reflection", description: "increase damage and energy drain by 50%
and +1 reflection for all lasers (gun, bot, mine)", isGunTech: true, maxCount: 9, count: 0, allowed() { return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser }, requires: "laser, not wide beam", effect() { tech.laserReflections++; tech.laserDamage += 0.08; //base is 0.12 tech.laserFieldDrain += 0.0008 //base is 0.002 }, remove() { tech.laserReflections = 2; tech.laserDamage = 0.16; tech.laserFieldDrain = 0.0016; } }, { name: "diffraction grating", description: `your laser gains 2 diverging beams
decrease individual beam damage by 10%`, isGunTech: true, maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("laser") && !tech.isWideLaser && !tech.isPulseAim && !tech.historyLaser }, requires: "laser, not specular reflection", effect() { tech.beamSplitter++ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } }, remove() { tech.beamSplitter = 0 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } } }, { name: "diffuse beam", description: "laser beam is wider and doesn't reflect
increase full beam damage by 175%", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser }, requires: "laser, not specular reflection
not diffraction grating", effect() { if (tech.wideLaser === 0) tech.wideLaser = 3 tech.isWideLaser = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } }, remove() { tech.wideLaser = 0 tech.isWideLaser = false; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } } }, { name: "output coupler", description: "widen diffuse laser beam by 40%
increase full beam damage by 40%", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("laser") && tech.isWideLaser }, requires: "laser, not specular reflection
not diffraction grating", effect() { tech.wideLaser = 4 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } }, remove() { if (tech.isWideLaser) { tech.wideLaser = 3 } else { tech.wideLaser = 0 } for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } } }, { name: "slow light propagation", description: "laser beam is spread into your recent past
increase total beam damage by 300%", isGunTech: true, maxCount: 9, count: 0, allowed() { return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser }, requires: "laser, not specular reflection
not diffraction grating", effect() { // this.description = `add 5 more laser beams into into your past` tech.historyLaser++ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } }, remove() { // this.description = "laser beam is spread into your recent past
increase total beam damage by 300%" tech.historyLaser = 0 for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } } }, { name: "pulse", description: "convert 25% of your energy into a pulsed laser
that instantly initiates a fusion explosion", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && !tech.historyLaser }, requires: "laser, not specular reflection, not diffuse", effect() { tech.isPulseLaser = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } }, remove() { tech.isPulseLaser = false; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod() } } }, { name: "shock wave", description: "mobs caught in pulse's explosion are stunned
for up to 2 seconds", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isPulseLaser }, requires: "pulse", effect() { tech.isPulseStun = true; }, remove() { tech.isPulseStun = false; } }, { name: "neocognitron", description: "pulse automatically aims at a nearby mob
50% decreased delay after firing", isGunTech: true, maxCount: 1, count: 0, allowed() { return tech.isPulseLaser && !tech.beamSplitter }, requires: "pulse", effect() { tech.isPulseAim = true; }, remove() { tech.isPulseAim = false; } }, //************************************************** //************************************************** field //************************************************** tech //************************************************** { name: "bremsstrahlung radiation", description: "blocking with standing wave harmonics
does damage to mobs", isFieldTech: true, maxCount: 9, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "standing wave harmonics" }, requires: "standing wave harmonics", effect() { tech.blockDmg += 0.75 //if you change this value also update the for loop in the electricity graphics in mech.pushMass }, remove() { tech.blockDmg = 0; } }, { name: "frequency resonance", description: "standing wave harmonics shield is retuned
increase size and blocking efficiency by 40%", isFieldTech: true, maxCount: 9, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "standing wave harmonics" }, requires: "standing wave harmonics", effect() { mech.fieldRange += 175 * 0.2 mech.fieldShieldingScale *= 0.55 }, remove() { mech.fieldRange = 175; mech.fieldShieldingScale = 1; } }, { name: "flux pinning", description: "blocking with perfect diamagnetism
stuns mobs for +1 second", isFieldTech: true, maxCount: 9, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "perfect diamagnetism" }, requires: "perfect diamagnetism", effect() { tech.isStunField += 60; }, remove() { tech.isStunField = 0; } }, { name: "eddy current brake", description: "your stored energy projects a field that
limits the top speed of mobs", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "perfect diamagnetism" }, requires: "perfect diamagnetism", effect() { tech.isPerfectBrake = true; }, remove() { tech.isPerfectBrake = false; } }, { name: "fracture analysis", description: "bullet impacts do 400% damage
to stunned mobs", isFieldTech: true, maxCount: 1, count: 0, allowed() { return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isPerpetualStun }, requires: "a stun effect", effect() { tech.isCrit = true; }, remove() { tech.isCrit = false; } }, { name: "pair production", description: "picking up a power up gives you 250 energy", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" }, requires: "nano-scale manufacturing", effect: () => { tech.isMassEnergy = true // used in mech.grabPowerUp mech.energy += 3 }, remove() { tech.isMassEnergy = false; } }, { name: "bot manufacturing", description: "use nano-scale manufacturing
to build 3 random bots", isFieldTech: true, maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" }, requires: "nano-scale manufacturing", effect: () => { mech.energy = 0.01; b.randomBot() b.randomBot() b.randomBot() }, remove() {} }, { name: "bot prototypes", description: "use nano-scale manufacturing to upgrade
all bots of a random type and build 2 of that bot", isFieldTech: true, maxCount: 1, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isNailBotUpgrade && tech.isFoamBotUpgrade && tech.isBoomBotUpgrade && tech.isLaserBotUpgrade && tech.isOrbitBotUpgrade) }, requires: "nano-scale manufacturing", effect: () => { mech.energy = 0.01; //fill array of available bots const notUpgradedBots = [] if (!tech.isNailBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("nail-bot upgrade") tech.setTechoNonRefundable("nail-bot upgrade") for (let i = 0; i < 2; i++) { b.nailBot() tech.nailBotCount++; } }) if (!tech.isFoamBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("foam-bot upgrade") tech.setTechoNonRefundable("foam-bot upgrade") for (let i = 0; i < 2; i++) { b.foamBot() tech.foamBotCount++; } }) if (!tech.isBoomBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("boom-bot upgrade") tech.setTechoNonRefundable("boom-bot upgrade") for (let i = 0; i < 2; i++) { b.boomBot() tech.boomBotCount++; } }) if (!tech.isLaserBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("laser-bot upgrade") tech.setTechoNonRefundable("laser-bot upgrade") for (let i = 0; i < 2; i++) { b.laserBot() tech.laserBotCount++; } }) if (!tech.isOrbitBotUpgrade) notUpgradedBots.push(() => { tech.giveTech("orbital-bot upgrade") tech.setTechoNonRefundable("orbital-bot upgrade") for (let i = 0; i < 2; i++) { b.orbitBot() tech.orbitBotCount++; } }) //choose random function from the array and run it notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() }, remove() {} }, { name: "mycelium manufacturing", description: "nano-scale manufacturing is repurposed
excess energy used to grow spores", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab) }, requires: "nano-scale manufacturing", effect() { tech.isSporeField = true; }, remove() { tech.isSporeField = false; } }, { name: "missile manufacturing", description: "nano-scale manufacturing is repurposed
excess energy used to construct missiles", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab) }, requires: "nano-scale manufacturing", effect() { tech.isMissileField = true; }, remove() { tech.isMissileField = false; } }, { name: "ice IX manufacturing", description: "nano-scale manufacturing is repurposed
excess energy used to synthesize ice IX", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab) }, requires: "nano-scale manufacturing", effect() { tech.isIceField = true; }, remove() { tech.isIceField = false; } }, { name: "degenerate matter", description: "reduce harm by 40%
while negative mass field is active", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" }, requires: "negative mass field", effect() { tech.isHarmReduce = true }, remove() { tech.isHarmReduce = false; } }, { name: "annihilation", description: "after touching mobs, they are annihilated
drains 33% of maximum energy", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" }, requires: "negative mass field", effect() { tech.isAnnihilation = true }, remove() { tech.isAnnihilation = false; } }, { name: "Bose Einstein condensate", description: "mobs inside your field are frozen
pilot wave, negative mass, time dilation", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" || mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" || mech.fieldUpgrades[mech.fieldMode].name === "time dilation field" }, requires: "pilot wave, negative mass field, time dilation field", effect() { tech.isFreezeMobs = true }, remove() { tech.isFreezeMobs = false } }, // { // name: "thermal reservoir", // description: "increase your plasma damage by 100%
plasma temporarily lowers health not energy", // isFieldTech: true, // maxCount: 1, // count: 0, // allowed() { // return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" && !tech.isEnergyHealth // }, // requires: "plasma torch, not mass-energy equivalence", // effect() { // tech.isPlasmaRange += 0.27; // }, // remove() { // tech.isPlasmaRange = 1; // } // }, { name: "plasma jet", description: "increase plasma torch's range by 27%", isFieldTech: true, maxCount: 9, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" }, requires: "plasma torch", effect() { tech.isPlasmaRange += 0.27; }, remove() { tech.isPlasmaRange = 1; } }, { name: "plasma-bot", description: "a bot uses energy to emit plasma
that damages and pushes mobs", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" }, requires: "plasma torch", effect() { tech.plasmaBotCount++; b.plasmaBot(); }, remove() { tech.plasmaBotCount = 0; } }, { name: "micro-extruder", description: "plasma torch extrudes a thin hot wire
increases damage, and energy drain", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" }, requires: "plasma torch", effect() { tech.isExtruder = true; }, remove() { tech.isExtruder = false; } }, { name: "timelike world line", description: "time dilation doubles your relative time rate
and makes you immune to harm", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "time dilation field" }, requires: "time dilation field", effect() { tech.isTimeSkip = true; b.setFireCD(); }, remove() { tech.isTimeSkip = false; b.setFireCD(); } }, { name: "Lorentz transformation", description: "permanently increase your relative time rate
move, jump, and shoot 40% faster", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "time dilation field" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" }, requires: "time dilation field", effect() { tech.fastTime = 1.40; tech.fastTimeJump = 1.11; mech.setMovement(); b.setFireCD(); }, remove() { tech.fastTime = 1; tech.fastTimeJump = 1; mech.setMovement(); b.setFireCD(); } }, { name: "time crystals", description: "quadruple your default energy regeneration", isFieldTech: true, maxCount: 1, count: 0, allowed() { return (mech.fieldUpgrades[mech.fieldMode].name === "time dilation field" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave") && tech.energyRegen !== 0; }, requires: "time dilation field", effect: () => { tech.energyRegen = 0.004; mech.fieldRegen = tech.energyRegen; }, remove() { tech.energyRegen = 0.001; mech.fieldRegen = tech.energyRegen; } }, { name: "phase decoherence", description: "become intangible while cloaked
but, passing through mobs drains your energy", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "metamaterial cloaking" }, requires: "metamaterial cloaking", effect() { tech.isIntangible = true; }, remove() { tech.isIntangible = false; } }, { name: "dazzler", description: "decloaking stuns nearby mobs
drains 30% of your stored energy", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "metamaterial cloaking" }, requires: "metamaterial cloaking", effect() { tech.isCloakStun = true; }, remove() { tech.isCloakStun = false; } }, { name: "discrete optimization", description: "increase damage by 50%
50% increased delay after firing", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "metamaterial cloaking" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" }, requires: "metamaterial cloaking", effect() { tech.aimDamage = 1.5 b.setFireCD(); }, remove() { tech.aimDamage = 1 b.setFireCD(); } }, { name: "cosmic string", description: "stun and do radioactive damage to mobs
if you tunnel through them with a wormhole", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" }, requires: "wormhole", effect() { tech.isWormholeDamage = true }, remove() { tech.isWormholeDamage = false } }, { name: "Penrose process", description: "after a block falls into a wormhole
you gain 50 energy", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" }, requires: "wormhole", effect() { tech.isWormholeEnergy = true }, remove() { tech.isWormholeEnergy = false } }, { name: "transdimensional spores", description: "when blocks fall into a wormhole
higher dimension spores are summoned", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" }, requires: "wormhole", effect() { tech.isWormSpores = true }, remove() { tech.isWormSpores = false } }, { name: "traversable geodesics", description: "your bullets can traverse wormholes
spawn a gun and ammo", isFieldTech: true, maxCount: 1, count: 0, allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" }, requires: "wormhole", effect() { tech.isWormBullets = true powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); powerUps.spawn(mech.pos.x, mech.pos.y, "ammo"); }, remove() { tech.isWormBullets = false } }, { name: "heals", description: "spawn 6 heals", maxCount: 9, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return true }, requires: "", effect() { for (let i = 0; i < 6; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "heal"); } this.count-- }, remove() {} }, { name: "ammo", description: "spawn 6 ammo", maxCount: 9, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return !tech.isEnergyNoAmmo }, requires: "not exciton lattice", effect() { for (let i = 0; i < 6; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "ammo"); } this.count-- }, remove() {} }, { name: "rerolls", description: "spawn 4 rerolls", maxCount: 9, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return !tech.isSuperDeterminism }, requires: "not superdeterminism", effect() { for (let i = 0; i < 4; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "reroll"); } this.count-- }, remove() {} }, { name: "gun", description: "spawn a gun", maxCount: 9, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return !tech.isSuperDeterminism }, requires: "not superdeterminism", effect() { powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); this.count-- }, remove() {} }, { name: "field", description: "spawn a field", maxCount: 9, count: 0, isNonRefundable: true, isCustomHide: true, allowed() { return !tech.isSuperDeterminism }, requires: "not superdeterminism", effect() { powerUps.spawn(mech.pos.x, mech.pos.y, "field"); this.count-- }, remove() {} }, ], //variables use for gun tech upgrades fireRate: null, bulletSize: null, energySiphon: null, healthDrain: null, isCrouchAmmo: null, isBulletsLastLonger: null, isImmortal: null, sporesOnDeath: null, isImmuneExplosion: null, isExplodeMob: null, isDroneOnDamage: null, isAcidDmg: null, isAnnihilation: null, largerHeals: null, squirrelFx: null, isCrit: null, isLowHealthDmg: null, isFarAwayDmg: null, isEntanglement: null, isMassEnergy: null, isExtraChoice: null, laserBotCount: null, nailBotCount: null, foamBotCount: null, boomBotCount: null, plasmaBotCount: null, missileBotCount: null, orbitBotCount: null, collisionImmuneCycles: null, blockDmg: null, isPiezo: null, isFastDrones: null, isFastSpores: null, superBallNumber: null, oneSuperBall: null, laserReflections: null, laserDamage: null, laserFieldDrain: null, isAmmoFromHealth: null, mobSpawnWithHealth: null, isEnergyRecovery: null, isHealthRecovery: null, isEnergyLoss: null, isDeathAvoid: null, isDeathAvoidedThisLevel: null, waveSpeedMap: null, waveSpeedBody: null, isSporeField: null, isMissileField: null, isIceField: null, isFlechetteMultiShot: null, isMineAmmoBack: null, isPlasmaRange: null, isFreezeMobs: null, isIceCrystals: null, throwChargeRate: null, isBlockStun: null, isStunField: null, isHarmDamage: null, isHeavyWater: null, energyRegen: null, isVacuumBomb: null, renormalization: null, fragments: null, isEnergyDamage: null, isBotSpawner: null, waveHelix: null, isSporeFollow: null, isNailPoison: null, isEnergyHealth: null, isPulseStun: null, restDamage: null, isRPG: null, missileCount: null, isDeterminism: null, isSuperDeterminism: null, isHarmReduce: null, nailsDeathMob: null, isSlowFPS: null, isNeutronStun: null, manyWorlds: null, isDamageFromBulletCount: null, isLaserDiode: null, isNailShot: null, slowFire: null, fastTime: null, squirrelJump: null, fastTimeJump: null, isFastDot: null, isArmorFromPowerUps: null, isAmmoForGun: null, isRapidPulse: null, isPulseAim: null, isSporeFreeze: null, isShotgunRecoil: null, isHealLowHealth: null, isAoESlow: null, isHarmArmor: null, isTurret: null, isRerollDamage: null, isHarmFreeze: null, isBotArmor: null, isRerollHaste: null, rerollHaste: null, isMineDrop: null, isRerollBots: null, isRailTimeSlow: null, isNailBotUpgrade: null, isFoamBotUpgrade: null, isLaserBotUpgrade: null, isBoomBotUpgrade: null, isOrbitBotUpgrade: null, isDroneGrab: null, isOneGun: null, isDamageForGuns: null, isGunCycle: null, isFastFoam: null, isSporeGrowth: null, isBayesian: null, nailGun: null, nailInstantFireRate: null, isCapacitor: null, isEnergyNoAmmo: null, isFreezeHarmImmune: null, isSmallExplosion: null, isExplosionHarm: null, armorFromPowerUps: null, bonusHealth: null, isIntangible: null, isCloakStun: null, bonusEnergy: null, healGiveMaxEnergy: null, healMaxEnergyBonus: null, aimDamage: null, isNoFireDefense: null, isNoFireDamage: null, duplicateChance: null, beamSplitter: null, iceEnergy: null, isPerfectBrake: null, explosiveRadius: null, isWormholeEnergy: null, isWormholeDamage: null, isNailCrit: null, isFlechetteExplode: null, isWormSpores: null, isWormBullets: null, isWideLaser: null, wideLaser: null, isPulseLaser: null, isRadioactive: null, isRailEnergyGain: null, isMineSentry: null, isIncendiary: null, overfillDrain: null, isNeutronSlow: null, isRailAreaDamage: null, historyLaser: null, isSpeedHarm: null, isSpeedDamage: null, isTimeSkip: null, isPerpetualReroll: null, isPerpetualAmmo: null, isPerpetualHeal: null, isPerpetualStun: null, isCancelDuplication: null, cancelCount: null, isCancelRerolls: null, isBotDamage: null, isBanish: null, isMaxEnergyTech: null, isLowEnergyDamage: null, isRewindBot: null, isRewindGrenade: null, isExtruder: null, isEndLevelPowerUp: null, isRewindGun: null, missileSize: null, isLaserMine: null, isAmmoFoamSize: null }