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
},
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 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 }], {
@@ -1696,7 +1696,7 @@ const b = {
angle: angle,
friction: 1,
frictionAir: 0.4,
thrustMag: 0.1,
// thrustMag: 0.1,
drain: tech.isRailEnergy ? 0.001 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
@@ -1808,7 +1808,7 @@ const b = {
if (m.energy < 0.05) {
m.fireCDcycle = m.cycle + 120; //fire cooldown
} 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
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
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 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.y -= returnForce.y
this.grabPowerUp()
@@ -1850,7 +1850,7 @@ const b = {
Matter.Body.setPosition(powerUp[i], this.vertices[2])
powerUp[i].collisionFilter.category = 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
break //just pull 1 power up if possible
}
@@ -1887,16 +1887,16 @@ const b = {
Matter.Body.rotate(this, -this.turnRate);
}
}
this.force.x += this.thrustMag * this.mass * Math.cos(this.angle);
this.force.y += this.thrustMag * this.mass * Math.sin(this.angle);
this.force.x += thrust * this.mass * Math.cos(this.angle);
this.force.y += thrust * this.mass * Math.sin(this.angle);
}
this.draw()
},
});
if (!isReturn && !target) {
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + 60 * Math.cos(bullet[me].angle),
y: m.Vy / 2 + 60 * Math.sin(bullet[me].angle)
x: m.Vx / 2 + 600 * thrust * Math.cos(bullet[me].angle),
y: m.Vy / 2 + 600 * thrust * Math.sin(bullet[me].angle)
});
bullet[me].frictionAir = 0.002
bullet[me].do = function() {
@@ -6790,7 +6790,7 @@ const b = {
}
//fire
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 = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
@@ -6800,25 +6800,27 @@ const b = {
target: null
}
//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
const SUB = Vector.sub(mob[i].position, m.pos)
const DISTANCE = Vector.magnitude(SUB)
if (DISTANCE < range + mob[i].radius) {
const DEPTH = 100 + Math.min(range - DISTANCE + mob[i].radius, 1500)
const FORCE = Vector.mult(Vector.normalise(SUB), 0.0015 * Math.sqrt(DEPTH) * mob[i].mass)
mob[i].force.x += FORCE.x;
mob[i].force.y += FORCE.y;
if (!mob[i].isUnblockable) {
const SUB = Vector.sub(mob[i].position, m.pos)
const DISTANCE = Vector.magnitude(SUB)
if (DISTANCE < range + mob[i].radius) {
const DEPTH = 100 + Math.min(range - DISTANCE + mob[i].radius, 1500)
const FORCE = Vector.mult(Vector.normalise(SUB), 0.0015 * Math.sqrt(DEPTH) * mob[i].mass)
mob[i].force.x += FORCE.x;
mob[i].force.y += FORCE.y;
let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 0.1 : 0.4)
simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x,
y: mob[i].position.y,
radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3,
color: 'rgba(100, 0, 200, 0.2)',
time: 15
});
mob[i].damage(dmg);
let dmg = m.dmgScale * (mob[i].isDropPowerUp ? 350 : 1100) * tech.harpoonDensity * this.charge
simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x,
y: mob[i].position.y,
radius: Math.log(dmg + 1.1) * 40 * mob[i].damageReduction + 3,
color: 'rgba(100, 0, 200, 0.4)',
time: 15
});
mob[i].damage(dmg);
}
}
}
for (let i = 0, len = body.length; i < len; ++i) { //push away blocks when firing
@@ -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
}
}
//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)
player.force.x -= recoil.x
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 thrust = 0.15 * (this.charge)
if (tech.extraHarpoons) {
let targetCount = 0
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 (this.ammo > -1) {
// 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
targetCount++
if (targetCount > tech.extraHarpoons) break
@@ -6873,14 +6888,10 @@ const b = {
if (targetCount < tech.extraHarpoons + 1) {
const num = tech.extraHarpoons + 1 - targetCount
for (let i = 0; i < num; i++) {
// if (this.ammo > -1) {
// this.ammo--
b.harpoon(where, null, angle, harpoonSize, false)
b.harpoon(where, null, angle, harpoonSize, false, 35, false, thrust)
angle += SPREAD
// }
}
}
// this.ammo++ //make up for the ammo used up in fire()
simulation.updateGunHUD();
} else {
//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;
@@ -6909,13 +6920,18 @@ const b = {
player.force.y = 0
}
m.fireCDcycle = m.cycle + 10 //can't fire until mouse is released
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
// const previousCharge = this.charge
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
// 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
//draw magnetic field
@@ -6936,9 +6952,11 @@ const b = {
X, Y)
}
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++) {
const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
const MAG = magSize * i * i * (0.93 + 0.07 * Math.random())
const ARC = arcSize * i * i * (0.93 + 0.07 * Math.random())
ctx.beginPath();
magField(MAG, ARC)
magField(MAG, -ARC)
@@ -6990,13 +7008,13 @@ const b = {
}
//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 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
const SPREAD = 0.1
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 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
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) {
@@ -7036,9 +7054,8 @@ const b = {
}
this.ammo++ //make up for the ammo used up in fire()
simulation.updateGunHUD();
m.fireCDcycle = m.cycle + 90 // cool down
} else {
//single harpoon
m.fireCDcycle = m.cycle + 90 // cool down is set when harpoon bullet returns to player
} else { //input.down makes a single harpoon with longer range
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) {
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 {
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
}
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
}
if (tech.isCollisionRealitySwitch) {
if (tech.isCollisionRealitySwitch && m.alive) {
m.switchWorlds()
simulation.trails()
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) {
console.log(event.code)
// console.log(event.code)
switch (event.code) {
case input.key.right:
case "ArrowRight":

View File

@@ -18,30 +18,31 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// 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
// tech.isRerollDamage = true
// powerUps.research.changeRerolls(50)
// powerUps.research.changeRerolls(1000)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// 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
// 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("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
// tech.giveTech("startle response")
// for (let i = 0; i < 1; ++i) tech.giveTech("junk DNA")
// b.guns[0].ammo = 10000
// tech.giveTech("plasma ball")
// tech.giveTech("dye laser")
// for (let i = 0; i < 1; ++i) tech.giveTech("grappling hook")
// for (let i = 0; i < 5; i++) tech.giveTech("laser-bot")
// for (let i = 0; i < 1; ++i) tech.giveTech("railgun")
// 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(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing();
// spawn.starter(1900, -500, 200)
// spawn.shooter(1900, -500, 200)
// spawn.starter(1900, -500)
// spawn.timeBoss(2538, -950)
// 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()
// localSettings.isHuman = true
// 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
// lore.unlockTesting();
@@ -101,6 +102,11 @@ const level = {
b.inventoryGun = tech.buffedGun;
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.isDroneRadioactive) {
@@ -119,8 +125,7 @@ const level = {
tech.healMaxEnergyBonus += 0.1 * powerUps.totalPowerUps //Math.min(0.02 * powerUps.totalPowerUps, 0.51)
m.setMaxEnergy();
}
if (tech.isSwitchReality && powerUps.research.count > 0) {
powerUps.research.changeRerolls(-1);
if (tech.isSwitchReality) {
simulation.makeTextLog(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
m.switchWorlds()
simulation.trails()
@@ -162,7 +167,8 @@ const level = {
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
}
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]) {
const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1
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;
}
},
// 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
if (!(simulation.cycle % this.seePlayerFreq)) {
if (Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && !m.isCloak) {
@@ -1255,12 +1249,12 @@ const mobs = {
}
if (tech.isBotSpawnerReset) {
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) {
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
}
if (tech.isAddRemoveMaxHealth) {

View File

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

View File

@@ -297,7 +297,7 @@ const spawn = {
me.showHealthBar = false;
me.collisionFilter.category = 0;
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() {
//chase player
@@ -394,6 +394,9 @@ const spawn = {
this.pushAway();
this.mode[this.totalModes].enter() //enter new mode
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
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
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.mode = [{
name: "boulders",
spawnRate: 120 - 6 * simulation.difficultyMode,
spawnRate: 170 - 6 * simulation.difficultyMode,
do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.boulder(me.position.x, me.position.y + 250)
@@ -423,19 +435,20 @@ const spawn = {
exit() {},
}, {
name: "mobs",
whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)],
spawnRate: 240 - 20 * simulation.difficultyMode,
// whoSpawn: spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)],
spawnRate: 280 - 20 * simulation.difficultyMode,
do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.torque += 0.000015 * me.inertia; //spin
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
const vertex = me.vertices[index]
const unit = Vector.normalise(Vector.sub(me.position, vertex))
const where = Vector.add(vertex, Vector.mult(unit, -30))
spawn[this.whoSpawn](where.x + 50 * (Math.random() - 0.5), where.y + 50 * (Math.random() - 0.5));
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 });
if (index === 0) me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; //fire a bullet from each vertex
me.spawnMobs(index)
// 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), -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() {},
@@ -443,7 +456,7 @@ const spawn = {
},
{
name: "hoppers",
spawnRate: 420 - 16 * simulation.difficultyMode,
spawnRate: 480 - 16 * simulation.difficultyMode,
do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) {
me.torque += 0.00002 * me.inertia; //spin
@@ -457,6 +470,10 @@ const spawn = {
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() {},
@@ -464,7 +481,7 @@ const spawn = {
},
{
name: "seekers",
spawnRate: 60 - 3 * simulation.difficultyMode,
spawnRate: 100 - 3 * simulation.difficultyMode,
do() {
if (!(me.cycle % this.spawnRate) && mob.length < me.maxMobs) { //spawn seeker
const index = Math.floor((me.cycle % 360) / 60)
@@ -482,7 +499,7 @@ const spawn = {
{
name: "mines",
bombCycle: 0,
bombInterval: 34 - 2 * simulation.difficultyMode,
bombInterval: 55 - 2 * simulation.difficultyMode,
do() {
const yOff = 120
this.bombCycle++
@@ -544,7 +561,7 @@ const spawn = {
},
{
name: "orbiters",
spawnRate: 30 - 2 * simulation.difficultyMode,
spawnRate: 42 - 2 * simulation.difficultyMode,
do() {
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)
@@ -602,7 +619,7 @@ const spawn = {
{
name: "black hole",
eventHorizon: 0,
eventHorizonRadius: 2200,
eventHorizonRadius: 2100,
eventHorizonCycle: 0,
do() {
this.eventHorizonCycle++
@@ -690,10 +707,10 @@ const spawn = {
for (let i = 0; i < this.totalModes; i++) this.mode[i].do()
}
// this.cycle++;
// this.mode[0].do()
// this.mode[4].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
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
@@ -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) {
for (let i = 0; i < domain.length; ++i) {
let vertices = domain[i].vertices;
@@ -1752,7 +1769,7 @@ const spawn = {
me.seeAtDistance2 = 1400000;
me.cellMassMax = 70
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
const k = 642 //k=r^2/m
@@ -2542,13 +2559,13 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "transparent");
let me = mob[mob.length - 1];
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.accelMag = 0.0001 * simulation.accelScale;
me.accelMag = 0.00012 * simulation.accelScale;
me.frictionAir = 0.025;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
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() {
//keep it slow, to stop issues from explosion knock backs
if (this.speed > 5) {
@@ -2675,11 +2692,11 @@ const spawn = {
me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = 1100; //required for black hole
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.frictionAir = 0.005;
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() {
//applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawnBossPowerUp(this.position.x, this.position.y)

View File

@@ -430,16 +430,11 @@ const tech = {
{
name: "pigeonhole principle",
descriptionFunction() {
var info = ""
let info = ""
if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
var 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>`
let gun = b.guns[b.inventory[tech.buffedGun]].name
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 `
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}`
@@ -574,7 +569,7 @@ const tech = {
{
name: "cache",
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,
// 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`,
@@ -587,7 +582,7 @@ const tech = {
},
requires: "not non-renewables",
effect() {
tech.ammoCap = 16;
tech.ammoCap = 15;
powerUps.ammo.effect()
},
remove() {
@@ -1049,7 +1044,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -1068,7 +1063,7 @@ const tech = {
{
name: "scrap bots",
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,
count: 0,
frequency: 1,
@@ -1088,7 +1083,7 @@ const tech = {
{
name: "scrap refit",
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,
count: 0,
frequency: 3,
@@ -3036,7 +3031,7 @@ const tech = {
{
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: `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,
count: 0,
frequency: 1,
@@ -3243,7 +3238,8 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -3252,16 +3248,18 @@ const tech = {
return !tech.isDeterminism
},
requires: "not determinism",
damage: 1.08,
effect() {
tech.extraChoices += 2;
this.refundAmount += tech.addJunkTechToPool(0.03)
tech.extraChoices += 1;
tech.damage *= this.damage
// this.refundAmount += tech.addJunkTechToPool(0.03)
},
refundAmount: 0,
remove() {
tech.extraChoices = 0;
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
if (this.count > 0) {
tech.damage /= this.damage
// if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
}
}
},
@@ -4825,7 +4823,7 @@ const tech = {
},
remove() {
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
simulation.updateGunHUD();
}
@@ -6188,9 +6186,31 @@ const tech = {
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",
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,
maxCount: 1,
count: 0,
@@ -6414,7 +6434,6 @@ const tech = {
},
remove() {
tech.isHarpoonPowerUp = false
tech.harpoonDensity = 0.004
}
},
{
@@ -8260,6 +8279,39 @@ const tech = {
},
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",
maxCount: 1,
@@ -8267,9 +8319,7 @@ const tech = {
frequency: 0,
isJunk: true,
isNonRefundable: true,
allowed() {
return !build.isExperimentSelection
},
allowed() { return !build.isExperimentSelection },
requires: "NOT EXPERIMENT MODE",
effect() {
powerUps.spawnDelay("boost", this.spawnCount)
@@ -8306,7 +8356,7 @@ const tech = {
allowed: () => true,
requires: "",
effect() {
if (Math.random() < 0.1) tech.damage *= 7.77
if (Math.random() < 0.1) tech.damage *= 8.77
},
remove() {}
},
@@ -10066,7 +10116,7 @@ const tech = {
allowed() { return m.isShipMode },
requires: "",
effect() {
tech.damage *= 2
tech.damage *= 3
m.look = () => {
// const scale = 0;
@@ -10984,4 +11034,5 @@ const tech = {
isJunkDNA: null,
buffedGun: 0,
isGunChoice: null,
railChargeRate: null,
}