Bitter electromagnet

harpoon
  default fire rate is 10% higher
  default harpoon range 15% higher
railgun
  tech: Bitter electromagnet - 33% slower charge time for railgun, 100% more density and damage
    area effect damage is increased 20%, scales with bitter electromagnet and total charge
  charging longer increases harpoon velocity/damage by up to 30%
  contributions to charge time are more uniform between:
    crouching, fire rate, Bitter electromagnet, and capacitor bank
  auto aims no longer disabled on crouch

emergence 2->1 extra choice, and +8% damage, and no added JUNK anymore
cache 16->15x ammo
many-worlds 1->0 research to enter an alternate reality on each new level

finalBoss
  health decays a bit faster
  spawns 6 mobs at each health threshold
  spawns from the different modes are reduced
  boss laser damage is 25% reduced
  hoppers spawn from the slime tunnel

JUNKtech: random - gives random +damage

bug fixes
This commit is contained in:
landgreen
2022-10-31 19:15:21 -07:00
parent f8188565a0
commit 500bb3f73e
9 changed files with 299 additions and 165 deletions

View File

@@ -1688,7 +1688,7 @@ const b = {
}); });
Composite.add(engine.world, bullet[me]); //add bullet to world Composite.add(engine.world, bullet[me]); //add bullet to world
}, },
harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true) { harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.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: -40 * harpoonSize, y: 2 * harpoonSize, index: 0, isInternal: false }, { x: -40 * harpoonSize, y: -2 * harpoonSize, index: 1, isInternal: false }, { x: 50 * harpoonSize, y: -3 * harpoonSize, index: 3, isInternal: false }, { x: 30 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], { bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -40 * harpoonSize, y: 2 * harpoonSize, index: 0, isInternal: false }, { x: -40 * harpoonSize, y: -2 * harpoonSize, index: 1, isInternal: false }, { x: 50 * harpoonSize, y: -3 * harpoonSize, index: 3, isInternal: false }, { x: 30 * harpoonSize, y: 2 * harpoonSize, index: 4, isInternal: false }], {
@@ -1696,7 +1696,7 @@ const b = {
angle: angle, angle: angle,
friction: 1, friction: 1,
frictionAir: 0.4, frictionAir: 0.4,
thrustMag: 0.1, // thrustMag: 0.1,
drain: tech.isRailEnergy ? 0.001 : 0.006, drain: tech.isRailEnergy ? 0.001 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015 turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(), drawStringControlMagnitude: 3000 + 5000 * Math.random(),
@@ -1808,7 +1808,7 @@ const b = {
if (m.energy < 0.05) { if (m.energy < 0.05) {
m.fireCDcycle = m.cycle + 120; //fire cooldown m.fireCDcycle = m.cycle + 120; //fire cooldown
} else if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) { } else if (m.cycle + 25 * b.fireCDscale < m.fireCDcycle) {
m.fireCDcycle = m.cycle + 35 * b.fireCDscale //lower cd to 25 if it is above 25 m.fireCDcycle = m.cycle + 25 * b.fireCDscale //lower cd to 25 if it is above 25
} }
//recoil on catching //recoil on catching
const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (input.down ? 0.0001 : 0.0002)) const momentum = Vector.mult(Vector.sub(this.velocity, player.velocity), (input.down ? 0.0001 : 0.0002))
@@ -1828,7 +1828,7 @@ const b = {
if (m.energy > this.drain) m.energy -= this.drain if (m.energy > this.drain) m.energy -= this.drain
const sub = Vector.sub(this.position, m.pos) const sub = Vector.sub(this.position, m.pos)
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass) const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * thrust * this.mass)
this.force.x -= returnForce.x this.force.x -= returnForce.x
this.force.y -= returnForce.y this.force.y -= returnForce.y
this.grabPowerUp() this.grabPowerUp()
@@ -1850,7 +1850,7 @@ const b = {
Matter.Body.setPosition(powerUp[i], this.vertices[2]) Matter.Body.setPosition(powerUp[i], this.vertices[2])
powerUp[i].collisionFilter.category = 0 powerUp[i].collisionFilter.category = 0
powerUp[i].collisionFilter.mask = 0 powerUp[i].collisionFilter.mask = 0
this.thrustMag *= 0.6 thrust *= 0.6
this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early this.endCycle += 0.5 //it pulls back slower, so this prevents it from ending early
break //just pull 1 power up if possible break //just pull 1 power up if possible
} }
@@ -1887,16 +1887,16 @@ const b = {
Matter.Body.rotate(this, -this.turnRate); Matter.Body.rotate(this, -this.turnRate);
} }
} }
this.force.x += this.thrustMag * this.mass * Math.cos(this.angle); this.force.x += thrust * this.mass * Math.cos(this.angle);
this.force.y += this.thrustMag * this.mass * Math.sin(this.angle); this.force.y += thrust * this.mass * Math.sin(this.angle);
} }
this.draw() this.draw()
}, },
}); });
if (!isReturn && !target) { if (!isReturn && !target) {
Matter.Body.setVelocity(bullet[me], { Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + 60 * Math.cos(bullet[me].angle), x: m.Vx / 2 + 600 * thrust * Math.cos(bullet[me].angle),
y: m.Vy / 2 + 60 * Math.sin(bullet[me].angle) y: m.Vy / 2 + 600 * thrust * Math.sin(bullet[me].angle)
}); });
bullet[me].frictionAir = 0.002 bullet[me].frictionAir = 0.002
bullet[me].do = function() { bullet[me].do = function() {
@@ -6790,7 +6790,7 @@ const b = {
} }
//fire //fire
if ((!input.fire && this.charge > 0.6)) { if ((!input.fire && this.charge > 0.6)) {
tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed // tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
const where = { const where = {
x: m.pos.x + 30 * Math.cos(m.angle), x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle) y: m.pos.y + 30 * Math.sin(m.angle)
@@ -6800,8 +6800,9 @@ const b = {
target: null target: null
} }
//push away blocks and mobs //push away blocks and mobs
const range = 1200 * this.charge const range = 600 + 500 * this.charge
for (let i = 0, len = mob.length; i < len; ++i) { //push away mobs when firing for (let i = 0, len = mob.length; i < len; ++i) { //push away mobs when firing
if (!mob[i].isUnblockable) {
const SUB = Vector.sub(mob[i].position, m.pos) const SUB = Vector.sub(mob[i].position, m.pos)
const DISTANCE = Vector.magnitude(SUB) const DISTANCE = Vector.magnitude(SUB)
if (DISTANCE < range + mob[i].radius) { if (DISTANCE < range + mob[i].radius) {
@@ -6810,17 +6811,18 @@ const b = {
mob[i].force.x += FORCE.x; mob[i].force.x += FORCE.x;
mob[i].force.y += FORCE.y; mob[i].force.y += FORCE.y;
let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 0.1 : 0.4) let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 350 : 1100) * tech.harpoonDensity * this.charge
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x, x: mob[i].position.x,
y: mob[i].position.y, y: mob[i].position.y,
radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3, radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3,
color: 'rgba(100, 0, 200, 0.2)', color: 'rgba(100, 0, 200, 0.4)',
time: 15 time: 15
}); });
mob[i].damage(dmg); mob[i].damage(dmg);
} }
} }
}
for (let i = 0, len = body.length; i < len; ++i) { //push away blocks when firing for (let i = 0, len = body.length; i < len; ++i) { //push away blocks when firing
const SUB = Vector.sub(body[i].position, m.pos) const SUB = Vector.sub(body[i].position, m.pos)
const DISTANCE = Vector.magnitude(SUB) const DISTANCE = Vector.magnitude(SUB)
@@ -6841,13 +6843,26 @@ const b = {
powerUp[i].force.y += FORCE.y - powerUp[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc powerUp[i].force.y += FORCE.y - powerUp[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc
} }
} }
//draw little dots near the edge of range
for (let i = 0, len = 10 + 25 * this.charge; i < len; i++) {
const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random())
const where = Vector.add(m.pos, Vector.mult(unit, range * (0.6 + 0.3 * Math.random())))
simulation.drawList.push({
x: where.x,
y: where.y,
radius: 5 + 12 * Math.random(),
color: "rgba(100, 0, 200, 0.1)",
time: Math.floor(5 + 35 * Math.random())
});
}
const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.03 : 0.06) const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.03 : 0.06)
player.force.x -= recoil.x player.force.x -= recoil.x
player.force.y -= recoil.y player.force.y -= recoil.y
tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed // tech.harpoonDensity = 0.0065 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
const harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1 const harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1
const thrust = 0.15 * (this.charge)
if (tech.extraHarpoons) { if (tech.extraHarpoons) {
let targetCount = 0 let targetCount = 0
const SPREAD = 0.06 + 0.05 * (!input.down) const SPREAD = 0.06 + 0.05 * (!input.down)
@@ -6861,7 +6876,7 @@ const b = {
if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target
// if (this.ammo > -1) { // if (this.ammo > -1) {
// this.ammo-- // this.ammo--
b.harpoon(where, input.down ? null : mob[i], angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 }) b.harpoon(where, input.down ? null : mob[i], angle, harpoonSize, false, 35, false, thrust) //harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
angle += SPREAD angle += SPREAD
targetCount++ targetCount++
if (targetCount > tech.extraHarpoons) break if (targetCount > tech.extraHarpoons) break
@@ -6873,14 +6888,10 @@ const b = {
if (targetCount < tech.extraHarpoons + 1) { if (targetCount < tech.extraHarpoons + 1) {
const num = tech.extraHarpoons + 1 - targetCount const num = tech.extraHarpoons + 1 - targetCount
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
// if (this.ammo > -1) { b.harpoon(where, null, angle, harpoonSize, false, 35, false, thrust)
// this.ammo--
b.harpoon(where, null, angle, harpoonSize, false)
angle += SPREAD angle += SPREAD
// }
} }
} }
// this.ammo++ //make up for the ammo used up in fire()
simulation.updateGunHUD(); simulation.updateGunHUD();
} else { } else {
//look for closest mob in player's LoS //look for closest mob in player's LoS
@@ -6895,7 +6906,7 @@ const b = {
} }
} }
} }
b.harpoon(where, input.down ? null : closest.target, m.angle, harpoonSize, false) b.harpoon(where, closest.target, m.angle, harpoonSize, false, 35, false, thrust)
} }
this.charge = 0; this.charge = 0;
@@ -6909,13 +6920,18 @@ const b = {
player.force.y = 0 player.force.y = 0
} }
m.fireCDcycle = m.cycle + 10 //can't fire until mouse is released m.fireCDcycle = m.cycle + 10 //can't fire until mouse is released
const previousCharge = this.charge // const previousCharge = this.charge
//small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
let smoothRate = tech.isCapacitor ? 0.85 : Math.min(0.998, 0.985 * (0.98 + 0.02 * b.fireCDscale))
if (input.down) smoothRate *= 0.995
this.charge = this.charge * smoothRate + 1 - smoothRate //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
// let smoothRate = tech.isCapacitor ? 0.85 : Math.min(0.998, 0.985 * (0.98 + 0.02 * b.fireCDscale))
const rate = Math.sqrt(b.fireCDscale) * tech.railChargeRate * (tech.isCapacitor ? 0.6 : 1) * (input.down ? 0.8 : 1)
let smoothRate = Math.min(0.998, 0.94 + 0.05 * rate)
this.charge = 1 - smoothRate + this.charge * smoothRate
if (m.energy > DRAIN) m.energy -= DRAIN if (m.energy > DRAIN) m.energy -= DRAIN
// console.log((this.charge).toFixed(2))
// m.energy += (this.charge - previousCharge) * ((tech.isRailEnergy ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen // m.energy += (this.charge - previousCharge) * ((tech.isRailEnergy ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
//draw magnetic field //draw magnetic field
@@ -6936,9 +6952,11 @@ const b = {
X, Y) X, Y)
} }
ctx.fillStyle = `rgba(50,0,100,0.05)`; ctx.fillStyle = `rgba(50,0,100,0.05)`;
const magSize = 8 * this.charge * tech.railChargeRate ** 3
const arcSize = 6 * this.charge * tech.railChargeRate ** 3
for (let i = 3; i < 7; i++) { for (let i = 3; i < 7; i++) {
const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random()) const MAG = magSize * i * i * (0.93 + 0.07 * Math.random())
const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random()) const ARC = arcSize * i * i * (0.93 + 0.07 * Math.random())
ctx.beginPath(); ctx.beginPath();
magField(MAG, ARC) magField(MAG, ARC)
magField(MAG, -ARC) magField(MAG, -ARC)
@@ -6990,13 +7008,13 @@ const b = {
} }
//look for closest mob in player's LoS //look for closest mob in player's LoS
const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (input.down ? 0.7 : 1) const harpoonSize = (tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1) //* (input.down ? 0.7 : 1)
const totalCycles = 5 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize) const totalCycles = 6 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) * Math.sqrt(harpoonSize)
if (tech.extraHarpoons && !input.down) { //multiple harpoons if (tech.extraHarpoons && !input.down) { //multiple harpoons
const SPREAD = 0.1 const SPREAD = 0.1
let angle = m.angle - SPREAD * tech.extraHarpoons / 2; let angle = m.angle - SPREAD * tech.extraHarpoons / 2;
const dir = { x: Math.cos(angle), y: Math.sin(angle) }; //make a vector for the player's direction of length 1; used in dot product const dir = { x: Math.cos(angle), y: Math.sin(angle) }; //make a vector for the player's direction of length 1; used in dot product
const range = 450 * (tech.isFilament ? 1 + 0.006 * Math.min(110, this.ammo) : 1) const range = 450 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1)
let targetCount = 0 let targetCount = 0
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].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) {
@@ -7036,9 +7054,8 @@ 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 + 90 // cool down m.fireCDcycle = m.cycle + 90 // cool down is set when harpoon bullet returns to player
} else { } else { //input.down makes a single harpoon with longer range
//single harpoon
const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product
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].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) {
@@ -7055,7 +7072,7 @@ const b = {
} else { } else {
b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles) b.harpoon(where, closest.target, m.angle, harpoonSize, true, totalCycles)
} }
m.fireCDcycle = m.cycle + 45 // cool down m.fireCDcycle = m.cycle + 45 // cool down is set when harpoon bullet returns to player
tech.harpoonDensity = 0.004 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed tech.harpoonDensity = 0.004 //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed
} }
const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.015 : 0.035) const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), input.down ? 0.015 : 0.035)

View File

@@ -154,7 +154,7 @@ function collisionChecks(event) {
m.damage(dmg); //normal damage m.damage(dmg); //normal damage
} }
if (tech.isCollisionRealitySwitch) { if (tech.isCollisionRealitySwitch && m.alive) {
m.switchWorlds() m.switchWorlds()
simulation.trails() simulation.trails()
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`); simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);

View File

@@ -963,7 +963,7 @@ window.addEventListener("keyup", function(event) {
}); });
window.addEventListener("keydown", function(event) { window.addEventListener("keydown", function(event) {
console.log(event.code) // console.log(event.code)
switch (event.code) { switch (event.code) {
case input.key.right: case input.key.right:
case "ArrowRight": case "ArrowRight":

View File

@@ -18,30 +18,31 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// tech.giveTech("performance") // tech.giveTech("performance")
// level.difficultyIncrease(2 * 4) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(15 * 4) //30 is near max on hard //60 is near max on why
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// tech.isRerollDamage = true // tech.isRerollDamage = true
// powerUps.research.changeRerolls(50) // powerUps.research.changeRerolls(1000)
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.couplingChange(5) // m.couplingChange(5)
// m.setField("time dilation") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave // m.setField("plasma torch") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave plasma torch
// simulation.molecularMode = 2 // simulation.molecularMode = 2
// m.damage(0.1); // m.damage(0.1);
// b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[9].ammo = 10000 // b.guns[0].ammo = 10000
// tech.giveTech("startle response") // tech.giveTech("plasma ball")
// for (let i = 0; i < 1; ++i) tech.giveTech("junk DNA")
// tech.giveTech("dye laser") // tech.giveTech("dye laser")
// for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook") // for (let i = 0; i < 1; ++i) tech.giveTech("railgun")
// for (let i = 0; i < 5; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 3; ++i) tech.giveTech("Bitter electromagnet")
// for (let i = 0; i < 1; i++) tech.giveTech("capacitor bank")
// for (let i = 0; i < 9; i++) tech.giveTech("heuristics")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing(); // level.testing();
// spawn.starter(1900, -500, 200) // spawn.shooter(1900, -500, 200)
// spawn.starter(1900, -500) // spawn.starter(1900, -500)
// spawn.timeBoss(2538, -950) // spawn.timeBoss(2538, -950)
// for (let i = 0; i < 5; ++i) spawn.sniper(1000 + 5000 * Math.random(), -500 + 300 * Math.random()) // for (let i = 0; i < 5; ++i) spawn.sniper(1000 + 5000 * Math.random(), -500 + 300 * Math.random())
@@ -66,7 +67,7 @@ const level = {
// level.null() // level.null()
// localSettings.isHuman = true // localSettings.isHuman = true
// tech.isNoDraftPause = false //disable pause // tech.isNoDraftPause = false //disable pause
// mobs.mobDeaths = 200 // mobs.mobDeaths = 200 //to prevent pacifist mode
// for (let i = 0; i < 13; i++) level.nextLevel(); //jump to final boss // for (let i = 0; i < 13; i++) level.nextLevel(); //jump to final boss
// lore.unlockTesting(); // lore.unlockTesting();
@@ -101,6 +102,11 @@ const level = {
b.inventoryGun = tech.buffedGun; b.inventoryGun = tech.buffedGun;
simulation.switchGun(); simulation.switchGun();
} }
if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) {
var gun = b.guns[b.inventory[tech.buffedGun]].name
simulation.makeTextLog(`pigeonhole principle: <strong>+${(31 * Math.max(0, b.inventory.length)).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`, 600);
}
if (tech.isForeverDrones) { if (tech.isForeverDrones) {
if (tech.isDroneRadioactive) { if (tech.isDroneRadioactive) {
@@ -119,8 +125,7 @@ const level = {
tech.healMaxEnergyBonus += 0.1 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51) tech.healMaxEnergyBonus += 0.1 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51)
m.setMaxEnergy(); m.setMaxEnergy();
} }
if (tech.isSwitchReality && powerUps.research.count > 0) { if (tech.isSwitchReality) {
powerUps.research.changeRerolls(-1);
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`); simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
m.switchWorlds() m.switchWorlds()
simulation.trails() simulation.trails()
@@ -162,7 +167,8 @@ const level = {
if (tech.isSpawnExitTech) { if (tech.isSpawnExitTech) {
for (let i = 0; i < 2; i++) powerUps.spawn(level.exit.x + 10 * (Math.random() - 0.5), level.exit.y - 100 + 10 * (Math.random() - 0.5), "tech", false) //exit for (let i = 0; i < 2; i++) powerUps.spawn(level.exit.x + 10 * (Math.random() - 0.5), level.exit.y - 100 + 10 * (Math.random() - 0.5), "tech", false) //exit
} }
if (m.plasmaBall) m.plasmaBall.reset() // if (m.plasmaBall) m.plasmaBall.reset()
if (m.plasmaBall) m.plasmaBall.fire()
if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) { if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) {
const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1 const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1
powerUps.directSpawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false); powerUps.directSpawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false);

View File

@@ -342,12 +342,6 @@ const mobs = {
this.seePlayer.position.y = player.position.y; this.seePlayer.position.y = player.position.y;
} }
}, },
// alwaysSeePlayerIfRemember() {
// if (!m.isCloak && this.seePlayer.recall) {
// this.seePlayer.position.x = player.position.x;
// this.seePlayer.position.y = player.position.y;
// }
// },
seePlayerByHistory(depth = 30) { //depth max 60? limit of history seePlayerByHistory(depth = 30) { //depth max 60? limit of history
if (!(simulation.cycle % this.seePlayerFreq)) { if (!(simulation.cycle % this.seePlayerFreq)) {
if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) { if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) {
@@ -1255,12 +1249,12 @@ const mobs = {
} }
if (tech.isBotSpawnerReset) { if (tech.isBotSpawnerReset) {
for (let i = 0, len = bullet.length; i < len; i++) { for (let i = 0, len = bullet.length; i < len; i++) {
if (bullet[i].botType && bullet[i].endCycle !== Infinity) bullet[i].endCycle = simulation.cycle + 840 //14 seconds if (bullet[i].botType && bullet[i].endCycle !== Infinity) bullet[i].endCycle = simulation.cycle + 780 //13 seconds
} }
} }
if (Math.random() < tech.botSpawner) { if (Math.random() < tech.botSpawner) {
b.randomBot(this.position, false) b.randomBot(this.position, false)
bullet[bullet.length - 1].endCycle = simulation.cycle + 840 //14 seconds bullet[bullet.length - 1].endCycle = simulation.cycle + 780 //13 seconds
this.leaveBody = false; // no body since it turned into the bot this.leaveBody = false; // no body since it turned into the bot
} }
if (tech.isAddRemoveMaxHealth) { if (tech.isAddRemoveMaxHealth) {

View File

@@ -2385,11 +2385,15 @@ const m = {
if (this.circleRadius < this.radiusLimit) this.reset() if (this.circleRadius < this.radiusLimit) this.reset()
}, },
reset() { reset() {
// console.log(this.circleRadius)
const scale = 1 / m.plasmaBall.circleRadius const scale = 1 / m.plasmaBall.circleRadius
Matter.Body.scale(m.plasmaBall, scale, scale); //grow Matter.Body.scale(m.plasmaBall, scale, scale); //grow
// console.log(this.circleRadius)
// this.circleRadius = 0
this.alpha = 0.7 this.alpha = 0.7
this.isOn = false this.isOn = false
this.isPopping = false this.isPopping = false
// this.isAttached = true;
}, },
do() { do() {
if (this.isOn) { if (this.isOn) {

View File

@@ -297,7 +297,7 @@ const spawn = {
me.showHealthBar = false; me.showHealthBar = false;
me.collisionFilter.category = 0; me.collisionFilter.category = 0;
me.collisionFilter.mask = 0; //cat.player //| cat.body me.collisionFilter.mask = 0; //cat.player //| cat.body
me.chaseSpeed = 1.2 + 2 * Math.random() me.chaseSpeed = 1.2 + 2.3 * Math.random()
me.awake = function() { me.awake = function() {
//chase player //chase player
@@ -394,6 +394,9 @@ const spawn = {
this.pushAway(); this.pushAway();
this.mode[this.totalModes].enter() //enter new mode this.mode[this.totalModes].enter() //enter new mode
this.totalModes++ this.totalModes++
//spawn 6 mobs
me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex
for (let i = 0; i < 6; i++) me.spawnMobs(i)
} }
ctx.beginPath(); //draw invulnerable ctx.beginPath(); //draw invulnerable
let vertices = this.vertices; let vertices = this.vertices;
@@ -408,12 +411,21 @@ const spawn = {
} }
} }
me.damageReductionDecay = function() { //slowly make the boss take more damage over time //damageReduction resets with each invulnerability phase me.damageReductionDecay = function() { //slowly make the boss take more damage over time //damageReduction resets with each invulnerability phase
if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.015 //only decay once a second //only decay if the player has done damage in the last 4 seconds if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.017 //only decay once a second //only decay if the player has done damage in the last 4 seconds
}
me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]
me.spawnMobs = function(index = 0) {
const vertex = me.vertices[index]
const unit = Vector.normalise(Vector.sub(me.position, vertex))
const where = Vector.add(vertex, Vector.mult(unit, -30))
spawn[me.mobType](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5));
const velocity = Vector.mult(Vector.perp(unit), -10) //give the mob a rotational velocity as if they were attached to a vertex
Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y });
} }
me.maxMobs = 400 me.maxMobs = 400
me.mode = [{ me.mode = [{
name: "boulders", name: "boulders",
spawnRate: 120 - 6 * simulation.difficultyMode, spawnRate: 170 - 6 * simulation.difficultyMode,
do() { do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.boulder(me.position.x, me.position.y + 250) me.boulder(me.position.x, me.position.y + 250)
@@ -423,19 +435,20 @@ const spawn = {
exit() {}, exit() {},
}, { }, {
name: "mobs", name: "mobs",
whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)], // whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)],
spawnRate: 240 - 20 * simulation.difficultyMode, spawnRate: 280 - 20 * simulation.difficultyMode,
do() { do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.torque += 0.000015 * me.inertia; //spin me.torque += 0.000015 * me.inertia; //spin
const index = Math.floor((me.cycle % (this.spawnRate * 6)) / this.spawnRate) //int from 0 to 5 const index = Math.floor((me.cycle % (this.spawnRate * 6)) / this.spawnRate) //int from 0 to 5
if (index === 0) this.whoSpawn = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex if (index === 0) me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex
const vertex = me.vertices[index] me.spawnMobs(index)
const unit = Vector.normalise(Vector.sub(me.position, vertex)) // const vertex = me.vertices[index]
const where = Vector.add(vertex, Vector.mult(unit, -30)) // const unit = Vector.normalise(Vector.sub(me.position, vertex))
spawn[this.whoSpawn](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5)); // const where = Vector.add(vertex, Vector.mult(unit, -30))
const velocity = Vector.mult(Vector.perp(unit), -18) //give the mob a rotational velocity as if they were attached to a vertex // spawn[me.mobType](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5));
Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y }); // const velocity = Vector.mult(Vector.perp(unit), -18) //give the mob a rotational velocity as if they were attached to a vertex
// Matter.Body.setVelocity(mob[mob.length - 1], { x: me.velocity.x + velocity.x, y: me.velocity.y + velocity.y });
} }
}, },
enter() {}, enter() {},
@@ -443,7 +456,7 @@ const spawn = {
}, },
{ {
name: "hoppers", name: "hoppers",
spawnRate: 420 - 16 * simulation.difficultyMode, spawnRate: 480 - 16 * simulation.difficultyMode,
do() { do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.torque += 0.00002 * me.inertia; //spin me.torque += 0.00002 * me.inertia; //spin
@@ -457,6 +470,10 @@ const spawn = {
y: me.velocity.y + velocity.y y: me.velocity.y + velocity.y
}); });
} }
let where = { x: 600 - Math.random() * 100, y: -225 }
if (simulation.isHorizontalFlipped) where.x = -600 + Math.random() * 100
spawn.hopBullet(where.x, where.y, 13 + Math.ceil(Math.random() * 8)); //hopBullet(x, y, radius = 10 + Math.ceil(Math.random() * 8))
Matter.Body.setDensity(mob[mob.length - 1], 0.002); //normal is 0.001
} }
}, },
enter() {}, enter() {},
@@ -464,7 +481,7 @@ const spawn = {
}, },
{ {
name: "seekers", name: "seekers",
spawnRate: 60 - 3 * simulation.difficultyMode, spawnRate: 100 - 3 * simulation.difficultyMode,
do() { do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { //spawn seeker if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { //spawn seeker
const index = Math.floor((me.cycle % 360) / 60) const index = Math.floor((me.cycle % 360) / 60)
@@ -482,7 +499,7 @@ const spawn = {
{ {
name: "mines", name: "mines",
bombCycle: 0, bombCycle: 0,
bombInterval: 34 - 2 * simulation.difficultyMode, bombInterval: 55 - 2 * simulation.difficultyMode,
do() { do() {
const yOff = 120 const yOff = 120
this.bombCycle++ this.bombCycle++
@@ -544,7 +561,7 @@ const spawn = {
}, },
{ {
name: "orbiters", name: "orbiters",
spawnRate: 30 - 2 * simulation.difficultyMode, spawnRate: 42 - 2 * simulation.difficultyMode,
do() { do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
const speed = (0.01 + 0.0005 * simulation.difficultyMode) * ((Math.random() < 0.5) ? 0.85 : -1.15) const speed = (0.01 + 0.0005 * simulation.difficultyMode) * ((Math.random() < 0.5) ? 0.85 : -1.15)
@@ -602,7 +619,7 @@ const spawn = {
{ {
name: "black hole", name: "black hole",
eventHorizon: 0, eventHorizon: 0,
eventHorizonRadius: 2200, eventHorizonRadius: 2100,
eventHorizonCycle: 0, eventHorizonCycle: 0,
do() { do() {
this.eventHorizonCycle++ this.eventHorizonCycle++
@@ -690,10 +707,10 @@ const spawn = {
for (let i = 0; i < this.totalModes; i++) this.mode[i].do() for (let i = 0; i < this.totalModes; i++) this.mode[i].do()
} }
// this.cycle++; // this.cycle++;
// this.mode[0].do() // this.mode[4].do()
// this.mode[7].do() // this.mode[7].do()
}; };
me.spawnRate = 4800 - 30 * simulation.difficultyMode * simulation.difficultyMode me.spawnRate = 5800 - 30 * simulation.difficultyMode * simulation.difficultyMode
me.spawnBoss = function() { //if the fight lasts too long start spawning bosses me.spawnBoss = function() { //if the fight lasts too long start spawning bosses
if (!(me.cycle % this.spawnRate) && this.health < 1) { if (!(me.cycle % this.spawnRate) && this.health < 1) {
this.spawnRate = Math.max(300, this.spawnRate - 10 * simulation.difficultyMode * simulation.difficultyMode) //reduce the timer each time a boss spawns this.spawnRate = Math.max(300, this.spawnRate - 10 * simulation.difficultyMode * simulation.difficultyMode) //reduce the timer each time a boss spawns
@@ -816,7 +833,7 @@ const spawn = {
} }
}; };
} }
me.lasers = function(where, angle, dmg = 0.13 * simulation.dmgScale) { me.lasers = function(where, angle, dmg = 0.1 * simulation.dmgScale) {
const vertexCollision = function(v1, v1End, domain) { const vertexCollision = function(v1, v1End, domain) {
for (let i = 0; i < domain.length; ++i) { for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices; let vertices = domain[i].vertices;
@@ -1752,7 +1769,7 @@ const spawn = {
me.seeAtDistance2 = 1400000; me.seeAtDistance2 = 1400000;
me.cellMassMax = 70 me.cellMassMax = 70
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map
Matter.Body.setDensity(me, 0.0002 + 0.00001 * simulation.difficulty) // normal density is 0.001 Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001
me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal
const k = 642 //k=r^2/m const k = 642 //k=r^2/m
@@ -2542,13 +2559,13 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "transparent"); mobs.spawn(x, y, 6, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; //used for drawSneaker me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = radius * 23; //required for blackhole me.eventHorizon = radius * 27; //required for blackhole
me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon
me.accelMag = 0.0001 * simulation.accelScale; me.accelMag = 0.00012 * simulation.accelScale;
me.frictionAir = 0.025; me.frictionAir = 0.025;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
me.memory = Infinity; me.memory = Infinity;
Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
me.do = function() { me.do = function() {
//keep it slow, to stop issues from explosion knock backs //keep it slow, to stop issues from explosion knock backs
if (this.speed > 5) { if (this.speed > 5) {
@@ -2675,11 +2692,11 @@ const spawn = {
me.stroke = "transparent"; //used for drawSneaker me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = 1100; //required for black hole me.eventHorizon = 1100; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon
me.accelMag = 0.00003 * simulation.accelScale; me.accelMag = 0.00004 * simulation.accelScale;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
// me.frictionAir = 0.005; // me.frictionAir = 0.005;
me.memory = 1600; me.memory = 1600;
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.04); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() { me.onDeath = function() {
//applying forces to player doesn't seem to work inside this method, not sure why //applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)

View File

@@ -430,16 +430,11 @@ const tech = {
{ {
name: "pigeonhole principle", name: "pigeonhole principle",
descriptionFunction() { descriptionFunction() {
var info = "" let info = ""
if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) { if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
var gun = b.guns[b.inventory[tech.buffedGun]].name let gun = b.guns[b.inventory[tech.buffedGun]].name
var info = `<br>this level: <strong>+${(31 * Math.max(0, b.inventory.length)).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>` info = `<br>this level: <strong>+${(31 * Math.max(0, b.inventory.length)).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`
} }
// return `
// a <strong class='color-g'>gun</strong> is <strong>chosen</strong> to be improved each <strong>level</strong>
// <br><strong>+${(31*b.inventory.length).toFixed(0)}%</strong> <strong class='color-d'>damage</strong> for ${gun}
// <br><strong class='color-d'>damage</strong> scales by 31% per unequipped <strong class='color-g'>gun</strong>`
return ` return `
a new <strong class='color-g'>gun</strong> is <strong>chosen</strong> to be improved each <strong>level</strong> a new <strong class='color-g'>gun</strong> is <strong>chosen</strong> to be improved each <strong>level</strong>
<br><strong>+31%</strong> <strong class='color-d'>damage</strong> per <strong class='color-g'>gun</strong> for the <strong>chosen</strong> <strong class='color-g'>gun</strong>${info}` <br><strong>+31%</strong> <strong class='color-d'>damage</strong> per <strong class='color-g'>gun</strong> for the <strong>chosen</strong> <strong class='color-g'>gun</strong>${info}`
@@ -574,7 +569,7 @@ const tech = {
{ {
name: "cache", name: "cache",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`,
description: `${powerUps.orb.ammo()} give <strong>1600%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`, description: `${powerUps.orb.ammo()} give <strong>1500%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
// ammo powerups always max out your gun, // ammo powerups always max out your gun,
// but the maximum ammo ti limited // but the maximum ammo ti limited
// description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`, // description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
@@ -587,7 +582,7 @@ const tech = {
}, },
requires: "not non-renewables", requires: "not non-renewables",
effect() { effect() {
tech.ammoCap = 16; tech.ammoCap = 15;
powerUps.ammo.effect() powerUps.ammo.effect()
}, },
remove() { remove() {
@@ -1049,7 +1044,7 @@ const tech = {
}, },
{ {
name: "anticorrelation", name: "anticorrelation",
description: "<strong>+100%</strong> <strong class='color-d'>damage</strong><br>after not using your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> for <strong>2</strong> seconds", description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>+100%</strong> <strong class='color-d'>damage</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1068,7 +1063,7 @@ const tech = {
{ {
name: "scrap bots", name: "scrap bots",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Scrap' class="link">scrap bots</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Scrap' class="link">scrap bots</a>`,
description: "after mobs <strong>die</strong> you have a <strong>+33%</strong> chance<br>to build scrap <strong class='color-bot'>bots</strong> that operate for <strong>14</strong> seconds", description: "after mobs <strong>die</strong> you have a <strong>+33%</strong> chance<br>to build scrap <strong class='color-bot'>bots</strong> that operate for <strong>13</strong> seconds",
maxCount: 3, maxCount: 3,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1088,7 +1083,7 @@ const tech = {
{ {
name: "scrap refit", name: "scrap refit",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Scrap' class="link">scrap refit</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Scrap' class="link">scrap refit</a>`,
description: "after mobs <strong>die</strong><br>reset scrap <strong class='color-bot'>bots</strong> to <strong>14</strong> seconds of operation", description: "after mobs <strong>die</strong><br>reset scrap <strong class='color-bot'>bots</strong> to <strong>13</strong> seconds of operation",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
@@ -3036,7 +3031,7 @@ const tech = {
{ {
name: "many-worlds", name: "many-worlds",
// description: "each <strong>level</strong> is an <strong class='alt'>alternate reality</strong>, where you<br>find a <strong class='color-m'>tech</strong> at the start of each level", // description: "each <strong>level</strong> is an <strong class='alt'>alternate reality</strong>, where you<br>find a <strong class='color-m'>tech</strong> at the start of each level",
description: `on each new <strong>level</strong> use ${powerUps.orb.research(1)} to enter an<br><strong class='alt'>alternate reality</strong> and spawn a <strong class='color-m'>tech</strong> power up`, description: `on each new <strong>level</strong> enter an<br><strong class='alt'>alternate reality</strong> and spawn a <strong class='color-m'>tech</strong> power up`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3243,7 +3238,8 @@ const tech = {
}, },
{ {
name: "emergence", name: "emergence",
description: "<strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>+2</strong> <strong>choices</strong><br><strong>+3%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool", description: "<strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>+1</strong> <strong>choice</strong><br><strong>+8%</strong> <strong class='color-d'>damage</strong>",
// description: "<strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>+2</strong> <strong>choices</strong><br><strong>+3%</strong> <strong class='color-j'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3252,16 +3248,18 @@ const tech = {
return !tech.isDeterminism return !tech.isDeterminism
}, },
requires: "not determinism", requires: "not determinism",
damage: 1.08,
effect() { effect() {
tech.extraChoices += 2; tech.extraChoices += 1;
this.refundAmount += tech.addJunkTechToPool(0.03) tech.damage *= this.damage
// this.refundAmount += tech.addJunkTechToPool(0.03)
}, },
refundAmount: 0, refundAmount: 0,
remove() { remove() {
tech.extraChoices = 0; tech.extraChoices = 0;
if (this.count > 0 && this.refundAmount > 0) { if (this.count > 0) {
tech.removeJunkTechFromPool(this.refundAmount) tech.damage /= this.damage
this.refundAmount = 0 // if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
} }
} }
}, },
@@ -4825,7 +4823,7 @@ const tech = {
}, },
remove() { remove() {
tech.infiniteWaveAmmo = 1 tech.infiniteWaveAmmo = 1
if (this.count > 1 && b.guns[3].savedAmmo !== undefined) { if (this.count > 0 && b.guns[3].savedAmmo !== undefined) {
b.guns[3].ammo = b.guns[3].savedAmmo b.guns[3].ammo = b.guns[3].savedAmmo
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
@@ -6188,9 +6186,31 @@ const tech = {
tech.isCapacitor = false; tech.isCapacitor = false;
} }
}, },
{
name: "Bitter electromagnet",
descriptionFunction() { return `<strong>railgun</strong> charges <strong>+33%</strong> slower<br><strong>+100%</strong> <strong>harpoon</strong> density and <strong class='color-d'>damage</strong>` },
isGunTech: true,
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("harpoon") && tech.isRailGun
},
requires: "harpoon, railgun",
effect() {
tech.railChargeRate *= 1.06
tech.harpoonDensity += 0.0065
},
remove() {
tech.railChargeRate = 0.97;
tech.harpoonDensity = 0.0065
}
},
{ {
name: "railgun", name: "railgun",
description: `<strong>+50%</strong> <strong>harpoon</strong> density, but they don't <strong>retract</strong><br><strong>+900%</strong> harpoon <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`, description: `<strong>harpoons</strong> can't <strong>retract</strong>, hold fire to charge<br><strong>+50%</strong> <strong>harpoon</strong> density and <strong class='color-d'>damage</strong>`,
// description: `<strong>+900%</strong> <strong>harpoon</strong> <strong class='color-ammo'>ammo</strong>, but it can't <strong>retract</strong><br><strong>+50%</strong> <strong>harpoon</strong> density and <strong class='color-d'>damage</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -6414,7 +6434,6 @@ const tech = {
}, },
remove() { remove() {
tech.isHarpoonPowerUp = false tech.isHarpoonPowerUp = false
tech.harpoonDensity = 0.004
} }
}, },
{ {
@@ -8260,6 +8279,39 @@ const tech = {
}, },
remove() {} remove() {}
}, },
{
name: "random",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Special:Random' class="link">random</a>`,
delay: 333,
descriptionFunction() {
const delay = 333
const loop = () => {
if ((simulation.isChoosing) && m.alive && !build.isExperimentSelection) {
const dmg = Math.floor(33 * Math.random()) * 0.01
this.text = `<strong style = "font-family: 'Courier New', monospace;">+${(dmg*100).toFixed(0).padStart(2, '0')}%</strong> <strong class='color-d'>damage</strong>`
this.damage = 1 + dmg
if (document.getElementById(`damage-JUNK-id${this.id}`)) document.getElementById(`damage-JUNK-id${this.id}`).innerHTML = this.text
setTimeout(() => { loop() }, delay);
}
}
setTimeout(() => { loop() }, delay);
this.id++
return `<span id = "damage-JUNK-id${this.id}">${this.text}</span>`
},
maxCount: 3,
count: 0,
frequency: 1,
isJunk: true,
allowed() { return !build.isExperimentSelection },
requires: "NOT EXPERIMENT MODE",
damage: 0,
effect() {
tech.damage *= this.damage
},
remove() {
if (this.count > 0) tech.damage /= this.damage
}
},
{ {
name: "boost", name: "boost",
maxCount: 1, maxCount: 1,
@@ -8267,9 +8319,7 @@ const tech = {
frequency: 0, frequency: 0,
isJunk: true, isJunk: true,
isNonRefundable: true, isNonRefundable: true,
allowed() { allowed() { return !build.isExperimentSelection },
return !build.isExperimentSelection
},
requires: "NOT EXPERIMENT MODE", requires: "NOT EXPERIMENT MODE",
effect() { effect() {
powerUps.spawnDelay("boost", this.spawnCount) powerUps.spawnDelay("boost", this.spawnCount)
@@ -8306,7 +8356,7 @@ const tech = {
allowed: () => true, allowed: () => true,
requires: "", requires: "",
effect() { effect() {
if (Math.random() < 0.1) tech.damage *= 7.77 if (Math.random() < 0.1) tech.damage *= 8.77
}, },
remove() {} remove() {}
}, },
@@ -10066,7 +10116,7 @@ const tech = {
allowed() { return m.isShipMode }, allowed() { return m.isShipMode },
requires: "", requires: "",
effect() { effect() {
tech.damage *= 2 tech.damage *= 3
m.look = () => { m.look = () => {
// const scale = 0; // const scale = 0;
@@ -10984,4 +11034,5 @@ const tech = {
isJunkDNA: null, isJunkDNA: null,
buffedGun: 0, buffedGun: 0,
isGunChoice: null, isGunChoice: null,
railChargeRate: null,
} }

125
todo.txt
View File

@@ -1,20 +1,93 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
harpoon
default fire rate is 10% higher
default harpoon range 15% higher
railgun
tech: Bitter electromagnet - 33% slower charge time for railgun, 100% more density and damage
area effect damage is increased 20%, scales with bitter electromagnet and total charge
charging longer increases harpoon velocity/damage by up to 30%
contributions to charge time are more uniform between:
crouching, fire rate, Bitter electromagnet, and capacitor bank
auto aims no longer disabled on crouch
plasma-bot does 15% more damage, but costs 2 research emergence 2->1 extra choice, and +8% damage, and no added JUNK anymore
fault tolerance 4->5 forever drones, but costs 2 research cache 16->15x ammo
surfactant 2->3 foam bots, but costs 2 research many-worlds 1->0 research to enter an alternate reality on each new level
missile-bot costs 1 research
shaped charge 4->3 research cost
renormalization 40->44% chance to refund research
exciton 18->16% chance to spawn
ground state 50->40% reduced energy regen
Bayesian statistics 3.8->3% damage per research, and spawns 3 research
JUNK tech: startle response - if mobs are near boost damage, and lock mouse until you press escape finalBoss
health decays a bit faster
spawns 6 mobs at each health threshold
spawns from the different modes are reduced
boss laser damage is 25% reduced
hoppers spawn from the slime tunnel
JUNKtech: random - gives random +damage
bug fixes
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
tech: zombie - sporangium infect mobs, making them fight for you
infected mobs get a status debuff. when they die they return as zombie mob type
zombie mobs run code similar to drones
they inherit color, sides, radius from host
tech: sporangium that grow little trees
the trees have an area of effect damage for about 6-10 seconds
maybe something similar to radioactive drones, but maybe a few smaller shapes
new bot type that makes phonon waves
name: phono-bot?
each bot has to generate it themselves, can't run code in gun.do
synergy with 2 resonance tech
not isotropic? I think no
synergy with bound? phase velocity, amplitude, propagation
harpoon tech that makes auto aim work much better
tech - super balls gain 20 seconds of time and are reset to original launch speed after hitting a mob
railgun
magnetic pinch: harpoon does damage to nearby mobs
draw charge graphic on harpoon
use same code as the damage when fire effect
hookBoss fires a hook that pulls player towards it
hook does a bit of damage
player targeted unless cloaking
also add effect to finalBoss
finalBoss
add synergies between modes:
new modes:
rotating quadrant immunity shield, can't take damage from that quadrant
maybe also attack player near that quadrant
but how to tell the angle of incoming damage
maybe a physics body like the shield but it only covers 1/3 of mob?
falling object warps to ceiling after hitting floor
doesn't end, player needs to kill it
slowly grows?
slow effect zones
random placement or place over player or both!
draw white dot and an outline of area of effect
expanding circle stroke, freeze effect triggers when stroke circle hits fill circle
after 1-2 seconds freeze player if in the zone
also freeze mobs
effect that makes player have to be close to boss
hook that tries to yank the player into hitting finalBoss
does damage
pulls player into center
counter with wormhole, negative mass
player targeted unless cloaking
mob status effect - emit - mobs fire lasers for a few seconds
tech: phosphorescence - mobs emit after being hit with laser beams
run canvas direct pixel editing while game is paused run canvas direct pixel editing while game is paused
(I tried it an it really hits performance hard)
just update once every second? just update once every second?
if it uses too much processing have a setting to toggle it off if it uses too much processing have a setting to toggle it off
this might help get players to spend more time relaxing on the power up selection this might help get players to spend more time relaxing on the power up selection
@@ -41,8 +114,6 @@ it would be nice if there was incentive to go slow when choosing tech so n-gon i
make freeze and __ not cause death at 50% health, but just 600% extra damage for that bullet make freeze and __ not cause death at 50% health, but just 600% extra damage for that bullet
new mob status effect - phosphorescence - mobs fire lasers for a few seconds after being hit with lasers
make a new coupling effect for perfect diamagnetism or standing wave make a new coupling effect for perfect diamagnetism or standing wave
make a faster smaller version of cell boss that also has map collisions make a faster smaller version of cell boss that also has map collisions
@@ -50,32 +121,6 @@ make a faster smaller version of cell boss that also has map collisions
laserMines need a copy of laser-bot method laserMines need a copy of laser-bot method
this is a very rare bug, so not a priority this is a very rare bug, so not a priority
finalBoss
add synergies between modes:
black hole can pull in bullets
laser can hurt bullets? maybe bad idea
old mode changes
mine color needs to be move vibrant
hoppers can hop out of the slime and the door on the sides
new modes:
rotating quadrant immunity shield, can't take damage from that quadrant
maybe also attack player near that quadrant
falling object warps to ceiling after hitting floor
doesn't end, player needs to kill it
slowly grows?
slow effect zones
random placement or place over player or both!
draw white dot and an outline of area of effect
expanding circle stroke, freeze effect triggers when stroke circle hits fill circle
after 1-2 seconds freeze player if in the zone
also freeze mobs
effect that makes player have to be close to boss
hook that tries to yank the player into hitting finalBoss
does damage
pulls player into center
counter with wormhole, negative mass
player targeted unless cloaking
JUNK tech description that changes similar to cards in inscription JUNK tech description that changes similar to cards in inscription
that changes based on mouse position that changes based on mouse position
can you tell if mouse is over card? can you tell if mouse is over card?
@@ -1059,8 +1104,8 @@ possible names for tech
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown. lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
p-zombie p-zombie
p-hacking JUNK tech p-hacking JUNK tech
https://en.wikipedia.org/wiki/High-entropy_alloys https://en.wikipedia.org/wiki/High-entropy_alloys high yield strength and low ductility, high temp resistance
https://en.wikipedia.org/wiki/Refractory_metals https://en.wikipedia.org/wiki/Refractory_metals hard, high temp resistance
https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves
prion quine - self replicating protein prion quine - self replicating protein
Unitarity - https://en.wikipedia.org/wiki/Unitarity_(physics) - all probabilities add up to 1, calculations work the same forward and backwards in time Unitarity - https://en.wikipedia.org/wiki/Unitarity_(physics) - all probabilities add up to 1, calculations work the same forward and backwards in time