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 nn = Vector.mult(n, 2 * Vector.dot(d, n));
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();
@@ -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)));
Matter.Body.setVelocity(bullet[me], velocity);
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].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
@@ -6744,8 +6744,12 @@ const b = {
isDischarge: false,
knockBack: 0.0005, //set in tech: cavitation
applyKnock(velocity) {
player.force.x -= this.knockBack * velocity.x
player.force.y -= 2 * this.knockBack * velocity.y
player.force.x -= 0.7 * this.knockBack * velocity.x
if (velocity.y > 0) {
player.force.y -= 4.3 * this.knockBack * velocity.y
} else {
player.force.y -= this.knockBack * velocity.y
}
},
chooseFireMethod() {
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) }
b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity)
this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
},
doCharges() {
@@ -6798,7 +6802,7 @@ const b = {
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity)
this.applyKnock(velocity)
this.charge -= 0.75
m.fireCDcycle = m.cycle + 2; //disable firing and adding more charge until empty
} 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) }
b.foam(position, Vector.rotate(velocity, spread), radius)
// this.applyKnock(velocity)
this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
this.charge += 1 + tech.isCapacitor
},
@@ -7386,8 +7390,8 @@ const b = {
m.energy -= drain
const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) }
b.laser(where, {
x: where.x + 3000 * Math.cos(m.angle),
y: where.y + 3000 * Math.sin(m.angle)
x: where.x + 5000 * Math.cos(m.angle),
y: where.y + 5000 * Math.sin(m.angle)
}, 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);
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) });
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) {
m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
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.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
mob[k].death();
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>
<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>
<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>
<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>

View File

@@ -17,6 +17,8 @@ const level = {
start() {
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.difficultyMode = 1
// 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
@@ -31,7 +33,7 @@ const level = {
// tech.tech[297].frequency = 100
// tech.addJunkTechToPool(0.5)
// 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
// powerUps.research.count = 3
// tech.isHookWire = true
@@ -48,28 +50,26 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("pigeonhole principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("generalist")
// for (let i = 0; i < 1; ++i) tech.giveTech("demineralization")
// for (let i = 0; i < 1; ++i) tech.giveTech("remineralization")
// m.skin.egg();
// 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("interest") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// 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);
// 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 **************************************************
// 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) 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 < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
//lore testing
@@ -145,22 +145,6 @@ const level = {
}
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
//used for generalist and pigeonhole principle
@@ -285,6 +269,46 @@ const level = {
}
},
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() {
//populate array with possible constraints and reset constraints
level.constraintDescription1 = level.constraintDescription2 = ""
@@ -303,7 +327,6 @@ const level = {
level.constraintDescription1 = level.constraint[level.constraintIndex].description
level.constraintIndex++
if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0
if (simulation.difficultyMode > 6 && possible.length) {
level.constraint[level.constraintIndex].effect()
possible.splice(level.constraintIndex, 1)
@@ -312,6 +335,24 @@ const level = {
if (level.constraintIndex > level.constraint.length - 1) level.constraintIndex = 0
}
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 {
document.getElementById("right-HUD-constraint").style.display = "none";
}
@@ -320,10 +361,10 @@ const level = {
}
//update HUD with constraints
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) {
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
@@ -427,7 +468,7 @@ const level = {
}
},
{
description: "0.3x damage after getting power ups",
description: "0.3x damage after using power ups",
effect() {
level.isNoDamage = true
level.noDamageCycle = 0
@@ -1719,7 +1760,7 @@ const level = {
},
vanish(x, y, width, height, isVertical = false, hide = {
x: 0,
y: 150
y: 400
}) {
x = x + width / 2
y = y + height / 2
@@ -6761,26 +6802,34 @@ const level = {
level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#dcdcde";
spawn.debris(-150, -775, 1425, 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(-150, -775, 1425, 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
powerUps.chooseRandomPowerUp(2075, -1525);
powerUps.chooseRandomPowerUp(2550, -1825);
powerUps.chooseRandomPowerUp(1975, 250);
//bottom floor
//entrance
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, 3975, 225);
spawn.mapRect(-1300, 275, 4025, 3300);
// spawn.mapRect(-1275, 275, 3975, 225);
spawn.mapRect(-1050, 0, 325, 50);
spawn.mapRect(-775, 0, 50, 140);
vanish.push(level.vanish(-725, 13, 150, 25))
spawn.mapRect(-200, -750, 100, 600);
// spawn.mapRect(1200, -750, 100, 600);
vanish.push(level.vanish(-350, -225, 150, 225))
vanish.push(level.vanish(-350, -450, 150, 223))
vanish.push(level.vanish(-525, -150, 425, 150))
vanish.push(level.vanish(-475, -300, 275, 150))
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(1200, -750, 100, 450);
spawn.mapRect(1200, -375, 250, 75);
powerUps.spawnStartingPowerUps(550, -100);
@@ -6789,10 +6838,18 @@ const level = {
spawn.bodyRect(1350, -175, 150, 175, 0.5);
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
spawn.bodyRect(215, -1175, 100, 100, 0.3);
spawn.mapRect(-1300, -1800, 250, 2300);
// spawn.mapRect(-1300, -2075, 250, 2575);
if (Math.random() < 0.5) {
spawn.mapRect(500, -1350, 525, 425);
spawn.mapRect(25, -1050, 300, 198);
@@ -6800,34 +6857,17 @@ const level = {
spawn.mapRect(500, -1350, 525, 497);
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.mapRect(600, -1800, 325, 225);
spawn.mapRect(1900, -1500, 325, 25);
// spawn.mapRect(600, -1800, 325, 225);
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);
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(1500, -1800, 225, 25))
vanish.push(level.vanish(-50, -1800, 450, 25))
//exit
// spawn.mapRect(-1050, -1450, 700, 25);
// spawn.mapRect(-1050, -1800, 525, 25);
spawn.mapRect(-575, -1800, 50, 200);
spawn.mapRect(-1050, -1800, 525, 75);
spawn.mapRect(-1050, -1450, 700, 75);
@@ -6864,8 +6904,10 @@ const level = {
level.exit.drawAndCheck();
level.enter.draw();
mover.push();
};
level.customTopLayer = () => {
mover.draw();
//shadow
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(-1450, -300, 150, 325);
@@ -6873,7 +6915,9 @@ const level = {
ctx.fillRect(725, 50, 325, 225)
ctx.fillRect(-325, -950, 300, 225)
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()
};
@@ -6888,16 +6932,20 @@ const level = {
level.exit.drawAndCheck();
level.enter.draw();
mover.push();
};
level.customTopLayer = () => {
mover.draw();
//shadow
ctx.fillStyle = "rgba(0,10,30,0.1)"
ctx.fillRect(1300, -300, 150, 325);
ctx.fillRect(-200, -675, 1500, 700)
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(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()
};
}
@@ -7178,6 +7226,12 @@ const level = {
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5d5";
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 lasers = []
@@ -7202,8 +7256,8 @@ const level = {
classType: "body",
holdX: 1762,
maxHeight: -1580,
minHeight: 130,
verticalForce: 0.03,
minHeight: 90,
verticalForce: 0.02,
isUp: false,
drag: 0.01,
move() {
@@ -7269,7 +7323,7 @@ const level = {
let buildMapOutline = function () {
//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, -5000, 8000, 3000); //map ceiling
spawn.mapRect(-4000, 2000, 8000, 3000); //floor
@@ -7325,13 +7379,13 @@ const level = {
//lower right side
//far right wall ledges
spawn.mapRect(1925, -1700, 200, 200);
spawn.mapRect(1925, -1200, 200, 200);
spawn.mapRect(1925, -700, 200, 200);
spawn.mapRect(1925, -200, 200, 200);
spawn.mapRect(1925, 300, 200, 200);
spawn.mapRect(1925, 800, 200, 200);
spawn.mapRect(1925, 1300, 200, 200);
spawn.mapRect(1925, -1700, 400, 200);
spawn.mapRect(1925, -1200, 400, 200);
spawn.mapRect(1925, -700, 400, 200);
spawn.mapRect(1925, -200, 400, 200);
spawn.mapRect(1925, 300, 400, 200);
spawn.mapRect(1925, 800, 400, 200);
spawn.mapRect(1925, 1300, 400, 200);
spawn.mapRect(1250, 1650, 500, 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");
//far right wall ledges
spawn.mapRect(1925, 1700 - 200, 200, 200);
spawn.mapRect(1925, 1200 - 200, 200, 200);
spawn.mapRect(1925, 700 - 200, 200, 200);
spawn.mapRect(1925, 200 - 200, 200, 200);
spawn.mapRect(1925, -300 - 200, 200, 200);
spawn.mapRect(1925, -800 - 200, 200, 200);
spawn.mapRect(1925, -1300 - 200, 200, 200);
spawn.mapRect(1925, 1700 - 200, 400, 200);
spawn.mapRect(1925, 1200 - 200, 400, 200);
spawn.mapRect(1925, 700 - 200, 400, 200);
spawn.mapRect(1925, 200 - 200, 400, 200);
spawn.mapRect(1925, -300 - 200, 400, 200);
spawn.mapRect(1925, -800 - 200, 400, 200);
spawn.mapRect(1925, -1300 - 200, 400, 200);
spawn.mapRect(1250, -1650 - 25, 500, 25);
spawn.mapRect(1300, -1125 - 25, 400, 25);
@@ -7559,7 +7613,7 @@ const level = {
//background structure
ctx.fillStyle = "#c3c7c7"
ctx.fillRect(1487, -75 - 1925, 25, 1925);
ctx.fillRect(1925, -2050, 125, 4100);
ctx.fillRect(1925, -2050, 300, 4100);
//exit room
ctx.fillStyle = "#d4f4f4"
@@ -7580,7 +7634,7 @@ const level = {
//background structure
ctx.fillStyle = "#c5c9c9"
ctx.fillRect(1487, 75, 25, 1925);
ctx.fillRect(1925, -2050, 125, 4100);
ctx.fillRect(1925, -2050, 300, 4100);
//draw flipped exit
ctx.fillStyle = "#d4f4f4"
@@ -7604,7 +7658,7 @@ const level = {
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);
//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
} else if (Math.floor(10 * (balance[i].angle % (Math.PI / 2))) === 0) {
Matter.Body.setAngularVelocity(balance[i], balance[i].angularVelocity * 0.1)
@@ -7653,6 +7707,8 @@ const level = {
spawn.bodyRect(1325, -1775, 175, 175);
spawn.bodyRect(-375, -1725, 100, 75, 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, 1825, 25, 175);
@@ -7708,6 +7764,9 @@ const level = {
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#c3d6e1";
color.map = "#444"
powerUps.chooseRandomPowerUp(-1825, 975);
powerUps.chooseRandomPowerUp(-3975, 975);
powerUps.chooseRandomPowerUp(3900, 925);
let buttons = []
level.isFlipped = false;
@@ -8220,12 +8279,14 @@ const level = {
spawn.randomMob(2825, 75, 0.9);
spawn.randomLevelBoss(2400, 600);
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.directSpawn(2825, 175, "heal");
powerUps.directSpawn(2475, -650, "heal");
powerUps.directSpawn(2100, 925, "heal");
powerUps.directSpawn(625, -100, "heal");
powerUps.chooseRandomPowerUp(2825, 175);
powerUps.chooseRandomPowerUp(2475, -650);
powerUps.chooseRandomPowerUp(2100, 925);
powerUps.chooseRandomPowerUp(625, -100);
},
corridor() {
// simulation.fallHeight = 4000
@@ -8235,6 +8296,10 @@ const level = {
document.body.style.backgroundColor = "#d0d5d5";
color.map = "#444"
powerUps.chooseRandomPowerUp(5925, -2125);
powerUps.chooseRandomPowerUp(75, -4225);
powerUps.chooseRandomPowerUp(2950, -1450);
// level.isHorizontalFlipped = true
if (level.isHorizontalFlipped) {
level.setPosToSpawn(14075, -625);
@@ -8473,8 +8538,8 @@ const level = {
spawn.randomMob(3575, 375, 0.6);
spawn.randomGroup(5300, -1400, 1.3);
spawn.randomLevelBoss(2025, -1825);
spawn.secondaryBossChance(-1900, -1800);
spawn.randomLevelBoss(2025, -1825, ["pulsarBoss", "shieldingBoss", "laserLayerBoss", "shooterBoss"]);
spawn.secondaryBossChance(-1900, -1800, ["historyBoss", "spawnerBossCulture", "blockBoss"]);
powerUps.spawnStartingPowerUps(11750, -1000);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
@@ -8948,18 +9013,17 @@ const level = {
button0.query();
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)
spawn.randomMob(918, 2695, 0.1);
spawn.randomMob(1818, 2719, 0.2);
spawn.randomMob(2530, 2460, 0.2);
spawn.randomMob(3109, 2665, 0.3);
spawn.randomMob(3909, 2191, 0.3);
spawn.randomMob(4705, 2711, 0.4);
spawn.randomMob(5800, 2796, 0.5);
spawn.randomMob(7287, 2757, 0.6);
spawn.randomMob(5759, 2691, 0.9);
spawn.randomMob(5675, 2225, 0.8);
spawn.randomMob(7450, 2775, 0.8);
spawn.randomMob(918, 2695, 0);
spawn.randomMob(1818, 2719, 0.1);
spawn.randomMob(2530, 2460, 0.1);
spawn.randomMob(3109, 2665, 0.2);
spawn.randomMob(3909, 2191, 0.2);
spawn.randomMob(4705, 2711, 0.3);
spawn.randomMob(5800, 2796, 0.3);
spawn.randomMob(7287, 2757, 0.4);
spawn.randomMob(5759, 2691, 0.4);
spawn.randomMob(5675, 2225, 0.5);
spawn.randomMob(7450, 2775, 0.5);
spawn.randomGroup(6600, 2400, 0.1);
if (simulation.difficulty > 1) spawn.randomLevelBoss(6076, 2341);
}
@@ -9050,7 +9114,9 @@ const level = {
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(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(1300, -357, "-300 0 -400 -100 400 -100 300 0");
spawn.bodyRect(1550, -308, 50, 208, 0.5);
@@ -9081,17 +9147,17 @@ const level = {
spawn.mapRect(7625, 2890, 400, 25);
spawn.mapRect(7800, 2880, 100, 25);
spawn.randomMob(2450, 250, 0.2);
spawn.randomMob(3250, 325, 0.2);
spawn.randomMob(3625, 350, 0.3);
spawn.randomMob(1750, -25, 0.4);
spawn.randomMob(1300, 1750, 0.5);
spawn.randomMob(2350, 1725, 0.6);
spawn.randomMob(3350, 1775, 0.7);
spawn.randomMob(1025, 750, 0.8);
spawn.randomMob(2400, 1775, 0.8);
spawn.randomMob(1250, 1725, 0.8);
spawn.randomMob(775, 1775, 0.9);
spawn.randomMob(2450, 250, 0);
spawn.randomMob(3250, 325, 0);
spawn.randomMob(3625, 350, 0.1);
spawn.randomMob(1750, -25, 0.1);
spawn.randomMob(1300, 1750, 0.2);
spawn.randomMob(2350, 1725, 0.2);
spawn.randomMob(3350, 1775, 0.2);
spawn.randomMob(1025, 750, 0.3);
spawn.randomMob(2400, 1775, 0.3);
spawn.randomMob(1250, 1725, 0.3);
spawn.randomMob(775, 1775, 0.4);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(1822, 1336)
@@ -9102,7 +9168,7 @@ const level = {
balance1 = level.rotor(-800 - 25, -395, 25, 390, 0.001) //entrance
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
button1.min.x = -button1.min.x - 126
@@ -9129,17 +9195,17 @@ const level = {
button0.query();
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)
spawn.randomMob(-7475, 2800, 0.1);
spawn.randomMob(-6475, 2500, 0.2);
spawn.randomMob(-4575, 2775, 0.3);
spawn.randomMob(-7575, 2850, 0.3);
spawn.randomMob(-6425, 2575, 0.3);
spawn.randomMob(-5750, 2775, 0.4);
spawn.randomMob(-4675, 2800, 0.5);
spawn.randomMob(-3425, 2800, 0.6);
spawn.randomMob(-2475, 2475, 0.7);
spawn.randomMob(-3350, 2250, 0.8);
spawn.randomMob(-1275, 2725, 0.9);
spawn.randomMob(-7475, 2800, 0);
spawn.randomMob(-6475, 2500, 0.1);
spawn.randomMob(-4575, 2775, 0.2);
spawn.randomMob(-7575, 2850, 0.2);
spawn.randomMob(-6425, 2575, 0.2);
spawn.randomMob(-5750, 2775, 0.3);
spawn.randomMob(-4675, 2800, 0.3);
spawn.randomMob(-3425, 2800, 0.4);
spawn.randomMob(-2475, 2475, 0.4);
spawn.randomMob(-3350, 2250, 0.5);
spawn.randomMob(-1275, 2725, 0.5);
spawn.randomGroup(-6225, 2400, 0.1);
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)
balance1 = level.rotor(800, -395, 25, 390, 0.001) //entrance
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
}
@@ -34957,8 +35023,8 @@ const level = {
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) {
g.energy -= 0.1 //* Math.max(g.maxEnergy, g.energy) //0.33 * g.energy
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.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
mob[k].death();
simulation.drawList.push({ //add dmg to draw queue

View File

@@ -1234,6 +1234,30 @@ const mobs = {
m.energy -= 0.05;
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);
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
mobs.mobDeaths++
@@ -1253,9 +1277,11 @@ const mobs = {
} else {
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())))
} else if (tech.nailsDeathMob) {
}
if (tech.nailsDeathMob) {
b.targetedNail(this.position, tech.nailsDeathMob, 39 + 6 * Math.random())
}
if (tech.isBotSpawnerReset) {
@@ -1269,7 +1295,7 @@ const mobs = {
this.leaveBody = false; // no body since it turned into the bot
}
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 (tech.isAddRemoveMaxHealth) {

View File

@@ -782,9 +782,9 @@ const m = {
defense() {
let dmg = 1
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.isZeno) dmg *= 0.15
if (tech.isZeno) dmg *= 0.2
if (tech.isFieldHarmReduction) dmg *= 0.6
if (tech.isHarmDarkMatter) dmg *= (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 0.25 : 0.4
if (tech.isImmortal) dmg *= 0.7
@@ -795,12 +795,20 @@ const m = {
if (tech.isHarmReduce && input.field) dmg *= 0.1
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
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.isTurret && m.crouch) dmg *= 0.3;
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.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
// dmg *= m.fieldHarmReduction
return dmg * m.fieldHarmReduction
@@ -2736,10 +2744,10 @@ const m = {
m.fieldThreshold = Math.cos((m.fieldArc) * Math.PI)
},
setHoldDefaults() {
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
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
}
// 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
// if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
// }
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
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
@@ -2835,7 +2843,7 @@ const m = {
} else if (m.fieldMode === 8) {
m.fieldRegen = 0.001667 //10 energy per second pilot wave
} 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) {
m.fieldRegen = 0.0015 //9 energy per second grappling hook
} else {
@@ -4011,14 +4019,14 @@ const m = {
{
name: "negative mass",
//<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,
effect: () => {
m.fieldFire = true;
m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.4;
m.fieldHarmReduction = 0.5;
m.fieldDrawRadius = 0;
m.hold = function () {
@@ -4032,8 +4040,7 @@ const m = {
if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen
m.grabPowerUp();
m.lookForPickUp();
const DRAIN = 0.00035
if (m.energy > DRAIN && m.fieldCDcycle < m.cycle) {
if (m.energy > tech.negativeMassCost && m.fieldCDcycle < m.cycle) {
if (tech.isFlyFaster) {
//look for nearby objects to make zero-g
function moveThis(who, range, mag = 1.06) {
@@ -4065,13 +4072,13 @@ const m = {
moveThis(powerUp, this.fieldDrawRadius, 0);
moveThis(body, this.fieldDrawRadius, 0);
} else if (input.up) { //up
m.energy -= 5 * DRAIN;
m.energy -= 5 * tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 1100 * 0.03;
player.force.y -= 2.25 * player.mass * simulation.g;
moveThis(powerUp, this.fieldDrawRadius, 1.8);
moveThis(body, this.fieldDrawRadius, 1.8);
} else {
m.energy -= DRAIN;
m.energy -= tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 800 * 0.03;
player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
moveThis(powerUp, this.fieldDrawRadius);
@@ -4109,13 +4116,13 @@ const m = {
verticalForce(powerUp, this.fieldDrawRadius, 0.7);
verticalForce(body, this.fieldDrawRadius, 0.7);
} else if (input.up) { //up
m.energy -= 5 * DRAIN;
m.energy -= 5 * tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 850 * 0.03;
player.force.y -= 1.45 * player.mass * simulation.g;
verticalForce(powerUp, this.fieldDrawRadius, 1.38);
verticalForce(body, this.fieldDrawRadius, 1.38);
} else {
m.energy -= DRAIN;
m.energy -= tech.negativeMassCost;
this.fieldDrawRadius = this.fieldDrawRadius * 0.97 + 650 * 0.03;
player.force.y -= 1.07 * player.mass * simulation.g; // slow upward drift
verticalForce(powerUp, this.fieldDrawRadius);
@@ -5051,7 +5058,7 @@ const m = {
}
}
if (tech.isCloakStun) { //stun nearby mobs after exiting cloak
let isMobsAround = false
// let isMobsAround = false
const stunRange = m.fieldDrawRadius * 1.25
// const drain = 0.01
// if (m.energy > drain) {
@@ -5358,7 +5365,7 @@ const m = {
{
name: "wormhole",
//<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,
effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5"
@@ -5454,8 +5461,10 @@ const m = {
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())))
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
}
@@ -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.energy += 0.02 * m.coupling * level.isReducedRegen
if (tech.isWormholeWorms) { //pandimensional spermia
b.worm(Vector.add(m.hole.pos1, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
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));
// 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
}
@@ -6239,8 +6247,8 @@ const m = {
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) {
m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy)
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.08) {
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
mob[k].death();
simulation.drawList.push({ //add dmg to draw queue

View File

@@ -256,6 +256,8 @@ const powerUps = {
powerUps.endDraft(type);
},
showDraft() {
simulation.isChoosing = true; //stops p from un pausing on key down
//disable clicking for 1/2 a second to prevent mistake clicks
document.getElementById("choose-grid").style.pointerEvents = "none";
document.body.style.cursor = "none";
@@ -264,7 +266,6 @@ const powerUps = {
document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s";
}, 400);
simulation.isChoosing = true; //stops p from un pausing on key down
if (!simulation.paused) {
if (tech.isNoDraftPause || level.isNoPause) {
@@ -909,7 +910,7 @@ const powerUps = {
}
},
cancelText(type) {
if (tech.isSuperDeterminism) {
if (tech.isSuperDeterminism || type === "constraint") {
return `<div></div>`
} 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>`
@@ -940,7 +941,9 @@ const powerUps = {
},
researchAndCancelText(type) {
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>`
} 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;"
@@ -1008,6 +1011,12 @@ const powerUps = {
return text
},
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) {
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}>
@@ -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) {
powerUps.spawn(x + 20, y, "tech", false)
powerUps.spawn(x - 20, y, "research", false)

View File

@@ -1,6 +1,6 @@
//main object for spawning things in a level
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
randomBossList: [
"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) {
spawn.randomLevelBoss(x, y);
spawn.randomLevelBoss(x, y, options);
powerUps.spawn(x - 30, y, "ammo");
powerUps.spawn(x + 30, y, "ammo");
} else {
@@ -3921,8 +3921,8 @@ const spawn = {
}
me.frictionStatic = 0;
me.friction = 0;
me.memory = 240
me.seePlayerFreq = 55
me.memory = 900;
me.seePlayerFreq = 41
me.delay = 5 + 2 * simulation.CDScale;//8 + 3 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
me.JumpDistance = 0//set in redMode()
@@ -4082,21 +4082,18 @@ const spawn = {
move()
} else if (this.seePlayer.recall) { //chase player's history
this.lostPlayer();
if (!m.isCloak) {
for (let i = 0; i < 50; i++) { //if lost player lock onto a player location in history
if (m.isCloak) {
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]
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
this.seePlayer.position.x = history.position.x;
this.seePlayer.position.y = history.position.y;
this.seePlayer.yes = true;
move()
move(history.position) //go after where you last saw the player
break
}
}
}
}
}
this.checkStatus();
if (this.isInvulnerable) {
@@ -4170,7 +4167,7 @@ const spawn = {
me.fire = function () {
// this.armor();
this.checkStatus();
if (!m.isCloak && !this.isStunned) {
if (!this.isStunned) {
if (this.isFiring) {
if (this.fireCycle > this.fireDelay) { //fire
this.isFiring = false
@@ -4221,7 +4218,9 @@ const spawn = {
}
} else { //aim at player
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
const angle = this.angle + Math.PI / 2;
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
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
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)
this.fireLockCount = 0
this.isFiring = true
@@ -4277,7 +4276,7 @@ const spawn = {
}, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location
if (
m.isCloak ||
// m.isCloak ||
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
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) {
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) };
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) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5663,7 +5662,7 @@ const spawn = {
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) };
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) {
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) {
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) };
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) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5854,7 +5853,7 @@ const spawn = {
me.laserSword = function (where, angle) {
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) };
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) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5964,7 +5963,7 @@ const spawn = {
me.laserSpear = function (where, angle) {
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) };
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)) {
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");
let me = mob[mob.length - 1];
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
Matter.Body.setDensity(me, 0.0002); //normal is 0.001
me.damageReduction = 0.1
@@ -6222,7 +6221,7 @@ const spawn = {
if (this.health < 0.8) me.seeAtDistance2 = 2000000;
}
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.checkStatus();
this.attraction();
@@ -7215,6 +7214,7 @@ const spawn = {
me.do = function () {
this.seePlayerByHistory(60);
this.attraction();
if (this.distanceToPlayer2() > 9000000) this.attraction(); //extra attraction if far away
this.checkStatus();
this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005)
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.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) {
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(`<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.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.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.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length
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.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.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.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.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
},
duplicationChance() {
@@ -430,7 +438,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -441,7 +449,7 @@ const tech = {
return !m.isAltSkin && !tech.isResearchReality && !tech.isSwitchReality
},
requires: "not skinned, Ψ(t) collapse, many-worlds",
damage: 4,
damage: 3,
effect() {
m.skin.anodize();
tech.damage *= this.damage
@@ -549,8 +557,8 @@ const tech = {
},
maxCount: 1,
count: 0,
frequency: 5,
frequencyDefault: 5,
frequency: 4,
frequencyDefault: 4,
allowed() {
return tech.isEnergyHealth && !tech.isOverHeal
},
@@ -781,7 +789,7 @@ const tech = {
{
name: "pigeonhole principle",
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() {
// let info = ""
@@ -1010,7 +1018,7 @@ const tech = {
{
name: "Pareto efficiency",
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,
count: 0,
@@ -1395,6 +1403,64 @@ const tech = {
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",
description: "after mobs <strong>die</strong><br>they fire a <strong>nail</strong> at nearby mobs",
@@ -1403,9 +1469,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
return true
},
requires: "no other mob death tech",
requires: "",
effect() {
tech.nailsDeathMob++
},
@@ -1421,9 +1487,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
return true
},
requires: "no other mob death tech",
requires: "",
effect() {
tech.isExplodeMob = true;
},
@@ -1437,22 +1503,16 @@ const tech = {
descriptionFunction() {
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,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.nailsDeathMob && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
return true
},
requires: "no other mob death tech",
requires: "",
effect() {
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() {
tech.sporesOnDeath = 0;
@@ -2658,7 +2718,7 @@ const tech = {
{
name: "non-Newtonian armor",
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,
count: 0,
frequency: 1,
@@ -2735,7 +2795,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -3066,7 +3126,7 @@ const tech = {
{
name: "stability",
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,
count: 0,
@@ -3168,7 +3228,7 @@ const tech = {
{
name: "Zenos paradox",
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,
count: 0,
@@ -3576,7 +3636,7 @@ const tech = {
{
name: "Ψ(t) collapse",
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,
count: 0,
frequency: 1,
@@ -5812,7 +5872,7 @@ const tech = {
},
{
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,
maxCount: 1,
count: 0,
@@ -5822,7 +5882,7 @@ const tech = {
return tech.haveGunCheck("missiles") && !tech.isMissileBig
},
requires: "missiles, not cruise missile",
ammoBonus: 1.2,
ammoBonus: 1.3,
effect() {
tech.missileFireCD = 10
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7898,7 +7958,7 @@ const tech = {
{
name: "radiative equilibrium",
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,
maxCount: 1,
@@ -7925,13 +7985,13 @@ const tech = {
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 200,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 8 || m.fieldMode === 3
},
requires: "negative mass, pilot wave",
effect() {
tech.lastHitDamage += 6;
tech.lastHitDamage += 8;
},
remove() {
tech.lastHitDamage = 0;
@@ -7946,9 +8006,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 3
return m.fieldMode === 3 && tech.negativeMassCost !== 0
},
requires: "negative mass",
requires: "negative mass, not equivalence principle",
effect() {
tech.isNeutronium = true
tech.baseFx *= 0.86
@@ -7966,29 +8026,51 @@ const tech = {
}
},
{
name: "aerostat",
descriptionFunction() {
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>`
},
name: "equivalence principle",
description: `<strong>negative mass</strong> field doesn't cost <strong class='color-f'>energy</strong><br>`,
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 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() {
return m.fieldMode === 3 || m.fieldMode === 10
},
requires: "negative mass, grappling hook",
effect() {
tech.isNoGroundDamage = true
tech.offGroundDamage++
},
remove() {
tech.isNoGroundDamage = false
tech.offGroundDamage = 1
}
},
{
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,
maxCount: 1,
count: 0,
@@ -8723,12 +8805,12 @@ const tech = {
},
{
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,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
frequency: 4,
frequencyDefault: 4,
allowed() {
return m.fieldMode === 8
},
@@ -8742,7 +8824,7 @@ const tech = {
},
{
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,
maxCount: 9,
count: 0,
@@ -8770,9 +8852,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
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() {
tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -8792,7 +8874,7 @@ const tech = {
{
name: "transdimensional worms",
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,
maxCount: 1,
count: 0,
@@ -8812,7 +8894,7 @@ const tech = {
{
name: "anyon",
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,
maxCount: 1,
@@ -8903,35 +8985,44 @@ const tech = {
},
{
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,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
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",
effect() {
for (let i = 0; i < this.cost; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
tech.isFreeWormHole = true
tech.baseFx *= 0.8
tech.baseJumpForce *= 0.8
m.setMovement()
// tech.baseFx *= 0.8
// tech.baseJumpForce *= 0.8
// m.setMovement()
},
//also removed in m.setHoldDefaults() if player switches into a bad field
remove() {
tech.isFreeWormHole = false
if (!tech.isNeutronium) {
tech.baseFx = 0.08
tech.baseJumpForce = 10.5
m.setMovement()
if (this.count) {
powerUps.research.changeRerolls(this.cost)
}
// if (!tech.isNeutronium) {
// tech.baseFx = 0.08
// tech.baseJumpForce = 10.5
// m.setMovement()
// }
}
},
{
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,
maxCount: 1,
count: 0,
@@ -10459,9 +10550,22 @@ const tech = {
requires: "",
effect() {
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()
simulation.trails()
}, 20000); //every 30 seconds
}, 20000); //every 20 seconds
},
remove() { }
},
@@ -10485,6 +10589,26 @@ const tech = {
},
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",
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,
isDilate: null,
isDiaphragm: null,
isNoGroundDamage: null,
offGroundDamage: null,
isSuperBounce: null,
isDivisor: null,
isFoamCavitation: null,
@@ -12236,4 +12360,9 @@ const tech = {
isWiki: null,
isStaticBlock: 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);
}
.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 {
position: absolute;
top: 12px;
@@ -768,6 +780,39 @@ summary {
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 {
z-index: 2;
position: absolute;
@@ -783,12 +828,6 @@ summary {
user-select: none;
}
.constraint {
color: rgb(141, 23, 88);
/* font-weight: 100; */
/* text-decoration: underline; */
}
.color-text {
color: #000;
}

160
todo.txt
View File

@@ -1,42 +1,65 @@
******************************************************** NEXT PATCH **************************************************
new level corridor
new level element fizzler - it removes blocks
interferometer has wider platforms, a few helpful blocks, and fewer mobs
level constraints are announced in console
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
foam gun no longer pushes the player back when firing
wave gun buffs
1.2x base damage
1.1x base ammo
0.1->0.13x speed in map
0.25->0.30x speed in blocks
tech: phase velocity 1.4->1.5x damage
pigeonhole principle gives 1.3->1.4 damage per gun
you can no longer switch guns, your gun cycles each level
quenching 0.4->0.5x overheal converts into max health
tungsten carbide no longer has reduced coyote cycles
control theory 1.5->2x damage at max health
stability 0.3->0.2 damage taken at max health
overcharge +88->100 max energy, 4->5% JUNK
zoospore vector 10->13% chance for spores on mob death
replication 15->10% JUNK
interest 6->5% of your power ups spawn each level
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
updated "about" details menu
moved classic n-gon to here from settings
added links to community content in "about"
Are there more links I should add?
added an n-gon SVG head image
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
bugs
fixed outline on splash screen doesn't sync right on safari browser
fixed possible lock out on training levels: "hold", "throw", "throwAt"
from losing block behind a door
shortcut sort buttons in experiment mode properly order tech without clicking sort
fixed/increased the horizontal velocity contribution for some guns
this makes bullets shot on moving platforms more realistic
nail gun, super balls, foam, harpoon
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
******************************************************** BUGS ********************************************************
@@ -59,14 +82,20 @@ player can become crouched while not touching the ground if they exit the ground
*********************************************************** TODO *****************************************************
tech: demineralization - 0.2x damage taken, but it slowly reduces effect
increase to full:
at start of level?
when you get the tech
decrease:
over time
at start of new level
tech synergy ideas
a tech that spawns mobs that the player can use to trigger mob death tech
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
!!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
@@ -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
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
spawn black hole mobs
after bosses die?
@@ -1210,7 +1264,6 @@ possible names for tech
amalgam, amalgamation - the action, process, or result of combining or uniting.
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.
equivalence principle - gravity and acceleration are the same
Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer
cyanoacrylate - superglue use for a slowing effect?
@@ -1254,25 +1307,4 @@ list of powerful synergies
interest + coupling, research + (peer review? or Bayesian statistics)
electronegativity and high energy?
electronegativity + anyon + duplication + Maxwells demon + interest + pair production
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
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level