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
}