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

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
}