merged shotgun tech

railgun and foam have a bit more ammo
capacitor bank makes foam gun fire a stream of foam
tech shift registers is now always on
  (set ON/OFF to ON at the start of a new level)
tech from applied science doesn't count for various tech that convert tech into other things (pure science, many worlds)
grappling hook now shows hooks on the grapple

merged similar gun tech
  needle gun+needle shot
  rivet gun+shotgun slug
  shockwave+blast mines
  nematodes+worm-shot
  necrophoresis+necrophage
    the worm aspect now spawns 3 copies instead of just a lifespan reset
This commit is contained in:
landgreen
2022-03-06 19:00:27 -08:00
parent 50fbd618a6
commit 4efc3d2d82
8 changed files with 391 additions and 332 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -82,12 +82,12 @@ const b = {
}, },
fireWithAmmo() { //triggers after firing when you have ammo fireWithAmmo() { //triggers after firing when you have ammo
b.guns[b.activeGun].fire(); b.guns[b.activeGun].fire();
if (tech.isCrouchAmmo && input.down) { if (tech.crouchAmmoCount && input.down) {
if (tech.isCrouchAmmo % 2) { if (tech.crouchAmmoCount % 2) {
b.guns[b.activeGun].ammo--; b.guns[b.activeGun].ammo--;
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
tech.isCrouchAmmo++ //makes the no ammo toggle off and on tech.crouchAmmoCount++ //makes the no ammo toggle off and on
} else { } else {
b.guns[b.activeGun].ammo--; b.guns[b.activeGun].ammo--;
simulation.updateGunHUD(); simulation.updateGunHUD();
@@ -103,9 +103,9 @@ const b = {
} }
}, },
refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to
if (tech.isCrouchAmmo && input.down) { if (tech.crouchAmmoCount && input.down) {
tech.isCrouchAmmo-- tech.crouchAmmoCount--
if ((tech.isCrouchAmmo) % 2) { if ((tech.crouchAmmoCount) % 2) {
b.guns[b.activeGun].ammo++; b.guns[b.activeGun].ammo++;
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
@@ -1351,7 +1351,7 @@ const b = {
grapple(where, angle = m.angle, harpoonSize = 1) { grapple(where, angle = m.angle, harpoonSize = 1) {
const me = bullet.length; const me = bullet.length;
const returnRadius = 100 * Math.sqrt(harpoonSize) const returnRadius = 100 * Math.sqrt(harpoonSize)
bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -70 * harpoonSize, y: 3 * harpoonSize, index: 0, isInternal: false }, { x: -70 * harpoonSize, y: -3 * harpoonSize, index: 1, isInternal: false }, { x: 45 * harpoonSize, y: -2 * harpoonSize, index: 2, isInternal: false }, { x: 50 * harpoonSize, y: 0, index: 3, isInternal: false }, { x: 45 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], { bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -50 * harpoonSize, y: 2 * harpoonSize, index: 0, isInternal: false }, { x: -50 * harpoonSize, y: -2 * harpoonSize, index: 1, isInternal: false }, { x: 45 * harpoonSize, y: -3 * harpoonSize, index: 2, isInternal: false }, { x: 50 * harpoonSize, y: 0, index: 3, isInternal: false }, { x: 45 * harpoonSize, y: 3 * harpoonSize, index: 4, isInternal: false }], {
angle: angle, angle: angle,
friction: 1, friction: 1,
frictionAir: 0.4, frictionAir: 0.4,
@@ -1420,8 +1420,20 @@ const b = {
ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y) ctx.quadraticCurveTo(controlPoint.x, controlPoint.y, this.vertices[0].x, this.vertices[0].y)
// ctx.lineTo(this.vertices[0].x, this.vertices[0].y); // ctx.lineTo(this.vertices[0].x, this.vertices[0].y);
ctx.stroke(); ctx.stroke();
//draw hook //draw harpoon spikes
// ctx.beginPath(); const spikeLength = 2
ctx.beginPath();
const spike1 = Vector.add(this.vertices[1], Vector.mult(Vector.sub(this.vertices[1], this.vertices[2]), spikeLength))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike1.x, spike1.y);
ctx.lineTo(this.vertices[3].x, this.vertices[3].y);
const spike2 = Vector.add(this.vertices[3], Vector.mult(Vector.sub(this.vertices[3], this.vertices[2]), spikeLength))
ctx.moveTo(this.vertices[2].x, this.vertices[2].y);
ctx.lineTo(spike2.x, spike2.y);
ctx.lineTo(this.vertices[1].x, this.vertices[1].y);
ctx.fillStyle = '#000'
ctx.fill();
}, },
returnToPlayer() { returnToPlayer() {
if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player if (Vector.magnitude(Vector.sub(this.position, m.pos)) < returnRadius) { //near player
@@ -2375,7 +2387,7 @@ const b = {
ctx.globalAlpha = 1; ctx.globalAlpha = 1;
} }
}, },
AoEStunEffect(where, range, cycles = 150 + 120 * Math.random()) { AoEStunEffect(where, range, cycles = 90 + 60 * Math.random()) {
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded && !mob[i].shield && !mob[i].isBadTarget) { if (mob[i].alive && !mob[i].isShielded && !mob[i].shield && !mob[i].isBadTarget) {
if (Vector.magnitude(Vector.sub(where, mob[i].position)) - mob[i].radius < range) mobs.statusStun(mob[i], cycles) if (Vector.magnitude(Vector.sub(where, mob[i].position)) - mob[i].radius < range) mobs.statusStun(mob[i], cycles)
@@ -2421,7 +2433,7 @@ const b = {
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0 Matter.Query.ray(body, this.position, mob[i].position).length === 0
) { ) {
if (tech.isMineStun) b.AoEStunEffect(this.position, 1300); if (tech.isExplosionStun) b.AoEStunEffect(this.position, 1300);
this.do = this.laserSpin this.do = this.laserSpin
if (this.angularSpeed < 0.5) this.torque += this.inertia * this.torqueMagnitude * 200 //spin if (this.angularSpeed < 0.5) this.torque += this.inertia * this.torqueMagnitude * 200 //spin
this.endCycle = simulation.cycle + 360 + 120 this.endCycle = simulation.cycle + 360 + 120
@@ -2555,7 +2567,7 @@ const b = {
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0 Matter.Query.ray(body, this.position, mob[i].position).length === 0
) { ) {
if (tech.isMineStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random); if (tech.isExplosionStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random);
if (tech.isMineSentry) { if (tech.isMineSentry) {
this.lookFrequency = 8 + Math.floor(3 * Math.random()) this.lookFrequency = 8 + Math.floor(3 * Math.random())
this.endCycle = simulation.cycle + 1020 this.endCycle = simulation.cycle + 1020
@@ -2619,13 +2631,15 @@ const b = {
y: 100 * (Math.random() - 0.5) y: 100 * (Math.random() - 0.5)
}, },
beforeDmg(who) { beforeDmg(who) {
if (tech.wormSurviveDmg && who.alive) { if (tech.isSpawnBulletsOnDeath && who.alive && who.isDropPowerUp) {
setTimeout(() => { setTimeout(() => {
if (!who.alive) { if (!who.alive) {
this.endCycle = simulation.cycle + Math.floor((600 + Math.floor(Math.random() * 420)) * tech.isBulletsLastLonger); //bullet ends cycle resets for (let i = 0; i < 3; i++) { //spawn 3 more
} else { b.worm(this.position)
this.endCycle = 0; //bullet ends cycle after doing damage bullet[bullet.length - 1].endCycle = Math.min(simulation.cycle + Math.floor(420 * tech.isBulletsLastLonger), this.endCycle + 180 + Math.floor(60 * Math.random())) //simulation.cycle + Math.floor(420 * tech.isBulletsLastLonger)
} }
}
this.endCycle = 0; //bullet ends cycle after doing damage
}, 1); }, 1);
} else { } else {
this.endCycle = 0; //bullet ends cycle after doing damage this.endCycle = 0; //bullet ends cycle after doing damage
@@ -2948,7 +2962,7 @@ const b = {
const who = b.guns[b.activeGun] const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) { if (who.name === "drones" && who.ammo > 0 && mob.length) {
b.drone({ x: this.position.x, y: this.position.y }, 0) b.drone({ x: this.position.x, y: this.position.y }, 0)
if (Math.random() < 0.25) { if (Math.random() < 0.2) {
b.guns[b.activeGun].ammo--; b.guns[b.activeGun].ammo--;
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
@@ -3143,7 +3157,7 @@ const b = {
const who = b.guns[b.activeGun] const who = b.guns[b.activeGun]
if (who.name === "drones" && who.ammo > 0 && mob.length) { if (who.name === "drones" && who.ammo > 0 && mob.length) {
b.droneRadioactive({ x: this.position.x, y: this.position.y }, 0) b.droneRadioactive({ x: this.position.x, y: this.position.y }, 0)
if (Math.random() < 0.25) { if (Math.random() < 0.2) {
b.guns[b.activeGun].ammo--; b.guns[b.activeGun].ammo--;
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
@@ -3409,7 +3423,7 @@ const b = {
} else if (this.target !== null) { //look for a new target } else if (this.target !== null) { //look for a new target
this.collisionFilter.category = cat.bullet; this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
if (tech.isFoamGrowOnDeath && bullet.length < 180 && !this.target.isMobBullet) { if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
let targets = [] let targets = []
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
@@ -4765,11 +4779,20 @@ const b = {
y: SPEED * Math.sin(m.angle) y: SPEED * Math.sin(m.angle)
}); });
bullet[me].endCycle = simulation.cycle + 180 bullet[me].endCycle = simulation.cycle + 180
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isIncendiary) {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
b.explosion(this.position, 100 + (Math.random() - 0.5) * 20); //makes bullet do explosive damage at end
}
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) { if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) {
b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
} }
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
if (this.speed > 4 && tech.fragments) {
b.targetedNail(this.position, 1.5 * tech.fragments * tech.nailSize)
this.endCycle = 0 //triggers despawn
}
}; };
bullet[me].minDmgSpeed = 10 bullet[me].minDmgSpeed = 10
@@ -4829,10 +4852,18 @@ const b = {
}); });
bullet[me].endCycle = simulation.cycle + 180 bullet[me].endCycle = simulation.cycle + 180
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isIncendiary) {
this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
b.explosion(this.position, 100 + (Math.random() - 0.5) * 20); //makes bullet do explosive damage at end
}
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) { if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) {
b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
} }
if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 0.7 : 0.24), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
if (this.speed > 4 && tech.fragments) {
b.targetedNail(this.position, 1.5 * tech.fragments * tech.nailSize)
this.endCycle = 0 //triggers despawn
}
}; };
bullet[me].minDmgSpeed = 10 bullet[me].minDmgSpeed = 10
@@ -4913,8 +4944,8 @@ const b = {
name: "shotgun", name: "shotgun",
description: "fire a wide <strong>burst</strong> of short range <strong> bullets</strong>", description: "fire a wide <strong>burst</strong> of short range <strong> bullets</strong>",
ammo: 0, ammo: 0,
ammoPack: 4, ammoPack: 3.8,
defaultAmmoPack: 4, defaultAmmoPack: 3.8,
have: false, have: false,
do() {}, do() {},
fire() { fire() {
@@ -4945,7 +4976,7 @@ const b = {
b.muzzleFlash(35); b.muzzleFlash(35);
if (tech.isSlugShot) { if (tech.isRivets) {
const me = bullet.length; const me = bullet.length;
// const dir = m.angle + 0.02 * (Math.random() - 0.5) // const dir = m.angle + 0.02 * (Math.random() - 0.5)
bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 60 * tech.nailSize, 27 * tech.nailSize, b.fireAttributes(m.angle)); bullet[me] = Bodies.rectangle(m.pos.x + 35 * Math.cos(m.angle), m.pos.y + 35 * Math.sin(m.angle), 60 * tech.nailSize, 27 * tech.nailSize, b.fireAttributes(m.angle));
@@ -5048,20 +5079,17 @@ const b = {
}, dmg) }, dmg)
} }
} }
} else if (tech.isWormShot) { } else if (tech.isSporeWorm) {
const where = { const where = { x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) }
x: m.pos.x + 35 * Math.cos(m.angle), const spread = (input.down ? 0.02 : 0.07)
y: m.pos.y + 35 * Math.sin(m.angle)
}
const spread = (input.down ? 0.04 : 0.08)
const number = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random() const number = 3 * (tech.isShotgunReversed ? 1.6 : 1) + Math.random()
let angle = m.angle - (number - 1) * spread * 0.5 let angle = m.angle - (number - 1) * spread * 0.5
for (let i = 0; i < number; i++) { for (let i = 0; i < number; i++) {
b.worm(where) b.worm(where)
const SPEED = (16 + 20 * input.down) * (1 + 0.15 * Math.random()) const SPEED = (8 + 10 * input.down) * (1 + 0.15 * Math.random())
Matter.Body.setVelocity(bullet[bullet.length - 1], { Matter.Body.setVelocity(bullet[bullet.length - 1], {
x: SPEED * Math.cos(angle), x: player.velocity.x * 0.5 + SPEED * Math.cos(angle),
y: SPEED * Math.sin(angle) y: player.velocity.y * 0.5 + SPEED * Math.sin(angle)
}); });
angle += spread angle += spread
} }
@@ -5083,7 +5111,7 @@ const b = {
const angle = m.angle + spread * (Math.random() - 0.5) const angle = m.angle + spread * (Math.random() - 0.5)
b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 5 + 8 * Math.random()) b.foam(where, { x: SPEED * Math.cos(angle), y: SPEED * Math.sin(angle) }, 5 + 8 * Math.random())
} }
} else if (tech.isNeedleShot) { } else if (tech.isNeedles) {
const number = 9 * (tech.isShotgunReversed ? 1.6 : 1) const number = 9 * (tech.isShotgunReversed ? 1.6 : 1)
const spread = (input.down ? 0.03 : 0.05) const spread = (input.down ? 0.03 : 0.05)
let angle = m.angle - (number - 1) * spread * 0.5 let angle = m.angle - (number - 1) * spread * 0.5
@@ -5249,12 +5277,15 @@ const b = {
propagationRate: 20, propagationRate: 20,
waves: [], //used in longitudinal mode waves: [], //used in longitudinal mode
chooseFireMethod() { //set in simulation.startGame chooseFireMethod() { //set in simulation.startGame
this.waves = [];
if (tech.isLongitudinal) {
if (tech.is360Longitudinal) { if (tech.is360Longitudinal) {
this.fire = this.fire360Longitudinal this.fire = this.fire360Longitudinal
this.do = this.do360Longitudinal this.do = this.do360Longitudinal
} else if (tech.isLongitudinal) { } else {
this.fire = this.fireLongitudinal this.fire = this.fireLongitudinal
this.do = this.doLongitudinal this.do = this.doLongitudinal
}
} else { } else {
this.fire = this.fireTransverse this.fire = this.fireTransverse
this.do = this.doTransverse this.do = this.doTransverse
@@ -5567,7 +5598,7 @@ const b = {
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
} }
}, },
fire() {}
}, },
{ {
name: "missiles", name: "missiles",
@@ -5817,11 +5848,53 @@ const b = {
name: "foam", name: "foam",
description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time", description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time",
ammo: 0, ammo: 0,
ammoPack: 22, ammoPack: 24,
have: false, have: false,
charge: 0, charge: 0,
isDischarge: false, isDischarge: false,
do() { chooseFireMethod() {
if (tech.isCapacitor) {
this.do = this.doStream
this.fire = this.fireStream
} else {
this.do = this.doCharges // () => {}
this.fire = this.fireCharges
}
},
doStream() {},
fireStream() {
const spread = (input.down ? 0.04 : 0.3) * (Math.random() - 0.5)
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5)
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
if (tech.foamFutureFire) {
simulation.drawList.push({ //add dmg to draw queue
x: position.x,
y: position.y,
radius: 5,
color: "rgba(0,50,50,0.3)",
time: 15 * tech.foamFutureFire
});
setTimeout(() => {
if (!simulation.paused) {
b.foam(position, Vector.rotate(velocity, spread), radius)
bullet[bullet.length - 1].damage *= (1 + 0.7 * tech.foamFutureFire)
}
}, 210 * tech.foamFutureFire);
} else {
b.foam(position, Vector.rotate(velocity, spread), radius)
}
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
},
doCharges() {
if (this.charge > 0) { if (this.charge > 0) {
//draw charge level //draw charge level
ctx.fillStyle = "rgba(0,50,50,0.3)"; ctx.fillStyle = "rgba(0,50,50,0.3)";
@@ -5833,7 +5906,7 @@ const b = {
if (this.isDischarge) { if (this.isDischarge) {
this.charge-- this.charge--
const spread = (input.down ? 0.05 : 0.6) * (Math.random() - 0.5) const spread = (input.down ? 0.04 : 0.5) * (Math.random() - 0.5)
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12 const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = 18 - radius * 0.4; const SPEED = 18 - radius * 0.4;
const dir = m.angle + 0.15 * (Math.random() - 0.5) const dir = m.angle + 0.15 * (Math.random() - 0.5)
@@ -5874,7 +5947,7 @@ const b = {
this.isDischarge = false this.isDischarge = false
} }
}, },
fire() { fireCharges() {
const capacity = 20 const capacity = 20
if (tech.isCapacitor && this.charge === 0 && b.guns[b.activeGun].ammo > capacity) { if (tech.isCapacitor && this.charge === 0 && b.guns[b.activeGun].ammo > capacity) {
this.charge = capacity this.charge = capacity
@@ -5884,6 +5957,8 @@ const b = {
this.charge++ this.charge++
m.fireCDcycle = m.cycle + Math.floor(1 + 0.3 * this.charge); m.fireCDcycle = m.cycle + Math.floor(1 + 0.3 * this.charge);
}, },
fire() {},
do() {},
}, },
{ {
name: "harpoon", name: "harpoon",
@@ -6089,7 +6164,10 @@ const b = {
this.ammo++ //make up for the ammo used up in fire() this.ammo++ //make up for the ammo used up in fire()
simulation.updateGunHUD(); simulation.updateGunHUD();
m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down
// } else if (input.down) {
// b.harpoon(where, null, m.angle, harpoonSize, false, 70)
} else { } else {
if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1
b.grapple(where, m.angle, harpoonSize) b.grapple(where, m.angle, harpoonSize)
} }
m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down m.fireCDcycle = m.cycle + Math.floor(75 * b.fireCDscale) // cool down
@@ -6974,7 +7052,7 @@ const b = {
x: 7.5 * Math.cos(m.angle - Math.PI / 2), x: 7.5 * Math.cos(m.angle - Math.PI / 2),
y: 7.5 * Math.sin(m.angle - Math.PI / 2) y: 7.5 * Math.sin(m.angle - Math.PI / 2)
} }
const dmg = 0.7 * tech.laserDamage // 3.5 * 0.55 = 200% more damage const dmg = 0.66 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const eye = { const eye = {
x: m.pos.x + 15 * Math.cos(m.angle), x: m.pos.x + 15 * Math.cos(m.angle),

View File

@@ -7,7 +7,9 @@ Math.hash = s => { for (var i = 0, h = 9; i < s.length;) h = Math.imul(h ^ s.cha
// console.log(date1.getUTCHours()) // console.log(date1.getUTCHours())
// document.getElementById("seed").placeholder = Math.initialSeed = String(date1.getUTCDate() * date1.getUTCFullYear()) // daily seed, day + year // document.getElementById("seed").placeholder = Math.initialSeed = String(date1.getUTCDate() * date1.getUTCFullYear()) // daily seed, day + year
document.getElementById("seed").placeholder = Math.initialSeed = Math.floor(Date.now() % 100000) //random every time: just the time in milliseconds UTC // document.getElementById("seed").placeholder = Math.initialSeed = Math.floor(Date.now() % 100000) //random every time: just the time in milliseconds UTC
document.getElementById("seed").placeholder = Math.initialSeed = String(Math.floor(Date.now() % 100000))
Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it Math.seed = Math.abs(Math.hash(Math.initialSeed)) //update randomizer seed in case the player changed it
Math.seededRandom = function(min = 0, max = 1) { // in order to work 'Math.seed' must NOT be undefined Math.seededRandom = function(min = 0, max = 1) { // in order to work 'Math.seed' must NOT be undefined
Math.seed = (Math.seed * 9301 + 49297) % 233280; Math.seed = (Math.seed * 9301 + 49297) % 233280;
@@ -1109,6 +1111,11 @@ window.addEventListener("keydown", function(event) {
setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 100); setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 100);
setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 200); setTimeout(() => { for (let i = 0, len = mob.length; i < len; ++i) mob[i].damage(Infinity, true) }, 200);
break break
case "l":
document.getElementById("field").style.display = "none"
document.getElementById("guns").style.display = "none"
document.getElementById("tech").style.display = "none"
break
} }
} }
}); });

View File

@@ -16,10 +16,10 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("time dilation") // m.setField("time dilation")
// b.giveGuns("harpoon") b.giveGuns("harpoon")
// for (let i = 0; i < 9; i++) tech.giveTech("smelting") tech.giveTech("railgun")
// tech.giveTech("exchange interaction") // tech.giveTech("necrophage")
// tech.giveTech("grappling hook") // tech.giveTech("isotropic radiator")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// for (let i = 0; i < 3; i++) tech.giveTech("undefined") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true } // for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true }
@@ -32,7 +32,7 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.reactor(); // level.reactor();
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
// level.pavilion() // level.highrise()
if (simulation.isTraining) { level.walk(); } else { level.intro(); } if (simulation.isTraining) { level.walk(); } else { level.intro(); }
// powerUps.research.changeRerolls(3000) // powerUps.research.changeRerolls(3000)
@@ -103,7 +103,8 @@ const level = {
for (let j = 0, len = 5; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false) for (let j = 0, len = 5; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false)
} }
for (let i = 0; i < tech.wimpExperiment; i++) spawn.WIMP() for (let i = 0; i < tech.wimpExperiment; i++) spawn.WIMP()
if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) { // if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true tech.isFlipFlopOn = true
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`); simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
@@ -2538,16 +2539,16 @@ const level = {
spawn.mapRect(4850, -275, 50, 175); spawn.mapRect(4850, -275, 50, 175);
//??? //???
level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
m.addHealth(Infinity) m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
// for (let i = 0; i < 10; ++i) spawn.hopper(1900, -500) for (let i = 0; i < 10; ++i) spawn.hopper(1900, -500)
// spawn.slashBoss(1900, -500) // spawn.slashBoss(1900, -500)
// spawn.launcherBoss(3200, -500) // spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500) // spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(1900, -500) // spawn.powerUpBoss(1900, -500)
spawn.powerUpBossBaby(3200, -500) // spawn.powerUpBossBaby(3200, -500)
// spawn.snakeBoss(1700, -500) // spawn.snakeBoss(1700, -500)
// spawn.streamBoss(3200, -500) // spawn.streamBoss(3200, -500)
// spawn.pulsarBoss(1700, -500) // spawn.pulsarBoss(1700, -500)
@@ -4729,7 +4730,7 @@ const level = {
const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 }, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 }, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
elevator1.addConstraint(); elevator1.addConstraint();
// const button1 = level.button(-500, -200) // const button1 = level.button(-500, -200)
const toggle1 = level.toggle(-500, -200) //(x,y,isOn,isLockOn = true/false) const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false)
const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
elevator2.addConstraint(); elevator2.addConstraint();
@@ -4843,7 +4844,7 @@ const level = {
spawn.bodyRect(-75, -300, 50, 50); spawn.bodyRect(-75, -300, 50, 50);
spawn.mapRect(-600, -200, 500, 250); //ledge for boarding elevator spawn.mapRect(-600, -200, 500, 250); //ledge for boarding elevator
spawn.bodyRect(-250, -300, 100, 100); //a nice block near the elevator spawn.bodyRect(-500, -300, 100, 100, 0.6); //a nice block near the elevator
spawn.bodyRect(-425, -1375, 400, 225); spawn.bodyRect(-425, -1375, 400, 225);
spawn.mapRect(-925, -1575, 50, 475); spawn.mapRect(-925, -1575, 50, 475);

View File

@@ -323,6 +323,7 @@ const m = {
} }
if ( if (
!tech.tech[i].isNonRefundable && !tech.tech[i].isNonRefundable &&
!tech.tech[i].isFromAppliedScience &&
tech.tech[i].name !== "many-worlds" && tech.tech[i].name !== "many-worlds" &&
tech.tech[i].name !== "Ψ(t) collapse" && tech.tech[i].name !== "Ψ(t) collapse" &&
tech.tech[i].name !== "non-unitary operator" && tech.tech[i].name !== "non-unitary operator" &&
@@ -891,7 +892,7 @@ const m = {
isSneakAttack: false, isSneakAttack: false,
duplicateChance: 0, duplicateChance: 0,
energy: 0, energy: 0,
fieldRegen: 0, fieldRegen: 0.001,
fieldMode: 0, fieldMode: 0,
fieldFire: false, fieldFire: false,
fieldHarmReduction: 1, fieldHarmReduction: 1,
@@ -923,7 +924,7 @@ const m = {
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
} }
if (m.energy < m.maxEnergy) m.energy = m.maxEnergy; if (m.energy < m.maxEnergy) m.energy = m.maxEnergy;
m.fieldRegen = 0.001 // m.fieldRegen = 0.001
m.fieldMeterColor = "#0cf" m.fieldMeterColor = "#0cf"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
m.fieldShieldingScale = 1; m.fieldShieldingScale = 1;

View File

@@ -399,7 +399,7 @@ const simulation = {
} }
} }
} }
if (tech.isCrouchAmmo) tech.isCrouchAmmo = 1 //this prevents hacking the tech by switching guns if (tech.crouchAmmoCount) tech.crouchAmmoCount = 1 //this prevents hacking the tech by switching guns
b.activeGun = b.inventory[b.inventoryGun]; b.activeGun = b.inventory[b.inventoryGun];
if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //if switching into foam set charge to 0 if (b.guns[b.activeGun].charge) b.guns[b.activeGun].charge = 0; //if switching into foam set charge to 0
@@ -653,6 +653,7 @@ const simulation = {
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod() if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
if (b.guns[i].name === "super balls") b.guns[i].chooseFireMethod() if (b.guns[i].name === "super balls") b.guns[i].chooseFireMethod()
if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod() if (b.guns[i].name === "harpoon") b.guns[i].chooseFireMethod()
if (b.guns[i].name === "foam") b.guns[i].chooseFireMethod()
} }
tech.dynamoBotCount = 0; tech.dynamoBotCount = 0;
tech.nailBotCount = 0; tech.nailBotCount = 0;
@@ -778,7 +779,7 @@ const simulation = {
} }
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine
if (b.guns[i].name === "mine") { if (b.guns[i].name === "mine") {
if (tech.isCrouchAmmo) count = Math.ceil(count / 2) if (tech.crouchAmmoCount) count = Math.ceil(count / 2)
b.guns[i].ammo += count b.guns[i].ammo += count
if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo) if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo)
simulation.updateGunHUD(); simulation.updateGunHUD();

View File

@@ -610,10 +610,10 @@ const tech = {
}, },
requires: "", requires: "",
effect() { effect() {
tech.isCrouchAmmo = true tech.crouchAmmoCount = true
}, },
remove() { remove() {
tech.isCrouchAmmo = false; tech.crouchAmmoCount = false;
} }
}, },
{ {
@@ -624,7 +624,7 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.isEnergyHealth //(tech.isCrouchAmmo || tech.isCrouchRegen) && return !tech.isEnergyHealth //(tech.crouchAmmoCount || tech.isCrouchRegen) &&
}, },
requires: "not mass-energy", //inductive coupling, desublimated ammunition, requires: "not mass-energy", //inductive coupling, desublimated ammunition,
effect() { effect() {
@@ -821,7 +821,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun || tech.isMineStun return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun
}, },
requires: "a stun effect", requires: "a stun effect",
effect() { effect() {
@@ -1619,7 +1619,7 @@ const tech = {
}, },
{ {
name: "Pauli exclusion", name: "Pauli exclusion",
description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1</strong> extra second`, description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.5</strong> extra seconds`,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1627,8 +1627,8 @@ const tech = {
allowed() { return true }, allowed() { return true },
requires: "", requires: "",
effect() { effect() {
tech.collisionImmuneCycles += 60; tech.collisionImmuneCycles += 90;
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
}, },
remove() { remove() {
tech.collisionImmuneCycles = 30; tech.collisionImmuneCycles = 30;
@@ -1783,24 +1783,24 @@ const tech = {
tech.isFlipFlopEnergy = false; tech.isFlipFlopEnergy = false;
} }
}, },
{ // {
name: "shift registers", // name: "shift registers",
description: "set to the <strong class='color-flop'>ON</strong> state<br>at the start of a <strong>level</strong>", // description: "set to the <strong class='color-flop'>ON</strong> state<br>at the start of a <strong>level</strong>",
maxCount: 1, // maxCount: 1,
count: 0, // count: 0,
frequency: 4, // frequency: 4,
frequencyDefault: 4, // frequencyDefault: 4,
allowed() { // allowed() {
return tech.isFlipFlopEnergy || tech.isFlipFlopDamage || tech.isFlipFlopHarm || tech.relayIce // return tech.isFlipFlopEnergy || tech.isFlipFlopDamage || tech.isFlipFlopHarm || tech.relayIce
}, // },
requires: "2 ON/OFF techs", // requires: "2 ON/OFF techs",
effect() { // effect() {
tech.isFlipFlopLevelReset = true; // tech.isFlipFlopLevelReset = true;
}, // },
remove() { // remove() {
tech.isFlipFlopLevelReset = false; // tech.isFlipFlopLevelReset = false;
} // }
}, // },
{ {
name: "thermocouple", name: "thermocouple",
description: "if <strong>relay switch</strong> is in the <strong class='color-flop'>ON</strong> state<br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals every second", description: "if <strong>relay switch</strong> is in the <strong class='color-flop'>ON</strong> state<br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals every second",
@@ -3341,7 +3341,7 @@ const tech = {
frequencyDefault: 10, frequencyDefault: 10,
isNonRefundable: true, isNonRefundable: true,
allowed() { allowed() {
return tech.duplicationChance() > 0.7 return tech.duplicationChance() > 0.6
}, },
requires: "duplication chance above 70%", requires: "duplication chance above 70%",
effect() { effect() {
@@ -3408,7 +3408,7 @@ const tech = {
effect() { effect() {
let pool = [] let pool = []
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (tech.tech[i].count && !tech.tech[i].isNonRefundable) pool.push(i) if (tech.tech[i].count && !tech.tech[i].isNonRefundable && !tech.tech[i].isFromAppliedScience) pool.push(i)
} }
pool = shuffle(pool); //shuffles order of maps pool = shuffle(pool); //shuffles order of maps
let removeCount = 0 let removeCount = 0
@@ -3645,9 +3645,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (tech.isNeedles || tech.isNeedleShot) && !tech.needleTunnel return (tech.isNeedles || tech.isNeedles) && !tech.needleTunnel
}, },
requires: "nail gun, needle gun, needle-shot, not nanowires", requires: "nail gun, needle gun, not nanowires",
effect() { effect() {
tech.isNeedleIce = true tech.isNeedleIce = true
}, },
@@ -3664,9 +3664,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return ((tech.haveGunCheck("nail gun") && tech.isNeedles) || (tech.isNeedleShot && tech.haveGunCheck("shotgun"))) && !tech.isNeedleIce return ((tech.haveGunCheck("nail gun") && tech.isNeedles) || (tech.isNeedles && tech.haveGunCheck("shotgun"))) && !tech.isNeedleIce
}, },
requires: "needle gun, needle-shot, not needle ice", requires: "needle gun, not needle ice",
effect() { effect() {
tech.needleTunnel = true tech.needleTunnel = true
}, },
@@ -3676,16 +3676,16 @@ const tech = {
}, },
{ {
name: "needle gun", name: "needle gun",
description: "<strong>nail gun</strong> fires <strong>3</strong> mob piercing <strong>needles</strong><br>requires <strong>3</strong> times more <strong>bullets</strong>", description: "<strong>nail gun</strong> and <strong>shot gun</strong> fire mob piercing <strong>needles</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.nailRecoil) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isRivets && !tech.isIncendiary && !tech.isIceCrystals
}, },
requires: "nail gun, not ice crystal, rivets, rotary cannon, or pneumatic actuator", requires: "nail gun, shotgun, not ice crystal, rivets, rotary cannon, or pneumatic, incendiary, nail-shot, rivets, foam-shot, worm-shot, ice-shot",
effect() { effect() {
tech.isNeedles = true tech.isNeedles = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3713,51 +3713,18 @@ const tech = {
} }
} }
}, },
// {
// name: "darts",
// description: "<strong>nail gun</strong> fires firing several <strong>self-steering</strong> darts",
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("nail gun")
// },
// requires: "nail gun",
// effect() {
// tech.isDarts = 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.isDarts) {
// tech.isDarts = 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 gun", name: "rivet gun",
description: "<strong>nail gun</strong> slowly fires a heavy <strong>rivet</strong>", description: "<strong>nail gun</strong> and <strong>shot gun</strong> slowly lob a heavy <strong>rivet</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isNeedles return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isNeedles && !tech.isIceCrystals
}, },
requires: "nail gun, not ice crystal, needles, or pneumatic actuator", requires: "nail gun shot gun, not ice crystal, needles, or pneumatic actuator",
effect() { effect() {
tech.isRivets = true tech.isRivets = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3777,21 +3744,71 @@ const tech = {
} }
} }
} }
tech.isRivets = false
} }
}, },
// {
// name: "slug",
// description: "<strong>shotgun</strong> lobs <strong>1</strong> huge <strong>bullet</strong>",
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isIceShot && !tech.isFoamShot && !tech.isSporeWorm && !tech.isNeedles
// },
// requires: "shotgun, not nail-shot, foam-shot, worm-shot, ice-shot, needle-shot",
// effect() {
// tech.isSlugShot = true;
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "shotgun") {
// b.guns[i].do = function() {
// if (!input.field && input.down) {
// ctx.beginPath()
// const speed = input.down ? 212 : 160
// const v = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) } //m.Vy / 2 + removed to make the path less jerky
// const where = { x: m.pos.x, y: m.pos.y }
// for (let i = 0; i < 20; i++) {
// v.x *= 0.9712
// v.y = v.y * 0.977 + 9.87
// where.x += v.x
// where.y += v.y
// ctx.lineTo(where.x, where.y)
// }
// ctx.strokeStyle = "rgba(68, 68, 68, 0.2)" //color.map
// ctx.lineWidth = 2
// ctx.stroke()
// }
// }
// break
// }
// }
// },
// remove() {
// if (tech.isSlugShot) {
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
// if (b.guns[i].name === "shotgun") {
// b.guns[i].do = function() {}
// break
// }
// }
// }
// tech.isSlugShot = false;
// }
// },
{ {
name: "pneumatic hammer", name: "pneumatic hammer",
description: `<span style = 'font-size:95%;'><strong>rivets</strong>, <strong>slugs</strong>, <strong>needles</strong>, and <strong>nails</strong> are <strong>18%</strong> larger</span><br>increases mass and physical <strong class='color-d'>damage</strong>`, description: `<span style = 'font-size:95%;'><strong>rivets</strong>, <strong>needles</strong>, and <strong>nails</strong> are <strong>18%</strong> larger</span><br>increases mass and physical <strong class='color-d'>damage</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
// return tech.haveGunCheck("nail gun") || tech.isSlugShot return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedleShot + tech.isNailShot + tech.isSlugShot) * 2 > 1
}, },
requires: "nails, nail gun, rivets, shotgun, slug", requires: "nails, nail gun, rivets, shotgun",
effect() { effect() {
tech.nailSize += 0.18 tech.nailSize += 0.18
}, },
@@ -3901,9 +3918,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (tech.isNailShot || tech.isNeedleShot || tech.nailBotCount > 1 || tech.haveGunCheck("nail gun")) return (tech.isNailShot || tech.isNeedles || tech.nailBotCount > 1 || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary
}, },
requires: "nail gun, nails", requires: "needles, nails, rivets, not incendiary",
effect() { effect() {
tech.isNailCrit = true tech.isNailCrit = true
}, },
@@ -3921,7 +3938,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) + tech.isNeedleShot + tech.isNailShot) * 2 > 1 return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) + tech.isNeedles + tech.isNailShot) * 2 > 1
}, },
requires: "nail gun, nails, rivets, not ceramic needles", requires: "nail gun, nails, rivets, not ceramic needles",
effect() { effect() {
@@ -4050,56 +4067,6 @@ const tech = {
tech.isShotgunReversed = false; tech.isShotgunReversed = false;
} }
}, },
{
name: "slug",
description: "<strong>shotgun</strong> lobs <strong>1</strong> huge <strong>bullet</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot
},
requires: "shotgun, not nail-shot, foam-shot, worm-shot, ice-shot, needle-shot",
effect() {
tech.isSlugShot = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "shotgun") {
b.guns[i].do = function() {
if (!input.field && input.down) {
ctx.beginPath()
const speed = input.down ? 212 : 160
const v = { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) } //m.Vy / 2 + removed to make the path less jerky
const where = { x: m.pos.x, y: m.pos.y }
for (let i = 0; i < 20; i++) {
v.x *= 0.9712
v.y = v.y * 0.977 + 9.87
where.x += v.x
where.y += v.y
ctx.lineTo(where.x, where.y)
}
ctx.strokeStyle = "rgba(68, 68, 68, 0.2)" //color.map
ctx.lineWidth = 2
ctx.stroke()
}
}
break
}
}
},
remove() {
if (tech.isSlugShot) {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "shotgun") {
b.guns[i].do = function() {}
break
}
}
}
tech.isSlugShot = false;
}
},
{ {
name: "nail-shot", name: "nail-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Nail_(fastener)' class="link">nail-shot</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Nail_(fastener)' class="link">nail-shot</a>`,
@@ -4110,9 +4077,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isSporeWorm && !tech.isNeedles
}, },
requires: "shotgun, not incendiary, slug, foam-shot, worm-shot, ice-shot, needle-shot", requires: "shotgun, not incendiary, rivets, foam-shot, worm-shot, ice-shot, needles",
effect() { effect() {
tech.isNailShot = true; tech.isNailShot = true;
}, },
@@ -4120,46 +4087,6 @@ const tech = {
tech.isNailShot = false; tech.isNailShot = false;
} }
}, },
{
name: "needle-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Needle' class="link">needle-shot</a>`,
description: "<strong>shotgun</strong> propels <strong>11</strong> mob piercing <strong>needles</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isIceShot
},
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot, ice-shot",
effect() {
tech.isNeedleShot = true;
},
remove() {
tech.isNeedleShot = false;
}
},
{
name: "worm-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Worm' class="link">worm-shot</a>`,
description: "<strong>shotgun</strong> hatches <strong>3-4</strong> mob seeking <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><em>worms benefit from spore technology</em>", //<br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> seek out nearby mobs
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedleShot
},
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, ice-shot, needle-shot",
effect() {
tech.isWormShot = true;
},
remove() {
tech.isWormShot = false;
}
},
{ {
name: "foam-shot", name: "foam-shot",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Foam' class="link">foam-shot</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Foam' class="link">foam-shot</a>`,
@@ -4170,9 +4097,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isIceShot && !tech.isWormShot && !tech.isNeedleShot return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isSporeWorm && !tech.isNeedles
}, },
requires: "shotgun, not incendiary, nail-shot, slug, worm-shot, ice-shot, needle-shot", requires: "shotgun, not incendiary, nail-shot, rivet, worm-shot, ice-shot, needle",
effect() { effect() {
tech.isFoamShot = true; tech.isFoamShot = true;
}, },
@@ -4190,9 +4117,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isSlugShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isRivets && !tech.isFoamShot && !tech.isSporeWorm && !tech.isNeedles
}, },
requires: "shotgun, not incendiary, nail-shot, slug, foam-shot, worm-shot", requires: "shotgun, not incendiary, nail-shot, rivet, foam-shot, worm-shot",
effect() { effect() {
tech.isIceShot = true; tech.isIceShot = true;
}, },
@@ -4202,16 +4129,16 @@ const tech = {
}, },
{ {
name: "incendiary ammunition", name: "incendiary ammunition",
description: "<strong>shotgun</strong>, <strong>super balls</strong>, and <strong>drones</strong><br>are loaded with <strong class='color-e'>explosives</strong>", description: "<strong>rivets</strong>, <strong>super balls</strong>, and <strong>drones</strong><br>are loaded with <strong class='color-e'>explosives</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return ((m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedleShot return tech.haveGunCheck("super balls") || (tech.isRivets && !tech.isNailCrit) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport)
}, },
requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", requires: "super balls, rivets, drones, not irradiated drones or burst drones",
effect() { effect() {
tech.isIncendiary = true tech.isIncendiary = true
}, },
@@ -4534,16 +4461,16 @@ const tech = {
}, },
{ {
name: "fragmentation", name: "fragmentation",
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, grenades, missiles, slugs, harpoon</em>", description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, grenades, missiles, rivets, harpoon</em>",
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || (tech.haveGunCheck("shotgun") && tech.isSlugShot) || tech.blockDamage > 0.075 return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075
}, },
requires: "grenades, missiles, shotgun slugs, harpoon, or mass driver", requires: "grenades, missiles, rivets, harpoon, or mass driver",
effect() { effect() {
tech.fragments++ tech.fragments++
}, },
@@ -4611,14 +4538,14 @@ const tech = {
}, },
{ {
name: "shock wave", name: "shock wave",
description: "<strong class='color-e'>explosions</strong> <strong>stun</strong> mobs for <strong>1-2</strong> seconds<br>decrease <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>30%</strong>", description: "<strong>mines</strong> and <strong class='color-e'>explosions</strong> <strong>stun</strong> for <strong>1-2</strong> seconds<br>decrease <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>30%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() return tech.haveGunCheck("mine") || (!tech.isExplodeRadio && tech.hasExplosiveDamageCheck())
}, },
requires: "an explosive damage source, not iridium-192", requires: "an explosive damage source, not iridium-192",
effect() { effect() {
@@ -4628,6 +4555,26 @@ const tech = {
tech.isExplosionStun = false; tech.isExplosionStun = false;
} }
}, },
// {
// name: "blast mines",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Anti-personnel_mine' class="link">blast mines</a>`,
// description: "when a <strong>mine</strong> <strong>activates</strong><br>it <strong>stuns</strong> nearby mobs for <strong>2-4</strong> seconds",
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("mine")
// },
// requires: "mines",
// effect() {
// tech.isMineStun = true;
// },
// remove() {
// tech.isMineStun = false;
// }
// },
{ {
name: "controlled explosion", name: "controlled explosion",
description: `use ${powerUps.orb.research(3)} to dynamically <strong>reduce</strong> all<br><strong class='color-e'>explosions</strong> until they do no <strong class='color-harm'>harm</strong>`, description: `use ${powerUps.orb.research(3)} to dynamically <strong>reduce</strong> all<br><strong class='color-e'>explosions</strong> until they do no <strong class='color-harm'>harm</strong>`,
@@ -4895,26 +4842,6 @@ const tech = {
tech.isMineSentry = false; tech.isMineSentry = false;
} }
}, },
{
name: "blast mines",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Anti-personnel_mine' class="link">blast mines</a>`,
description: "when a <strong>mine</strong> <strong>activates</strong><br>it <strong>stuns</strong> nearby mobs for <strong>2-4</strong> seconds",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("mine")
},
requires: "mines",
effect() {
tech.isMineStun = true;
},
remove() {
tech.isMineStun = false;
}
},
{ {
name: "mycelial fragmentation", name: "mycelial fragmentation",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Fungus' class="link">mycelial fragmentation</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Fungus' class="link">mycelial fragmentation</a>`,
@@ -4965,7 +4892,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm
}, },
requires: "spore gun, spores or worms", requires: "spore gun, spores or worms",
effect() { effect() {
@@ -4984,7 +4911,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormShot return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm
}, },
requires: "spore gun, spores or worms", requires: "spore gun, spores or worms",
effect() { effect() {
@@ -5003,7 +4930,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isWormShot return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isSporeWorm
}, },
requires: "spore gun, spores, worms, not mass-energy", requires: "spore gun, spores, worms, not mass-energy",
effect() { effect() {
@@ -5013,16 +4940,36 @@ const tech = {
tech.isMutualism = false tech.isMutualism = false
} }
}, },
// {
// name: "worm-shot",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Worm' class="link">worm-shot</a>`,
// description: "<strong>shotgun</strong> hatches <strong>3-4</strong> mob seeking <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><em>worms benefit from spore technology</em>", //<br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> seek out nearby mobs
// isGunTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles
// },
// requires: "shotgun, not incendiary, nail-shot, rivets, foam-shot, ice-shot, needles",
// effect() {
// tech.isWormShot = true;
// },
// remove() {
// tech.isWormShot = false;
// }
// },
{ {
name: "nematodes", name: "nematodes",
description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>250%</strong> more <strong class='color-d'>damage</strong>", description: "<strong>shotgun</strong> and <strong class='color-p' style='letter-spacing: 2px;'>sporangium</strong> hatch <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong>", //<br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>250%</strong> more <strong class='color-d'>damage</strong>
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormholeSpores return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormholeSpores || (tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles && !tech.isNailShot)
}, },
requires: "spore gun, spores", requires: "spore gun, spores",
effect() { effect() {
@@ -5041,7 +4988,7 @@ const tech = {
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return tech.isSporeWorm || tech.isWormShot return tech.isSporeWorm
}, },
requires: "spore gun, shotgun, worms", requires: "spore gun, shotgun, worms",
effect() { effect() {
@@ -5051,25 +4998,6 @@ const tech = {
tech.wormSize = 0 tech.wormSize = 0
} }
}, },
{
name: "necrophage",
description: "if <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>they reset their <strong>lifespan</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isSporeWorm || tech.isWormShot
},
requires: "spore gun, shotgun, worms",
effect() {
tech.wormSurviveDmg = true
},
remove() {
tech.wormSurviveDmg = false
}
},
{ {
name: "anti-shear topology", name: "anti-shear topology",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Topology' class="link">anti-shear topology</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Topology' class="link">anti-shear topology</a>`,
@@ -5080,7 +5008,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isWormShot || tech.foamBotCount > 1 return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.foamBotCount > 1
}, },
requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX", requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX",
effect() { effect() {
@@ -5143,7 +5071,7 @@ const tech = {
{ {
name: "drone repair", name: "drone repair",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unmanned_aerial_vehicle' class="link">drone repair</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unmanned_aerial_vehicle' class="link">drone repair</a>`,
description: "after a <strong>drone</strong> expires it <strong>redeploys</strong><br>for a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong> <strong class='color-ammo'>ammo</strong>", description: "after a <strong>drone</strong> expires it <strong>redeploys</strong><br>for a <strong>20%</strong> chance to use <strong>1</strong> <strong>drone</strong> <strong class='color-ammo'>ammo</strong>",
// description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>", // description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -5276,7 +5204,7 @@ const tech = {
}, },
{ {
name: "fault tolerance", name: "fault tolerance",
description: "spawn <strong>8</strong> <strong>drones</strong> that last <strong>forever</strong><br>remove your <strong>drone gun</strong>", description: "spawn <strong>6</strong> <strong>drones</strong> that last <strong>forever</strong><br>remove your <strong>drone gun</strong>",
isGunTech: true, isGunTech: true,
isRemoveGun: true, isRemoveGun: true,
maxCount: 1, maxCount: 1,
@@ -5288,7 +5216,7 @@ const tech = {
}, },
requires: "drones, not drone repair, anti-shear topology", requires: "drones, not drone repair, anti-shear topology",
effect() { effect() {
const num = 8 const num = 6
tech.isForeverDrones += num tech.isForeverDrones += num
if (tech.haveGunCheck("drones", false)) b.removeGun("drones") if (tech.haveGunCheck("drones", false)) b.removeGun("drones")
//spawn drones //spawn drones
@@ -5311,7 +5239,7 @@ const tech = {
}, },
{ {
name: "surfactant", name: "surfactant",
description: "trade your <strong>foam gun</strong> for <strong>2</strong> <strong class='color-bot'>foam-bots</strong><br>and <strong>upgrade</strong> all bots to foam<br>", description: "trade your <strong>foam gun</strong> for <strong>2</strong> <strong class='color-bot'>foam-bots</strong><br>and <strong>upgrade</strong> all bots to foam",
isGunTech: true, isGunTech: true,
isRemoveGun: true, isRemoveGun: true,
maxCount: 1, maxCount: 1,
@@ -5321,9 +5249,9 @@ const tech = {
isBot: true, isBot: true,
isBotTech: true, isBotTech: true,
isNonRefundable: true, isNonRefundable: true,
requires: "foam gun, NOT EXPERIMENT MODE, bot upgrades, fractionation, quantum foam", requires: "at least 3 guns, foam gun, NOT EXPERIMENT MODE, bot upgrades, fractionation, quantum foam, capacitor",
allowed() { allowed() {
return tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.foamFutureFire return b.inventory.length > 2 && tech.haveGunCheck("foam", false) && !b.hasBotUpgrade() && !tech.isAmmoFoamSize && !tech.foamFutureFire && !tech.isCapacitor
}, },
effect() { effect() {
tech.giveTech("foam-bot upgrade") tech.giveTech("foam-bot upgrade")
@@ -5381,22 +5309,22 @@ const tech = {
} }
}, },
{ {
name: "necrophoresis", name: "necrophage",
description: "<strong>foam</strong> bubbles grow and split into 3 <strong>copies</strong><br> when the mob they are stuck to <strong>dies</strong>", description: "if <strong>foam</strong> or <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>grow 3 <strong>copies</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isSporeWorm
}, },
requires: "foam", requires: "foam, worms",
effect() { effect() {
tech.isFoamGrowOnDeath = true tech.isSpawnBulletsOnDeath = true
}, },
remove() { remove() {
tech.isFoamGrowOnDeath = false; tech.isSpawnBulletsOnDeath = false;
} }
}, },
{ {
@@ -5473,14 +5401,26 @@ const tech = {
requires: "throwing blocks, railgun, foam, pulse, tokamak", requires: "throwing blocks, railgun, foam, pulse, tokamak",
effect() { effect() {
tech.isCapacitor = true; tech.isCapacitor = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "foam") {
b.guns[i].chooseFireMethod()
break
}
}
}, },
remove() { remove() {
tech.isCapacitor = false; tech.isCapacitor = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "foam") {
b.guns[i].chooseFireMethod()
break
}
}
} }
}, },
{ {
name: "railgun", name: "railgun",
description: `<strong>harpoons</strong> are <strong>50% denser</strong>, but don't <strong>retract</strong><br>gain <strong>500%</strong> more harpoon <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`, description: `<strong>harpoons</strong> are <strong>50% denser</strong>, but don't <strong>retract</strong><br>gain <strong>600%</strong> more harpoon <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5490,7 +5430,7 @@ const tech = {
return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple
}, },
requires: "harpoon, not filament, toggling harpoon, grappling hook", requires: "harpoon, not filament, toggling harpoon, grappling hook",
ammoBonus: 5, ammoBonus: 6,
effect() { effect() {
tech.isRailGun = true; tech.isRailGun = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -5558,7 +5498,7 @@ const tech = {
// }, // },
{ {
name: "grappling hook", name: "grappling hook",
description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you in<br>your <strong>rope</strong> extends while holding <strong>fire</strong>`, description: `<strong>harpoons</strong> attach to the <strong>map</strong> and pull you<br>your <strong>rope</strong> extends while holding <strong>fire</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5630,9 +5570,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || (tech.isNeedles || tech.isNeedleShot) return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles
}, },
requires: "nail gun, needle gun, needle-shot, harpoon, not Bessemer process", requires: "nail gun, needle gun, needle, harpoon, not Bessemer process",
effect() { effect() {
tech.isShieldPierce = true tech.isShieldPierce = true
}, },
@@ -5662,28 +5602,29 @@ const tech = {
{ {
name: "smelting", name: "smelting",
// description: `spend ${powerUps.orb.ammo(2)}to upgrade the <strong>harpoon</strong><br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot`, // description: `spend ${powerUps.orb.ammo(2)}to upgrade the <strong>harpoon</strong><br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot`,
description: `forge <strong>2</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot`, description: `forge <strong>3</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot`,
// descriptionFunction() { return `forge <strong>${tech.isRailGun? 10: 2}</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot` }, // descriptionFunction() { return `forge <strong>${tech.isRailGun? 10: 2}</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot` },
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') > 1 + this.count * 2 return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') > 2 + this.count * 3
}, },
requires: "harpoon", requires: "harpoon",
effect() { effect() {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "harpoon") { if (b.guns[i].name === "harpoon") {
b.guns[i].ammo -= 2 + this.count b.guns[i].ammo -= 3 + this.count * 3
console.log(3 + this.count * 3)
if (b.guns[i].ammo < 0) b.guns[i].ammo = 0 if (b.guns[i].ammo < 0) b.guns[i].ammo = 0
simulation.updateGunHUD(); simulation.updateGunHUD();
tech.extraHarpoons++; tech.extraHarpoons++;
break break
} }
} }
this.description = `forge <strong>${2+(this.count+1)*2}</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot` this.description = `forge <strong>${3+(this.count+1)*3}</strong> <strong class='color-ammo'>ammo</strong> into a new harpoon<br>fire <strong>+1</strong> <strong>harpoon</strong> with each shot`
}, },
remove() { remove() {
if (tech.extraHarpoons) { if (tech.extraHarpoons) {
@@ -5930,7 +5871,7 @@ const tech = {
}, },
{ {
name: "output coupler", name: "output coupler",
description: "<strong>widen</strong> diffuse <strong class='color-laser'>laser</strong> beam by <strong>40%</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>40%</strong>", description: "<strong>widen</strong> diffuse <strong class='color-laser'>laser</strong> beam by <strong>30%</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>30%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -6167,7 +6108,7 @@ const tech = {
}, },
{ {
name: "eddy current brake", name: "eddy current brake",
description: "project a field that limits the <strong>top speed</strong> of mobs<br>field <strong>radius</strong> scales with stored <strong class='color-f'>energy</strong>", description: "<strong>perfect diamagnetism</strong> <strong class='color-s'>slows</strong> nearby mobs<br>effect <strong>radius</strong> scales with stored <strong class='color-f'>energy</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -9188,7 +9129,7 @@ const tech = {
bulletSize: null, bulletSize: null,
energySiphon: null, energySiphon: null,
healthDrain: null, healthDrain: null,
isCrouchAmmo: null, crouchAmmoCount: null,
isBulletsLastLonger: null, isBulletsLastLonger: null,
isImmortal: null, isImmortal: null,
sporesOnDeath: null, sporesOnDeath: null,
@@ -9378,7 +9319,7 @@ const tech = {
isFlipFlop: null, isFlipFlop: null,
isFlipFlopHarm: null, isFlipFlopHarm: null,
isFlipFlopOn: null, isFlipFlopOn: null,
isFlipFlopLevelReset: null, // isFlipFlopLevelReset: null,
isFlipFlopDamage: null, isFlipFlopDamage: null,
isFlipFlopEnergy: null, isFlipFlopEnergy: null,
isRelay: null, isRelay: null,
@@ -9430,17 +9371,13 @@ const tech = {
isFastTime: null, isFastTime: null,
isAnthropicTech: null, isAnthropicTech: null,
isSporeWorm: null, isSporeWorm: null,
isWormShot: null,
isFoamShot: null, isFoamShot: null,
isIceShot: null, isIceShot: null,
isNeedleShot: null,
isBlockRestitution: null, isBlockRestitution: null,
isZeno: null, isZeno: null,
isFieldFree: null, isFieldFree: null,
wormSurviveDmg: null,
isExtraGunField: null, isExtraGunField: null,
isBigField: null, isBigField: null,
isMineStun: null,
isSmartRadius: null, isSmartRadius: null,
isFilament: null, isFilament: null,
isLargeHarpoon: null, isLargeHarpoon: null,

View File

@@ -1,19 +1,55 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
grapple goes 40% farther before it retracts automatically railgun and foam have a bit more ammo
grapple now works well with fire delay reduction capacitor bank makes foam gun fire a stream of foam
or it's annoying, you decide! tech shift registers is now always on
smelting cost more ammo as you increase stacks (set ON/OFF to ON at the start of a new level)
tech from applied science doesn't count for various tech that convert tech into other things (pure science, many worlds)
grappling hook now shows hooks on the grapple
grappling hook tech: bulk modulus - immune to harm while grappling, but drain a bit of energy merged similar gun tech
needle gun+needle shot
particle collider renamed pure science - and it gives 1 research instead of energy when it fails: 4% chance rivet gun+shotgun slug
shockwave+blast mines
nematodes+worm-shot
necrophoresis+necrophage
the worm aspect now spawns 3 copies instead of just a lifespan reset
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
buff railgun
damage? ammo?
make railgun push blocks in the same direction railgun moves
make block intangible for a sec, like a block throw
buff drone tech, but not drones?
const ctx = canvas.getContext('2d', {willReadFrequently': true});
//deal with game crashes?
canvas.addEventListener("contextlost", onContextLost);
canvas.addEventListener("contextrestored", redraw);
ctx.reset();
a mine tech that makes mines you can stand on
works similar to the field block throwing system
but you don't need to find a block to throw
blocks explode after mobs touch them
or 3 seconds after you touch them
benefits from all block tech
setting to remove UI, except health bar
except active gun? to see ammo
checkbox in pause and in settings
bug: often game puts player position at NaN
clues:
after apoximis?
vanish level?
very high level for tech, duplication
maybe not about JUNK though
grappling hook grappling hook
draw the hook part directly
two backwards angled spikes near the front
give player more control over motion while hanging and retracting give player more control over motion while hanging and retracting
reduce friction effects so player swing around? reduce friction effects so player swing around?
up down left right push player around? up down left right push player around?
@@ -27,10 +63,6 @@ add coyote jump
log game m.cycle when last on ground log game m.cycle when last on ground
for jump check if game cycle is < last on ground cycle -2 for jump check if game cycle is < last on ground cycle -2
setting to remove UI, except health bar
except active gun? to see ammo
checkbox in pause and in settings
tech - Plasma railgun tech - Plasma railgun
like foam, or phonon? like foam, or phonon?
@@ -41,6 +73,8 @@ pause time like invariant for other things...
bug - url sharing still broken sometimes bug - url sharing still broken sometimes
maybe? timing QTE for charging effects, if you fire right before the charge gets full it's better
+damage for each different bot type you have +damage for each different bot type you have
disables bot upgrades? disables bot upgrades?