nail gun rework

damage immunity graphic is more obvious
difficulty mode no longer increases after killing final boss (it was too confusing)

tech: Higgs mechanism - you can't move when firing, reduce harm by 60% when firing
  removed Galilean group

removed gun flechettes
removed critical bifrication
removed railroad ties
removed incendiary (for nail gun)

nail gun:
  needle gun: accurate, piercing mobs, fire 3 at a time
  rivet gun: accurate, ballistic arc, doesn't use much ammo
    tech: bigger rivets (9x stack)
  all nails
    radioactive 2s tick (about 70% damage increase)
      0.5s full tick
      4s longer tick
    critical hits -> explosion (from flechettes)
This commit is contained in:
landgreen
2021-01-16 08:30:27 -08:00
parent 8bcda6ebf6
commit 261977b774
9 changed files with 464 additions and 414 deletions

View File

@@ -2177,14 +2177,16 @@ const b = {
},
nail(pos, velocity, dmg = 0) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * tech.biggerNails, 2 * tech.biggerNails, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
bullet[me] = Bodies.rectangle(pos.x, pos.y, 25, 2, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
Matter.Body.setVelocity(bullet[me], velocity);
World.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = simulation.cycle + 60 + 18 * Math.random();
bullet[me].dmg = dmg
bullet[me].dmg = tech.isNailRadiation ? 0 : dmg
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isNailPoison) mobs.statusDoT(who, dmg * 0.24, 120) // one tick every 30 cycles
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.99) this.dmg *= 5 //crit if hit near center
if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 2 : 0.5), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 150 + 30 * Math.random()); //makes bullet do explosive damage at end
}
};
bullet[me].do = function() {};
},
@@ -2839,59 +2841,167 @@ const b = {
name: "nail gun",
description: "use compressed air to fire a stream of <strong>nails</strong><br><strong>delay</strong> after firing <strong>decreases</strong> as you shoot",
ammo: 0,
ammoPack: 55,
defaultAmmoPack: 55,
ammoPack: 50,
defaultAmmoPack: 50,
recordedAmmo: 0,
have: false,
nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
startingHoldCycle: 0,
chooseFireMethod() { //set in simulation.startGame
if (tech.isRivets) {
this.fire = this.fireRivets
} else if (tech.isNeedles) {
this.fire = this.fireNeedles
} else if (tech.nailInstantFireRate) {
this.fire = this.fireNailFireRate
} else if (tech.nailFireRate) {
this.fire = this.fireNailFireRate
} else {
this.fire = this.fireNormal
}
},
fire() {
let CD
if (tech.nailFireRate) { //fire delay decreases as you hold fire, down to 3 from 15
if (tech.nailInstantFireRate) {
CD = 2
} else {
},
fireNormal() {
if (this.nextFireCycle + 1 < mech.cycle) this.startingHoldCycle = mech.cycle //reset if not constantly firing
CD = Math.max(7.5 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
const CD = Math.max(11 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
this.nextFireCycle = mech.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down
}
} else {
if (this.nextFireCycle + 1 < mech.cycle) this.startingHoldCycle = mech.cycle //reset if not constantly firing
CD = Math.max(11 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
this.nextFireCycle = mech.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down
}
mech.fireCDcycle = mech.cycle + Math.floor(CD * b.fireCD); // cool down
const speed = 30 + 6 * Math.random() + 9 * tech.nailInstantFireRate
const angle = mech.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (mech.crouch ? 1.35 : 3.2) / CD
if (tech.isIncendiary) {
this.baseFire(mech.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (mech.crouch ? 1.35 : 3.2) / CD)
},
fireNeedles() {
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 40 : 30) * b.fireCD); // cool down
function makeFlechette(angle = mech.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(mech.pos.x + 50 * Math.cos(mech.angle), mech.pos.y + 50 * Math.sin(mech.angle), 25, 2, {
density: 0.0001, //frictionAir: 0.01, //restitution: 0,
angle: angle,
friction: 0.5,
frictionAir: 0,
dmg: 0, //damage done in addition to the damage from momentum
endCycle: Math.floor(mech.crouch ? 28 : 13) + Math.random() * 5 + simulation.cycle,
classType: "bullet",
collisionFilter: {
category: cat.bullet,
mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
},
minDmgSpeed: 10,
beforeDmg() {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
},
onEnd() {
b.explosion(this.position, 72 + (Math.random() - 0.5) * 30); //makes bullet do explosive damage at end
},
do() {}
});
Matter.Body.setVelocity(bullet[me], {
x: speed * Math.cos(angle),
y: speed * Math.sin(angle)
});
World.add(engine.world, bullet[me]); //add bullet to world
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 50, 1, b.fireAttributes(angle));
bullet[me].collisionFilter.mask = cat.mobShield | cat.body
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
who = whom[0].bodyA
if (who && who.mob) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) {
if (this.immuneList[i] === who.id) {
immune = true
break
}
}
if (!immune) {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 200 + 30 * Math.random()); //makes bullet do explosive damage at end
}
this.immuneList.push(who.id)
who.foundPlayer();
if (tech.isNailRadiation) {
mobs.statusDoT(who, tech.isFastRadiation ? 10 : 2.5, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else {
let dmg = b.dmgScale * 5
if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: Math.log(2 * dmg + 1.1) * 40,
color: simulation.playerDmgColor,
time: simulation.drawTime
});
}
// if (tech.isFastRadiation) {
// mobs.statusDoT(who, 3.78, 30)
// } else {
// mobs.statusDoT(who, 0.63, tech.isSlowRadiation ? 360 : 180)
// }
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
this.collisionFilter.mask = 0;
Matter.Body.setAngularVelocity(this, 0)
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
this.do = function() {}
} else if (this.speed < 30) {
this.force.y += this.mass * 0.0007; //no gravity until it slows down to improve aiming
}
};
const SPEED = 50
Matter.Body.setVelocity(bullet[me], {
x: mech.Vx / 2 + SPEED * Math.cos(angle),
y: mech.Vy / 2 + SPEED * Math.sin(angle)
});
Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
}
const spread = (mech.crouch ? 0.01 : 0.045)
makeFlechette(mech.angle + spread)
makeFlechette()
makeFlechette(mech.angle - spread)
},
fireRivets() {
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 20) * b.fireCD); // cool down
const me = bullet.length;
const size = tech.rivetSize * 6
bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle), mech.pos.y + 35 * Math.sin(mech.angle), 5 * size, size, b.fireAttributes(mech.angle));
bullet[me].dmg = tech.isNailRadiation ? 0 : 2.75
Matter.Body.setDensity(bullet[me], 0.002);
World.add(engine.world, bullet[me]); //add bullet to world
const SPEED = mech.crouch ? 55 : 46
Matter.Body.setVelocity(bullet[me], {
x: SPEED * Math.cos(mech.angle),
y: SPEED * Math.sin(mech.angle)
});
bullet[me].endCycle = simulation.cycle + 180
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
}
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 1 : 0.25), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
};
bullet[me].minDmgSpeed = 10
bullet[me].frictionAir = 0.006;
bullet[me].do = function() {
this.force.y += this.mass * 0.0008
//rotates bullet to face current velocity?
if (this.speed > 7) {
const facing = {
x: Math.cos(this.angle),
y: Math.sin(this.angle)
}
const mag = 0.002 * this.mass
if (Vector.cross(Vector.normalise(this.velocity), facing) < 0) {
this.torque += mag
} else {
this.torque -= mag
}
}
};
b.muzzleFlash(30);
},
fireNailFireRate() {
if (this.nextFireCycle + 1 < mech.cycle) this.startingHoldCycle = mech.cycle //reset if not constantly firing
const CD = Math.max(7.5 - 0.06 * (mech.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
this.nextFireCycle = mech.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down
mech.fireCDcycle = mech.cycle + Math.floor(CD * b.fireCD); // cool down
this.baseFire(mech.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (mech.crouch ? 1.35 : 3.2) / CD)
},
fireInstantFireRate() {
mech.fireCDcycle = mech.cycle + Math.floor(2 * b.fireCD); // cool down
this.baseFire(mech.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (mech.crouch ? 1.35 : 3.2) / 2)
},
baseFire(angle) {
const speed = 30 + 6 * Math.random() + 9 * tech.nailInstantFireRate
const dmg = 0.9
b.nail({
x: mech.pos.x + 30 * Math.cos(mech.angle),
@@ -2903,19 +3013,17 @@ const b = {
if (tech.isIceCrystals) {
bullet[bullet.length - 1].beforeDmg = function(who) {
mobs.statusSlow(who, 30)
if (tech.isNailPoison) mobs.statusDoT(who, dmg * 0.24, 120) // one tick every 30 cycles
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.99) this.dmg *= 5 //crit if hit near center
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 150 + 30 * Math.random()); //makes bullet do explosive damage at end
}
};
if (mech.energy < 0.01) {
mech.fireCDcycle = mech.cycle + 60; // cool down
} else {
mech.energy -= mech.fieldRegen + 0.01
}
}
}
}
},
},
{
name: "shotgun",
@@ -2953,7 +3061,7 @@ const b = {
const me = bullet.length;
const dir = mech.angle + 0.02 * (Math.random() - 0.5)
bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle), mech.pos.y + 35 * Math.sin(mech.angle), 45, 20, b.fireAttributes(dir));
Matter.Body.setDensity(bullet[me], 0.0022);
Matter.Body.setDensity(bullet[me], 0.003);
World.add(engine.world, bullet[me]); //add bullet to world
const SPEED = (mech.crouch ? 52 : 43) + Math.random() * 7
Matter.Body.setVelocity(bullet[me], {
@@ -3147,109 +3255,6 @@ const b = {
}
}
},
{
name: "flechettes",
description: "fire a volley of <strong class='color-p'>uranium-235</strong> <strong>needles</strong><br>does <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over <strong>3</strong> seconds",
ammo: 0,
ammoPack: 75,
defaultAmmoPack: 75,
have: false,
count: 0, //used to track how many shots are in a volley before a big CD
lastFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
fire() {
function makeFlechette(angle = mech.angle + 0.02 * (Math.random() - 0.5)) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 45, 1, b.fireAttributes(angle));
bullet[me].collisionFilter.mask = tech.pierce ? 0 : cat.body; //cat.mobShield | //cat.map | cat.body |
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].dmg = 0;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
who = whom[0].bodyA
if (who && who.mob) {
if (tech.pierce) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) {
if (this.immuneList[i] === who.id) immune = true
}
if (!immune) {
this.immuneList.push(who.id)
who.foundPlayer();
if (tech.isFastDot) {
mobs.statusDoT(who, 3.78, 30)
} else {
mobs.statusDoT(who, 0.63, tech.isSlowDot ? 360 : 180)
}
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: 40,
color: "rgba(0,80,80,0.3)",
time: simulation.drawTime
});
}
} else {
this.endCycle = 0;
if (tech.isFlechetteExplode && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
this.explodeRad = 300 + 60 * Math.random();
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
}
who.foundPlayer();
if (tech.isFastDot) {
mobs.statusDoT(who, 4, 30)
} else {
mobs.statusDoT(who, 0.7, tech.isSlowDot ? 360 : 180)
}
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: 40,
color: "rgba(0,80,80,0.3)",
time: simulation.drawTime
});
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
this.collisionFilter.mask = 0;
Matter.Body.setAngularVelocity(this, 0)
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
this.do = function() {}
} else if (this.speed < 30) {
this.force.y += this.mass * 0.0007; //no gravity until it slows down to improve aiming
}
};
const SPEED = 50
Matter.Body.setVelocity(bullet[me], {
x: mech.Vx / 2 + SPEED * Math.cos(angle),
y: mech.Vy / 2 + SPEED * Math.sin(angle)
});
Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
}
makeFlechette()
if (tech.isFlechetteMultiShot) {
makeFlechette(mech.angle + 0.02 + 0.005 * Math.random())
makeFlechette(mech.angle - 0.02 - 0.005 * Math.random())
}
const CD = (mech.crouch) ? 40 : 15
if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD
this.lastFireCycle = mech.cycle
if (this.count > ((mech.crouch) ? 8 : 1)) {
this.count = 0
mech.fireCDcycle = mech.cycle + Math.floor(CD * b.fireCD); // cool down
} else {
this.count++
mech.fireCDcycle = mech.cycle + Math.floor(2 * b.fireCD); // cool down
}
}
},
{
name: "wave beam",
description: "emit a <strong>sine wave</strong> of oscillating particles<br>propagates through <strong>walls</strong>",

View File

@@ -108,7 +108,7 @@ function collisionChecks(event) {
return
}
mech.damage(dmg);
if (tech.isPiezo) mech.energy += 2;
if (tech.isPiezo) mech.energy += 4;
if (tech.isBayesian) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k);
mech.immuneCycle = mech.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles

View File

@@ -13,13 +13,19 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(20)
// level.difficultyIncrease(30)
// simulation.zoomScale = 1000;
// simulation.setZoom();
// mech.setField("plasma torch")
// b.giveGuns("laser")
// b.giveGuns("nail gun")
// tech.giveTech("rivet gun")
// tech.giveTech("needle gun")
// tech.giveTech("supercritical fission")
// tech.giveTech("irradiated nails")
// tech.giveTech("4s half-life")
// tech.giveTech("1/2s half-life")
// tech.isMineSentry = true
// tech.giveTech("diffuse beam")
// for (let i = 0; i < 60; i++) tech.giveTech("output coupler")
// tech.giveTech("missile-bot")
// tech.giveTech("nail-bot")
@@ -231,16 +237,16 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 200) //big boy
spawn.starter(1900, -500, 200) //big boy
// spawn.exploder(2900, -500)
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500)
spawn.shooter(1700, -120)
// spawn.shooter(1700, -120)
// spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
spawn.streamBoss(1600, -500)
// spawn.streamBoss(1600, -500)
// spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);

View File

@@ -164,16 +164,16 @@ const mobs = {
time: simulation.drawTime
});
}
if (true) {
//check for nearby mobs
// if (true) {
// //check for nearby mobs
}
// }
},
endEffect() {},
dmg: tickDamage,
type: "dot",
endCycle: simulation.cycle + cycles,
startCycle: simulation.cycle
startCycle: simulation.cycle + 29 //makes sure it doesn't tick on first application
})
}
},

View File

@@ -494,7 +494,7 @@ const mech = {
let dmg = 1
dmg *= mech.fieldHarmReduction
if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0185, 0.55)
if (tech.isSlowFPS) dmg *= 0.85
if (tech.isSlowFPS) dmg *= 0.8
if (tech.isPiezo) dmg *= 0.85
if (tech.isHarmReduce && mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" && mech.isFieldActive) dmg *= 0.6
if (tech.isBotArmor) dmg *= 0.97 ** tech.totalBots()

View File

@@ -515,6 +515,10 @@ const simulation = {
b.removeAllGuns();
simulation.isNoPowerUps = false;
tech.setupAllTech(); //sets tech to default values
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod()
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
}
tech.laserBotCount = 0;
tech.orbitBotCount = 0;
tech.nailBotCount = 0;

View File

@@ -101,24 +101,24 @@ const spawn = {
level.exit.x = 5500;
level.exit.y = -330;
//ramp up damage
// for (let i = 0; i < 2; i++) level.difficultyIncrease(simulation.difficultyMode)
for (let i = 0; i < 3; i++) level.difficultyIncrease(simulation.difficultyMode)
//set game to the next highest difficulty level if not on why
if (simulation.difficultyMode < 6) {
if (simulation.difficultyMode === 0) {
simulation.difficultyMode = 1
} else if (simulation.difficultyMode === 1) {
simulation.difficultyMode = 2
} else if (simulation.difficultyMode === 2) {
simulation.difficultyMode = 4
} else {
simulation.difficultyMode = 6
}
document.getElementById("difficulty-select").value = simulation.difficultyMode
localSettings.difficultyMode = simulation.difficultyMode
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
simulation.makeTextLog(`<span class='color-var'>simulation</span>.difficultyMode<span class='color-symbol'>++</span>`);
}
// if (simulation.difficultyMode < 6) {
// if (simulation.difficultyMode === 0) {
// simulation.difficultyMode = 1
// } else if (simulation.difficultyMode === 1) {
// simulation.difficultyMode = 2
// } else if (simulation.difficultyMode === 2) {
// simulation.difficultyMode = 4
// } else {
// simulation.difficultyMode = 6
// }
// document.getElementById("difficulty-select").value = simulation.difficultyMode
// localSettings.difficultyMode = simulation.difficultyMode
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// simulation.makeTextLog(`<span class='color-var'>simulation</span>.difficultyMode<span class='color-symbol'>++</span>`);
// }
//pull in particles
for (let i = 0, len = body.length; i < len; ++i) {

View File

@@ -109,7 +109,7 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return b.inventory.length < 2
return b.inventory.length < 2 //&& !tech.haveGunCheck("CPT gun")
},
requires: "no more than 1 gun",
effect() {
@@ -364,7 +364,7 @@ const tech = {
},
{
name: "Higgs mechanism",
description: "<strong>movement</strong> isn't possible while <strong>firing</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>60%</strong> when <strong>firing</strong>",
description: "while <strong>firing</strong> your <strong>position</strong> is locked<br> and <strong class='color-harm'>harm</strong> is reduced by <strong>60%</strong>",
maxCount: 1,
count: 0,
allowed() {
@@ -507,7 +507,7 @@ const tech = {
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
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1
},
requires: "an explosive damage source",
effect: () => {
@@ -523,7 +523,7 @@ const tech = {
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
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1
},
requires: "an explosive damage source",
effect: () => {
@@ -539,7 +539,7 @@ const tech = {
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
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField
},
requires: "an explosive damage source",
effect: () => {
@@ -556,7 +556,7 @@ const tech = {
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
return tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isMissileField || tech.isExplodeMob || tech.isPulseLaser
},
requires: "an explosive damage source",
effect: () => {
@@ -572,7 +572,7 @@ const tech = {
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
return (tech.haveGunCheck("missiles") || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("vacuum bomb") || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1) && !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.isBotSpawner
},
requires: "an explosive damage source, no other mob death tech",
effect: () => {
@@ -1136,7 +1136,7 @@ const tech = {
},
{
name: "clock gating",
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>`,
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>`,
maxCount: 1,
count: 0,
allowed() {
@@ -2100,14 +2100,14 @@ const tech = {
},
{
name: "incendiary ammunition",
description: "some <strong>bullets</strong> are loaded with <strong class='color-e'>explosives</strong><br><em style = 'font-size: 90%'>nail gun, shotgun, super balls, drones</em>",
description: "<strong>shotgun</strong>, <strong>super balls</strong>, and <strong>drones</strong><br>are loaded with <strong class='color-e'>explosives</strong>",
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
return ((mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) || tech.haveGunCheck("drones") || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot
},
requires: "drones, super balls, nail gun, shotgun",
requires: "drones, super balls, shotgun",
effect() {
tech.isIncendiary = true
},
@@ -2156,7 +2156,7 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("flechettes") || tech.isNailPoison || tech.isWormholeDamage || tech.isNeutronBomb
return tech.isNailRadiation || tech.isWormholeDamage || tech.isNeutronBomb
},
requires: "radiation damage source",
effect() {
@@ -2200,6 +2200,91 @@ const tech = {
tech.isDamageFromBulletCount = false
}
},
{
name: "needle gun",
description: "<strong>nail gun</strong> slowly fires <strong>3</strong> piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong class='color-g'>ammo</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals
},
requires: "nail gun, not ice crystal or pneumatic actuator",
effect() {
tech.isNeedles = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") {
b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 3);
b.guns[i].ammoPack = Math.ceil(b.guns[i].defaultAmmoPack / 3);
b.guns[i].chooseFireMethod()
simulation.updateGunHUD();
break
}
}
},
remove() {
if (tech.isNeedles) {
tech.isNeedles = false
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") {
b.guns[i].chooseFireMethod()
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 3);
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
simulation.updateGunHUD();
break
}
}
}
}
},
{
name: "rivet gun",
description: "<strong>nail gun</strong> slowly fires a heavy <strong>rivet</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals
},
requires: "nail gun, not ice crystal or pneumatic actuator",
effect() {
tech.isRivets = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") {
b.guns[i].chooseFireMethod()
break
}
}
},
remove() {
if (tech.isRivets) {
tech.isRivets = false
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") {
b.guns[i].chooseFireMethod()
break
}
}
}
}
},
{
name: "rivet diameter",
description: `your <strong>rivets</strong> are <strong>20%</strong> larger<br>increases mass and physical <strong class='color-d'>damage</strong>`,
isGunTech: true,
maxCount: 9,
count: 0,
allowed() {
return tech.isRivets
},
requires: "rivet gun",
effect() {
tech.rivetSize += 0.2
},
remove() {
tech.rivetSize = 1;
}
},
{
name: "ice crystal nucleation",
description: "the <strong>nail gun</strong> uses <strong class='color-f'>energy</strong> to condense<br>unlimited <strong class='color-s'>freezing</strong> <strong>ice shards</strong>",
@@ -2207,9 +2292,9 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIncendiary
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isRivets && !tech.isNeedles && !tech.isNailRadiation && !tech.isNailCrit
},
requires: "nail gun, not incendiary, not powder-actuated",
requires: "nail gun, not powder-actuated, rivets, needles, irradiated, or fission",
effect() {
tech.isIceCrystals = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -2224,6 +2309,7 @@ const tech = {
},
remove() {
if (tech.isIceCrystals) {
tech.isIceCrystals = false;
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;
@@ -2233,24 +2319,6 @@ const tech = {
}
}
}
tech.isIceCrystals = false;
}
},
{
name: "critical bifurcation",
description: "nail gun <strong>nails</strong> do <strong>400%</strong> more <strong class='color-d'>damage</strong><br>when they strike near the <strong>center</strong> 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
}
},
{
@@ -2260,14 +2328,22 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun")
return tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles
},
requires: "nail gun",
requires: "nail gun, not rivets or needles",
effect() {
tech.nailFireRate = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
}
},
remove() {
if (tech.nailFireRate) {
tech.nailFireRate = false
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
}
}
}
},
{
@@ -2282,9 +2358,85 @@ const tech = {
requires: "nail gun and pneumatic actuator",
effect() {
tech.nailInstantFireRate = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
}
},
remove() {
if (tech.nailInstantFireRate) {
tech.nailInstantFireRate = false
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
}
}
}
},
{
name: "supercritical fission",
description: "<strong>nails</strong>, <strong>needles</strong>, and <strong>rivets</strong> can <strong class='color-e'>explode</strong><br>if they strike mobs near their <strong>center</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.isIceCrystals
},
requires: "nail gun, not ice crystals",
effect() {
tech.isNailCrit = true
},
remove() {
tech.isNailCrit = false
}
},
{
name: "irradiated nails",
description: "<strong>nails</strong>, <strong>needles</strong>, and <strong>rivets</strong> are <strong class='color-p'>radioactive</strong><br>about <strong>70%</strong> more <strong class='color-d'>damage</strong> over <strong>2</strong> 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")) * 2 > 1) && !tech.isIceCrystals
},
requires: "nails, not ice crystals",
effect() {
tech.isNailRadiation = true;
},
remove() {
tech.isNailRadiation = false;
}
},
{
name: "4s half-life",
description: "<strong>nails</strong> are made of <strong class='color-p'>plutonium-238</strong><br>increase <strong class='color-d'>damage</strong> by <strong>100%</strong> over <strong>6</strong> seconds",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.isNailRadiation && !tech.isFastRadiation
},
requires: "irradiated nails",
effect() {
tech.isSlowRadiation = true;
},
remove() {
tech.isSlowRadiation = false;
}
},
{
name: "1/2s half-life",
description: "<strong>nails</strong> are made of <strong class='color-p'>lithium-8</strong><br>flechette <strong class='color-d'>damage</strong> occurs after <strong>1/2</strong> a second",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
return tech.isNailRadiation && !tech.isSlowRadiation
},
requires: "irradiated nails",
effect() {
tech.isFastRadiation = true;
},
remove() {
tech.isFastRadiation = false;
}
},
{
@@ -2428,121 +2580,6 @@ const tech = {
tech.bulletSize = 1;
}
},
{
name: "flechettes cartridges",
description: "<strong>flechettes</strong> release <strong>three</strong> needles in each shot<br><strong class='color-g'>ammo</strong> costs are <strong>tripled</strong>",
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: "<strong>flechette</strong> needles made of <strong class='color-p'>plutonium-238</strong><br>increase <strong class='color-d'>damage</strong> by <strong>100%</strong> over <strong>6</strong> 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: "<strong>flechette</strong> needles made of <strong class='color-p'>lithium-8</strong><br>flechette <strong class='color-d'>damage</strong> occurs after <strong>1/2</strong> 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: "<strong>flechettes</strong> can <strong class='color-e'>explode</strong><br>if they strike mobs near their <strong>center</strong>",
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: "piercing needles",
description: "<strong>needles</strong> penetrate <strong>mobs</strong> and <strong>blocks</strong><br>potentially hitting <strong>multiple</strong> 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: "<strong>wave beam</strong> emits <strong>two</strong> oscillating particles<br>decrease wave <strong class='color-d'>damage</strong> by <strong>20%</strong>",
@@ -2550,7 +2587,7 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("wave beam") && !tech.isExtruder
return tech.haveGunCheck("wave beam")
},
requires: "wave beam",
effect() {
@@ -2567,7 +2604,7 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("wave beam") && !tech.isWaveReflect && !tech.isExtruder
return tech.haveGunCheck("wave beam") && !tech.isWaveReflect
},
requires: "wave beam",
effect() {
@@ -2586,7 +2623,7 @@ const tech = {
maxCount: 1,
count: 0,
allowed() {
return tech.haveGunCheck("wave beam") && tech.waveSpeedMap !== 3 && !tech.isExtruder
return tech.haveGunCheck("wave beam") && tech.waveSpeedMap !== 3
},
requires: "wave beam",
effect() {
@@ -2790,40 +2827,6 @@ const tech = {
tech.isMineSentry = false;
}
},
{
name: "irradiated nails",
description: "<strong>nails</strong> are made with a <strong class='color-p'>cobalt-60</strong> alloy<br><strong>85%</strong> <strong class='color-p'>radioactive</strong> <strong class='color-d'>damage</strong> over <strong>2</strong> 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: "<strong>nails</strong> are <strong>40%</strong> <strong>larger</strong><br>increases physical <strong class='color-d'>damage</strong> by about <strong>20%</strong>",
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: "<strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> release an extra <strong class='color-p' style='letter-spacing: 2px;'>spore</strong><br> once a <strong>second</strong> during their <strong>growth</strong> phase",
@@ -3153,11 +3156,13 @@ const tech = {
}
},
remove() {
if (tech.beamSplitter !== 0) {
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",
@@ -3177,12 +3182,14 @@ const tech = {
}
},
remove() {
if (tech.isWideLaser) {
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",
@@ -3230,11 +3237,13 @@ const tech = {
},
remove() {
// this.description = "<strong>laser</strong> beam is <strong>spread</strong> into your recent <strong>past</strong><br>increase total beam <strong class='color-d'>damage</strong> by <strong>300%</strong>"
if (tech.historyLaser) {
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",
@@ -3253,11 +3262,13 @@ const tech = {
}
},
remove() {
if (tech.isPulseLaser) {
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",
@@ -3768,7 +3779,7 @@ const tech = {
},
{
name: "discrete optimization",
description: "increase <strong class='color-d'>damage</strong> by <strong>50%</strong><br><strong>50%</strong> increased <strong><em>delay</em></strong> after firing",
description: "increase <strong class='color-d'>damage</strong> by <strong>66%</strong><br><strong>50%</strong> increased <strong><em>delay</em></strong> after firing",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -3777,7 +3788,7 @@ const tech = {
},
requires: "metamaterial cloaking",
effect() {
tech.aimDamage = 1.5
tech.aimDamage = 1.66
b.setFireCD();
},
remove() {
@@ -3998,7 +4009,6 @@ const tech = {
isSporeField: null,
isMissileField: null,
isIceField: null,
isFlechetteMultiShot: null,
isMineAmmoBack: null,
isPlasmaRange: null,
isFreezeMobs: null,
@@ -4015,7 +4025,7 @@ const tech = {
isBotSpawner: null,
waveHelix: null,
isSporeFollow: null,
isNailPoison: null,
isNailRadiation: null,
isEnergyHealth: null,
isPulseStun: null,
restDamage: null,
@@ -4035,7 +4045,7 @@ const tech = {
fastTime: null,
squirrelJump: null,
fastTimeJump: null,
isFastDot: null,
isFastRadiation: null,
isArmorFromPowerUps: null,
isAmmoForGun: null,
isRapidPulse: null,
@@ -4134,5 +4144,7 @@ const tech = {
isTechDamage: null,
isFireNotMove: null,
isRestHarm: null,
isFireMoveLock: null
isFireMoveLock: null,
isRivets: null,
isNeedles: null
}

View File

@@ -1,12 +1,31 @@
******************************************************** NEXT PATCH ********************************************************
damage immunity graphic is more obvious
difficulty mode no longer increases after killing final boss (it was too confusing)
tech: Higgs mechanism - you can't move when firing, reduce harm by 60% when firing
removed Galilean group
damage immunity graphic is more obvious
removed gun flechettes
removed critical bifrication
removed railroad ties
removed incendiary (for nail gun)
nail gun:
needle gun: accurate, piercing mobs, fire 3 at a time
rivet gun: accurate, ballistic arc, doesn't use much ammo
tech: bigger rivets (9x stack)
all nails
radioactive 2s tick (about 70% damage increase)
0.5s full tick
4s longer tick
critical hits -> explosion (from flechettes)
******************************************************** BUGS ********************************************************
Laser+slow light prop+crouch= all but one laser stays in original position
log crouch state and apply that to laser, rewind
CPT check for crouch after rewind
(always) make it so that when you are immune to harm you can either jump on mobs or you pass through them
@@ -24,12 +43,16 @@ CPT check for crouch after rewind
******************************************************** TODO ********************************************************
tech: nail gun no longer ramps up in speed, nail gun fires slugs (like the shotgun)
tech: increase maxHealth by 100%, but you can no longer see your health
tech: you are unable to move while firing
float in mid air
modify tech: increase squirrel cage speed, but also increase harm taken by 5-10%
tech: can't fire while moving, get attack speed and damage
tech: explosions are radioactive
tech: double your rerolls
set your duplication chance to zero
requires 5 rerolls and 20% duplication chance
might want to use a single variable for all duplication
bot that follows the players history
could have the same shape as the mech circle head