super n-gon bros

new community level - superNgonBros by DesBoot

tech: induction brake - after using a heal slow nearby mobs for 15 seconds
tech: null hypothesis - +9 damage, spawn several research after removing
reworked: strange attractor - +7% damage, +10% duplication after removing

bremsstrahlung does 50% more damage
time crystals 200 -> 150% passive energy regen
  it also tells you how much energy regen you will get
aperture (-50 to +150) -> (-10 to +110) damage
diaphragm (-33 to +100) -> (+8 to +80) defense
tungsten carbide 200 -> 222 health
CPT symmetry 30 -> 20 energy per second of rewind
quenching gives more max health, but also does more damage per over heal

final boss has 50% faster armor decay
  so it takes even more damage the longer you fight it

a few more images
some bug fixes
This commit is contained in:
landgreen
2023-04-16 18:04:54 -07:00
parent 2e76b5c181
commit 1b23dec950
20 changed files with 762 additions and 135 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 53 KiB

BIN
img/induction brake.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 61 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 23 KiB

BIN
img/null hypothesis.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -116,6 +116,7 @@
<option value="stereoMadness">
<option value="house">
<option value="dripp">
<option value="superNgonBros">
<option value="crossfire">
<option value="temple">
<option value="run">

View File

@@ -1738,7 +1738,7 @@ const b = {
// m.fireCDcycle = m.cycle + 30; // cool down if out of energy
m.fireCDcycle = m.cycle + 5 + 40 * b.fireCDscale + 60 * (m.energy < 0.05)
this.endCycle = simulation.cycle + 10
if (m.crouch) { //down
if (input.down) { //down
dist = 0
player.force.y += 5 * player.mass * simulation.g;
}

View File

@@ -10,7 +10,7 @@ const level = {
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (intro, ... , reservoir or factory, reactor, ... , gauntlet, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour"],
communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
start() {
@@ -18,7 +18,7 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// tech.giveTech("performance")
// level.difficultyIncrease(12 * 4) //30 is near max on hard //60 is near max on why
// level.difficultyIncrease(4 * 4) //30 is near max on hard //60 is near max on why
// spawn.setSpawnList();
// spawn.setSpawnList();
// m.maxHealth = m.health = 100
@@ -31,26 +31,26 @@ const level = {
// m.energy = 0
// simulation.molecularMode = 2
// m.damage(0.1);
// b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("foam") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[3].ammo = 100000000
// tech.giveTech("surface plasmons")
// tech.giveTech("relativistic momentum")
// tech.giveTech("induction brake")
// tech.giveTech("null hypothesis")
// for (let i = 0; i < 1; ++i) tech.giveTech("dye laser")
// for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser")
// for (let i = 0; i < 1; ++i) tech.giveTech("causality bots")
// for (let i = 0; i < 1; ++i) tech.giveTech("waste heat recovery")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("foam-bot") });
// for (let i = 0; i < 1; i++) tech.giveTech("foam-bot upgrade")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
// level.testing();
// level.superNgonBros();
// spawn.nodeGroup(3200, -300, "sniper")
// spawn.nodeGroup(2200, -300, "sniper")
// spawn.nodeGroup(2200, -300, "sniper")
// spawn.mantisBoss(1900, -500)
// spawn.cellBoss(1900, -500)
// for (let i = 0; i < 5; ++i) spawn.sneaker(1900, -500, 50)
// for (let i = 0; i < 5; ++i) spawn.starter(1900, -500, 50)
// spawn.sneaker(1900, -500, 25)
// spawn.sniper(2000, -450)
// spawn.zombie(1000 + 1000 * Math.random(), -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
@@ -67,7 +67,7 @@ const level = {
// simulation.setZoom();
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "gun");
// for (let i = 0; i < 10; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "heal");
// for (let i = 0; i < 3; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "heal");
// 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
// for (let i = 0; i < 5; i++) tech.giveTech("undefined")
@@ -3106,7 +3106,7 @@ const level = {
//???
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
m.addHealth(Infinity)
// m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy
// for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500)
@@ -21047,7 +21047,525 @@ const level = {
const obj = { restoreBoss };
Object.assign(spawn, obj); //ez
},
superNgonBros() {
simulation.makeTextLog(`<strong>Super N-gon Bros</strong> by <span class='color-var'>DesBoot</span>`);
let bowserKilled = 0
let flagY = -750
let flagReached = 0
const elevator1 = level.elevator(3975, -11650, 450, 50, -13100, 0.003)
const elevator2 = level.elevator(5575, -11650, 450, 50, -13100, 0.003)
let firstElevatorY = -11650
const portal = level.portal({ x: 3990, y: 100 }, 1.5 * Math.PI, { x: 100, y: -13500 }, -1.5 * Math.PI)
const portal2 = level.portal({ x: 7135, y: -12270 }, -1 * Math.PI, { x: 12325, y: -2000 }, -1.5 * Math.PI)
const bowser = function (x, y, radius = 150) { //define the mob the same as spawn mob code
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1];
me.accelMag = 0.05;
me.g = 0.002; //required if using this.gravity
me.frictionAir = 0.01;
me.friction = 1
me.frictionStatic = 1
me.restitution = 0;
me.delay = 80 * simulation.CDScale;
me.randomHopFrequency = 200 + Math.floor(Math.random() * 150);
me.randomHopCD = simulation.cycle + me.randomHopFrequency;
Matter.Body.rotate(me, Math.random() * Math.PI);
spawn.shield(me, x, y);
me.do = function () {
//spawn.grenade(me.position.x, me.position.y);
// //const v = 5 * simulation.accelScale;
// Matter.Body.setVelocity(mob[mob.length - 1], {
// x: this.velocity.x + this.fireDir.x * v + Math.random(),
// y: this.velocity.y + this.fireDir.y * v + Math.random()
// });
this.gravity();
this.seePlayerCheck();
this.checkStatus();
if (this.seePlayer.recall) {
if (this.cd < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
this.cd = simulation.cycle + this.delay;
const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass;
const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
this.force.x += forceMag * Math.cos(angle) * 0.5;
this.force.y += (forceMag * Math.sin(angle) - (Math.random() * 0.07 + 0.1) * this.mass) * 0.7; //antigravity
if (Math.random() < 0.5) {
spawn.grenade(me.position.x, me.position.y - 250 * Math.random(), 500);
Matter.Body.setVelocity(mob[mob.length - 1], {
x: -5,
y: 0
});
} else {
spawn.bullet(this.position.x, this.position.y, 25);
Matter.Body.setVelocity(mob[mob.length - 1], {
x: -25,
y: -25
});
}
}
} else {
//randomly hob if not aware of player
if (this.randomHopCD < simulation.cycle && (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length)) {
this.randomHopCD = simulation.cycle + this.randomHopFrequency;
//slowly change randomHopFrequency after each hop
this.randomHopFrequency = Math.max(100, this.randomHopFrequency + (0.5 - Math.random()) * 200);
const forceMag = (this.accelMag + this.accelMag * Math.random()) * this.mass * (0.1 + Math.random() * 0.3);
const angle = -Math.PI / 2 + (Math.random() - 0.5) * Math.PI;
this.force.x += forceMag * Math.cos(angle);
this.force.y += forceMag * Math.sin(angle) - 0.07 * this.mass; //antigravity
spawn.grenade(me.position.x, me.position.y - 250 * Math.random(), 500);
Matter.Body.setVelocity(mob[mob.length - 1], {
x: -5,
y: 0
});
}
}
};
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
bowserKilled = 1
}
}
bowser(20500, -400) //call the mob
//fire(15300, -200)
const brick = function (x, y, angle = Math.PI * 0.5, radius = 53) {//credit to Richard0820 for the code
mobs.spawn(x, y, 4, radius, "#ab6101");
let me = mob[mob.length - 1];
me.stroke = "transparent";
me.isDropPowerUp = false;
me.showHealthBar = false;
Matter.Body.setDensity(me, 999999)
me.collisionFilter.mask = cat.player | cat.mob | cat.bullet;
me.constraint = Constraint.create({
pointA: {
x: me.position.x,
y: me.position.y
},
bodyB: me,
stiffness: 0,
damping: 0
});
me.do = function () {
this.isStunned = true;
if (this.health < 1) {
this.health += 0.001; //regen
}
this.checkStatus();
Matter.Body.setAngle(me, angle);
if ((player.velocity.y < 0 && player.position.y > me.position.y || player.velocity.y > 30 && player.position.y < me.position.y) && Math.abs(player.position.x - me.position.x) < 50 && Math.abs(player.position.y - me.position.y) < 150) {
me.death()
}
};
me.onHit = function () {
if (player.velocity.y < 0 && player.position.y > me.position.y || player.velocity.y > 30 && player.position.y < me.position.y) {
me.death()
}
}
me.onDeath = function () {
if (Math.random() < 0.1) {
spawn.randomSmallMob(me.position.x, me.position.y - 75);
simulation.makeTextLog('mob')
} else {
if (Math.random() < 0.07) {
powerUps.spawn(me.position.x, me.position.y + (75 * (player.velocity.y / Math.abs(player.velocity.y))), "tech", true);
simulation.makeTextLog('tech')
} else {
if (Math.random() < 0.4) {
powerUps.spawn(me.position.x, me.position.y + (75 * (player.velocity.y / Math.abs(player.velocity.y))), "heal", true);
simulation.makeTextLog('heal')
} else {
//if (Math.random() < 0.8){
powerUps.spawn(me.position.x, me.position.y + (75 * (player.velocity.y / Math.abs(player.velocity.y))), "ammo", true);
simulation.makeTextLog('ammo')
//}
}
}
}
}
Composite.add(engine.world, me.constraint);
}
simulation.enableConstructMode()
let firstMobsSpawned = 1
let secondMobsSpawned = 0
let thirdMobsSpawned = 0
let fourthMobsSpawned = 0
let firstMobsReached = 0
let secondMobsReached = 0
let thirdMobsReached = 0
let fourthMobsReached = 0
let finalRoomReached = 0
let undergroundMobsSpawned = 0
let undergroundMobsReached = 0
level.setPosToSpawn(0, -50); //normal spawn
level.exit.x = 22100;
level.exit.y = -40;
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 1800
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#a2a5ff";
// color.map = "#444" //custom map color
level.custom = () => {
if (player.position.x > 14950 && flagReached == 0) {
flagReached = 1
}
if (flagReached == 1 && flagY < -150) {
flagY += 5
}
ctx.fillStyle = "rgba(64,64,64,0.97)"
ctx.fillRect(4200, -13100, 2, 1450)
ctx.fillRect(5800, -13100, 2, 1450)
if (firstElevatorY < -12099) {
firstElevatorY = -11650
} else {
firstElevatorY -= 5
}
//simulation.makeTextLog(firstElevatorY)
elevator1.move();
elevator2.move();
if (player.position.x > 0 && player.position.y < -9000 && player.position.y > -10000) {
//m.death()
m.damage(0.05 * simulation.difficultyMode)
Matter.Body.setPosition(player, {
x: 275,
y: -12175
});
}
portal[2].query()
portal[3].query()
portal2[2].query()
portal2[3].query()
//simulation.makeTextLog(firstBlockBroken)
level.exit.drawAndCheck();
if (player.position.x > 4100 && secondMobsReached == 0) {
secondMobsSpawned = 1
}
if (player.position.x > 7000 && thirdMobsReached == 0) {
thirdMobsSpawned = 1
}
if (player.position.x > 14300 && fourthMobsReached == 0) {
fourthMobsSpawned = 1
}
if (player.position.y < -11000 && undergroundMobsReached == 0) {
undergroundMobsSpawned = 1
}//player.position.x > 14300 &&
if (m.onGround) {
if (Math.abs(player.velocity.x) > 0.3) {
Matter.Body.setVelocity(player, {
x: player.velocity.x + (0.1 * (Math.abs(player.velocity.x) / player.velocity.x)),
y: player.velocity.y + 0.2
});
} else {
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: player.velocity.y + 0.2
});
}
} else {
if (input.down) {
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: player.velocity.y + 2
});
} else {
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: player.velocity.y + 0.2
});
}
}
level.enter.draw();
if (finalRoomReached == 0 && player.position.x > 21150) {
finalRoomReached = 1
simulation.makeTextLog('Thank you M, but our techs are in another castle!')
}
//mobs
if (firstMobsSpawned == 1 && firstMobsReached == 0) {
spawn.randomSmallMob(1260, -75);
spawn.randomMob(2100, -75, 0.4);
spawn.randomSmallMob(2400, -75);
spawn.randomSmallMob(2500, -75);
spawn.randomMob(2900, -75, 0.2);
spawn.randomMob(3400, -75, 0.4);
spawn.randomMob(3400, -75, 0.4);
firstMobsReached = 1
}
if (secondMobsSpawned == 1 && secondMobsReached == 0) {
spawn.randomSmallMob(4400, -75);
spawn.randomSmallMob(5500, -75);
spawn.randomSmallMob(5835.6, -402.4);
spawn.randomSmallMob(5835.6, -402.4);
spawn.randomSmallMob(6543.2, -730.0);
spawn.randomMob(6795.4, -162.4, 0.1);
spawn.randomMob(6795.4, -162.4, 0.1);
secondMobsReached = 1
}
if (thirdMobsSpawned == 1 && thirdMobsReached == 0) {
spawn.randomMob(8465.6, -469.9, 0.1);
spawn.randomMob(9839.6, -444.5, 0.4);
spawn.randomSmallMob(11033.2, -155.3);
spawn.randomMob(12161.3, -85.1, 0.3);
spawn.randomMob(12161.3, -85.1, 0.3);
spawn.randomMob(13399.8, -93.4, 0.4);
thirdMobsReached = 1
}
if (fourthMobsSpawned == 1 && fourthMobsReached == 0) {
spawn.randomSmallMob(16500, -400);
spawn.randomSmallMob(19278.9, -211.1);
spawn.randomMob(18839.0, -463.2, 0.3);
spawn.randomMob(18036.9, -205.9, 0.3);
spawn.randomMob(16950.4, -365.2, 0.4);
spawn.randomMob(16355.6, -390.8, 0.1);
fourthMobsReached = 1
}
if (undergroundMobsSpawned == 1 && undergroundMobsReached == 0) {
spawn.randomSmallMob(1140.0, -12228.0);
spawn.randomSmallMob(2429.9, -12371.2);
spawn.randomSmallMob(4899.4, -12139.6);
spawn.randomMob(18839.0, -463.2, 0.3);
spawn.randomMob(2844.5, -12281.0, 0.2);
spawn.randomMob(4967.5, -12550.8, 0.4);
spawn.randomMob(6696.9, -12437.9, 0.1);
undergroundMobsReached = 1
}
portal[0].draw();
portal[1].draw();
portal[2].draw();
portal[3].draw();
portal2[0].draw();
portal2[1].draw();
portal2[2].draw();
portal2[3].draw();
};
level.customTopLayer = () => {
//spawn.mapRect(886, firstElevatorY + 10000, 75, 5);
ctx.fillStyle = "rgba(64,64,64,0.97)"
ctx.fillRect(3928, -300, 120, 500)
//6940, -12360, 200, 5
ctx.fillRect(6940, -12350, 170, 120)
ctx.fillRect(7090, -12380, 120, 200)
ctx.fillRect(14980, -750, 10, 750)//flagpole
ctx.beginPath()
ctx.moveTo(14980, flagY)
ctx.lineTo(14905, flagY)
ctx.lineTo(14980, flagY + 75)
ctx.fill()
};
brick(923.5, -262);
spawn.mapRect(886, -304, 75, 5);
spawn.mapRect(886, -229, 75, 5);
spawn.mapRect(883, -304, 5, 80);
spawn.mapRect(958, -304, 5, 80);
brick(1250.5, -262);
spawn.mapRect(1138, -304, 375, 5);
spawn.mapRect(1138, -229, 375, 5);
brick(1400.5, -262);
brick(1325.5, -562);
spawn.mapRect(1288, -604, 75, 5);
spawn.mapRect(1288, -529, 75, 5);
spawn.mapRect(1285, -604, 5, 80);
spawn.mapRect(1360, -604, 5, 80);
brick(5787.5, -262);
spawn.mapRect(5675, -304, 225, 5);
spawn.mapRect(5675, -229, 225, 5);
brick(6987.5, -562);
spawn.mapRect(6725, -604, 300, 5);
spawn.mapRect(6725, -529, 300, 5);
spawn.mapRect(7025, -604, 5, 80);
brick(7887.5, -262);//4 separated blocks in the middle
spawn.mapRect(7850, -304, 75, 5);
spawn.mapRect(7850, -225, 75, 5);
spawn.mapRect(7850, -304, 5, 80);
spawn.mapRect(7925, -304, 5, 84);
brick(8112.5, -262);
spawn.mapRect(8075, -304, 75, 5);
spawn.mapRect(8075, -225, 75, 5);
spawn.mapRect(8075, -304, 5, 80);
spawn.mapRect(8150, -304, 5, 84);
brick(8337.5, -262);
spawn.mapRect(8300, -304, 75, 5);
spawn.mapRect(8300, -225, 75, 5);
spawn.mapRect(8300, -304, 5, 80);
spawn.mapRect(8375, -304, 5, 84);
brick(8112.5, -562);
spawn.mapRect(8075, -604, 75, 5);
spawn.mapRect(8075, -525, 75, 5);
spawn.mapRect(8075, -604, 5, 80);
spawn.mapRect(8150, -604, 5, 84);
brick(9612.5, -562);
spawn.mapRect(9500, -604, 300, 5);
spawn.mapRect(9500, -525, 300, 5);
spawn.mapRect(9647.5, -600, 5, 75);
brick(9687.5, -562);
brick(12887.5, -262);
spawn.mapRect(12700, -304, 300, 5);
spawn.mapRect(12700, -225, 300, 5);
brick(5212.5, -12337.5);
spawn.mapRect(4725, -12377, 525, 5);
spawn.mapRect(4725, -12303, 525, 5);
spawn.mapRect(5250, -12377, 5, 79);
spawn.mapRect(-100, 0, 4033, 2000);
spawn.mapRect(4043, 0, 882, 2000);
spawn.mapRect(3909.5, 203.6, 150, 2000);
spawn.mapRect(1138, -300, 75, 75);
spawn.mapRect(1288, -300, 75, 75);
spawn.mapRect(1438, -300, 75, 75);
spawn.mapRect(1738, -150, 150, 75);//pipe 1
spawn.mapRect(1753, -150, 120, 150);
spawn.mapRect(2488, -225, 150, 75);//pipe 2
spawn.mapRect(2503, -225, 120, 225);
spawn.mapRect(3088, -300, 150, 75);//pipe 3
spawn.mapRect(3103, -300, 120, 300);
spawn.mapRect(3913, -300, 20, 75);//pipe 4
spawn.mapRect(3928, -300, 5, 300);
spawn.mapRect(4043, -300, 20, 75);
spawn.mapRect(4043, -300, 5, 300);
spawn.mapRect(5225, 0, 1125, 2000);
spawn.mapRect(6575, 0, 4900, 2000);
spawn.mapRect(5675, -300, 75, 75);
spawn.mapRect(5825, -300, 75, 75);
spawn.mapRect(5900, -600, 600, 75);
spawn.mapRect(6725, -600, 225, 75);
spawn.mapRect(6950, -300, 75, 75);
spawn.mapRect(7400, -300, 150, 75);
spawn.mapRect(8750, -300, 75, 75);
spawn.mapRect(8975, -600, 225, 75);//raised platform
spawn.mapRect(9575, -300, 150, 75);
spawn.mapRect(9500, -600, 75, 75);//upper block with double bricks
spawn.mapRect(9725, -600, 75, 75);
spawn.mapRect(9950, -75, 300, 75);//staircase
spawn.mapRect(10025, -150, 225, 75);
spawn.mapRect(10100, -225, 150, 75);
spawn.mapRect(10175, -300, 75, 75);
spawn.mapRect(10475, -75, 300, 75);
spawn.mapRect(10475, -150, 225, 75);
spawn.mapRect(10475, -225, 150, 75);
spawn.mapRect(10475, -300, 75, 75);
spawn.mapRect(11100, -75, 375, 75);//staircase 2
spawn.mapRect(11175, -150, 300, 75);
spawn.mapRect(11250, -225, 225, 75);
spawn.mapRect(11325, -300, 150, 75);
spawn.mapRect(11725, -75, 300, 75);
spawn.mapRect(11725, -150, 225, 75);
spawn.mapRect(11725, -225, 150, 75);
spawn.mapRect(11725, -300, 75, 75);
spawn.mapRect(11725, 0, 5975, 2000);//platform after the staircase
spawn.mapRect(12325, -150, 150, 75);//exit pipe
spawn.mapRect(12340, -150, 120, 300);
spawn.mapRect(12700, -300, 150, 75);
spawn.mapRect(12925, -300, 75, 75);
spawn.mapRect(13525, -150, 150, 72);//final pipe
spawn.mapRect(13540, -150, 120, 150);
spawn.mapRect(13675, -75, 675, 75);//final staircase
spawn.mapRect(13750, -150, 600, 75);
spawn.mapRect(13825, -225, 525, 75);
spawn.mapRect(13900, -300, 450, 75);
spawn.mapRect(13975, -375, 375, 75);
spawn.mapRect(14050, -450, 300, 75);
spawn.mapRect(14125, -525, 225, 75);
spawn.mapRect(14200, -600, 150, 75);
//flag
spawn.mapRect(14950, -75, 75, 75);
spawn.mapRect(1750, -4600, 500, 25);//loss
spawn.mapRect(2000, -4850, 25, 500);
spawn.mapRect(1800, -4800, 25, 150);
spawn.mapRect(2075, -4800, 25, 150);
spawn.mapRect(2150, -4775, 25, 125);
spawn.mapRect(1875, -4550, 25, 150);
spawn.mapRect(1800, -4550, 25, 150);
spawn.mapRect(2075, -4550, 25, 150);
spawn.mapRect(2123, -4430, 100, 25);
// spawn.mapRect(-250, -600, 500, 25);
// spawn.mapRect(-250, -600, 500, 25);
//underground area
spawn.mapRect(0, -12000, 2025, 2000);
spawn.mapRect(2325, -12225, 150, 2000);
spawn.mapRect(2775, -12000, 900, 2000);
spawn.mapRect(3525, -12300, 150, 300);
spawn.mapRect(3450, -12225, 75, 300);
spawn.mapRect(3375, -12150, 75, 300);
spawn.mapRect(3300, -12075, 75, 300);
spawn.mapRect(4725, -12375, 450, 75);
spawn.mapRect(4725, -12000, 600, 2000);
spawn.mapRect(-100, -13500, 100, 3500);
spawn.mapRect(-100, -13500, 100, 3500);
spawn.mapRect(6375, -12225, 1650, 2000);
spawn.mapRect(7225, -13225, 2850, 3000);
spawn.mapRect(-100, -13700, 100, 200);//roof
spawn.mapRect(-100, -13700, 3775, 100);
spawn.mapRect(6450, -13225, 1000, 100);
spawn.mapRect(7090, -13225, 120, 885);//pipe
//spawn.mapRect(6940, -12360, 200, 120);
spawn.mapRect(6940, -12350, 200, 5);
spawn.mapRect(6950, -12240, 140, 5);
spawn.mapRect(6940, -12365, 75, 15);
spawn.mapRect(6940, -12235, 75, 15);
//castle
spawn.mapRect(17700, 0, 4975, 2000);
spawn.mapRect(18600, -225, 375, 2225);
spawn.mapRect(19500, -225, 450, 2225);
spawn.mapRect(19500, -825, 450, 225);
spawn.mapRect(15924, -1575, 6751, 750);
spawn.mapRect(19950, -225, 975, 75);
spawn.mapRect(20925, -300, 225, 300);
spawn.mapRect(21000, -825, 150, 300);
spawn.mapRect(15924, -225, 1776, 2225);
spawn.mapRect(17175, -825, 525, 225);
spawn.mapRect(22600, -825, 75, 825);
// powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
// spawn.randomSmallMob(1300, -70);
// spawn.randomMob(2650, -975, 0.8);
// spawn.randomGroup(1700, -900, 0.4);
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
// spawn.secondaryBossChance(100, -1500)
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
// ********************************************************************************************************
// ********************************************************************************************************
// ***************************************** training levels **********************************************

View File

@@ -335,10 +335,7 @@ const m = {
if (
!tech.tech[i].isNonRefundable &&
!tech.tech[i].isFromAppliedScience &&
tech.tech[i].name !== "many-worlds" &&
tech.tech[i].name !== "Ψ(t) collapse" &&
tech.tech[i].name !== "Hilbert space" &&
tech.tech[i].name !== "-quantum leap-"
!tech.tech[i].isAltRealityTech
) {
totalTech += tech.tech[i].count
tech.tech[i].remove();
@@ -351,7 +348,7 @@ const m = {
// tech.removeLoreTechFromPool();
// tech.addLoreTechToPool();
// tech.removeJunkTechFromPool();
tech.cancelCount = 0;
tech.duplication = 0;
tech.extraMaxHealth = 0;
tech.totalCount = 0;
tech.countJunkTech();
@@ -528,7 +525,7 @@ const m = {
},
baseHealth: 1,
setMaxHealth() {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 2 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth //+ (m.fieldMode === 0 || m.fieldMode === 5) * 0.5 * m.coupling
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 2.22 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth //+ (m.fieldMode === 0 || m.fieldMode === 5) * 0.5 * m.coupling
document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth;
@@ -544,7 +541,7 @@ const m = {
dmg *= m.fieldHarmReduction
// if (!tech.isFlipFlopOn && tech.isFlipFlopHealth) dmg *= 0.5
// 1.25 + Math.sin(m.cycle * 0.01)
if (tech.isDiaphragm) dmg *= 0.66 + 0.66 * Math.sin(m.cycle * 0.0075);
if (tech.isDiaphragm) dmg *= 0.56 + 0.36 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.5
if (tech.isHarmMACHO) dmg *= 0.4
@@ -641,7 +638,7 @@ const m = {
});
}
}
m.energy = Math.max(m.energy - steps / 250, 0.01)
m.energy = Math.max(m.energy - steps / 330, 0.01)
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles
let isDrawPlayer = true
@@ -1895,9 +1892,9 @@ const m = {
},
}
},
setMaxEnergy() {
setMaxEnergy(isMessage = true) {
m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.5 * m.coupling + 0.4 * tech.isStandingWaveExpand
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`)
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`)
},
fieldMeterColor: "#0cf",
drawRegenEnergy(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) {
@@ -1950,7 +1947,7 @@ const m = {
}
if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.00133 * m.coupling //return `generate <strong>${(6*couple).toFixed(0)}</strong> <strong class='color-f'>energy</strong> per second`
if (tech.isTimeCrystals) {
m.fieldRegen *= 3
m.fieldRegen *= 2.5
} else if (tech.isGroundState) {
m.fieldRegen *= 0.6
}
@@ -2269,7 +2266,7 @@ const m = {
minEnergyToDeflect: 0.05,
pushMass(who, fieldBlockCost = (0.025 + Math.sqrt(who.mass) * Vector.magnitude(Vector.sub(who.velocity, player.velocity)) * 0.002) * m.fieldShieldingScale) {
if (m.energy > m.minEnergyToDeflect) { //shield needs at least some of the cost to block
if (who.isShielded) fieldBlockCost *= 1.5; //shielded mobs take more energy to block
if (who.isShielded) fieldBlockCost *= 2; //shielded mobs take more energy to block
m.energy -= fieldBlockCost
if (m.energy < m.minEnergyToDeflect) {
m.energy = 0;
@@ -2319,7 +2316,7 @@ const m = {
}
const step = 40
ctx.beginPath(); //draw electricity
for (let i = 0, len = 0.8 * tech.blockDmg; i < len; i++) {
for (let i = 0, len = 0.5 * tech.blockDmg; i < len; i++) {
let x = m.pos.x - 20 * unit.x;
let y = m.pos.y - 20 * unit.y;
ctx.moveTo(x, y);
@@ -2500,7 +2497,7 @@ const m = {
m.coupling = 0 //can't go negative
}
m.setMaxEnergy();
m.setMaxEnergy(false);
// m.setMaxHealth();
m.setFieldRegen()
mobs.setMobSpawnHealth();
@@ -2599,7 +2596,7 @@ const m = {
const fieldRange2 = (0.68 + 0.37 * Math.sin(m.cycle / 37)) * m.fieldRange * m.harmonicRadius
const fieldRange3 = (0.7 + 0.35 * Math.sin(m.cycle / 47)) * m.fieldRange * m.harmonicRadius
const netFieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
ctx.fillStyle = "rgba(110,170,200," + Math.min(0.6, (0.04 + m.energy * (0.1 + 0.11 * Math.random()))) + ")";
ctx.fillStyle = "rgba(110,170,200," + Math.min(0.6, (0.04 + 0.7 * m.energy * (0.1 + 0.11 * Math.random()))) + ")";
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, fieldRange1, 0, 2 * Math.PI);
ctx.fill();
@@ -2629,7 +2626,7 @@ const m = {
const radius = m.fieldRange * m.harmonicRadius
ctx.lineWidth = 1;
ctx.strokeStyle = "rgba(110,170,200,0.8)"
ctx.fillStyle = "rgba(110,170,200," + Math.min(0.6, m.energy * (0.11 + 0.1 * Math.random()) * (3 / tech.harmonics)) + ")";
ctx.fillStyle = "rgba(110,170,200," + Math.min(0.6, 0.7 * m.energy * (0.11 + 0.1 * Math.random()) * (3 / tech.harmonics)) + ")";
// ctx.fillStyle = "rgba(110,170,200," + Math.min(0.7, m.energy * (0.22 - 0.01 * tech.harmonics) * (0.5 + 0.5 * Math.random())) + ")";
for (let i = 0; i < tech.harmonics; i++) {
ctx.beginPath();
@@ -2762,7 +2759,7 @@ const m = {
// }
const step = 40
ctx.beginPath();
for (let i = 0, len = 0.8 * tech.blockDmg; i < len; i++) {
for (let i = 0, len = 0.5 * tech.blockDmg; i < len; i++) {
let x = m.fieldPosition.x - 20 * unit.x;
let y = m.fieldPosition.y - 20 * unit.y;
ctx.moveTo(x, y);

View File

@@ -168,7 +168,11 @@ const powerUps = {
setPowerUpMode() {
if (tech.duplicationChance() > 0 || tech.isAnthropicTech) {
if (tech.isPowerUpsVanish) {
powerUps.do = powerUps.doDuplicatesVanish
if (this.tech.isHealAttract) {
powerUps.do = powerUps.doAttractDuplicatesVanish
} else {
powerUps.do = powerUps.doDuplicatesVanish
}
} else if (tech.isHealAttract) {
powerUps.do = powerUps.doAttractDuplicates
} else {
@@ -221,6 +225,18 @@ const powerUps = {
}
}
},
doAttractDuplicatesVanish() {
powerUps.doDuplicatesVanish();
for (let i = 0; i < powerUp.length; i++) { //attract heal power ups to player
if (powerUp[i].name === "heal") {
//&& Vector.magnitudeSquared(Vector.sub(powerUp[i].position, m.pos)) < 500000
let attract = Vector.mult(Vector.normalise(Vector.sub(m.pos, powerUp[i].position)), 0.015 * powerUp[i].mass)
powerUp[i].force.x += attract.x;
powerUp[i].force.y += attract.y - powerUp[i].mass * simulation.g; //negate gravity
Matter.Body.setVelocity(powerUp[i], Vector.mult(powerUp[i].velocity, 0.7));
}
}
},
doDuplicates() { //draw power ups but give duplicates some electricity
ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6;
for (let i = 0, len = powerUp.length; i < len; ++i) {
@@ -355,7 +371,7 @@ const powerUps = {
return
}
if (tech.isCancelDuplication) {
tech.cancelCount++
tech.duplication += 0.043
tech.maxDuplicationEvent()
simulation.makeTextLog(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${0.043}`)
simulation.circleFlare(0.043);
@@ -547,8 +563,8 @@ const powerUps = {
m.addHealth(heal);
simulation.makeTextLog(`<span class='color-var'>m</span>.health <span class='color-symbol'>+=</span> ${(healOutput).toFixed(3)}`) // <br>${m.health.toFixed(3)}
if (tech.isOverHeal && overHeal > 0) { //tech quenching
const scaledOverHeal = overHeal * 0.7
m.damage(scaledOverHeal*0.9);
const scaledOverHeal = overHeal * 0.9
m.damage(scaledOverHeal);
simulation.makeTextLog(`<span class='color-var'>m</span>.health <span class='color-symbol'>-=</span> ${(scaledOverHeal).toFixed(3)}`) // <br>${m.health.toFixed(3)}
simulation.drawList.push({ //add dmg to draw queue
x: m.pos.x,
@@ -564,12 +580,54 @@ const powerUps = {
powerUps.directSpawn(this.position.x, this.position.y, "heal", true, null, overHeal * 40 * (simulation.healScale ** 0.25))// directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
});
}
if (tech.isHealBrake) {
const totalTime = 900
//check if you already have this effect
let foundActiveEffect = false
for (let i = 0; i < simulation.ephemera.length; i++) {
if (simulation.ephemera[i].name === "healPush") {
foundActiveEffect = true
simulation.ephemera[i].count = 0.5 * simulation.ephemera[i].count + totalTime //add time
simulation.ephemera[i].scale = 0.5 * (simulation.ephemera[i].scale + Math.min(Math.max(0.6, heal * 6), 2.3)) //take average of scale
}
}
if (!foundActiveEffect) {
simulation.ephemera.push({
name: "healPush",
count: totalTime, //cycles before it self removes
range: 0,
scale: Math.min(Math.max(0.7, heal * 4), 2.2), //typically heal is 0.35
do() {
this.count--
if (this.count < 0) simulation.removeEphemera(this.name)
this.range = this.range * 0.99 + 0.01 * (300 * this.scale + 100 * Math.sin(m.cycle * 0.022))
if (this.count < 120) this.range -= 5 * this.scale
this.range = Math.max(this.range, 1) //don't go negative
// const range = 300 + 100 * Math.sin(m.cycle * 0.022)
for (let i = 0; i < mob.length; i++) {
const distance = Vector.magnitude(Vector.sub(m.pos, mob[i].position))
if (distance < this.range) {
const cap = mob[i].isShielded ? 3 : 1
if (mob[i].speed > cap && Vector.dot(mob[i].velocity, Vector.sub(m.pos, mob[i].position)) > 0) { // if velocity is directed towards player
Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(mob[i].velocity), cap)); //set velocity to cap, but keep the direction
}
}
}
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, this.range, 0, 2 * Math.PI);
ctx.fillStyle = "hsla(200,50%,61%,0.18)";
ctx.fill();
},
})
}
}
}
}
if (powerUps.healGiveMaxEnergy) {
tech.healMaxEnergyBonus += 0.08 * tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)
m.setMaxEnergy();
}
},
spawn(x, y, size) { //used to spawn a heal with a specific size / heal amount, not normally used
powerUps.directSpawn(x, y, "heal", false, null, size)

View File

@@ -766,7 +766,7 @@ const simulation = {
simulation.ephemera = []
b.removeAllGuns();
tech.setupAllTech(); //sets tech to default values
tech.cancelCount = 0;
tech.duplication = 0;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "laser") b.guns[i].chooseFireMethod()
if (b.guns[i].name === "nail gun") b.guns[i].chooseFireMethod()
@@ -1181,7 +1181,7 @@ const simulation = {
}
const damage = tech.damageFromTech() //update damage bar
if (m.lastCalculatedDamage !== damage) {
document.getElementById("damage-bar").style.height = Math.floor(Math.atan(0.25 * damage - 0.25) / 1.65 * canvas.height) + "px";
document.getElementById("damage-bar").style.height = Math.floor((Math.atan(0.25 * damage - 0.25) + 0.25) * 0.53 * canvas.height) + "px";
m.lastCalculatedDamage = damage
}
}
@@ -1232,7 +1232,16 @@ const simulation = {
}
if (isNaN(player.position.x)) m.death();
if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob
if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05
if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) {
m.energy += m.maxEnergy * 0.05
simulation.drawList.push({ //add dmg to draw queue
x: m.pos.x,
y: m.pos.y - 45,
radius: Math.sqrt(m.maxEnergy * 0.05) * 60,
color: "rgba(0, 204, 255,0.4)", //#0cf
time: 4
});
}
if (tech.isHealthRecovery) {
const heal = 0.005 * m.maxHealth
m.addHealth(heal)
@@ -1240,8 +1249,8 @@ const simulation = {
x: m.pos.x,
y: m.pos.y,
radius: Math.sqrt(heal) * 150,
color: "rgba(0,255,200,0.6)",
time: 8
color: "rgba(0,255,200,0.5)",
time: 4
});
}
}

View File

@@ -97,8 +97,6 @@ const spawn = {
}
}
// for (let i = 0, len = mob.length; i < len; i++) {
// if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss
// if (mob[i].isFinalBoss) {
@@ -414,7 +412,7 @@ const spawn = {
}
}
me.damageReductionDecay = function () { //slowly make the boss take more damage over time //damageReduction resets with each invulnerability phase
if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.02 //only decay once a second //only decay if the player has done damage in the last 4 seconds
if (!(me.cycle % 60) && this.lastDamageCycle + 240 > this.cycle) this.damageReduction *= 1.04 //only decay once a second //only decay if the player has done damage in the last 4 seconds
}
me.mobType = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]
me.spawnMobs = function (index = 0) {

View File

@@ -3,10 +3,10 @@ const tech = {
setupAllTech() {
tech.damage = 1
for (let i = 0, len = tech.tech.length; i < len; i++) {
tech.tech[i].count = 0
tech.tech[i].isLost = false
tech.tech[i].isBanished = false
tech.tech[i].remove();
tech.tech[i].count = 0
if (tech.tech[i].isJunk) {
tech.tech[i].frequency = 0
} else if (tech.tech[i].frequencyDefault) {
@@ -223,13 +223,13 @@ const tech = {
if (tech.isDivisor) {
for (let i = 0; i < b.inventory.length; i++) {
if (b.guns[b.inventory[i]].ammo % 3 === 0) {
dmg *= 1.4
dmg *= 1.44
break
}
}
}
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.78 : 1.88
if (tech.isDilate) dmg *= 1.5 + Math.sin(m.cycle * 0.0075)
if (tech.isDilate) dmg *= 1.5 + 0.6 * Math.sin(m.cycle * 0.0075)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
if (powerUps.boost.endCycle > m.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.15 * m.coupling
@@ -258,7 +258,7 @@ const tech = {
return dmg
},
duplicationChance() {
return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.016 * (simulation.difficultyMode ** 2)))) // + (m.fieldMode === 0 || m.fieldMode === 9) * 0.03 * m.coupling)
return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.duplication + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.016 * (simulation.difficultyMode ** 2)))) // + (m.fieldMode === 0 || m.fieldMode === 9) * 0.03 * m.coupling)
},
isScaleMobsWithDuplication: false,
maxDuplicationEvent() {
@@ -309,7 +309,7 @@ const tech = {
},
tech: [{
name: "tungsten carbide",
description: "<strong>+200</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>",
description: "<strong>+222</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -362,7 +362,7 @@ const tech = {
},
{
name: "aperture",
description: "every <strong>6</strong> seconds your <strong class='color-d'>damage</strong> cycles<br>between <strong>-50%</strong> and <strong>+150%</strong> <strong class='color-d'>damage</strong>",
description: "every <strong>6</strong> seconds your <strong class='color-d'>damage</strong> cycles<br>between <strong>-10%</strong> and <strong>+110%</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 1,
@@ -383,7 +383,7 @@ const tech = {
},
{
name: "diaphragm",
description: "every <strong>6</strong> seconds your <strong class='color-defense'>defense</strong> cycles<br>between <strong>+100%</strong> and <strong>-33%</strong> <strong class='color-defense'>defense</strong>",
description: "every <strong>6</strong> seconds your <strong class='color-defense'>defense</strong> cycles<br>between <strong>+8%</strong> and <strong>+80%</strong> <strong class='color-defense'>defense</strong>",
maxCount: 1,
count: 0,
frequency: 2,
@@ -452,8 +452,8 @@ const tech = {
},
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isEnergyHealth
},
@@ -479,7 +479,7 @@ const tech = {
// description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-defense'>defense</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
// description: "after losing <strong class='color-h'>health</strong>, if you have <strong>full</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>44</strong> <strong class='color-f'>energy</strong> per second",
descriptionFunction() {
return `after losing <strong class='color-h'>health</strong>, if you have <strong>${(100 * Math.min(100, m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>40</strong> <strong class='color-f'>energy</strong> per second`
return `after losing <strong class='color-h'>health</strong>, if you have <strong>${(100 * Math.min(100, m.maxEnergy)).toFixed(0)}</strong> <strong class='color-f'>energy</strong><br><strong>rewind</strong> time for <strong>20</strong> <strong class='color-f'>energy</strong> per second`
},
maxCount: 1,
count: 0,
@@ -541,7 +541,7 @@ const tech = {
{
name: "ternary", //"divisor",
descriptionFunction() {
return `<strong>+40%</strong> <strong class='color-d'>damage</strong> while one of your <strong class='color-g'>guns</strong><br>has <strong class='color-ammo'>ammo</strong> divisible by <strong>3</strong>`
return `<strong>+44%</strong> <strong class='color-d'>damage</strong> while one of your <strong class='color-g'>guns</strong><br>has <strong class='color-ammo'>ammo</strong> divisible by <strong>3</strong>`
},
maxCount: 1,
count: 0,
@@ -1247,18 +1247,18 @@ const tech = {
{
name: "collider",
descriptionFunction() {
return `after mobs <strong>die</strong> there is a <strong>+33%</strong> chance to<br>collide <strong>power ups</strong> to form different <strong>power ups</strong>`
return `after mobs <strong>die</strong> there is a <strong>+50%</strong> chance to<br>collide <strong>power ups</strong> to form different <strong>power ups</strong>`
// return `after mobs <strong>die</strong> there is a <strong>+33%</strong> chance to convert<br>${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, ${powerUps.orb.research(1)}, <strong class='color-m'>tech</strong>, <strong class='color-f'>field</strong>, <strong class='color-g'>gun</strong> into other types`
},
maxCount: 3,
maxCount: 2,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed: () => true,
requires: "",
effect() {
tech.collidePowerUps += 0.33333
tech.collidePowerUps += 0.5
},
remove() {
tech.collidePowerUps = 0
@@ -2462,7 +2462,7 @@ const tech = {
},
{
name: "Pauli exclusion",
description: `after mob collisions<br>become <strong>invulnerable</strong> for <strong>+3</strong> seconds`,
description: `after mob collisions<br>become <strong>invulnerable</strong> for <strong>+3.5</strong> seconds`,
maxCount: 9,
count: 0,
frequency: 1,
@@ -2472,7 +2472,7 @@ const tech = {
},
requires: "",
effect() {
m.collisionImmuneCycles += 180;
m.collisionImmuneCycles += 210;
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
},
remove() {
@@ -2481,7 +2481,7 @@ const tech = {
},
{
name: "spinstatistics theorem",
description: `every <strong>7</strong> seconds<br>become <strong>invulnerable</strong> for <strong>+1.8</strong> seconds`,
description: `every <strong>7</strong> seconds<br>become <strong>invulnerable</strong> for <strong>+1.9</strong> seconds`,
maxCount: 3,
count: 0,
frequency: 1,
@@ -2491,7 +2491,7 @@ const tech = {
},
requires: "",
effect() {
tech.cyclicImmunity += 108;
tech.cyclicImmunity += 114;
},
remove() {
tech.cyclicImmunity = 0;
@@ -2946,7 +2946,25 @@ const tech = {
tech.isAcidDmg = false;
}
},
{
name: "induction brake",
description: `after using ${powerUps.orb.heal()} <strong class='color-s'>slow</strong> nearby mobs for <strong>15</strong> seconds<br>spawn ${powerUps.orb.heal(3)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isPerfectBrake
},
requires: "not eddy current brake",
effect() {
tech.isHealBrake = true;
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal");
},
remove() {
tech.isHealBrake = false;
}
},
{
name: "adiabatic healing",
descriptionFunction() {
@@ -3070,7 +3088,7 @@ const tech = {
},
requires: "",
effect() {
tech.healthDrain += 0.02;
tech.healthDrain += 0.023;
},
remove() {
tech.healthDrain = 0;
@@ -3193,6 +3211,7 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isAltRealityTech: true,
allowed() {
return !tech.isResearchReality && !tech.isSwitchReality
},
@@ -3215,6 +3234,7 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isAltRealityTech: true,
allowed() {
return !tech.isResearchReality && !tech.isCollisionRealitySwitch
},
@@ -3234,6 +3254,7 @@ const tech = {
count: 0,
frequency: 1,
frequencyDefault: 1,
isAltRealityTech: true,
allowed() {
return !tech.isSwitchReality && !tech.isCollisionRealitySwitch && !tech.isJunkResearch
},
@@ -3894,7 +3915,7 @@ const tech = {
},
requires: "below 100% duplication chance, not superdeterminism",
effect() {
tech.isCancelDuplication = true //search for tech.cancelCount to balance
tech.isCancelDuplication = true //search for tech.duplication to balance
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
},
remove() {
@@ -4027,6 +4048,57 @@ const tech = {
tech.is100Duplicate = false;
}
},
{
name: "strange attractor",
descriptionFunction() {
return `<strong>+7%</strong> <strong class='color-d'>damage</strong><br><strong>removing</strong> this increases <strong class='color-dup'>duplication</strong> by <strong>+10%</strong>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isBadRandomOption: true,
allowed() {
return true
},
requires: "",
damage: 1.07,
effect() {
tech.damage *= this.damage
},
remove() {
if (this.count > 0) {
tech.duplication += 0.1
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
tech.damage /= this.damage
this.frequency = 0
}
}
},
{
name: "null hypothesis",
description: `<strong>+9%</strong> <strong class='color-d'>damage</strong><br><strong>removing</strong> this spawns ${powerUps.orb.research(15)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isBadRandomOption: true,
allowed() {
return true
},
requires: "",
damage: 1.09,
effect() {
tech.damage *= this.damage
},
remove() {
if (this.count > 0) {
tech.damage /= this.damage
powerUps.spawnDelay("research", 15)
this.frequency = 0
}
}
},
{
name: "Born rule",
description: "<strong>remove</strong> all current <strong class='color-m'>tech</strong><br>spawn new <strong class='color-m'>tech</strong> to replace them",
@@ -4145,30 +4217,6 @@ const tech = {
},
remove() { }
},
{
name: "strange attractor",
descriptionFunction() {
return `use ${powerUps.orb.research(2)} to spawn <strong>1</strong> <strong class='color-m'>tech</strong> with<br><strong>double</strong> your <strong class='color-dup'>duplication</strong> chance <em>(${(2 * tech.duplicationChance() * 100).toFixed(0)}%)</em>`
},
// description: `use ${powerUps.orb.research(2)} to spawn <strong>1</strong> <strong class='color-m'>tech</strong> with <strong>double</strong><br>your <strong class='color-dup'>duplication</strong> chance <em>(${(2*tech.duplicationChance()*100).toFixed(0)}%)</em>`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return !tech.isSuperDeterminism && tech.duplicationChance() > 0 && powerUps.research.count > 1
},
requires: "some duplication, not superdeterminism",
effect() {
powerUps.research.changeRerolls(-2)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 2`)
powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
if (Math.random() < tech.duplicationChance() * 2) powerUps.directSpawn(m.pos.x + 10, m.pos.y + 5, "tech");
},
remove() { }
},
{
name: "reinforcement learning",
description: "increase the <strong class='flicker'>frequency</strong> of finding copies of<br>your current <strong class='color-m'>tech</strong> by <strong>1000%</strong>",
@@ -7189,7 +7237,7 @@ const tech = {
//**************************************************
{
name: "spherical harmonics",
description: "<strong>+50%</strong> <strong>standing wave</strong> deflection efficiency", //<strong>standing wave</strong> oscillates in a 3rd dimension<br>
description: "<strong>+50%</strong> <strong>standing wave</strong> deflection efficiency<br>shield deflection radius maintains it's maximum range", //<strong>standing wave</strong> oscillates in a 3rd dimension<br>
isFieldTech: true,
maxCount: 9,
count: 0,
@@ -7281,7 +7329,7 @@ const tech = {
{
name: "electronegativity",
descriptionFunction() {
return `<strong>+0.22%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(up to +${(22 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
return `<strong>+0.22%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(+${(22 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
},
// description: "<strong>+1%</strong> <strong class='color-d'>damage</strong> per <strong>8</strong> stored <strong class='color-f'>energy</strong>",
isFieldTech: true,
@@ -7313,7 +7361,7 @@ const tech = {
},
requires: "standing wave, perfect diamagnetism, pilot wave",
effect() {
tech.blockDmg += 3 //if you change this value also update the for loop in the electricity graphics in m.pushMass
tech.blockDmg += 5 //if you change this value also update the for loop in the electricity graphics in m.pushMass
},
remove() {
tech.blockDmg = 0;
@@ -7389,9 +7437,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldMode === 2
return m.fieldMode === 2 && !tech.isHealBrake
},
requires: "perfect diamagnetism",
requires: "perfect diamagnetism, not induction brake",
effect() {
tech.isPerfectBrake = true;
},
@@ -8030,12 +8078,12 @@ const tech = {
requires: "time dilation, not CPT symmetry",
effect() {
tech.isRewindField = true;
m.fieldUpgrades[m.fieldMode].set()
m.fieldUpgrades[6].set()
m.wakeCheck();
},
remove() {
tech.isRewindField = false;
if (this.count) m.fieldUpgrades[m.fieldMode].set()
if (this.count) m.fieldUpgrades[6].set()
}
},
{
@@ -8088,7 +8136,10 @@ const tech = {
},
{
name: "time crystals",
description: "<strong>+200%</strong> passive <strong class='color-f'>energy</strong> generation",
// description: "<strong>+150%</strong> passive <strong class='color-f'>energy</strong> generation<br>${}",
descriptionFunction() {
return `<strong>+150%</strong> passive <strong class='color-f'>energy</strong> generation<br><em>(+${(150 * m.fieldRegen * 60).toFixed(1)} energy per second)</em>`
},
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8101,10 +8152,16 @@ const tech = {
effect() {
tech.isTimeCrystals = true
m.setFieldRegen()
this.descriptionFunction = function () {
return `<strong>+150%</strong> passive <strong class='color-f'>energy</strong> generation<br><em>(+${(60 * m.fieldRegen * 60).toFixed(1)} energy per second)</em>`
}
},
remove() {
tech.isTimeCrystals = false
m.setFieldRegen()
this.descriptionFunction = function () {
return `<strong>+150%</strong> passive <strong class='color-f'>energy</strong> generation<br><em>(+${(150 * m.fieldRegen * 60).toFixed(1)} energy per second)</em>`
}
}
},
{
@@ -8133,18 +8190,20 @@ const tech = {
{
name: "quantum eraser",
descriptionFunction() {
return `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>+${100 - 1.6 * simulation.difficultyMode ** 2}%</strong> <strong class='color-dup'>duplication</strong></span>`
return `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>+${(100 - 1.1 * simulation.difficultyMode ** 2).toFixed(0)}%</strong> <strong class='color-dup'>duplication</strong></span>`
},
// description: `<span style = 'font-size:90%;'>for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br><strong>kill</strong> a mob as they spawn at <strong>100%</strong> <strong class='color-dup'>duplication</strong></span>`,
// descriptionFunction() {
// return `for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br>`
// },
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 7 || m.fieldMode === 6) && !tech.cloakDuplication
return (m.fieldMode === 7) && !tech.cloakDuplication
},
requires: "cloaking or time dilation",
requires: "cloaking",
effect() {
tech.quantumEraserCount = 0
tech.isQuantumEraserDuplication = 0
@@ -11292,7 +11351,7 @@ const tech = {
isSpeedDamage: null,
isTimeSkip: null,
isCancelDuplication: null,
cancelCount: null,
duplication: null,
isCancelRerolls: null,
isCancelTech: null,
isBotDamage: null,
@@ -11484,4 +11543,5 @@ const tech = {
isFoamCavitation: null,
isHealAttract: null,
isLaserField: null,
isHealBrake: null
}

View File

@@ -1,41 +1,34 @@
******************************************************** NEXT PATCH **************************************************
retrocausality drains 30% less energy as time rewinds, but each time you start to rewind you drain 30 energy
no longer provides immunity for 1 second after exiting rewind
spawns 20% fewer bots
new community level - superNgonBros by DesBoot
deflecting changes
shielded mobs take 50% more energy to deflect
deflecting shielded mobs now only disables your shield for perfect diamagnetism and not for very long
you can deflect any mob if you have at least 5% energy, but if deflecting brings you below that your shield is disabled for 1 second
also you can't passively regen energy while shield is disabled
tech: induction brake - after using a heal slow nearby mobs for 15 seconds
tech: null hypothesis - +9 damage, spawn several research after removing
reworked: strange attractor - +7% damage, +10% duplication after removing
standing wave rework
coupling gives iceIX -> max energy
expansion gives deflection efficiency -> +50 max energy
spherical harmonics gives 40 -> 50% deflection efficiency
electronegativity is a fieldTech for standing wave, wormhole, and pilot wave
also 0.15 -> 0.22% damage per energy
dynamic equilibrium is no longer unlocked by standing wave
bremsstrahlung does 50% more damage
time crystals 200 -> 150% passive energy regen
it also tells you how much energy regen you will get
aperture (-50 to +150) -> (-10 to +110) damage
diaphragm (-33 to +100) -> (+8 to +80) defense
tungsten carbide 200 -> 222 health
CPT symmetry 30 -> 20 energy per second of rewind
quenching gives more max health, but also does more damage per over heal
tech: surface plasmons - after deflecting drains all your energy, shoot lasers in every direction
added a generic system to add code that loops for a set time
Example code:
simulation.ephemera.push({
name: "uniqueName",
count: 60, //cycles before it self removes
do() {
this.count--
if (this.count < 0) simulation.removeEphemera(this.name)
//run code here
},
})
final boss has 50% faster armor decay
so it takes even more damage the longer you fight it
a few more images
some bug fixes
also new bugs probably
*********************************************************** TODO *****************************************************
maybe use ⚆ in game text?
increase font?
rework quantum eraser
test bremsstrahlung damage
and make sure it actually does more damage with the dot tech
use ephemera to replace things
JUNK?
@@ -222,12 +215,6 @@ for tech power ups no tech options are displayed until you research once
or display only JUNK until you research once
increase the number of options after each research
Tech: Grandfather Paradox - After rewinding, +300 damage during rewinded time
maybe instead of +damage spawn a copy of player that shoots at things?
how... there is no way to reproduce firing
Requires: CPT symmetry, retrocausality
CPT adjacent tech is actually a bit too strong right now, maybe nerf a bit after testing
When receiving damage, in addition to becoming invulnerable to attacks, also become intangible for the set period of time
tech increase max energy and energy to 5000, but you can no longer regen energy through any process
@@ -1170,7 +1157,6 @@ add sounds
possible names for tech
strange loop
homeostasis
holonomy - parallel transport of a vector leads to movement (applies to curved space)
hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.
swarm intelligence - for a drone tech
@@ -1201,7 +1187,6 @@ possible names for tech
superluminal signalling
NP-complete
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
p-zombie
p-hacking JUNK tech
https://en.wikipedia.org/wiki/High-entropy_alloys high yield strength and low ductility, high temp resistance
https://en.wikipedia.org/wiki/Refractory_metals hard, high temp resistance
@@ -1260,6 +1245,7 @@ if pause is pressed while selecting power ups, display pause menu on top of sele
harpoon - iron harpoon on a rope weapon art white background by Eiichiro Oda --no fish --ar 3:2 --v 5 --s 750
mine - by Dan McPharlin
laser - complex optical scientific equipment
knolling photography
guns, ammo - isometric clean pixel art image cutaway of , style of tekkonkinkreet
defensive - Paper cutout