demineralization

tech: demineralization - after mobs die gain 0.85x damage taken, effect stacks, but fades 10% every second
tech: remineralization - after mobs die gain 1.08x damage, effect stacks, but fades 10% every second
tech: equivalence principle - negative mass field doesn't cost energy
new JUNK tech: aerodynamics

interferometer
  slower elevator and lasers
  wider side ledges
  large laser blocking blocks
flocculation
  fewer mobs
  it's easier to get out of the slime
pavilion
  move vanish elements
  easier traversal
  secret tunnel
  removed debris, but added power ups and blocks
corridor
  limited to bosses that don't interact with the movers poorly
gravitron, substructure, corridor, interferometer
  added more heal and ammo power ups to match other levels
because some newer levels are zoomed out more
  laser max range is 3000->5000
  nails last 1/3 of a second longer
bosses spawn an extra ammo power up
  and 2 extra ammo on the hardest 2 difficulties
slasher mob's laserSwords will now damage a cloaked player
constraint announcement text looks more like computer code style to match game theme

foam recoil is back: 1->0.7x horizontal force and 2->4.3x vertical up force
  this makes it less annoying to horizontally and easier to kinda fly/float
negative mass field damage reduction 0.4->0.5x
holographic principle no longer slows player movement
  added 2 research cost
fermion gives 6->5 seconds of invulnerability after mobs die
stability 0.2->0.1x damage taken at max health
non-Newtonian armor 0.3->0.4x damage taken after collisions
Zeno's paradox 0.15->0.2x damage taken
annihilation energy cost 10->8 to destroy mobs after collisions
radiative equilibrium damage is 3->4x for 8->4 seconds
aerostat can be taken 1->3 times
dynamic equilibrium damage increased by 6->8x damage per last damage taken
aerostat no longer has 0.9x damage for being on the ground
launch system 1.2->1.3x ammo for missiles
research says that repeatedly entering alternate realities builds up some positive effects
  Hilbert space 4x->3x damage
  Ψ(t) collapse 6->4 research on boss death
transdimensional worms: 50% chance for a second worm per block in wormhole
wormhole 7->8 energy regen per second
hidden-variable theory 1.15->1.2 damage after choosing a field tech
ghoster mobs are less likely to get knocked far away from the player for long periods of time

bug fixes
  dynamic equilibrium was set to 100 times higher frequency then normal
  when constraints hide health bar's it's now hidden in the pause menu
  mobs aiming at cloaked player
    snakeBoss more intelligently chases player for a few seconds
    pulsarBoss aims at player's history 3 seconds in past
    pulsar will not stop firing
      but it will still not fire at cloaked player
This commit is contained in:
landgreen
2025-01-04 21:33:32 -08:00
parent 2daeae1ff4
commit 1040d1ff7e
14 changed files with 648 additions and 333 deletions

BIN
img/demineralization.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

BIN
img/remineralization.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@@ -2180,7 +2180,7 @@ const b = {
const d = Vector.sub(path[path.length - 1], path[path.length - 2]); const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
const nn = Vector.mult(n, 2 * Vector.dot(d, n)); const nn = Vector.mult(n, 2 * Vector.dot(d, n));
const r = Vector.normalise(Vector.sub(d, nn)); const r = Vector.normalise(Vector.sub(d, nn));
path[path.length] = Vector.add(Vector.mult(r, 3000), path[path.length - 1]); path[path.length] = Vector.add(Vector.mult(r, 5000), path[path.length - 1]);
}; };
checkForCollisions(); checkForCollisions();
@@ -3929,7 +3929,7 @@ const b = {
bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * tech.bulletSize, 2 * tech.bulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x))); bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * tech.bulletSize, 2 * tech.bulletSize, b.fireAttributes(Math.atan2(velocity.y, velocity.x)));
Matter.Body.setVelocity(bullet[me], velocity); Matter.Body.setVelocity(bullet[me], velocity);
Composite.add(engine.world, bullet[me]); //add bullet to world Composite.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = simulation.cycle + 60 + 18 * Math.random(); bullet[me].endCycle = simulation.cycle + 80 + 18 * Math.random();
bullet[me].dmg = tech.isNailRadiation ? 0 : dmg bullet[me].dmg = tech.isNailRadiation ? 0 : dmg
bullet[me].beforeDmg = function (who) { //beforeDmg is rewritten with ice crystal tech bullet[me].beforeDmg = function (who) { //beforeDmg is rewritten with ice crystal tech
if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 1.3 : 0.44), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 1.3 : 0.44), tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles
@@ -6744,8 +6744,12 @@ const b = {
isDischarge: false, isDischarge: false,
knockBack: 0.0005, //set in tech: cavitation knockBack: 0.0005, //set in tech: cavitation
applyKnock(velocity) { applyKnock(velocity) {
player.force.x -= this.knockBack * velocity.x player.force.x -= 0.7 * this.knockBack * velocity.x
player.force.y -= 2 * this.knockBack * velocity.y if (velocity.y > 0) {
player.force.y -= 4.3 * this.knockBack * velocity.y
} else {
player.force.y -= this.knockBack * velocity.y
}
}, },
chooseFireMethod() { chooseFireMethod() {
if (tech.isFoamPressure) { if (tech.isFoamPressure) {
@@ -6771,7 +6775,7 @@ const b = {
} }
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
b.foam(position, Vector.rotate(velocity, spread), radius) b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity) this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale); m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
}, },
doCharges() { doCharges() {
@@ -6798,7 +6802,7 @@ const b = {
y: m.pos.y + 30 * Math.sin(m.angle) y: m.pos.y + 30 * Math.sin(m.angle)
} }
b.foam(position, Vector.rotate(velocity, spread), radius) b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity) this.applyKnock(velocity)
this.charge -= 0.75 this.charge -= 0.75
m.fireCDcycle = m.cycle + 2; //disable firing and adding more charge until empty m.fireCDcycle = m.cycle + 2; //disable firing and adding more charge until empty
} else if (!input.fire) { } else if (!input.fire) {
@@ -6826,7 +6830,7 @@ const b = {
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
b.foam(position, Vector.rotate(velocity, spread), radius) b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity) this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale); m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
this.charge += 1 + tech.isCapacitor this.charge += 1 + tech.isCapacitor
}, },
@@ -7386,8 +7390,8 @@ const b = {
m.energy -= drain m.energy -= drain
const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) } const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) }
b.laser(where, { b.laser(where, {
x: where.x + 3000 * Math.cos(m.angle), x: where.x + 5000 * Math.cos(m.angle),
y: where.y + 3000 * Math.sin(m.angle) y: where.y + 5000 * Math.sin(m.angle)
}, tech.laserDamage / b.fireCDscale * this.lensDamage); }, tech.laserDamage / b.fireCDscale * this.lensDamage);
} }
}, },

View File

@@ -177,8 +177,8 @@ function collisionChecks(event) {
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) }); Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) });
Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) }); Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.08 && mob[k].damageReduction > 0) {
m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy m.energy -= 0.08 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death(); mob[k].death();
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue

View File

@@ -497,7 +497,7 @@ const build = {
<span style="float: right;"><strong class='color-d'>level</strong> ${((m.dmgScale)).toPrecision(4)}x</span> <span style="float: right;"><strong class='color-d'>level</strong> ${((m.dmgScale)).toPrecision(4)}x</span>
<br><strong class='color-defense'>damage taken</strong> ${(m.defense()).toPrecision(4)}x <br><strong class='color-defense'>damage taken</strong> ${(m.defense()).toPrecision(4)}x
<span style="float: right;"><strong class='color-defense'>level</strong> ${(simulation.dmgScale).toPrecision(4)}x</span> <span style="float: right;"><strong class='color-defense'>level</strong> ${(simulation.dmgScale).toPrecision(4)}x</span>
<br><strong class='color-h'>health</strong> (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)}) <br><strong class='color-h'>health</strong> (${level.isHideHealth ? "null" : (m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
<span style="float: right;">${powerUps.research.count} ${powerUps.orb.research()}</span> <span style="float: right;">${powerUps.research.count} ${powerUps.orb.research()}</span>
<br><strong class='color-f'>energy</strong> (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000 * level.isReducedRegen).toFixed(0)}/s) <br><strong class='color-f'>energy</strong> (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000 * level.isReducedRegen).toFixed(0)}/s)
<span style="float: right;">${tech.totalCount} ${powerUps.orb.tech()}</span> <span style="float: right;">${tech.totalCount} ${powerUps.orb.tech()}</span>

View File

@@ -17,6 +17,8 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.difficultyMode = 1
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
@@ -31,7 +33,7 @@ const level = {
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// tech.addJunkTechToPool(0.5) // tech.addJunkTechToPool(0.5)
// m.couplingChange(10) // m.couplingChange(10)
// m.setField("time dilation") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook // m.setField("negative mass") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0 // m.energy = 0
// powerUps.research.count = 3 // powerUps.research.count = 3
// tech.isHookWire = true // tech.isHookWire = true
@@ -48,28 +50,26 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("non-renewables") }); // requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter") // tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5) // tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("pigeonhole principle") // for (let i = 0; i < 1; ++i) tech.giveTech("demineralization")
// for (let i = 0; i < 1; ++i) tech.giveTech("generalist") // for (let i = 0; i < 1; ++i) tech.giveTech("remineralization")
// m.skin.egg(); // m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds") // for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("interest") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("interest") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest") // for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle // m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "warp"); // for (let i = 0; i < 7; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false); // for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false);
// spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing // spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing
// level.corridor(); // level.testing();
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500) // for (let i = 0; i < 10; ++i) spawn.starter(1900, -500)
// for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500) // for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500)
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement"); // for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "boost"); // for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "gun");
// for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo"); // for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false); // for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
//lore testing //lore testing
@@ -145,22 +145,6 @@ const level = {
} }
level.setConstraints() level.setConstraints()
if (!localSettings.isHideHUD) {
requestAnimationFrame(() => {
//grow and get bright
document.getElementById("right-HUD-constraint").style.opacity = 1
document.getElementById("right-HUD-constraint").style.fontSize = "23px"
document.getElementById("right-HUD-constraint").style.top = simulation.difficultyMode > 6 ? "6px" : "9px"
setTimeout(() => {
if (m.alive) {
//fade to background
document.getElementById("right-HUD-constraint").style.opacity = 0.35
document.getElementById("right-HUD-constraint").style.fontSize = "20px"
document.getElementById("right-HUD-constraint").style.top = "12px"
}
}, 5000);
});
}
}, },
newLevelOrPhase() { //runs on each new level but also on final boss phases newLevelOrPhase() { //runs on each new level but also on final boss phases
//used for generalist and pigeonhole principle //used for generalist and pigeonhole principle
@@ -285,6 +269,46 @@ const level = {
} }
}, },
constraintIndex: 0, constraintIndex: 0,
constraintPopUp() {
//pause
if (!simulation.paused) {
simulation.paused = true;
simulation.isChoosing = true; //stops p from un pausing on key down
document.body.style.cursor = "auto";
document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s";
}
//build level info
document.getElementById("choose-grid").classList.add('choose-grid-no-images')
document.getElementById("choose-grid").classList.remove('choose-grid')
document.getElementById("choose-grid").style.gridTemplateColumns = "auto"//"450px"
let text = `<div class="constraint-module metallic-sparkle">${level.constraintDescription1}</div>`
if (level.constraintDescription2) text += `<div class="constraint-module metallic-sparkle"><span>${level.constraintDescription2}</div>`
text += `<div class="choose-grid-module" id = "choose-unPause" style="font-size: 1em;text-align: center;padding: 13px;border-radius:5px;">continue</div>`
document.getElementById("choose-grid").innerHTML = text
//show level info
document.getElementById("choose-grid").style.opacity = "1"
document.getElementById("choose-grid").style.transitionDuration = "0.25s"; //how long is the fade in on
document.getElementById("choose-grid").style.visibility = "visible"
document.getElementById("choose-unPause").addEventListener("click", () => {
level.unPause()
document.body.style.cursor = "none";
//reset hide image style
if (localSettings.isHideImages) {
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
} else {
document.getElementById("choose-grid").classList.add('choose-grid');
document.getElementById("choose-grid").classList.remove('choose-grid-no-images');
}
});
requestAnimationFrame(() => {
ctx.fillStyle = `rgba(150,150,150,0.9)`; //`rgba(221,221,221,0.6)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
},
setConstraints() { setConstraints() {
//populate array with possible constraints and reset constraints //populate array with possible constraints and reset constraints
level.constraintDescription1 = level.constraintDescription2 = "" level.constraintDescription1 = level.constraintDescription2 = ""
@@ -303,7 +327,6 @@ const level = {
level.constraintDescription1 = level.constraint[level.constraintIndex].description level.constraintDescription1 = level.constraint[level.constraintIndex].description
level.constraintIndex++ level.constraintIndex++
if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0 if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0
if (simulation.difficultyMode > 6 && possible.length) { if (simulation.difficultyMode > 6 && possible.length) {
level.constraint[level.constraintIndex].effect() level.constraint[level.constraintIndex].effect()
possible.splice(level.constraintIndex, 1) possible.splice(level.constraintIndex, 1)
@@ -312,6 +335,24 @@ const level = {
if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0 if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0
} }
document.getElementById("right-HUD-constraint").style.display = "block"; document.getElementById("right-HUD-constraint").style.display = "block";
// level.constraintPopUp()
//animate making constraint HUD bigger then smaller
if (!localSettings.isHideHUD) {
requestAnimationFrame(() => {
//grow and get bright
document.getElementById("right-HUD-constraint").style.opacity = 1
document.getElementById("right-HUD-constraint").style.fontSize = "23px"
document.getElementById("right-HUD-constraint").style.top = simulation.difficultyMode > 6 ? "6px" : "9px"
setTimeout(() => {
if (m.alive) {
//fade to background
document.getElementById("right-HUD-constraint").style.opacity = 0.35
document.getElementById("right-HUD-constraint").style.fontSize = "20px"
document.getElementById("right-HUD-constraint").style.top = "12px"
}
}, 5000);
});
}
} else { } else {
document.getElementById("right-HUD-constraint").style.display = "none"; document.getElementById("right-HUD-constraint").style.display = "none";
} }
@@ -320,10 +361,10 @@ const level = {
} }
//update HUD with constraints //update HUD with constraints
let text = `${level.constraintDescription1}` let text = `${level.constraintDescription1}`
if (level.constraintDescription1) simulation.inGameConsole(`<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);">constraint</span>: ${level.constraintDescription1}`) if (level.constraintDescription1) simulation.inGameConsole(`level<span class='color-symbol'>.</span>constraint<span class='color-symbol'>.</span>description<span class='color-symbol'>:</span> "<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);border-radius:6px;padding:3px;">${level.constraintDescription1}</span>"`)
if (simulation.difficultyMode > 6 && level.constraintDescription2) { if (simulation.difficultyMode > 6 && level.constraintDescription2) {
text += `<br>${level.constraintDescription2}` text += `<br>${level.constraintDescription2}`
if (level.constraintDescription2) simulation.inGameConsole(`<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);">constraint</span>: ${level.constraintDescription2}`) if (level.constraintDescription2) simulation.inGameConsole(`level<span class='color-symbol'>.</span>constraint<span class='color-symbol'>.</span>description<span class='color-symbol'>:</span> "<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);border-radius:6px;padding:3px;">${level.constraintDescription2}</span>"`)
} }
document.getElementById("right-HUD-constraint").innerHTML = text document.getElementById("right-HUD-constraint").innerHTML = text
@@ -427,7 +468,7 @@ const level = {
} }
}, },
{ {
description: "0.3x damage after getting power ups", description: "0.3x damage after using power ups",
effect() { effect() {
level.isNoDamage = true level.isNoDamage = true
level.noDamageCycle = 0 level.noDamageCycle = 0
@@ -1719,7 +1760,7 @@ const level = {
}, },
vanish(x, y, width, height, isVertical = false, hide = { vanish(x, y, width, height, isVertical = false, hide = {
x: 0, x: 0,
y: 150 y: 400
}) { }) {
x = x + width / 2 x = x + width / 2
y = y + height / 2 y = y + height / 2
@@ -6761,26 +6802,34 @@ const level = {
level.defaultZoom = 1500 level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#dcdcde";
spawn.debris(-150, -775, 1425, 3); //16 debris per level // spawn.debris(-150, -775, 1425, 3); //16 debris per level
spawn.debris(1525, -25, 950, 3); //16 debris per level // spawn.debris(1525, -25, 950, 3); //16 debris per level
spawn.debris(-650, -2100, 575, 2); //16 debris per level // spawn.debris(-650, -2100, 575, 2); //16 debris per level
powerUps.chooseRandomPowerUp(2075, -1525);
powerUps.chooseRandomPowerUp(2550, -1825);
powerUps.chooseRandomPowerUp(1975, 250);
//bottom floor //bottom floor
//entrance //entrance
spawn.mapRect(-200, -750, 1500, 100); spawn.mapRect(-200, -750, 1500, 100);
spawn.mapRect(-575, 0, 2150, 500); // spawn.mapRect(-575, 0, 2150, 500);
spawn.mapRect(-575, 0, 2150, 165);
const mover = level.mover(-525, 270, 2050, 75, 15 * (simulation.isHorizontalFlipped ? -1 : 1))
spawn.bodyRect(-1050, -75, 75, 75);
spawn.bodyRect(-573, 170, 30, 105);
// spawn.mapRect(-1275, 275, 875, 225); // spawn.mapRect(-1275, 275, 875, 225);
spawn.mapRect(-1275, 275, 3975, 225); spawn.mapRect(-1300, 275, 4025, 3300);
// spawn.mapRect(-1275, 275, 3975, 225);
spawn.mapRect(-1050, 0, 325, 50); spawn.mapRect(-1050, 0, 325, 50);
spawn.mapRect(-775, 0, 50, 140); spawn.mapRect(-775, 0, 50, 140);
vanish.push(level.vanish(-725, 13, 150, 25)) vanish.push(level.vanish(-725, 13, 150, 25))
spawn.mapRect(-200, -750, 100, 600); spawn.mapRect(-200, -750, 100, 600);
// spawn.mapRect(1200, -750, 100, 600); vanish.push(level.vanish(-525, -150, 425, 150))
vanish.push(level.vanish(-350, -225, 150, 225)) vanish.push(level.vanish(-475, -300, 275, 150))
vanish.push(level.vanish(-350, -450, 150, 223)) vanish.push(level.vanish(-425, -450, 225, 150))
vanish.push(level.vanish(-375, -600, 175, 150))
vanish.push(level.vanish(-325, -750, 125, 150))
spawn.mapRect(2475, -1800, 250, 2300); spawn.mapRect(2475, -1800, 250, 2300);
spawn.mapRect(1200, -750, 100, 450); spawn.mapRect(1200, -750, 100, 450);
spawn.mapRect(1200, -375, 250, 75); spawn.mapRect(1200, -375, 250, 75);
powerUps.spawnStartingPowerUps(550, -100); powerUps.spawnStartingPowerUps(550, -100);
@@ -6789,10 +6838,18 @@ const level = {
spawn.bodyRect(1350, -175, 150, 175, 0.5); spawn.bodyRect(1350, -175, 150, 175, 0.5);
spawn.bodyRect(1350, -600, 125, 225, 0.2); spawn.bodyRect(1350, -600, 125, 225, 0.2);
spawn.bodyRect(1575, 50, 50, 225);
vanish.push(level.vanish(1900, -25, 325, 25))
vanish.push(level.vanish(1925, -375, 275, 25))
vanish.push(level.vanish(1950, -725, 225, 25))
vanish.push(level.vanish(1950, -1075, 225, 25))
spawn.mapRect(1950, -1500, 225, 25);
vanish.push(level.vanish(1350, -1075, 225, 25))
vanish.push(level.vanish(1637, -1300, 225, 25))
//middle floor //middle floor
spawn.bodyRect(215, -1175, 100, 100, 0.3); spawn.bodyRect(215, -1175, 100, 100, 0.3);
spawn.mapRect(-1300, -1800, 250, 2300); spawn.mapRect(-1300, -1800, 250, 2300);
// spawn.mapRect(-1300, -2075, 250, 2575);
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
spawn.mapRect(500, -1350, 525, 425); spawn.mapRect(500, -1350, 525, 425);
spawn.mapRect(25, -1050, 300, 198); spawn.mapRect(25, -1050, 300, 198);
@@ -6800,34 +6857,17 @@ const level = {
spawn.mapRect(500, -1350, 525, 497); spawn.mapRect(500, -1350, 525, 497);
spawn.mapRect(25, -1050, 300, 150); spawn.mapRect(25, -1050, 300, 150);
} }
if (Math.random() < 0.5) {
vanish.push(level.vanish(400, -1600, 175, 25))
vanish.push(level.vanish(950, -1600, 175, 25))
} else {
vanish.push(level.vanish(550, -1575, 50, 225))
vanish.push(level.vanish(925, -1575, 50, 225))
}
// vanish.push(level.vanish(575, -1575, 375, 225))
spawn.bodyRect(225, -850, 50, 100, 0.4); spawn.bodyRect(225, -850, 50, 100, 0.4);
spawn.mapRect(600, -1800, 325, 225); // spawn.mapRect(600, -1800, 325, 225);
spawn.mapRect(1900, -1500, 325, 25); spawn.mapRect(650, -1800, 225, 225);
vanish.push(level.vanish(600, -1575, 100, 225))
vanish.push(level.vanish(825, -1575, 100, 225))
spawn.bodyRect(1050, -1825, 250, 20, 0.2); spawn.bodyRect(1050, -1825, 250, 20, 0.2);
if (Math.random() < 0.5) {
vanish.push(level.vanish(1400, -1000, 200, 25))
vanish.push(level.vanish(1625, -1250, 200, 25))
} else {
vanish.push(level.vanish(1400, -1075, 175, 175))
vanish.push(level.vanish(1575, -1250, 175, 175))
}
vanish.push(level.vanish(1125, -1800, 625, 25)) vanish.push(level.vanish(1125, -1800, 625, 25))
// vanish.push(level.vanish(1500, -1800, 225, 25))
vanish.push(level.vanish(-50, -1800, 450, 25)) vanish.push(level.vanish(-50, -1800, 450, 25))
//exit //exit
// spawn.mapRect(-1050, -1450, 700, 25);
// spawn.mapRect(-1050, -1800, 525, 25);
spawn.mapRect(-575, -1800, 50, 200); spawn.mapRect(-575, -1800, 50, 200);
spawn.mapRect(-1050, -1800, 525, 75); spawn.mapRect(-1050, -1800, 525, 75);
spawn.mapRect(-1050, -1450, 700, 75); spawn.mapRect(-1050, -1450, 700, 75);
@@ -6864,8 +6904,10 @@ const level = {
level.exit.drawAndCheck(); level.exit.drawAndCheck();
level.enter.draw(); level.enter.draw();
mover.push();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
mover.draw();
//shadow //shadow
ctx.fillStyle = "rgba(0,10,30,0.1)" ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(-1450, -300, 150, 325); ctx.fillRect(-1450, -300, 150, 325);
@@ -6873,7 +6915,9 @@ const level = {
ctx.fillRect(725, 50, 325, 225) ctx.fillRect(725, 50, 325, 225)
ctx.fillRect(-325, -950, 300, 225) ctx.fillRect(-325, -950, 300, 225)
ctx.fillRect(-1025, -1000, 525, 275); ctx.fillRect(-1025, -1000, 525, 275);
ctx.fillRect(-925, -1600, 325, 275); ctx.fillRect(-875, -1600, 225, 275);
ctx.fillStyle = "rgba(68,68,68,0.93)"
ctx.fillRect(-1575, 150, 2150, 150);
for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query() for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
}; };
@@ -6888,16 +6932,20 @@ const level = {
level.exit.drawAndCheck(); level.exit.drawAndCheck();
level.enter.draw(); level.enter.draw();
mover.push();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
mover.draw();
//shadow //shadow
ctx.fillStyle = "rgba(0,10,30,0.1)" ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(1300, -300, 150, 325); ctx.fillRect(1300, -300, 150, 325);
ctx.fillRect(-200, -675, 1500, 700) ctx.fillRect(-200, -675, 1500, 700)
ctx.fillRect(500, -950, 525, 225); ctx.fillRect(500, -950, 525, 225);
ctx.fillRect(600, -1600, 325, 275); ctx.fillRect(650, -1600, 225, 275);
ctx.fillRect(-1050, 50, 325, 225) ctx.fillRect(-1050, 50, 325, 225)
ctx.fillRect(25, -950, 300, 225) ctx.fillRect(25, -950, 300, 225)
ctx.fillStyle = "rgba(68,68,68,0.93)"
ctx.fillRect(-575, 150, 2150, 150);
for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query() for (let i = 0, len = vanish.length; i < len; i++) vanish[i].query()
}; };
} }
@@ -7178,6 +7226,12 @@ const level = {
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5d5"; document.body.style.backgroundColor = "#d0d5d5";
color.map = "#444" color.map = "#444"
powerUps.chooseRandomPowerUp(-1550, 300);
powerUps.chooseRandomPowerUp(200, 50);
powerUps.chooseRandomPowerUp(-975, -1475);
powerUps.chooseRandomPowerUp(2150, -750);
powerUps.chooseRandomPowerUp(1850, 1925);
let buttons = [] let buttons = []
let lasers = [] let lasers = []
@@ -7202,8 +7256,8 @@ const level = {
classType: "body", classType: "body",
holdX: 1762, holdX: 1762,
maxHeight: -1580, maxHeight: -1580,
minHeight: 130, minHeight: 90,
verticalForce: 0.03, verticalForce: 0.02,
isUp: false, isUp: false,
drag: 0.01, drag: 0.01,
move() { move() {
@@ -7269,7 +7323,7 @@ const level = {
let buildMapOutline = function () { let buildMapOutline = function () {
//boxes center on zero,zero with deep walls to hide background //boxes center on zero,zero with deep walls to hide background
spawn.mapRect(2025, -2000, 1975, 4000); //right map wall spawn.mapRect(2225, -2000, 1775, 4000); //right map wall
spawn.mapRect(-4000, -2000, 2000, 4000); //left map wall spawn.mapRect(-4000, -2000, 2000, 4000); //left map wall
spawn.mapRect(-4000, -5000, 8000, 3000); //map ceiling spawn.mapRect(-4000, -5000, 8000, 3000); //map ceiling
spawn.mapRect(-4000, 2000, 8000, 3000); //floor spawn.mapRect(-4000, 2000, 8000, 3000); //floor
@@ -7325,13 +7379,13 @@ const level = {
//lower right side //lower right side
//far right wall ledges //far right wall ledges
spawn.mapRect(1925, -1700, 200, 200); spawn.mapRect(1925, -1700, 400, 200);
spawn.mapRect(1925, -1200, 200, 200); spawn.mapRect(1925, -1200, 400, 200);
spawn.mapRect(1925, -700, 200, 200); spawn.mapRect(1925, -700, 400, 200);
spawn.mapRect(1925, -200, 200, 200); spawn.mapRect(1925, -200, 400, 200);
spawn.mapRect(1925, 300, 200, 200); spawn.mapRect(1925, 300, 400, 200);
spawn.mapRect(1925, 800, 200, 200); spawn.mapRect(1925, 800, 400, 200);
spawn.mapRect(1925, 1300, 200, 200); spawn.mapRect(1925, 1300, 400, 200);
spawn.mapRect(1250, 1650, 500, 25); spawn.mapRect(1250, 1650, 500, 25);
spawn.mapRect(1300, 1125, 400, 25); spawn.mapRect(1300, 1125, 400, 25);
@@ -7402,13 +7456,13 @@ const level = {
spawn.mapVertex(-350, -835, "-225 -475 225 -475 225 475 0 500 -225 475"); spawn.mapVertex(-350, -835, "-225 -475 225 -475 225 475 0 500 -225 475");
//far right wall ledges //far right wall ledges
spawn.mapRect(1925, 1700 - 200, 200, 200); spawn.mapRect(1925, 1700 - 200, 400, 200);
spawn.mapRect(1925, 1200 - 200, 200, 200); spawn.mapRect(1925, 1200 - 200, 400, 200);
spawn.mapRect(1925, 700 - 200, 200, 200); spawn.mapRect(1925, 700 - 200, 400, 200);
spawn.mapRect(1925, 200 - 200, 200, 200); spawn.mapRect(1925, 200 - 200, 400, 200);
spawn.mapRect(1925, -300 - 200, 200, 200); spawn.mapRect(1925, -300 - 200, 400, 200);
spawn.mapRect(1925, -800 - 200, 200, 200); spawn.mapRect(1925, -800 - 200, 400, 200);
spawn.mapRect(1925, -1300 - 200, 200, 200); spawn.mapRect(1925, -1300 - 200, 400, 200);
spawn.mapRect(1250, -1650 - 25, 500, 25); spawn.mapRect(1250, -1650 - 25, 500, 25);
spawn.mapRect(1300, -1125 - 25, 400, 25); spawn.mapRect(1300, -1125 - 25, 400, 25);
@@ -7559,7 +7613,7 @@ const level = {
//background structure //background structure
ctx.fillStyle = "#c3c7c7" ctx.fillStyle = "#c3c7c7"
ctx.fillRect(1487, -75 - 1925, 25, 1925); ctx.fillRect(1487, -75 - 1925, 25, 1925);
ctx.fillRect(1925, -2050, 125, 4100); ctx.fillRect(1925, -2050, 300, 4100);
//exit room //exit room
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
@@ -7580,7 +7634,7 @@ const level = {
//background structure //background structure
ctx.fillStyle = "#c5c9c9" ctx.fillStyle = "#c5c9c9"
ctx.fillRect(1487, 75, 25, 1925); ctx.fillRect(1487, 75, 25, 1925);
ctx.fillRect(1925, -2050, 125, 4100); ctx.fillRect(1925, -2050, 300, 4100);
//draw flipped exit //draw flipped exit
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
@@ -7604,7 +7658,7 @@ const level = {
ctx.moveTo(balance[i].center.x, balance[i].center.y) ctx.moveTo(balance[i].center.x, balance[i].center.y)
ctx.arc(balance[i].center.x, balance[i].center.y, 9, 0, 2 * Math.PI); ctx.arc(balance[i].center.x, balance[i].center.y, 9, 0, 2 * Math.PI);
//rotor spins and stops at vertical and horizontal angles //rotor spins and stops at vertical and horizontal angles
if ((simulation.cycle % 90) < 15) { if ((simulation.cycle % 140) < 15) {
balance[i].torque = 0.0002 * balance[i].inertia balance[i].torque = 0.0002 * balance[i].inertia
} else if (Math.floor(10 * (balance[i].angle % (Math.PI / 2))) === 0) { } else if (Math.floor(10 * (balance[i].angle % (Math.PI / 2))) === 0) {
Matter.Body.setAngularVelocity(balance[i], balance[i].angularVelocity * 0.1) Matter.Body.setAngularVelocity(balance[i], balance[i].angularVelocity * 0.1)
@@ -7653,6 +7707,8 @@ const level = {
spawn.bodyRect(1325, -1775, 175, 175); spawn.bodyRect(1325, -1775, 175, 175);
spawn.bodyRect(-375, -1725, 100, 75, 0.5); spawn.bodyRect(-375, -1725, 100, 75, 0.5);
spawn.bodyRect(-900, -1625, 125, 200, 0.5); spawn.bodyRect(-900, -1625, 125, 200, 0.5);
spawn.bodyRect(875, -25, 200, 175);
spawn.bodyRect(-1662, 1325, 25, 175); spawn.bodyRect(-1662, 1325, 25, 175);
spawn.bodyRect(-1662, 1825, 25, 175); spawn.bodyRect(-1662, 1825, 25, 175);
@@ -7708,6 +7764,9 @@ const level = {
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#c3d6e1"; document.body.style.backgroundColor = "#c3d6e1";
color.map = "#444" color.map = "#444"
powerUps.chooseRandomPowerUp(-1825, 975);
powerUps.chooseRandomPowerUp(-3975, 975);
powerUps.chooseRandomPowerUp(3900, 925);
let buttons = [] let buttons = []
level.isFlipped = false; level.isFlipped = false;
@@ -8220,12 +8279,14 @@ const level = {
spawn.randomMob(2825, 75, 0.9); spawn.randomMob(2825, 75, 0.9);
spawn.randomLevelBoss(2400, 600); spawn.randomLevelBoss(2400, 600);
spawn.secondaryBossChance(800, -300) spawn.secondaryBossChance(800, -300)
powerUps.spawnStartingPowerUps(600, 375); powerUps.chooseRandomPowerUp(600, 375);
powerUps.chooseRandomPowerUp(600, 925);
powerUps.spawnStartingPowerUps(1750, -325);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
powerUps.directSpawn(2825, 175, "heal"); powerUps.chooseRandomPowerUp(2825, 175);
powerUps.directSpawn(2475, -650, "heal"); powerUps.chooseRandomPowerUp(2475, -650);
powerUps.directSpawn(2100, 925, "heal"); powerUps.chooseRandomPowerUp(2100, 925);
powerUps.directSpawn(625, -100, "heal"); powerUps.chooseRandomPowerUp(625, -100);
}, },
corridor() { corridor() {
// simulation.fallHeight = 4000 // simulation.fallHeight = 4000
@@ -8235,6 +8296,10 @@ const level = {
document.body.style.backgroundColor = "#d0d5d5"; document.body.style.backgroundColor = "#d0d5d5";
color.map = "#444" color.map = "#444"
powerUps.chooseRandomPowerUp(5925, -2125);
powerUps.chooseRandomPowerUp(75, -4225);
powerUps.chooseRandomPowerUp(2950, -1450);
// level.isHorizontalFlipped = true // level.isHorizontalFlipped = true
if (level.isHorizontalFlipped) { if (level.isHorizontalFlipped) {
level.setPosToSpawn(14075, -625); level.setPosToSpawn(14075, -625);
@@ -8473,8 +8538,8 @@ const level = {
spawn.randomMob(3575, 375, 0.6); spawn.randomMob(3575, 375, 0.6);
spawn.randomGroup(5300, -1400, 1.3); spawn.randomGroup(5300, -1400, 1.3);
spawn.randomLevelBoss(2025, -1825); spawn.randomLevelBoss(2025, -1825, ["pulsarBoss", "shieldingBoss", "laserLayerBoss", "shooterBoss"]);
spawn.secondaryBossChance(-1900, -1800); spawn.secondaryBossChance(-1900, -1800, ["historyBoss", "spawnerBossCulture", "blockBoss"]);
powerUps.spawnStartingPowerUps(11750, -1000); powerUps.spawnStartingPowerUps(11750, -1000);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
}, },
@@ -8948,18 +9013,17 @@ const level = {
button0.query(); button0.query();
if (!button0.isUp) { //summon second set of mobs if (!button0.isUp) { //summon second set of mobs
//1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving) //1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving)
spawn.randomMob(918, 2695, 0.1); spawn.randomMob(918, 2695, 0);
spawn.randomMob(1818, 2719, 0.2); spawn.randomMob(1818, 2719, 0.1);
spawn.randomMob(2530, 2460, 0.2); spawn.randomMob(2530, 2460, 0.1);
spawn.randomMob(3109, 2665, 0.3); spawn.randomMob(3109, 2665, 0.2);
spawn.randomMob(3909, 2191, 0.3); spawn.randomMob(3909, 2191, 0.2);
spawn.randomMob(4705, 2711, 0.4); spawn.randomMob(4705, 2711, 0.3);
spawn.randomMob(5800, 2796, 0.5); spawn.randomMob(5800, 2796, 0.3);
spawn.randomMob(7287, 2757, 0.6); spawn.randomMob(7287, 2757, 0.4);
spawn.randomMob(5759, 2691, 0.9); spawn.randomMob(5759, 2691, 0.4);
spawn.randomMob(5675, 2225, 0.8); spawn.randomMob(5675, 2225, 0.5);
spawn.randomMob(7450, 2775, 0.8); spawn.randomMob(7450, 2775, 0.5);
spawn.randomGroup(6600, 2400, 0.1); spawn.randomGroup(6600, 2400, 0.1);
if (simulation.difficulty > 1) spawn.randomLevelBoss(6076, 2341); if (simulation.difficulty > 1) spawn.randomLevelBoss(6076, 2341);
} }
@@ -9050,7 +9114,9 @@ const level = {
spawn.bodyRect(3825, 2240, 150, 75, 0.5); spawn.bodyRect(3825, 2240, 150, 75, 0.5);
spawn.mapVertex(3500, 2452, "-500 -135 500 -135 500 35 400 135 -400 135 -500 35"); spawn.mapVertex(3500, 2452, "-500 -135 500 -135 500 35 400 135 -400 135 -500 35");
spawn.mapVertex(1200, 2875, "-400 0 -300 -100 300 -100 400 0"); spawn.mapVertex(1200, 2850, "-500 -100 -550 -50 500 -100 550 -50 550 300 -550 300");
// spawn.mapVertex(1200, 2875, "-400 0 -300 -100 300 -100 400 0");
spawn.mapVertex(1317, 275, "-500 0 -300 -200 300 -200 550 50 550 500 -500 500"); spawn.mapVertex(1317, 275, "-500 0 -300 -200 300 -200 550 50 550 500 -500 500");
spawn.mapVertex(1300, -357, "-300 0 -400 -100 400 -100 300 0"); spawn.mapVertex(1300, -357, "-300 0 -400 -100 400 -100 300 0");
spawn.bodyRect(1550, -308, 50, 208, 0.5); spawn.bodyRect(1550, -308, 50, 208, 0.5);
@@ -9081,17 +9147,17 @@ const level = {
spawn.mapRect(7625, 2890, 400, 25); spawn.mapRect(7625, 2890, 400, 25);
spawn.mapRect(7800, 2880, 100, 25); spawn.mapRect(7800, 2880, 100, 25);
spawn.randomMob(2450, 250, 0.2); spawn.randomMob(2450, 250, 0);
spawn.randomMob(3250, 325, 0.2); spawn.randomMob(3250, 325, 0);
spawn.randomMob(3625, 350, 0.3); spawn.randomMob(3625, 350, 0.1);
spawn.randomMob(1750, -25, 0.4); spawn.randomMob(1750, -25, 0.1);
spawn.randomMob(1300, 1750, 0.5); spawn.randomMob(1300, 1750, 0.2);
spawn.randomMob(2350, 1725, 0.6); spawn.randomMob(2350, 1725, 0.2);
spawn.randomMob(3350, 1775, 0.7); spawn.randomMob(3350, 1775, 0.2);
spawn.randomMob(1025, 750, 0.8); spawn.randomMob(1025, 750, 0.3);
spawn.randomMob(2400, 1775, 0.8); spawn.randomMob(2400, 1775, 0.3);
spawn.randomMob(1250, 1725, 0.8); spawn.randomMob(1250, 1725, 0.3);
spawn.randomMob(775, 1775, 0.9); spawn.randomMob(775, 1775, 0.4);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(1822, 1336) spawn.secondaryBossChance(1822, 1336)
@@ -9102,7 +9168,7 @@ const level = {
balance1 = level.rotor(-800 - 25, -395, 25, 390, 0.001) //entrance balance1 = level.rotor(-800 - 25, -395, 25, 390, 0.001) //entrance
balance2 = level.rotor(-2605 - 390, 500, 390, 25, 0.001) //falling balance2 = level.rotor(-2605 - 390, 500, 390, 25, 0.001) //falling
balance3 = level.rotor(-2608 - 584, 1950, 584, 25, 0.001) //falling balance3 = level.rotor(-2608 - 400, 1950, 400, 25, 0.001) //falling
balance5 = level.rotor(-2605 - 390, 1020, 390, 25, 0.001) //falling balance5 = level.rotor(-2605 - 390, 1020, 390, 25, 0.001) //falling
button1.min.x = -button1.min.x - 126 button1.min.x = -button1.min.x - 126
@@ -9129,17 +9195,17 @@ const level = {
button0.query(); button0.query();
if (!button0.isUp) { //summon second set of mobs if (!button0.isUp) { //summon second set of mobs
//1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving) //1 boss, 1-2 groups, 11 mobs (all on lower ground level, where the slime is leaving)
spawn.randomMob(-7475, 2800, 0.1); spawn.randomMob(-7475, 2800, 0);
spawn.randomMob(-6475, 2500, 0.2); spawn.randomMob(-6475, 2500, 0.1);
spawn.randomMob(-4575, 2775, 0.3); spawn.randomMob(-4575, 2775, 0.2);
spawn.randomMob(-7575, 2850, 0.3); spawn.randomMob(-7575, 2850, 0.2);
spawn.randomMob(-6425, 2575, 0.3); spawn.randomMob(-6425, 2575, 0.2);
spawn.randomMob(-5750, 2775, 0.4); spawn.randomMob(-5750, 2775, 0.3);
spawn.randomMob(-4675, 2800, 0.5); spawn.randomMob(-4675, 2800, 0.3);
spawn.randomMob(-3425, 2800, 0.6); spawn.randomMob(-3425, 2800, 0.4);
spawn.randomMob(-2475, 2475, 0.7); spawn.randomMob(-2475, 2475, 0.4);
spawn.randomMob(-3350, 2250, 0.8); spawn.randomMob(-3350, 2250, 0.5);
spawn.randomMob(-1275, 2725, 0.9); spawn.randomMob(-1275, 2725, 0.5);
spawn.randomGroup(-6225, 2400, 0.1); spawn.randomGroup(-6225, 2400, 0.1);
if (simulation.difficulty > 1) spawn.randomLevelBoss(-6250, 2350); if (simulation.difficulty > 1) spawn.randomLevelBoss(-6250, 2350);
} }
@@ -9168,7 +9234,7 @@ const level = {
rotor2 = level.rotor(1525, 1900, 650, 50, 0.001, 0, 0.01, 0, -0.0007) rotor2 = level.rotor(1525, 1900, 650, 50, 0.001, 0, 0.01, 0, -0.0007)
balance1 = level.rotor(800, -395, 25, 390, 0.001) //entrance balance1 = level.rotor(800, -395, 25, 390, 0.001) //entrance
balance2 = level.rotor(2605, 500, 390, 25, 0.001) //falling balance2 = level.rotor(2605, 500, 390, 25, 0.001) //falling
balance3 = level.rotor(2608, 1950, 584, 25, 0.001) //falling balance3 = level.rotor(2608, 1950, 400, 25, 0.001) //falling
balance5 = level.rotor(2605, 1020, 390, 25, 0.001) //falling balance5 = level.rotor(2605, 1020, 390, 25, 0.001) //falling
} }
@@ -34957,8 +35023,8 @@ const level = {
y: mob[k].velocity.y - 8 * Math.sin(angle) y: mob[k].velocity.y - 8 * Math.sin(angle)
}); });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && g.energy > 0.1 && mob[k].damageReduction > 0) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && g.energy > 0.08 && mob[k].damageReduction > 0) {
g.energy -= 0.1 //* Math.max(g.maxEnergy, g.energy) //0.33 * g.energy g.energy -= 0.08 //* Math.max(g.maxEnergy, g.energy) //0.33 * g.energy
if (g.immuneCycle === g.cycle + g.collisionImmuneCycles) g.immuneCycle = 0; //genisis doesn't go immune to collision damage if (g.immuneCycle === g.cycle + g.collisionImmuneCycles) g.immuneCycle = 0; //genisis doesn't go immune to collision damage
mob[k].death(); mob[k].death();
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue

View File

@@ -1234,6 +1234,30 @@ const mobs = {
m.energy -= 0.05; m.energy -= 0.05;
if (m.energy < 0) m.energy = 0 if (m.energy < 0) m.energy = 0
} }
if (tech.isRemineralize) {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
//apply mineral damage reduction
tech.mineralDamageReduction *= 0.85
}
if (tech.isDemineralize) {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
//apply mineral damage
tech.mineralDamage *= 1.08
}
powerUps.spawnRandomPowerUp(this.position.x, this.position.y); powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks() m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
mobs.mobDeaths++ mobs.mobDeaths++
@@ -1253,9 +1277,11 @@ const mobs = {
} else { } else {
for (let i = 0; i < amount; i++) b.spore(this.position) for (let i = 0; i < amount; i++) b.spore(this.position)
} }
} else if (tech.isExplodeMob) { }
if (tech.isExplodeMob) {
b.explosion(this.position, Math.min(700, Math.sqrt(this.mass + 6) * (30 + 60 * Math.random()))) b.explosion(this.position, Math.min(700, Math.sqrt(this.mass + 6) * (30 + 60 * Math.random())))
} else if (tech.nailsDeathMob) { }
if (tech.nailsDeathMob) {
b.targetedNail(this.position, tech.nailsDeathMob, 39 + 6 * Math.random()) b.targetedNail(this.position, tech.nailsDeathMob, 39 + 6 * Math.random())
} }
if (tech.isBotSpawnerReset) { if (tech.isBotSpawnerReset) {
@@ -1269,7 +1295,7 @@ const mobs = {
this.leaveBody = false; // no body since it turned into the bot this.leaveBody = false; // no body since it turned into the bot
} }
if (tech.isMobDeathImmunity) { if (tech.isMobDeathImmunity) {
const immuneTime = 360 const immuneTime = 300
if (m.immuneCycle < m.cycle + immuneTime) m.immuneCycle = m.cycle + immuneTime; //player is immune to damage if (m.immuneCycle < m.cycle + immuneTime) m.immuneCycle = m.cycle + immuneTime; //player is immune to damage
} }
if (tech.isAddRemoveMaxHealth) { if (tech.isAddRemoveMaxHealth) {

View File

@@ -782,9 +782,9 @@ const m = {
defense() { defense() {
let dmg = 1 let dmg = 1
if (powerUps.boost.isDefense && powerUps.boost.endCycle > simulation.cycle) dmg *= 0.3 if (powerUps.boost.isDefense && powerUps.boost.endCycle > simulation.cycle) dmg *= 0.3
if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.2 if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.1
if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075); if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15 if (tech.isZeno) dmg *= 0.2
if (tech.isFieldHarmReduction) dmg *= 0.6 if (tech.isFieldHarmReduction) dmg *= 0.6
if (tech.isHarmDarkMatter) dmg *= (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 0.25 : 0.4 if (tech.isHarmDarkMatter) dmg *= (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 0.25 : 0.4
if (tech.isImmortal) dmg *= 0.7 if (tech.isImmortal) dmg *= 0.7
@@ -795,12 +795,20 @@ const m = {
if (tech.isHarmReduce && input.field) dmg *= 0.1 if (tech.isHarmReduce && input.field) dmg *= 0.1
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05 if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
if (tech.isBotArmor) dmg *= 0.96 ** b.totalBots() if (tech.isBotArmor) dmg *= 0.96 ** b.totalBots()
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.3; if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.4;
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3 if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3
if (tech.isTurret && m.crouch) dmg *= 0.3; if (tech.isTurret && m.crouch) dmg *= 0.3;
if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length
// if (tech.isLowHealthDefense) dmg *= Math.pow(0.3, Math.max(0, (tech.isEnergyHealth ? m.maxEnergy - m.energy : m.maxHealth - m.health))) // if (tech.isLowHealthDefense) dmg *= Math.pow(0.3, Math.max(0, (tech.isEnergyHealth ? m.maxEnergy - m.energy : m.maxHealth - m.health)))
if (tech.isLowHealthDefense) dmg *= Math.pow(0.2, Math.max(0, 1 - (tech.isEnergyHealth ? m.energy / m.maxEnergy : m.health / m.maxHealth))) if (tech.isLowHealthDefense) dmg *= Math.pow(0.2, Math.max(0, 1 - (tech.isEnergyHealth ? m.energy / m.maxEnergy : m.health / m.maxHealth)))
if (tech.isRemineralize) {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
dmg *= tech.mineralDamageReduction
}
// return tech.isEnergyHealth ? Math.pow(dmg, 0.7) : dmg //defense has less effect // return tech.isEnergyHealth ? Math.pow(dmg, 0.7) : dmg //defense has less effect
// dmg *= m.fieldHarmReduction // dmg *= m.fieldHarmReduction
return dmg * m.fieldHarmReduction return dmg * m.fieldHarmReduction
@@ -2736,10 +2744,10 @@ const m = {
m.fieldThreshold = Math.cos((m.fieldArc) * Math.PI) m.fieldThreshold = Math.cos((m.fieldArc) * Math.PI)
}, },
setHoldDefaults() { setHoldDefaults() {
if (tech.isFreeWormHole && m.fieldMode !== 9) { //not wormhole // if (tech.isFreeWormHole && m.fieldMode !== 9) { //not wormhole
const removed = tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field // const removed = tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); // if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
} // }
if (tech.isNeutronium && m.fieldMode !== 3) { //not negative mass field if (tech.isNeutronium && m.fieldMode !== 3) { //not negative mass field
const removed = tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field const removed = tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
@@ -2835,7 +2843,7 @@ const m = {
} else if (m.fieldMode === 8) { } else if (m.fieldMode === 8) {
m.fieldRegen = 0.001667 //10 energy per second pilot wave m.fieldRegen = 0.001667 //10 energy per second pilot wave
} else if (m.fieldMode === 9) { } else if (m.fieldMode === 9) {
m.fieldRegen = 0.00117 //7 energy per second wormhole m.fieldRegen = 0.001334 //8 energy per second wormhole
} else if (m.fieldMode === 10) { } else if (m.fieldMode === 10) {
m.fieldRegen = 0.0015 //9 energy per second grappling hook m.fieldRegen = 0.0015 //9 energy per second grappling hook
} else { } else {
@@ -4011,14 +4019,14 @@ const m = {
{ {
name: "negative mass", name: "negative mass",
//<br>hold <strong class='color-block'>blocks</strong> as if they have a lower <strong>mass</strong> //<br>hold <strong class='color-block'>blocks</strong> as if they have a lower <strong>mass</strong>
description: `use <strong class='color-f'>energy</strong> to nullify &nbsp;<strong style='letter-spacing: 7px;'>gravity</strong><br><strong>0.4x</strong> <strong class='color-defense'>damage taken</strong><br><strong>6</strong> <strong class='color-f'>energy</strong> per second`, description: `use <strong class='color-f'>energy</strong> to nullify &nbsp;<strong style='letter-spacing: 7px;'>gravity</strong><br><strong>0.5x</strong> <strong class='color-defense'>damage taken</strong><br><strong>6</strong> <strong class='color-f'>energy</strong> per second`,
fieldDrawRadius: 0, fieldDrawRadius: 0,
effect: () => { effect: () => {
m.fieldFire = true; m.fieldFire = true;
m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333" m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.4; m.fieldHarmReduction = 0.5;
m.fieldDrawRadius = 0; m.fieldDrawRadius = 0;
m.hold = function () { m.hold = function () {
@@ -4032,8 +4040,7 @@ const m = {
if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
m.grabPowerUp(); m.grabPowerUp();
m.lookForPickUp(); m.lookForPickUp();
const DRAIN = 0.00035 if (m.energy > tech.negativeMassCost && m.fieldCDcycle < m.cycle) {
if (m.energy > DRAIN && m.fieldCDcycle < m.cycle) {
if (tech.isFlyFaster) { if (tech.isFlyFaster) {
//look for nearby objects to make zero-g //look for nearby objects to make zero-g
function moveThis(who, range, mag = 1.06) { function moveThis(who, range, mag = 1.06) {
@@ -4065,13 +4072,13 @@ const m = {
moveThis(powerUp, this.fieldDrawRadius, 0); moveThis(powerUp, this.fieldDrawRadius, 0);
moveThis(body, this.fieldDrawRadius, 0); moveThis(body, this.fieldDrawRadius, 0);
} else if (input.up) { //up } else if (input.up) { //up
m.energy -= 5 * DRAIN; m.energy -= 5 * tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 1100 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 1100 * 0.03;
player.force.y -= 2.25 * player.mass * simulation.g; player.force.y -= 2.25 * player.mass * simulation.g;
moveThis(powerUp, this.fieldDrawRadius, 1.8); moveThis(powerUp, this.fieldDrawRadius, 1.8);
moveThis(body, this.fieldDrawRadius, 1.8); moveThis(body, this.fieldDrawRadius, 1.8);
} else { } else {
m.energy -= DRAIN; m.energy -= tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 800 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 800 * 0.03;
player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
moveThis(powerUp, this.fieldDrawRadius); moveThis(powerUp, this.fieldDrawRadius);
@@ -4109,13 +4116,13 @@ const m = {
verticalForce(powerUp, this.fieldDrawRadius, 0.7); verticalForce(powerUp, this.fieldDrawRadius, 0.7);
verticalForce(body, this.fieldDrawRadius, 0.7); verticalForce(body, this.fieldDrawRadius, 0.7);
} else if (input.up) { //up } else if (input.up) { //up
m.energy -= 5 * DRAIN; m.energy -= 5 * tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
player.force.y -= 1.45 * player.mass * simulation.g; player.force.y -= 1.45 * player.mass * simulation.g;
verticalForce(powerUp, this.fieldDrawRadius, 1.38); verticalForce(powerUp, this.fieldDrawRadius, 1.38);
verticalForce(body, this.fieldDrawRadius, 1.38); verticalForce(body, this.fieldDrawRadius, 1.38);
} else { } else {
m.energy -= DRAIN; m.energy -= tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03; this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
verticalForce(powerUp, this.fieldDrawRadius); verticalForce(powerUp, this.fieldDrawRadius);
@@ -5051,7 +5058,7 @@ const m = {
} }
} }
if (tech.isCloakStun) { //stun nearby mobs after exiting cloak if (tech.isCloakStun) { //stun nearby mobs after exiting cloak
let isMobsAround = false // let isMobsAround = false
const stunRange = m.fieldDrawRadius * 1.25 const stunRange = m.fieldDrawRadius * 1.25
// const drain = 0.01 // const drain = 0.01
// if (m.energy > drain) { // if (m.energy > drain) {
@@ -5358,7 +5365,7 @@ const m = {
{ {
name: "wormhole", name: "wormhole",
//<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br> //<strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br>
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>7</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong>+8%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>8</strong> <strong class='color-f'>energy</strong> per second", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
drain: 0, drain: 0,
effect: function () { effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5" m.fieldMeterColor = "#bbf" //"#0c5"
@@ -5454,8 +5461,10 @@ const m = {
if (tech.isWormholeWorms) { //pandimensional spermia if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random()))) b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10)); Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) { if (Math.random() < 0.5) { //chance for a second worm
// } b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10));
}
} }
break break
} }
@@ -5475,13 +5484,12 @@ const m = {
if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling * level.isReducedRegen if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling * level.isReducedRegen
if (m.fieldMode === 0 || m.fieldMode === 9) m.energy += 0.02 * m.coupling * level.isReducedRegen if (m.fieldMode === 0 || m.fieldMode === 9) m.energy += 0.02 * m.coupling * level.isReducedRegen
if (tech.isWormholeWorms) { //pandimensional spermia if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos1, Vector.rotate({ b.worm(Vector.add(m.hole.pos1, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5)); Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
// for (let i = 0, len = Math.ceil(1.25 * Math.random()); i < len; i++) { if (Math.random() < 0.5) { //chance for a second worm
// } b.worm(Vector.add(m.hole.pos1, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
}
} }
break break
} }
@@ -6239,8 +6247,8 @@ const m = {
y: mob[k].velocity.y - 8 * Math.sin(angle) y: mob[k].velocity.y - 8 * Math.sin(angle)
}); });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.08) {
m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) m.energy -= 0.08 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
m.immuneCycle = 0; //player doesn't go immune to collision damage m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death(); mob[k].death();
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue

View File

@@ -256,6 +256,8 @@ const powerUps = {
powerUps.endDraft(type); powerUps.endDraft(type);
}, },
showDraft() { showDraft() {
simulation.isChoosing = true; //stops p from un pausing on key down
//disable clicking for 1/2 a second to prevent mistake clicks //disable clicking for 1/2 a second to prevent mistake clicks
document.getElementById("choose-grid").style.pointerEvents = "none"; document.getElementById("choose-grid").style.pointerEvents = "none";
document.body.style.cursor = "none"; document.body.style.cursor = "none";
@@ -264,7 +266,6 @@ const powerUps = {
document.getElementById("choose-grid").style.pointerEvents = "auto"; document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s"; document.getElementById("choose-grid").style.transitionDuration = "0s";
}, 400); }, 400);
simulation.isChoosing = true; //stops p from un pausing on key down
if (!simulation.paused) { if (!simulation.paused) {
if (tech.isNoDraftPause || level.isNoPause) { if (tech.isNoDraftPause || level.isNoPause) {
@@ -909,7 +910,7 @@ const powerUps = {
} }
}, },
cancelText(type) { cancelText(type) {
if (tech.isSuperDeterminism) { if (tech.isSuperDeterminism || type === "constraint") {
return `<div></div>` return `<div></div>`
} else if (tech.isCancelTech && tech.cancelTechCount === 0) { } else if (tech.isCancelTech && tech.cancelTechCount === 0) {
return `<div class='cancel-card sticky' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>` return `<div class='cancel-card sticky' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>`
@@ -940,7 +941,9 @@ const powerUps = {
}, },
researchAndCancelText(type) { researchAndCancelText(type) {
let text = `<div class='research-cancel'>` let text = `<div class='research-cancel'>`
if (type === "entanglement") { if (type === "constraint") {
return
} else if (type === "entanglement") {
text += `<span class='research-card entanglement flipX' style="width: 275px;" onclick='powerUps.endDraft("${type}",true)'><span style="letter-spacing: 6px;">entanglement</span></span>` text += `<span class='research-card entanglement flipX' style="width: 275px;" onclick='powerUps.endDraft("${type}",true)'><span style="letter-spacing: 6px;">entanglement</span></span>`
} else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) { } else if (tech.isJunkResearch && powerUps.research.currentRerollCount < 2) {
text += `<span onclick="powerUps.research.use('${type}')" class='research-card' style="width: 275px;float: left;">` // style = "margin-left: 192px; margin-right: -192px;" text += `<span onclick="powerUps.research.use('${type}')" class='research-card' style="width: 275px;float: left;">` // style = "margin-left: 192px; margin-right: -192px;"
@@ -1008,6 +1011,12 @@ const powerUps = {
return text return text
}, },
hideStyle: `style="height:auto; border: none; background-color: transparent;"`, hideStyle: `style="height:auto; border: none; background-color: transparent;"`,
constraintText(choose, click) {
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${powerUps.hideStyle}>
<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choose].name}</div>
${m.fieldUpgrades[choose].description}</div></div>`
},
gunText(choose, click) { gunText(choose, click) {
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/gun/${b.guns[choose].name}.webp');"` const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-image: url('img/gun/${b.guns[choose].name}.webp');"`
return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}" ${style}> return `<div class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}" ${style}>
@@ -1607,6 +1616,8 @@ const powerUps = {
} }
} }
} }
powerUps.spawn(x + 25, y - 25, "ammo", false);
if (simulation.difficultyMode > 5) powerUps.spawn(x - 25, y - 50, "ammo", false);
if (tech.isAddRemoveMaxHealth) { if (tech.isAddRemoveMaxHealth) {
powerUps.spawn(x + 20, y, "tech", false) powerUps.spawn(x + 20, y, "tech", false)
powerUps.spawn(x - 20, y, "research", false) powerUps.spawn(x - 20, y, "research", false)

View File

@@ -1,6 +1,6 @@
//main object for spawning things in a level //main object for spawning things in a level
const spawn = { const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"], nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture", "snakeBoss"],
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss, hopMotherBoss //these need a particular level to work so they are not included in the random pool // other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss, hopMotherBoss //these need a particular level to work so they are not included in the random pool
randomBossList: [ randomBossList: [
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
@@ -114,9 +114,9 @@ const spawn = {
} }
} }
}, },
secondaryBossChance(x, y) { secondaryBossChance(x, y, options = []) {
if (simulation.difficultyMode > 2 && level.levelsCleared > 1) { if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
spawn.randomLevelBoss(x, y); spawn.randomLevelBoss(x, y, options);
powerUps.spawn(x - 30, y, "ammo"); powerUps.spawn(x - 30, y, "ammo");
powerUps.spawn(x + 30, y, "ammo"); powerUps.spawn(x + 30, y, "ammo");
} else { } else {
@@ -3921,8 +3921,8 @@ const spawn = {
} }
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
me.memory = 240 me.memory = 900;
me.seePlayerFreq = 55 me.seePlayerFreq = 41
me.delay = 5 + 2 * simulation.CDScale;//8 + 3 * simulation.CDScale; me.delay = 5 + 2 * simulation.CDScale;//8 + 3 * simulation.CDScale;
me.nextBlinkCycle = me.delay; me.nextBlinkCycle = me.delay;
me.JumpDistance = 0//set in redMode() me.JumpDistance = 0//set in redMode()
@@ -4082,21 +4082,18 @@ const spawn = {
move() move()
} else if (this.seePlayer.recall) { //chase player's history } else if (this.seePlayer.recall) { //chase player's history
this.lostPlayer(); this.lostPlayer();
if (!m.isCloak) { if (m.isCloak) {
for (let i = 0; i < 50; i++) { //if lost player lock onto a player location in history move(this.seePlayer.position) //go after where you last saw the player
} else {
for (let i = 0; i < 55; i++) { //if lost player lock onto a player location in history
let history = m.history[(m.cycle - 10 * i) % 600] let history = m.history[(m.cycle - 10 * i) % 600]
if (Matter.Query.ray(map, this.position, history.position).length === 0) { if (Matter.Query.ray(map, this.position, history.position).length === 0) {
this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep move(history.position) //go after where you last saw the player
this.seePlayer.position.x = history.position.x;
this.seePlayer.position.y = history.position.y;
this.seePlayer.yes = true;
move()
break break
} }
} }
} }
} }
} }
this.checkStatus(); this.checkStatus();
if (this.isInvulnerable) { if (this.isInvulnerable) {
@@ -4170,7 +4167,7 @@ const spawn = {
me.fire = function () { me.fire = function () {
// this.armor(); // this.armor();
this.checkStatus(); this.checkStatus();
if (!m.isCloak && !this.isStunned) { if (!this.isStunned) {
if (this.isFiring) { if (this.isFiring) {
if (this.fireCycle > this.fireDelay) { //fire if (this.fireCycle > this.fireDelay) { //fire
this.isFiring = false this.isFiring = false
@@ -4221,7 +4218,9 @@ const spawn = {
} }
} else { //aim at player } else { //aim at player
this.fireCycle++ this.fireCycle++
this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire //if cloaked, aim at player's history from 3 seconds ago
const whereIsPlayer = m.isCloak ? m.history[(m.cycle - 180) % 600].position : m.pos
this.fireDir = Vector.normalise(Vector.sub(whereIsPlayer, this.position)); //set direction to turn to fire
//rotate towards fireAngle //rotate towards fireAngle
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
@@ -4233,7 +4232,7 @@ const spawn = {
} else if (this.fireCycle > 45) { //fire } else if (this.fireCycle > 45) { //fire
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100) unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit) this.fireTarget = Vector.add(this.vertices[1], unit)
if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur if (Vector.magnitude(Vector.sub(whereIsPlayer, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
Matter.Body.setAngularVelocity(this, 0) Matter.Body.setAngularVelocity(this, 0)
this.fireLockCount = 0 this.fireLockCount = 0
this.isFiring = true this.isFiring = true
@@ -4277,7 +4276,7 @@ const spawn = {
}, Vector.normalise(Vector.sub(this.fireTarget, this.position))); }, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location //distance between the target and the player's location
if ( if (
m.isCloak || // m.isCloak ||
dot > 0.03 || // not looking at target dot > 0.03 || // not looking at target
Matter.Query.ray(map, this.fireTarget, this.position).length || Matter.Query.ray(body, this.fireTarget, this.position).length || //something blocking line of sight Matter.Query.ray(map, this.fireTarget, this.position).length || Matter.Query.ray(body, this.fireTarget, this.position).length || //something blocking line of sight
Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) > 1000 // distance from player to target is very far, (this is because dot product can't tell if facing 180 degrees away) Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) > 1000 // distance from player to target is very far, (this is because dot product can't tell if facing 180 degrees away)
@@ -5056,7 +5055,7 @@ const spawn = {
me.laserSword = function (where, angle, length) { me.laserSword = function (where, angle, length) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) }; const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) };
best = vertexCollision(where, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]); best = vertexCollision(where, look, [map, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second
m.damage(this.swordDamage); m.damage(this.swordDamage);
@@ -5663,7 +5662,7 @@ const spawn = {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) }; const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
@@ -5762,7 +5761,7 @@ const spawn = {
me.laserSword = function (where, angle) { me.laserSword = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) }; const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage); m.damage(this.swordDamage);
@@ -5854,7 +5853,7 @@ const spawn = {
me.laserSword = function (where, angle) { me.laserSword = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) }; const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage); m.damage(this.swordDamage);
@@ -5964,7 +5963,7 @@ const spawn = {
me.laserSpear = function (where, angle) { me.laserSpear = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) }; const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead)) { if (best.who && (best.who === playerBody || best.who === playerHead)) {
this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player
@@ -6180,7 +6179,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, "transparent"); mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.seeAtDistance2 = 500000; me.seeAtDistance2 = 500000;
me.accelMag = 0.00007 + 0.0001 * simulation.accelScale; me.accelMag = 0.0002 + 0.0001 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
Matter.Body.setDensity(me, 0.0002); //normal is 0.001 Matter.Body.setDensity(me, 0.0002); //normal is 0.001
me.damageReduction = 0.1 me.damageReduction = 0.1
@@ -6222,7 +6221,7 @@ const spawn = {
if (this.health < 0.8) me.seeAtDistance2 = 2000000; if (this.health < 0.8) me.seeAtDistance2 = 2000000;
} }
me.do = function () { me.do = function () {
if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion if (this.speed > 6) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
this.seePlayerCheckByDistance(); this.seePlayerCheckByDistance();
this.checkStatus(); this.checkStatus();
this.attraction(); this.attraction();
@@ -7215,6 +7214,7 @@ const spawn = {
me.do = function () { me.do = function () {
this.seePlayerByHistory(60); this.seePlayerByHistory(60);
this.attraction(); this.attraction();
if (this.distanceToPlayer2() > 9000000) this.attraction(); //extra attraction if far away
this.checkStatus(); this.checkStatus();
this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005) this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005)
if (!simulation.isTimeSkipping) { if (!simulation.isTimeSkipping) {

View File

@@ -141,7 +141,7 @@ const tech = {
if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech
if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false //stops the bug where you can't gets stacks of tech you take with decoherence, I think if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false //stops the bug where you can't gets stacks of tech you take with decoherence, I think
if (tech.isDamageFieldTech && tech.tech[index].isFieldTech) { if (tech.isDamageFieldTech && tech.tech[index].isFieldTech) {
tech.damage *= 1.15 tech.damage *= 1.2
// simulation.inGameConsole(`<strong class='color-d'>damage</strong> <span class='color-symbol'>*=</span> ${1.05}`) // simulation.inGameConsole(`<strong class='color-d'>damage</strong> <span class='color-symbol'>*=</span> ${1.05}`)
simulation.inGameConsole(`<span class='color-var'>tech</span>.damage *= ${1.1} //hidden-variable theory`); simulation.inGameConsole(`<span class='color-var'>tech</span>.damage *= ${1.1} //hidden-variable theory`);
} }
@@ -273,7 +273,7 @@ const tech = {
if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.4 : 4 if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.4 : 4
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 2 if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 2
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9 if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.9 : 2 if (tech.offGroundDamage && !m.onGround) dmg *= tech.offGroundDamage
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01) if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
if (tech.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length if (tech.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length
if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage
@@ -294,11 +294,19 @@ const tech = {
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
if (tech.isSpeedDamage) dmg *= 1 + Math.min(2, ((tech.speedAdded + player.speed) * 0.033))//1 + Math.min(1, (tech.speedAdded + player.speed) * 0.0193) if (tech.isSpeedDamage) dmg *= 1 + Math.min(2, ((tech.speedAdded + player.speed) * 0.033))//1 + Math.min(1, (tech.speedAdded + player.speed) * 0.0193)
if (tech.isAxion && tech.isHarmDarkMatter) dmg *= ((tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 3.2 : 2) if (tech.isAxion && tech.isHarmDarkMatter) dmg *= ((tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 3.2 : 2)
if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3; if (tech.isHarmDamage && m.lastHarmCycle + 240 > m.cycle) dmg *= 4;
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit
// if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, 1 - (tech.isEnergyHealth ? m.energy : m.health)) // if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, 1 - (tech.isEnergyHealth ? m.energy : m.health))
if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, (tech.isEnergyHealth ? m.maxEnergy - m.energy : m.maxHealth - m.health)) if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, (tech.isEnergyHealth ? m.maxEnergy - m.energy : m.maxHealth - m.health))
if (tech.isJunkDNA) dmg *= 1 + 2 * (tech.junkChance + level.junkAdded) if (tech.isJunkDNA) dmg *= 1 + 2 * (tech.junkChance + level.junkAdded)
if (tech.isDemineralize) {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
dmg *= tech.mineralDamage
}
return dmg return dmg
}, },
duplicationChance() { duplicationChance() {
@@ -430,7 +438,7 @@ const tech = {
}, },
{ {
name: "Hilbert space", name: "Hilbert space",
description: "<strong>4x</strong> <strong class='color-d'>damage</strong><br>after a <strong>collision</strong> enter an <strong class='alt'>alternate reality</strong>", description: "<strong>3x</strong> <strong class='color-d'>damage</strong><br>after a <strong>collision</strong> enter an <strong class='alt'>alternate reality</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -441,7 +449,7 @@ const tech = {
return !m.isAltSkin && !tech.isResearchReality && !tech.isSwitchReality return !m.isAltSkin && !tech.isResearchReality && !tech.isSwitchReality
}, },
requires: "not skinned, Ψ(t) collapse, many-worlds", requires: "not skinned, Ψ(t) collapse, many-worlds",
damage: 4, damage: 3,
effect() { effect() {
m.skin.anodize(); m.skin.anodize();
tech.damage *= this.damage tech.damage *= this.damage
@@ -549,8 +557,8 @@ const tech = {
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 5, frequency: 4,
frequencyDefault: 5, frequencyDefault: 4,
allowed() { allowed() {
return tech.isEnergyHealth && !tech.isOverHeal return tech.isEnergyHealth && !tech.isOverHeal
}, },
@@ -781,7 +789,7 @@ const tech = {
{ {
name: "pigeonhole principle", name: "pigeonhole principle",
descriptionFunction() { descriptionFunction() {
return `<strong>1.4x</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()}<br>cycles each level and you can't <strong>switch</strong>` return `<strong>1.4x</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.gun()}, but your active ${powerUps.orb.gun()}<br>cycles each level and you can't <strong>switch</strong>`
}, },
// descriptionFunction() { // descriptionFunction() {
// let info = "" // let info = ""
@@ -1010,7 +1018,7 @@ const tech = {
{ {
name: "Pareto efficiency", name: "Pareto efficiency",
descriptionFunction() { descriptionFunction() {
return `for each ${powerUps.orb.gun()} in your inventory<br>randomly get <strong>5x</strong> or <strong>0.2x</strong> <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}` return `all you ${powerUps.orb.gun()} randomly get<br><strong>5x</strong> or <strong>0.2x</strong> <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -1395,6 +1403,64 @@ const tech = {
tech.isCrit = false; tech.isCrit = false;
} }
}, },
{
name: "remineralization",
descriptionFunction() {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
return `after <strong>mobs</strong> <strong>die</strong> gain <strong>0.85x</strong> <strong class='color-defense'>damage taken</strong><br>effects stack, but fade <strong>10%</strong> every second<em style ="float: right;">(${tech.mineralDamageReduction.toFixed(2)}x)</em>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isRemineralize = true
tech.mineralDamageReduction = 1
tech.mineralLastCheck = simulation.cycle
},
remove() {
tech.isRemineralize = false
tech.mineralDamageReduction = 1
tech.mineralLastCheck = simulation.cycle
}
},
{
name: "demineralization",
descriptionFunction() {
//reduce mineral percent based on time since last check
const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
tech.mineralLastCheck = simulation.cycle
tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
return `after <strong>mobs</strong> <strong>die</strong> gain <strong>1.08x</strong> <strong class='color-d'>damage</strong><br>effects stack, but fade <strong>10%</strong> every second<em style ="float: right;">(${tech.mineralDamage.toFixed(2)}x)</em>`
},
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return true
},
requires: "",
effect() {
tech.isDemineralize = true
tech.mineralDamage = 1
tech.mineralLastCheck = simulation.cycle
},
remove() {
tech.isDemineralize = false
tech.mineralDamage = 1
tech.mineralLastCheck = simulation.cycle
}
},
{ {
name: "shear stress", name: "shear stress",
description: "after mobs <strong>die</strong><br>they fire a <strong>nail</strong> at nearby mobs", description: "after mobs <strong>die</strong><br>they fire a <strong>nail</strong> at nearby mobs",
@@ -1403,9 +1469,9 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath return true
}, },
requires: "no other mob death tech", requires: "",
effect() { effect() {
tech.nailsDeathMob++ tech.nailsDeathMob++
}, },
@@ -1421,9 +1487,9 @@ const tech = {
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath return true
}, },
requires: "no other mob death tech", requires: "",
effect() { effect() {
tech.isExplodeMob = true; tech.isExplodeMob = true;
}, },
@@ -1437,22 +1503,16 @@ const tech = {
descriptionFunction() { descriptionFunction() {
return `after mobs <strong>die</strong> there is a <strong>13%</strong> chance<br>they grow ${b.guns[6].nameString('s')}` return `after mobs <strong>die</strong> there is a <strong>13%</strong> chance<br>they grow ${b.guns[6].nameString('s')}`
}, },
// description: "after mobs <strong>die</strong><br>they have a <strong>+10%</strong> chance to grow <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.nailsDeathMob && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath return true
}, },
requires: "no other mob death tech", requires: "",
effect() { effect() {
tech.sporesOnDeath += 0.13; tech.sporesOnDeath += 0.13;
// if (tech.isSporeWorm) {
// for (let i = 0; i < 4; i++) b.worm(m.pos)
// } else {
// for (let i = 0; i < 8; i++) b.spore(m.pos)
// }
}, },
remove() { remove() {
tech.sporesOnDeath = 0; tech.sporesOnDeath = 0;
@@ -2658,7 +2718,7 @@ const tech = {
{ {
name: "non-Newtonian armor", name: "non-Newtonian armor",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Non-Newtonian_fluid' class="link">non-Newtonian armor</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Non-Newtonian_fluid' class="link">non-Newtonian armor</a>`,
description: "after mob <strong>collisions</strong><br><strong>0.3x</strong> <strong class='color-defense'>damage taken</strong> for <strong>10</strong> seconds", description: "after mob <strong>collisions</strong><br><strong>0.4x</strong> <strong class='color-defense'>damage taken</strong> for <strong>10</strong> seconds",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2735,7 +2795,7 @@ const tech = {
}, },
{ {
name: "fermion", name: "fermion",
description: `for <strong>6</strong> seconds after mobs <strong>die</strong><br>become <strong class="color-invulnerable">invulnerable</strong> and <em style="opacity: 0.3;">inhibit <strong class='color-f'>energy</strong> regen</em>`, description: `for <strong>5</strong> seconds after mobs <strong>die</strong><br>become <strong class="color-invulnerable">invulnerable</strong> and <em style="opacity: 0.3;">inhibit <strong class='color-f'>energy</strong> regen</em>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3066,7 +3126,7 @@ const tech = {
{ {
name: "stability", name: "stability",
descriptionFunction() { descriptionFunction() {
return `<strong>0.2x</strong> <strong class='color-defense'>damage taken</strong><br>while your <strong class='color-h'>health</strong> is at maximum` return `<strong>0.1x</strong> <strong class='color-defense'>damage taken</strong><br>while your <strong class='color-h'>health</strong> is at maximum`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -3168,7 +3228,7 @@ const tech = {
{ {
name: "Zenos paradox", name: "Zenos paradox",
descriptionFunction() { descriptionFunction() {
return `<strong>0.15x</strong> <strong class='color-defense'>damage taken</strong><br><strong>5%</strong> of current ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} every <strong>5</strong> seconds` return `<strong>0.2x</strong> <strong class='color-defense'>damage taken</strong><br><strong>5%</strong> of current ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} every <strong>5</strong> seconds`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -3576,7 +3636,7 @@ const tech = {
{ {
name: "Ψ(t) collapse", name: "Ψ(t) collapse",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Wave_function_collapse' class="link">Ψ(t) collapse</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Wave_function_collapse' class="link">Ψ(t) collapse</a>`,
description: `after a <strong>boss</strong> <strong>dies</strong> spawn ${powerUps.orb.research(6)}<br>if you <strong class='color-r'>research</strong> enter an <strong class='alt'>alternate reality</strong>`, description: `after a <strong>boss</strong> <strong>dies</strong> spawn ${powerUps.orb.research(4)}<br>if you <strong class='color-r'>research</strong> enter an <strong class='alt'>alternate reality</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -5812,7 +5872,7 @@ const tech = {
}, },
{ {
name: "launch system", name: "launch system",
description: `<strong>5x</strong> <strong>missile</strong> <em>fire rate</em><br><strong>1.2x</strong> missile <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`, description: `<strong>5x</strong> <strong>missile</strong> <em>fire rate</em><br><strong>1.3x</strong> missile <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)}`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5822,7 +5882,7 @@ const tech = {
return tech.haveGunCheck("missiles") && !tech.isMissileBig return tech.haveGunCheck("missiles") && !tech.isMissileBig
}, },
requires: "missiles, not cruise missile", requires: "missiles, not cruise missile",
ammoBonus: 1.2, ammoBonus: 1.3,
effect() { effect() {
tech.missileFireCD = 10 tech.missileFireCD = 10
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7898,7 +7958,7 @@ const tech = {
{ {
name: "radiative equilibrium", name: "radiative equilibrium",
descriptionFunction() { descriptionFunction() {
return `after losing ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"}<br><strong>3x</strong> <strong class='color-d'>damage</strong> for <strong>8</strong> seconds` return `after losing ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"}<br><strong>4x</strong> <strong class='color-d'>damage</strong> for <strong>4</strong> seconds`
}, },
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
@@ -7925,13 +7985,13 @@ const tech = {
maxCount: 3, maxCount: 3,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 200, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldMode === 8 || m.fieldMode === 3 return m.fieldMode === 8 || m.fieldMode === 3
}, },
requires: "negative mass, pilot wave", requires: "negative mass, pilot wave",
effect() { effect() {
tech.lastHitDamage += 6; tech.lastHitDamage += 8;
}, },
remove() { remove() {
tech.lastHitDamage = 0; tech.lastHitDamage = 0;
@@ -7946,9 +8006,9 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldMode === 3 return m.fieldMode === 3 && tech.negativeMassCost !== 0
}, },
requires: "negative mass", requires: "negative mass, not equivalence principle",
effect() { effect() {
tech.isNeutronium = true tech.isNeutronium = true
tech.baseFx *= 0.86 tech.baseFx *= 0.86
@@ -7966,29 +8026,51 @@ const tech = {
} }
}, },
{ {
name: "aerostat", name: "equivalence principle",
descriptionFunction() { description: `<strong>negative mass</strong> field doesn't cost <strong class='color-f'>energy</strong><br>`,
return `<strong>2x</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong><br><strong>0.9x</strong> <strong class='color-d'>damage</strong> while <strong>on</strong> the <strong>ground</strong><em style ="float: right;">(${(m.onGround ? 0.9 : 2).toFixed(1)}x)</em>`
},
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() {
return m.fieldMode === 3 && !tech.isNeutronium
},
requires: "negative mass, not neutronium",
effect() {
tech.negativeMassCost = 0
},
//also removed in m.setHoldDefaults() if player switches into a bad field
remove() {
tech.negativeMassCost = 0.00035
}
},
{
name: "aerostat",
descriptionFunction() {
const damage = m.onGround ? 1 : (tech.offGroundDamage)
const infoText = this.count ? `<br><em style ="float: right;">(${damage.toFixed(0)}x)</em>` : ""
return `<strong>2x</strong> <strong class='color-d'>damage</strong> while <strong>off</strong> the <strong>ground</strong>${infoText}`
},
isFieldTech: true,
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() { allowed() {
return m.fieldMode === 3 || m.fieldMode === 10 return m.fieldMode === 3 || m.fieldMode === 10
}, },
requires: "negative mass, grappling hook", requires: "negative mass, grappling hook",
effect() { effect() {
tech.isNoGroundDamage = true tech.offGroundDamage++
}, },
remove() { remove() {
tech.isNoGroundDamage = false tech.offGroundDamage = 1
} }
}, },
{ {
name: "annihilation", name: "annihilation",
description: "after <strong>colliding</strong> with non-boss mobs<br>they are <strong>annihilated</strong> and <strong>10</strong> <strong class='color-f'>energy</strong>", description: "<strong>mobs</strong> you <strong>collide</strong> with are <strong>annihilated</strong><br><strong>8</strong> <strong class='color-f'>energy</strong> each time",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -8723,12 +8805,12 @@ const tech = {
}, },
{ {
name: "hidden-variable theory", name: "hidden-variable theory",
description: `<strong>1.15x</strong> <strong class='color-d'>damage</strong> each time you <strong class='color-choice'><span>ch</span><span>oo</span><span>se</span></strong> ${powerUps.orb.fieldTech()}`, description: `<strong>1.2x</strong> <strong class='color-d'>damage</strong> after you <strong class='color-choice'><span>ch</span><span>oo</span><span>se</span></strong> ${powerUps.orb.fieldTech()}`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 4,
frequencyDefault: 1, frequencyDefault: 4,
allowed() { allowed() {
return m.fieldMode === 8 return m.fieldMode === 8
}, },
@@ -8742,7 +8824,7 @@ const tech = {
}, },
{ {
name: "WIMPs", name: "WIMPs",
description: `at each <strong>level's</strong> exit, spawn ${powerUps.orb.research(4)}<br> and a dangerous particle that slowly <strong>chases</strong> you`, description: `at the exit to each <strong>level</strong> spawn ${powerUps.orb.research(4)}<br>and a dangerous particle that slowly <strong>chases</strong> you`,
isFieldTech: true, isFieldTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -8770,9 +8852,9 @@ const tech = {
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2) return (m.fieldMode === 8 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2)
}, },
requires: "wormhole, time dilation, negative mass, pilot wave", requires: "wormhole, pilot wave",
effect() { effect() {
tech.fieldDuplicate = 0.11 tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -8792,7 +8874,7 @@ const tech = {
{ {
name: "transdimensional worms", name: "transdimensional worms",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Dimension' class="link">transdimensional worms</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Dimension' class="link">transdimensional worms</a>`,
description: "after a <strong class='color-block'>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>spawn a <strong class='color-p' style='letter-spacing: 2px;'>worm</strong>", description: "after a <strong class='color-block'>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>spawn <strong>1-2</strong> <strong class='color-p' style='letter-spacing: 2px;'>worms</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -8812,7 +8894,7 @@ const tech = {
{ {
name: "anyon", name: "anyon",
descriptionFunction() { descriptionFunction() {
return `<strong>2x</strong> <strong class='color-f'>energy</strong> after <strong class='color-dup'>duplicating</strong> a power up<br><strong>+6%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>` return `<strong>2x</strong> stored <strong class='color-f'>energy</strong> after <strong class='color-dup'>duplicating</strong> power ups<br><strong>+6%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`
}, },
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
@@ -8903,35 +8985,44 @@ const tech = {
}, },
{ {
name: "holographic principle", name: "holographic principle",
description: `<strong>0.8x</strong> <strong>movement</strong> and <strong>jumping</strong><br><strong class='color-worm'>wormholes</strong> cost <strong>zero</strong> <strong class='color-f'>energy</strong>`, cost: 2,
descriptionFunction() {
return `use ${powerUps.orb.research(this.cost)}<br>making <strong class='color-worm'>wormholes</strong> doesn't cost <strong class='color-f'>energy</strong>`
},
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldMode === 9 && !tech.isWormholeMapIgnore return m.fieldMode === 9 && !tech.isWormholeMapIgnore && (build.isExperimentSelection || powerUps.research.count > this.cost - 1)
}, },
requires: "wormhole, not affine connection", requires: "wormhole, not affine connection",
effect() { effect() {
for (let i = 0; i < this.cost; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
tech.isFreeWormHole = true tech.isFreeWormHole = true
tech.baseFx *= 0.8 // tech.baseFx *= 0.8
tech.baseJumpForce *= 0.8 // tech.baseJumpForce *= 0.8
m.setMovement() // m.setMovement()
}, },
//also removed in m.setHoldDefaults() if player switches into a bad field //also removed in m.setHoldDefaults() if player switches into a bad field
remove() { remove() {
tech.isFreeWormHole = false tech.isFreeWormHole = false
if (!tech.isNeutronium) { if (this.count) {
tech.baseFx = 0.08 powerUps.research.changeRerolls(this.cost)
tech.baseJumpForce = 10.5
m.setMovement()
} }
// if (!tech.isNeutronium) {
// tech.baseFx = 0.08
// tech.baseJumpForce = 10.5
// m.setMovement()
// }
} }
}, },
{ {
name: "affine connection", name: "affine connection",
description: "<strong class='color-worm'>wormholes</strong> can tunnel through <strong>anything</strong><br>for <strong>2x</strong> <strong class='color-f'>energy</strong> cost", description: "<strong class='color-worm'>wormholes</strong> can tunnel through <strong>anything</strong><br><strong>2x</strong> <strong class='color-f'>energy</strong> cost going through <strong>solids</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -10459,9 +10550,22 @@ const tech = {
requires: "", requires: "",
effect() { effect() {
setInterval(() => { setInterval(() => {
const unit = {
x: 1,
y: 0
}
for (let i = 0; i < 5; i++) {
const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 2000 * Math.random()))
spawn.sucker(where.x, where.y, 140)
const who = mob[mob.length - 1]
who.locatePlayer()
// who.damageReduction = 0.2
}
m.switchWorlds() m.switchWorlds()
simulation.trails() simulation.trails()
}, 20000); //every 30 seconds
}, 20000); //every 20 seconds
}, },
remove() { } remove() { }
}, },
@@ -10485,6 +10589,26 @@ const tech = {
}, },
remove() { } remove() { }
}, },
{
name: "aerodynamics",
description: "reduce air friction for all power ups",
maxCount: 1,
count: 0,
frequency: 0,
isInstant: true,
isJunk: true,
allowed() {
return true
},
requires: "",
effect() {
const styleEl = document.createElement('style');
document.head.appendChild(styleEl);
const myStyle = styleEl.sheet;
myStyle.insertRule(".choose-grid-no-images {border-radius: 50%;}", 0);
},
remove() { }
},
{ {
name: "pop-ups", name: "pop-ups",
description: "sign up to learn endless easy ways to win n-gon<br>that Landgreen doesn't want you to know!!!1!!", description: "sign up to learn endless easy ways to win n-gon<br>that Landgreen doesn't want you to know!!!1!!",
@@ -12204,7 +12328,7 @@ const tech = {
collidePowerUps: null, collidePowerUps: null,
isDilate: null, isDilate: null,
isDiaphragm: null, isDiaphragm: null,
isNoGroundDamage: null, offGroundDamage: null,
isSuperBounce: null, isSuperBounce: null,
isDivisor: null, isDivisor: null,
isFoamCavitation: null, isFoamCavitation: null,
@@ -12236,4 +12360,9 @@ const tech = {
isWiki: null, isWiki: null,
isStaticBlock: null, isStaticBlock: null,
isDamageFieldTech: null, isDamageFieldTech: null,
isRemineralize: null,
mineralDamageReduction: null,
isDemineralize: null,
mineralDamage: null,
negativeMassCost: null,
} }

View File

@@ -746,6 +746,18 @@ summary {
background-color: rgba(255, 255, 255, 0.4); background-color: rgba(255, 255, 255, 0.4);
} }
.constraint-module {
line-height: 160%;
padding: 20px;
border-radius: 5px;
font-size: 1.2em;
font-family: monospace;
font-weight: 800;
text-align: center;
color: #624;
background-color: rgba(255, 240, 250, 1);
}
#right-HUD-constraint { #right-HUD-constraint {
position: absolute; position: absolute;
top: 12px; top: 12px;
@@ -768,6 +780,39 @@ summary {
transition: all 0.5s linear; transition: all 0.5s linear;
} }
.constraint {
color: rgb(141, 23, 88);
}
.metallic-sparkle {
background: linear-gradient(90deg,
#c38aa6,
#e6c0d9,
#dca4c6,
#c38aa6,
#e6c0d9,
#dca4c6,
#c38aa6);
background-size: 200% 100%;
background-clip: text;
color: transparent;
animation: shimmer 4s infinite linear;
}
@keyframes shimmer {
0% {
background-position: 0% 50%;
}
50% {
background-position: 100% 50%;
}
100% {
background-position: 0% 50%;
}
}
#text-log { #text-log {
z-index: 2; z-index: 2;
position: absolute; position: absolute;
@@ -783,12 +828,6 @@ summary {
user-select: none; user-select: none;
} }
.constraint {
color: rgb(141, 23, 88);
/* font-weight: 100; */
/* text-decoration: underline; */
}
.color-text { .color-text {
color: #000; color: #000;
} }

160
todo.txt
View File

@@ -1,42 +1,65 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
new level corridor tech: demineralization - after mobs die gain 0.85x damage taken, effect stacks, but fades 10% every second
new level element fizzler - it removes blocks tech: remineralization - after mobs die gain 1.08x damage, effect stacks, but fades 10% every second
interferometer has wider platforms, a few helpful blocks, and fewer mobs tech: equivalence principle - negative mass field doesn't cost energy
level constraints are announced in console new JUNK tech: aerodynamics
foam gun no longer pushes the player back when firing interferometer
wave gun buffs slower elevator and lasers
1.2x base damage wider side ledges
1.1x base ammo large laser blocking blocks
0.1->0.13x speed in map flocculation
0.25->0.30x speed in blocks fewer mobs
tech: phase velocity 1.4->1.5x damage it's easier to get out of the slime
pigeonhole principle gives 1.3->1.4 damage per gun pavilion
you can no longer switch guns, your gun cycles each level move vanish elements
quenching 0.4->0.5x overheal converts into max health easier traversal
tungsten carbide no longer has reduced coyote cycles secret tunnel
control theory 1.5->2x damage at max health removed debris, but added power ups and blocks
stability 0.3->0.2 damage taken at max health corridor
overcharge +88->100 max energy, 4->5% JUNK limited to bosses that don't interact with the movers poorly
zoospore vector 10->13% chance for spores on mob death gravitron, substructure, corridor, interferometer
replication 15->10% JUNK added more heal and ammo power ups to match other levels
interest 6->5% of your power ups spawn each level because some newer levels are zoomed out more
laser max range is 3000->5000
nails last 1/3 of a second longer
bosses spawn an extra ammo power up
and 2 extra ammo on the hardest 2 difficulties
slasher mob's laserSwords will now damage a cloaked player
constraint announcement text looks more like computer code style to match game theme
updated "about" details menu foam recoil is back: 1->0.7x horizontal force and 2->4.3x vertical up force
moved classic n-gon to here from settings this makes it less annoying to horizontally and easier to kinda fly/float
added links to community content in "about" negative mass field damage reduction 0.4->0.5x
Are there more links I should add? holographic principle no longer slows player movement
added an n-gon SVG head image added 2 research cost
fermion gives 6->5 seconds of invulnerability after mobs die
stability 0.2->0.1x damage taken at max health
non-Newtonian armor 0.3->0.4x damage taken after collisions
Zeno's paradox 0.15->0.2x damage taken
annihilation energy cost 10->8 to destroy mobs after collisions
radiative equilibrium damage is 3->4x for 8->4 seconds
aerostat can be taken 1->3 times
dynamic equilibrium damage increased by 6->8x damage per last damage taken
aerostat no longer has 0.9x damage for being on the ground
launch system 1.2->1.3x ammo for missiles
research says that repeatedly entering alternate realities builds up some positive effects
Hilbert space 4x->3x damage
Ψ(t) collapse 6->4 research on boss death
transdimensional worms: 50% chance for a second worm per block in wormhole
wormhole 7->8 energy regen per second
hidden-variable theory 1.15->1.2 damage after choosing a field tech
ghoster mobs are less likely to get knocked far away from the player for long periods of time
bugs bug fixes
fixed outline on splash screen doesn't sync right on safari browser dynamic equilibrium was set to 100 times higher frequency then normal
fixed possible lock out on training levels: "hold", "throw", "throwAt" when constraints hide health bar's it's now hidden in the pause menu
from losing block behind a door mobs aiming at cloaked player
shortcut sort buttons in experiment mode properly order tech without clicking sort snakeBoss more intelligently chases player for a few seconds
fixed/increased the horizontal velocity contribution for some guns pulsarBoss aims at player's history 3 seconds in past
this makes bullets shot on moving platforms more realistic pulsar will not stop firing
nail gun, super balls, foam, harpoon but it will still not fire at cloaked player
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -59,14 +82,20 @@ player can become crouched while not touching the ground if they exit the ground
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
tech: demineralization - 0.2x damage taken, but it slowly reduces effect tech synergy ideas
increase to full: a tech that spawns mobs that the player can use to trigger mob death tech
at start of level?
when you get the tech
decrease:
over time
at start of new level
wormhole field needs a buff
it's good on wide open maps, but it needs a defensive effect on more closed maps
fix?
increase energy regen?
new tech?
a way to make more blocks
the block can feed into worms/coupling energy
tech: - remove the research costs of all tech
there's about 15 tech with a research cost
!!conformal - similar rules for small and big scales linked to holographic principle !!conformal - similar rules for small and big scales linked to holographic principle
!!holonomy - parallel transport of a vector leads to movement (applies to curved space) !!holonomy - parallel transport of a vector leads to movement (applies to curved space)
when far away from your wormhole regenerate 1% of your max energy per second when far away from your wormhole regenerate 1% of your max energy per second
@@ -179,6 +208,31 @@ improve new player experience
When foam is in an explosion it also explodes with size proportional to the size of the foam bubble When foam is in an explosion it also explodes with size proportional to the size of the foam bubble
Requires foam, explosion source, not aerogel Requires foam, explosion source, not aerogel
new level similar to ash tray maze
!!not sure how this works with theme (most levels are locations that have industrial stuff)
this might work as another line of sight level?
could be fine without line of sight if rooms don't exist until they open up?
where to put in game sequence?
watch a run through https://www.youtube.com/watch?v=nudSXUMBEV4
close off doors as player gets close
open up doors as player gets close
holes in the floor
slide large walls back to open up levels below
show a zone, then close it off, but eventually reveal it later
rise up pillars during combat
small maze rooms, 1-2 really huge rooms, long corridors, medium combat rooms
triggers for changes
clearing mobs in a zone
or time based if player is too slow
player gets close to a zone
make map elements shift around as player moves through the game
start with map elements filling everywhere and slow open up new zones
need a cool way to animate adding and removing map elements
maybe for the entire level redraw the map every 15 cycles?
simulation.draw.setPaths() //update map graphics
slide map around
small map squares that each add in sequentially
Cosmological natural selection: do something with black holes Cosmological natural selection: do something with black holes
spawn black hole mobs spawn black hole mobs
after bosses die? after bosses die?
@@ -1210,7 +1264,6 @@ possible names for tech
amalgam, amalgamation - the action, process, or result of combining or uniting. amalgam, amalgamation - the action, process, or result of combining or uniting.
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
ergosphere - region of a spinning black hole that might allow FTL or alternate realities. ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
equivalence principle - gravity and acceleration are the same
Casimir effect - attractive force between two close conductive plates Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer difference engine - early calculator/computer
cyanoacrylate - superglue use for a slowing effect? cyanoacrylate - superglue use for a slowing effect?
@@ -1254,25 +1307,4 @@ list of powerful synergies
interest + coupling, research + (peer review? or Bayesian statistics) interest + coupling, research + (peer review? or Bayesian statistics)
electronegativity and high energy? electronegativity and high energy?
electronegativity + anyon + duplication + Maxwells demon + interest + pair production electronegativity + anyon + duplication + Maxwells demon + interest + pair production
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
************************************************* COMMUNITY LINKS *************************************************
load old commits
www.cornbread2100.com/n-gon-loader
n-gon fork
kgurchiek.github.io/n-gon-portal-gun
3xiondev.github.io/n-gon-upgraded
coaldeficit.github.io/c-gon
n-gon-enhanced.vercel.app
bookmarlet
github.com/Whyisthisnotavalable/n-scythe
github.com/kgurchiek/n-gon-mobile
github.com/kgurchiek/n-gon-controller
text
ngon.fandom.com/wiki/N-gon
github.com/3xionDev/n-docs