diff --git a/.DS_Store b/.DS_Store
index fea2eb3..6ef377d 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 8d1d258..b4403ea 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -307,23 +307,25 @@ const b = {
explosionRange() {
return tech.explosiveRadius * (tech.isExplosionHarm ? 1.8 : 1) * (tech.isSmallExplosion ? 0.8 : 1) * (tech.isExplodeRadio ? 1.25 : 1)
},
- explosion(where, radius) { // typically explode is used for some bullets with .onEnd
+ explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd
radius *= tech.explosiveRadius
let dist, sub, knock;
let dmg = radius * 0.013;
if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area
if (tech.isSmallExplosion) {
+ color = "rgba(255,0,30,0.7)"
radius *= 0.8
dmg *= 1.6
}
if (tech.isExplodeRadio) { //radiation explosion
radius *= 1.25; //alert range
+ color = "rgba(25,139,170,0.25)"
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
radius: radius,
- color: "rgba(25,139,170,0.25)",
+ color: color,
time: simulation.drawTime * 2
});
@@ -360,7 +362,7 @@ const b = {
x: where.x,
y: where.y,
radius: radius,
- color: "rgba(255,25,0,0.6)",
+ color: color,
time: simulation.drawTime
});
const alertRange = 100 + radius * 2; //alert range
@@ -2246,7 +2248,7 @@ const b = {
this.target = null
this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
- if (tech.isFoamGrowOnDeath && bullet.length < 300) {
+ if (tech.isFoamGrowOnDeath && bullet.length < 250) {
let targets = []
for (let i = 0, len = mob.length; i < len; i++) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
@@ -2290,6 +2292,20 @@ const b = {
this.radius *= SCALE;
} else {
this.force.y += this.mass * 0.00008; //gravity
+
+ if (tech.isFoamAttract) {
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (mob[i].dropPowerUp && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
+ const slow = 0.9
+ Matter.Body.setVelocity(this, {
+ x: this.velocity.x * slow,
+ y: this.velocity.y * slow
+ });
+ break
+ }
+ }
+ }
}
}
}
@@ -4063,7 +4079,7 @@ const b = {
setTimeout(() => {
if (!simulation.paused) {
b.foam(position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
- bullet[bullet.length - 1].damage = (1 + 1.43 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage
+ bullet[bullet.length - 1].damage = (1 + 1.27 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage
}
}, 250 * tech.foamFutureFire);
} else {
diff --git a/js/index.js b/js/index.js
index 428ecf7..3b49285 100644
--- a/js/index.js
+++ b/js/index.js
@@ -217,7 +217,7 @@ const build = {
text += `
${m.fieldUpgrades[m.fieldMode].name}
${m.fieldUpgrades[m.fieldMode].description}
`
let countTech = 0
for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (tech.tech[i].count > 0) {
+ if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) {
const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isFieldTech) {
text += `
@@ -235,8 +235,8 @@ const build = {
${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
} else if (tech.tech[i].isLore) {
text += ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
- } else if (tech.tech[i].isJunk) {
- text += ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
+ // } else if (tech.tech[i].isJunk) {
+ // text += ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
} else {
text += ` ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
`
}
@@ -756,10 +756,6 @@ window.addEventListener("keydown", function(event) {
document.getElementById("pause-field").innerHTML = ` ${m.fieldUpgrades[m.fieldMode].name}
${m.fieldUpgrades[m.fieldMode].description}`
});
}
- if (simulation.testing) {
-
-
- }
}
}
break
diff --git a/js/level.js b/js/level.js
index bfdce9c..f88289d 100644
--- a/js/level.js
+++ b/js/level.js
@@ -16,7 +16,7 @@ const level = {
// simulation.zoomScale = 1000;
// simulation.setZoom();
// m.setField("nano-scale manufacturing")
- // b.giveGuns("shotgun")
+ // b.giveGuns("foam")
// tech.isExplodeRadio = true
// for (let i = 0; i < 1; i++) tech.giveTech("dynamo-bot")
// tech.giveTech("supercritical fission")
@@ -50,21 +50,20 @@ const level = {
// level.warehouse();
// level.highrise();
// level.office();
- // level.gauntlet(); //only fighting, very simple map
- // level.house() //fan level
- // level.detours() //fan level
- // level.basement(); //fan level
- // level.stronghold() //fan level
- // level.testChamber2() //fan level
-
+ // level.gauntlet(); //only fighting, very simple map, before final boss
+ // level.house() //community level
+ // level.detours() //community level
+ // level.basement(); //community level
+ // level.stronghold() //community level
+ // level.perplex() //community level
+ // level.coliseum() //community level
// powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "tech");
// tech.giveTech("undefined")
- // lore.techCount = 7
- // localSettings.loreCount = 1;
- // simulation.isCheating = false //true;
+ // lore.techCount = 6
// localSettings.loreCount = 1;
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
+ // simulation.isCheating = false //true;
// level.null()
} else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
@@ -622,7 +621,7 @@ const level = {
ctx.fillStyle = this.color
ctx.fill();
}
- query = function() {
+ query = function(isRemoveBlocks = false) {
if (Matter.Query.collides(this, [player]).length === 0) { //not touching player
if (player.isInPortal === this) player.isInPortal = null
} else if (player.isInPortal !== this) { //touching player
@@ -666,6 +665,11 @@ const level = {
if (Matter.Query.collides(this, [body[i]]).length === 0) {
if (body[i].isInPortal === this) body[i].isInPortal = null
} else if (body[i].isInPortal !== this) { //touching this portal, but for the first time
+ if (isRemoveBlocks) {
+ Matter.World.remove(engine.world, body[i]);
+ body.splice(i, 1);
+ break
+ }
body[i].isInPortal = this.portalPair
//teleport
if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down
@@ -683,11 +687,6 @@ const level = {
let v = Vector.mult(this.portalPair.unit, mag)
Matter.Body.setVelocity(body[i], v);
}
- // else if (body[i].speed < 0.1) { //touching this portal and very slow
- // Matter.World.remove(engine.world, body[i]);
- // body.splice(i, 1);
- // break
- // }
}
}
// }
@@ -4673,7 +4672,7 @@ const level = {
}
}
},
- testChamber2() {
+ perplex() {
level.setPosToSpawn(-600, 400);
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 550;
@@ -4699,10 +4698,10 @@ const level = {
level.custom = () => {
level.playerExitCheck();
- portal[2].query()
- portal[3].query()
- portal2[2].query()
- portal2[3].query()
+ portal[2].query(true)
+ portal[3].query(true)
+ portal2[2].query(true)
+ portal2[3].query(true)
rotor.rotate();
};
@@ -4739,19 +4738,33 @@ const level = {
y: -250,
width: 1500,
height: 700,
- color: "rgba(0,0,0,0.1)"
+ color: "rgba(0,0,0,0.03)"
});
level.fill.push({
x: -925,
y: -505,
width: 930,
height: 255,
- color: "rgba(0,0,0,0.1)"
+ color: "rgba(0,0,0,0.03)"
});
+ // level.fill.push({
+ // x: -1280,
+ // y: -700,
+ // width: 355,
+ // height: 800,
+ // color: "rgba(0,0,0,0.03)"
+ // });
//section 2: lower central room (gone through main portals 1 time)
spawn.mapRect(920, 245, 160, 455); //below right portal
spawn.mapRect(1075, -300, 500, 1000); //2-1 right floor
+ spawn.bodyRect(100, -1000, 50, 350);
+ spawn.bodyRect(100, -1015, 250, 15);
+ spawn.mapRect(-925, -1600, 100, 1000); //2-2 left wall
+ spawn.mapRect(725, -2150, 200, 750); //2-2 right wall
+ spawn.mapRect(725, -1200, 200, 200); //2-2 right wall 2
+ spawn.mapRect(300, -1000, 625, 50); //2 central ledge
+ //shute
spawn.mapRect(1075, -2005, 550, 1055); //shute right wall
spawn.mapRect(875, -1000, 50, 300); //shute left 1
spawn.mapRect(860, -1030, 50, 300); //shute left 2
@@ -4761,12 +4774,21 @@ const level = {
spawn.mapRect(1090, -1030, 50, 300); //shute right 2
spawn.mapRect(1100, -1100, 50, 300); //shute right 3
spawn.mapRect(1120, -980, 50, 50); //shute right 4
- spawn.bodyRect(100, -1000, 50, 350);
- spawn.bodyRect(100, -1015, 250, 15);
- spawn.mapRect(-925, -1600, 100, 1000); //2-2 left wall
- spawn.mapRect(725, -2150, 200, 750); //2-2 right wall
- spawn.mapRect(725, -1200, 200, 200); //2-2 right wall 2
- spawn.mapRect(300, -1000, 625, 50); //2 central ledge
+ spawn.mapRect(1850, -650, 400, 50); //drop from 4-1
+ // level.fill.push({
+ // x: 150,
+ // y: -1000,
+ // width: 775,
+ // height: 700,
+ // color: "rgba(0,0,0,0.03)"
+ // });
+ // level.fill.push({
+ // x: 1075,
+ // y: -1000,
+ // width: 500,
+ // height: 700,
+ // color: "rgba(0,0,0,0.03)"
+ // });
level.fill.push({
x: 725,
y: -1400,
@@ -4774,91 +4796,100 @@ const level = {
height: 200,
color: "rgba(0,0,0,0.1)"
});
- level.fill.push({
+ level.fill.push({ //lower shute
x: 925,
y: -2150,
width: 150,
height: 2175,
color: "rgba(0,0,0,0.1)"
});
- level.fill.push({
+ level.fill.push({ //upper shute
x: 925,
- y: -3450,
+ y: -3400,
width: 150,
- height: 900,
+ height: 850,
color: "rgba(0,0,0,0.1)"
});
//section 3: upper left room and upper central room (gone through main portals 2 times)
+ //3-2 is just the upper part of 2-2
spawn.mapRect(-1775, -1000, 700, 300); //3-1 floor
spawn.mapRect(-1900, -2300, 175, 1600); //3-1 left wall
spawn.mapRect(-1375, -1300, 300, 50); //3-1 platform 1
spawn.mapRect(-1600, -1650, 300, 50); //3-1 platform 2
spawn.mapRect(-1775, -2300, 700, 300); //3-1 ceiling
- spawn.mapRect(-830, -1600, 300, 50); //2 upper left ledge
- spawn.mapRect(250, -2150, 675, 50); //2 upper right ledge
- spawn.mapRect(-925, -2300, 100, 400); //3-2 left wall
+ spawn.mapRect(-830, -1600, 300, 50); //3-2 left ledge
+ spawn.mapRect(250, -2150, 675, 50); //3-2 right ledge
+ spawn.mapRect(-925, -2300, 100, 300); //3-2 left wall
spawn.mapRect(-600, -2700, 1525, 150); //3-2 ceiling
spawn.mapRect(1075, -2150, 250, 150); //next to upper portal
- level.fill.push({
- x: -1730,
- y: -2300,
- width: 870,
- height: 1600,
- color: "rgba(0,0,0,0.1)"
- });
+ // level.fill.push({
+ // x: -1730,
+ // y: -2300,
+ // width: 870,
+ // height: 1600,
+ // color: "rgba(0,0,0,0.03)"
+ // });
//section 4: upper right portals
spawn.mapRect(1475, -2700, 150, 700); //4-1 left wall
spawn.mapRect(1775, -1650, 250, 150); //4-1 floor-ish
spawn.mapRect(1575, -1505, 450, 555); //below upper right portal
spawn.mapRect(1800, -2250, 400, 50); //4-1 platform 2
- spawn.bodyRect(2200, -2250, 25, 300);
+ spawn.bodyRect(2200, -2250, 15, 300);
spawn.mapRect(2200, -1950, 400, 50); //4-1 platform 1
//spawn.bodyRect(2575, -2600, 25, 650);
spawn.mapRect(2600, -1650, 400, 50); //4-1 platform 0
spawn.mapRect(2200, -1350, 400, 50); //4-1 platform -1
- spawn.bodyRect(2200, -1900, 25, 550);
- spawn.bodyRect(2575, -1650, 25, 300);
+ spawn.bodyRect(2200, -1900, 15, 550);
+ spawn.bodyRect(2585, -1650, 15, 300);
- spawn.mapRect(1780, -4200, 820, 1600); //top right corner
+ spawn.mapRect(1800, -4200, 800, 1600); //4-2 right wall
spawn.mapRect(800, -4200, 1800, -500); //4-2 ceiling
- spawn.mapRect(1075, -3450, 250, 900); //4-2 center block
- spawn.mapRect(800, -3450, 125, 900); //4-2 left wall
- spawn.mapRect(1550, -4200, 310, 600); //4-2 upper right wall
- level.fill.push({
- x: 1800,
- y: -2200,
- width: 225,
- height: 550,
- color: "rgba(0,0,0,0.1)"
- });
+ spawn.mapRect(1075, -3400, 225, 850); //upper shute right wall
+ spawn.mapRect(800, -3400, 125, 850); //upper shute left wall
+ // level.fill.push({
+ // x: 1800,
+ // y: -2200,
+ // width: 225,
+ // height: 550,
+ // color: "rgba(0,0,0,0.1)"
+ // });
level.fill.push({
x: 1800,
y: -2600,
width: 400,
height: 400,
- color: "rgba(0,0,0,0.1)"
+ color: "rgba(0,0,0,0.03)"
});
level.fill.push({
x: 2200,
y: -2600,
width: 400,
height: 1250,
- color: "rgba(0,0,0,0.1)"
+ color: "rgba(0,0,0,0.03)"
});
//section 5: after portals (gone through main portals 3 times)
spawn.mapRect(-700, -2700, 100, 450); //5-1 right wall
spawn.mapRect(-1450, -2700, 900, 50); //5-1 ceiling
spawn.mapRect(-925, -2300, 325, 50); //5-1 right floor
- level.fill.push({
- x: -1450,
- y: -2655,
- width: 755,
- height: 355,
- color: "rgba(0,0,0,0.1)"
- });
+ spawn.mapRect(-1900, -3000, 450, 50); //stair cover
+ spawn.bodyRect(-1150, -2950, 200, 250); //5-2 block
+ // level.fill.push({
+ // x: -1450,
+ // y: -2655,
+ // width: 755,
+ // height: 355,
+ // color: "rgba(0,0,0,0.03)"
+ // });
+ // level.fill.push({
+ // x: -1900,
+ // y: -3000,
+ // width: 450,
+ // height: 700,
+ // color: "rgba(0,0,0,0.03)"
+ // });
//top left corner stuff
if (true) {
@@ -4872,10 +4903,10 @@ const level = {
//exit room
spawn.mapRect(350, -3000, 50, 100); //exit room left wall
spawn.mapRect(350, -3000, 450, -1700); //exit room ceiling
- spawn.bodyRect(350, -2900, 50, 50); //door
- spawn.bodyRect(350, -2850, 50, 50); //door
- spawn.bodyRect(350, -2800, 50, 50); //door
- spawn.bodyRect(350, -2750, 50, 50); //door
+ spawn.bodyRect(350, -2900, 50, 50.5); //door
+ spawn.bodyRect(350, -2850, 50, 50.5); //door
+ spawn.bodyRect(350, -2800, 50, 50.5); //door
+ spawn.bodyRect(350, -2750, 50, 50.5); //door
level.fillBG.push({
x: 375,
y: -3000,
@@ -4884,9 +4915,9 @@ const level = {
color: "#d4f4f4"
});
- spawn.debris(-800, -50, 400, 6); //16 debris per level
+ spawn.debris(-400, 450, 400, 5); //16 debris per level
spawn.debris(-1650, -2300, 250, 4); //16 debris per level
- spawn.debris(-750, -650, 750, 6); //16 debris per level
+ spawn.debris(-750, -650, 750, 3); //16 debris per level
//mobs
spawn.randomMob(-650, -100, 0.7); //1-2 left
@@ -4895,7 +4926,7 @@ const level = {
//spawn.randomMob(-1500, -300, 0.3); //1-4 platform
spawn.randomMob(1450, -450, 0); //2-1 right
spawn.randomMob(1700, -800, 1); //2-1 off the edge. chance is 1 because some enemies just fall
- spawn.randomGroup(-550, -1000, -0.3); //2-2
+ spawn.randomGroup(-550, -900, -0.3); //2-2
spawn.randomMob(-1550, -1800, 0.7); //3-1 upper platform
//spawn.randomMob(-1225, -1400, 0.3); //3-1 lower platform
spawn.randomMob(450, -2350, 0.3); //3-2 right ledge
@@ -4903,8 +4934,8 @@ const level = {
spawn.randomGroup(2400, -2300, -0.3); //4-1 floating
spawn.randomMob(2400, -1450, 0); //4-1 platform -1
spawn.randomMob(2800, -1800, 0.5); //4-1 platform 0
- spawn.randomMob(-1100, -2800, 0.5); //5-2 left
- spawn.randomMob(-550, -2800, 0.5); //5-2 middle
+ spawn.randomMob(-1700, -3200, 0.7); //5-2 left platform
+ spawn.randomMob(-550, -2800, 0.3); //5-2 middle
if (simulation.difficulty > 3) {
if (Math.random() < 0.5) {
spawn.randomLevelBoss(450, -1350, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "shieldingBoss", "pulsarBoss", "laserBoss"]);
@@ -4915,4 +4946,153 @@ const level = {
powerUps.addRerollToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
},
+ coliseum() {
+ level.custom = () => {
+ level.playerExitCheck();
+ };
+ level.customTopLayer = () => {};
+ level.defaultZoom = 1800
+ simulation.zoomTransition(level.defaultZoom)
+ document.body.style.backgroundColor = "#dcdcde";
+ //Level
+ level.setPosToSpawn(200, 50);
+
+ level.exit.x = 8950;
+ level.exit.y = 200;
+
+ //Map
+ spawn.mapRect(150, 90, 100, 100);
+ spawn.mapRect(8950, 190, 100, 100);
+ spawn.mapRect(-100, -400, 100, 600);
+ spawn.mapRect(-100, 100, 700, 100);
+ spawn.mapRect(500, 100, 100, 1700);
+ spawn.mapRect(500, 1700, 4000, 100);
+ spawn.mapRect(4100, 600, 400, 100);
+ spawn.mapRect(4400, 600, 100, 1600);
+ spawn.mapRect(4400, 2100, 4300, 100);
+ spawn.mapRect(8600, 200, 100, 2000);
+ spawn.mapRect(8600, 200, 700, 100);
+ spawn.mapRect(9200, -300, 100, 600);
+ spawn.mapRect(8600, -300, 700, 100);
+ spawn.mapRect(8600, -700, 100, 500);
+ spawn.mapRect(4400, -700, 4300, 100);
+ spawn.mapRect(4400, -700, 100, 900);
+ spawn.mapRect(-100, -400, 4600, 100);
+
+ //Platforms
+ spawn.mapRect(1100, 400, 300, 100);
+ spawn.mapRect(500, 500, 300, 100);
+ spawn.mapRect(1050, 800, 300, 100);
+ spawn.mapRect(1770, 1050, 300, 100);
+ spawn.mapRect(1800, 500, 300, 100);
+ spawn.mapRect(2550, 900, 300, 100);
+ spawn.mapRect(2800, 1400, 300, 100);
+ spawn.mapRect(1250, 1350, 300, 100);
+ spawn.mapRect(4750, 850, 300, 100);
+ spawn.mapRect(3200, 1050, 300, 100);
+ spawn.mapRect(4700, 100, 300, 100);
+ spawn.mapRect(5350, 0, 300, 100);
+ spawn.mapRect(3800, 900, 300, 100);
+ spawn.mapRect(5100, 500, 300, 100);
+ spawn.mapRect(5900, -300, 300, 100);
+ spawn.mapRect(6500, -700, 300, 1300);
+ spawn.mapRect(7900, 0, 300, 100);
+ spawn.mapRect(8050, 800, 300, 100);
+ spawn.mapRect(7800, 1900, 300, 100);
+ spawn.mapRect(8300, 450, 300, 100);
+ spawn.mapRect(8400, 1200, 300, 100);
+ spawn.mapRect(7570, 1100, 300, 100);
+ spawn.mapRect(6700, 1850, 300, 100);
+ spawn.mapRect(8000, 1500, 300, 100);
+ spawn.mapRect(7120, -100, 300, 100);
+ spawn.mapRect(7000, 1500, 300, 100);
+ spawn.mapRect(6500, 1000, 300, 2100);
+ spawn.mapRect(5800, 1100, 300, 100);
+ spawn.mapRect(5900, 1700, 300, 100);
+ spawn.mapRect(5300, 1400, 300, 100);
+ spawn.mapRect(5200, 1100, 300, 100);
+ spawn.mapRect(6700, 1100, 300, 100);
+ spawn.mapRect(4800, 1650, 300, 100);
+
+ //Room 1 Spawning
+ spawn.randomMob(1000, 700, 0.7);
+ spawn.randomGroup(1100, 700, 0.5);
+ spawn.randomMob(1900, 400, 0.7);
+ spawn.randomGroup(2000, 400, 0.4);
+ spawn.randomGroup(1800, 1100, 0.4);
+ spawn.randomGroup(2700, 700, 0.5);
+ spawn.randomMob(2900, 1200, 0.7);
+ spawn.randomSmallMob(3200, 300, 0.9);
+ spawn.randomSmallMob(3700, 800, 0.9);
+ spawn.randomMob(1100, 700, 0.6);
+ spawn.randomGroup(1200, 700, 0.5);
+ spawn.randomMob(2000, 400, 0.8);
+ spawn.randomGroup(2100, 400, 0.5);
+ spawn.randomGroup(1900, 1100, 0.5);
+ spawn.randomGroup(2800, 700, 0.5);
+ spawn.randomMob(3000, 1200, 0.7);
+ spawn.randomSmallMob(3200, 300, 0.9);
+ spawn.randomSmallMob(3700, 800, 0.9);
+ spawn.randomMob(800, 1500, 0.9);
+ spawn.randomMob(1500, 1500, 0.7);
+ spawn.randomMob(2200, 1500, 0.6);
+ spawn.randomMob(2500, 1500, 0.7);
+ spawn.randomMob(2800, 1500, 0.7);
+ spawn.randomMob(3300, 1500, 0.6);
+
+ //Room 2 Spawning
+ spawn.randomGroup(4700, 2000, 0.9);
+ spawn.randomMob(5000, 2000, 0.5);
+ spawn.randomSmallMob(5700, 1500, 0.9);
+ spawn.randomMob(8500, 2000, 0.6);
+ spawn.randomGroup(8000, 1300, 0.9);
+ spawn.randomMob(8300, -300, 0.4);
+ spawn.randomSmallMob(7600, -200, 0.9);
+ spawn.randomMob(5200, -300, 0.5);
+ spawn.randomSmallMob(4700, -200, 0.5);
+ spawn.randomGroup(4700, 2000, 0.8);
+ spawn.randomMob(5000, 2000, 0.5);
+ spawn.randomSmallMob(5700, 1500, 0.9);
+ spawn.randomGroup(8500, 2000, 0.3);
+ spawn.randomSmallMob(8000, 1300, 0.4);
+ spawn.randomMob(8300, -300, 0.3);
+ spawn.randomGroup(7600, -200, 0.5);
+ spawn.randomMob(5200, -300, 0.3);
+ spawn.randomGroup(4700, -200, 0.4);
+ spawn.randomGroup(8650, -200, 0.9); //end guards
+ spawn.randomMob(8650, -200, 0.9); //end guards
+
+
+ //Boss Spawning
+ spawn.randomLevelBoss(6000, 700, ["pulsarBoss", "laserTargetingBoss", "powerUpBoss", "bomberBoss", "historyBoss", "orbitalBoss"]);
+ spawn.shieldingBoss(7200, 500);
+ if (simulation.difficulty > 20) {
+ spawn.randomLevelBoss(2000, 300, ["historyBoss", "shooterBoss"]);
+ }
+
+ //Blocks
+ spawn.bodyRect(550, -300, 50, 400); //spawn door
+ spawn.bodyRect(4400, 200, 100, 400); //boss door
+ spawn.bodyRect(6600, 600, 50, 400); //boss 2 door
+ spawn.debris(400, 800, 400, 2);
+ spawn.debris(3800, 1600, 1200, 6);
+ spawn.debris(7500, 2000, 800, 4);
+ spawn.debris(5500, 2000, 800, 4);
+
+ //Powerups
+ powerUps.spawnStartingPowerUps(1250, 1500);
+ powerUps.spawnStartingPowerUps(1500, 1500);
+ powerUps.spawn(8650, -200, "ammo");
+ powerUps.spawn(8650, -200, "ammo");
+ powerUps.spawn(8650, -200, "ammo");
+ powerUps.spawn(8650, -200, "ammo");
+ powerUps.spawn(200, 50, "heal");
+ powerUps.spawn(200, 50, "ammo");
+ powerUps.spawn(200, 50, "ammo");
+ powerUps.spawn(200, 50, "ammo");
+
+ powerUps.addRerollToLevel() //needs to run after mobs are spawned
+
+ if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(6600, 600, ["historyBoss", "powerUpBoss", "pulsarBoss", "orbitalBoss"]);
+ },
};
\ No newline at end of file
diff --git a/js/player.js b/js/player.js
index 6575a3d..0821f09 100644
--- a/js/player.js
+++ b/js/player.js
@@ -380,13 +380,7 @@ const m = {
//find what tech I could get
let options = [];
for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (
- tech.tech[i].count < tech.tech[i].maxCount &&
- tech.tech[i].allowed() &&
- !tech.tech[i].isBadRandomOption &&
- !tech.tech[i].isLore &&
- (!tech.tech[i].isJunk || Math.random() < 0.15)
- ) {
+ if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBadRandomOption && !tech.tech[i].isLore && !tech.tech[i].isJunk) {
for (let j = 0; j < tech.tech[i].frequency; j++) options.push(i);
}
}
diff --git a/js/powerup.js b/js/powerup.js
index c2c5668..a9a67a9 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -630,6 +630,23 @@ const powerUps = {
m.fieldCDcycle = m.cycle + 30; //disable field so you can't pick up the ejected tech
}
},
+ removeRandomTech() {
+ const have = [] //find which tech you have
+ for (let i = 0; i < tech.tech.length; i++) {
+ if (tech.tech[i].count > 0) have.push(i)
+ }
+ if (have.length) {
+ const choose = have[Math.floor(Math.random() * have.length)]
+ simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`)
+ const totalRemoved = tech.tech[choose].count
+ tech.tech[choose].count = 0;
+ tech.tech[choose].remove(); // remove a random tech form the list of tech you have
+ tech.tech[choose].isLost = true
+ simulation.updateTechHUD();
+ return totalRemoved
+ }
+ return 0
+ },
directSpawn(x, y, target, moving = true, mode = null, size = powerUps[target].size()) {
let index = powerUp.length;
target = powerUps[target];
diff --git a/js/simulation.js b/js/simulation.js
index d940daf..617ba52 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -307,7 +307,7 @@ const simulation = {
if (tech.tech[i].isLost) {
if (text) text += "
" //add a new line, but not on the first line
text += `${tech.tech[i].name}`
- } else if (tech.tech[i].count > 0) {
+ } else if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) {
if (text) text += "
" //add a new line, but not on the first line
text += tech.tech[i].name
if (tech.tech[i].nameInfo) {
@@ -521,13 +521,24 @@ const simulation = {
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) {
+
level.levels.push("stronghold");
level.levels.push("basement");
- level.levels.push("detours");
+ // level.levels.push("detours");
level.levels.push("house");
- level.levels.push("testChamber2");
+ level.levels.push("perplex");
+ level.levels.push("coliseum");
// level.levels.push("vats");
level.levels.splice(0, 5); //remove some random levels to make up for adding the community levels
+
+ //remove undefined tech for community maps
+ lore.techCount = 0;
+ for (let i = 0, len = tech.tech.length; i < len; i++) {
+ if (tech.tech[i].isLore) {
+ tech.tech[i].frequency = 0;
+ tech.tech[i].count = 0;
+ }
+ }
}
level.levels = shuffle(level.levels); //shuffles order of maps
level.levels.unshift("intro"); //add level to the start of the randomized levels list
diff --git a/js/spawn.js b/js/spawn.js
index 386c57e..3d6f380 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1491,9 +1491,10 @@ const spawn = {
me.fireCycle = 0
me.fireTarget = { x: 0, y: 0 }
me.pulseRadius = Math.min(500, 230 + simulation.difficulty * 3)
- me.fireDelay = Math.max(60, 190 - simulation.difficulty * 2)
+ me.fireDelay = Math.max(60, 140 - simulation.difficulty * 2)
me.isFiring = false
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
+ me.isBoss = true;
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random(), 1)
me.onDeath = function() {
@@ -1560,11 +1561,11 @@ const spawn = {
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
- const threshold = 0.03;
+ const threshold = 0.04;
if (c > threshold) {
- this.torque += 0.000001 * this.inertia;
+ this.torque += 0.0000015 * this.inertia;
} else if (c < -threshold) {
- this.torque -= 0.000001 * this.inertia;
+ this.torque -= 0.0000015 * this.inertia;
} else if (this.fireCycle > 45) { //fire
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
@@ -1590,8 +1591,8 @@ const spawn = {
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.fireCycle = Infinity
me.fireTarget = { x: 0, y: 0 }
- me.pulseRadius = Math.min(400, 165 + simulation.difficulty * 3)
- me.fireDelay = Math.max(75, 150 - simulation.difficulty * 0.5)
+ me.pulseRadius = Math.min(400, 170 + simulation.difficulty * 3)
+ me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.isFiring = false
me.onHit = function() {};
me.canSeeTarget = function() {
@@ -1677,11 +1678,11 @@ const spawn = {
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
- const threshold = 0.03;
+ const threshold = 0.04;
if (dot > threshold) { //rotate towards fireAngle
- this.torque += 0.000001 * this.inertia;
+ this.torque += 0.0000015 * this.inertia;
} else if (dot < -threshold) {
- this.torque -= 0.000001 * this.inertia;
+ this.torque -= 0.0000015 * this.inertia;
} else if (this.fireCycle > 60) { // aim
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
diff --git a/js/tech.js b/js/tech.js
index 97cf91a..41782a0 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -87,7 +87,7 @@
if (!found) return //if name not found don't give any tech
}
if (tech.isMetaAnalysis && tech.tech[index].isJunk) {
- tech.giveTech('random', true)
+ tech.giveTech('random')
for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "research");
return
}
@@ -252,7 +252,6 @@
maxCount: 1,
count: 0,
frequency: 1,
- isNonRefundable: true,
allowed() {
return (tech.isDamageForGuns || tech.isFireRateForGuns) && (b.inventory.length + 5) < b.guns.length
},
@@ -262,7 +261,12 @@
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
},
remove() {
- tech.isGunCycle = false;
+ if (tech.isGunCycle) {
+ for (let i = 0; i < 6; i++) {
+ if (b.inventory.length) b.removeGun(b.guns[b.inventory[b.inventory.length - 1]].name) //remove your last gun
+ }
+ tech.isGunCycle = false;
+ }
}
},
{
@@ -573,7 +577,7 @@
}
},
{
- name: "electrostatic discharge",
+ name: "simulated annealing",
description: "increase damage by 20%
20% increased delay after firing",
maxCount: 1,
count: 0,
@@ -1126,7 +1130,6 @@
count: 0,
frequency: 1,
isBotTech: true,
- // isNonRefundable: true,
allowed() {
return (b.totalBots() > 1 && powerUps.research.count > 0) || build.isExperimentSelection
},
@@ -1189,7 +1192,6 @@
frequency: 1,
isBotTech: true,
isNonRefundable: true,
- // isExperimentHide: true,
isBadRandomOption: true,
allowed() {
return b.totalBots() > 3
@@ -2040,8 +2042,6 @@
count: 0,
frequency: 1,
isNonRefundable: true,
- // isExperimentHide: true,
- // isBadRandomOption: true,
allowed() {
return true
},
@@ -2080,7 +2080,7 @@
powerUps.research.changeRerolls(0)
}, 1000);
},
- description: "once per level use 1 research to avoid dying
and spawn 6 heal power ups",
+ description: "use 1 research to avoid dying
and spawn 6 heal power ups once per level",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2258,9 +2258,8 @@
maxCount: 1,
count: 0,
frequency: 1,
- // isNonRefundable: true,
+ isNonRefundable: true,
isBadRandomOption: true,
- // isExperimentHide: true,
allowed() {
return (tech.totalCount > 6)
},
@@ -2269,19 +2268,17 @@
//remove active bullets //to get rid of bots
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = [];
- let count = 0 //count tech
+ let count = 1 //count tech
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (!tech.tech[i].isNonRefundable) count += tech.tech[i].count
}
- if (tech.isDeterminism) count -= 3 //remove the bonus tech
- if (tech.isSuperDeterminism) count -= 2 //remove the bonus tech
+ if (tech.isDeterminism) count -= 4 //remove the bonus tech
+ if (tech.isSuperDeterminism) count -= 4 //remove the bonus tech
tech.setupAllTech(); // remove all tech
lore.techCount = 0;
// tech.addLoreTechToPool();
- for (let i = 0; i < count; i++) { // spawn new tech power ups
- powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
- }
+ for (let i = 0; i < count; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "tech"); // spawn new tech power ups
//have state is checked in m.death()
},
remove() {}
@@ -2343,7 +2340,6 @@
maxCount: 9,
count: 0,
frequency: 1,
- // isNonRefundable: true,
allowed() {
return tech.duplicationChance() < 1
},
@@ -2472,7 +2468,6 @@
count: 0,
frequency: 1,
isNonRefundable: true,
- // isExperimentHide: true,
allowed() {
return (tech.totalCount > 3) && !tech.isSuperDeterminism
},
@@ -2502,24 +2497,13 @@
count: 0,
frequency: 1,
isNonRefundable: true,
- // isExperimentHide: true,
allowed() {
return (tech.totalCount > 3) && !tech.isSuperDeterminism && tech.duplicationChance() > 0
},
requires: "at least 1 tech, a chance to duplicate power ups",
effect: () => {
- const have = [] //find which tech you have
- for (let i = 0; i < tech.tech.length; i++) {
- if (tech.tech[i].count > 0) have.push(i)
- }
- const choose = have[Math.floor(Math.random() * have.length)]
- simulation.makeTextLog(`tech.remove("${tech.tech[choose].name}")`)
- for (let i = 0; i < tech.tech[choose].count; i++) powerUps.spawn(m.pos.x, m.pos.y, "tech");
- powerUps.spawn(m.pos.x, m.pos.y, "tech");
- tech.tech[choose].count = 0;
- tech.tech[choose].remove(); // remove a random tech form the list of tech you have
- tech.tech[choose].isLost = true
- simulation.updateTechHUD();
+ const removeTotal = powerUps.removeRandomTech()
+ for (let i = 0; i < removeTotal + 1; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
},
remove() {}
}, {
@@ -2529,7 +2513,6 @@
count: 0,
frequency: 1,
isNonRefundable: true,
- // isExperimentHide: true,
allowed() {
return !tech.isSuperDeterminism && tech.duplicationChance() > 0 && powerUps.research.count > 1
},
@@ -2565,8 +2548,6 @@
name: "dark patterns",
description: "reduce combat difficulty by 1 level
add 18 junk tech to the potential pool",
maxCount: 1,
- // isNonRefundable: true,
- // isExperimentHide: true,
count: 0,
frequency: 1,
allowed() {
@@ -2608,9 +2589,7 @@
maxCount: 1,
count: 0,
frequency: 1,
- // isNonRefundable: true,
- // isExperimentHide: true,
- // isBadRandomOption: true,
+ isNonRefundable: true,
allowed() {
return !tech.isSuperDeterminism
},
@@ -2622,11 +2601,11 @@
}
},
remove() {
- if (this.count > 1) {
- for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (tech.tech[i].isFieldTech) tech.tech[i].frequency /= 2
- }
- }
+ // if (this.count > 1) {
+ // for (let i = 0, len = tech.tech.length; i < len; i++) {
+ // if (tech.tech[i].isFieldTech) tech.tech[i].frequency /= 2
+ // }
+ // }
}
},
{
@@ -2635,7 +2614,6 @@
maxCount: 1,
count: 0,
frequency: 1,
- isNonRefundable: true,
allowed() {
return tech.totalCount > 9
},
@@ -2647,7 +2625,7 @@
},
remove() {
for (let i = 0, len = tech.tech.length; i < len; i++) {
- if (tech.tech[i].count > 0) tech.tech[i].frequency /= 100
+ if (tech.tech[i].count > 0 && tech.tech[i].frequency > 1) tech.tech[i].frequency /= 100
}
}
}, {
@@ -2672,7 +2650,6 @@
maxCount: 1,
count: 0,
frequency: 1,
- isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return !tech.isExtraChoice && !tech.isCancelDuplication && !tech.isCancelRerolls
@@ -2680,11 +2657,12 @@
requires: "not cardinality, not futures or commodities exchanges",
effect: () => {
tech.isDeterminism = true;
- //if you change the six also change it in Born rule
+ //if you change the number spawned also change it in Born rule
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
},
remove() {
tech.isDeterminism = false;
+ for (let i = 0; i < 5; i++) powerUps.removeRandomTech()
}
}, {
name: "superdeterminism",
@@ -2693,7 +2671,6 @@
count: 0,
frequency: 3,
frequencyDefault: 3,
- isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return tech.isDeterminism && !tech.manyWorlds && !tech.isGunSwitchField
@@ -2701,11 +2678,12 @@
requires: "determinism, not unified field theory",
effect: () => {
tech.isSuperDeterminism = true;
- //if you change the six also change it in Born rule
- for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
+ //if you change the number spawned also change it in Born rule
+ for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
},
remove() {
tech.isSuperDeterminism = false;
+ for (let i = 0; i < 5; i++) powerUps.removeRandomTech()
}
},
//**************************************************
@@ -3656,6 +3634,41 @@
remove() {
tech.isFastFoam = false;
}
+ },
+ {
+ name: "electrostatic induction",
+ description: "foam bullets are electrically charged
causing attraction to nearby mobs",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ allowed() {
+ return tech.haveGunCheck("foam") || tech.foamBotCount > 1
+ },
+ requires: "foam",
+ effect() {
+ tech.isFoamAttract = true
+ },
+ remove() {
+ tech.isFoamAttract = false
+ }
+ }, {
+ name: "quantum foam",
+ description: "foam gun fires 0.25 seconds into the future
increase foam gun damage by 127%",
+ isGunTech: true,
+ maxCount: 9,
+ count: 0,
+ frequency: 1,
+ allowed() {
+ return tech.haveGunCheck("foam")
+ },
+ requires: "foam",
+ effect() {
+ tech.foamFutureFire++
+ },
+ remove() {
+ tech.foamFutureFire = 0;
+ }
}, {
name: "foam fractionation",
description: "foam gun bubbles are 100% larger
when you have below 300 ammo",
@@ -3673,23 +3686,6 @@
remove() {
tech.isAmmoFoamSize = false;
}
- }, {
- name: "quantum foam",
- description: "foam gun fires 0.25 seconds into the future
increase foam gun damage by 143%",
- isGunTech: true,
- maxCount: 9,
- count: 0,
- frequency: 1,
- allowed() {
- return tech.haveGunCheck("foam")
- },
- requires: "foam",
- effect() {
- tech.foamFutureFire++
- },
- remove() {
- tech.foamFutureFire = 0;
- }
},
// {
@@ -5522,7 +5518,7 @@
count: 0,
frequency: 1,
isLore: true,
- isNonRefundable: true,
+ // isNonRefundable: true,
isExperimentHide: true,
allowed() {
return true
@@ -5798,5 +5794,6 @@
isFlipFlopLevelReset: null,
isFlipFlopDamage: null,
isFlipFlopEnergy: null,
- isMetaAnalysis: null
+ isMetaAnalysis: null,
+ isFoamAttract: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index f644ede..72846d0 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,10 +1,12 @@
******************************************************** NEXT PATCH ********************************************************
-meta-analysis - if you choose a junk tech you instead get a random tech and spawn 2 research
-micro-extruder should have 50% less lag
+tech: electrostatic induction - foam bullets are attracted to nearby mobs
-new community level testChamber2! by Oranger on n-gon discord
-(be sure to enable community levels in settings)
+portals on perplex map, now remove blocks that fall in
+new community map! coliseum by iNoobBoi
+
+a few more tech can be refunded properly
+nonRefundable tech don't show up in the list of tech you have
******************************************************** BUGS ********************************************************
@@ -39,10 +41,6 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ********************************************************
-allow levels to adjust the teleport limit in simulation.checks
-
-copy time-like foam to shotgun
-
mob sniper: draw aim graphics before fire
tech laser: photon - laser, but it can only move 100 pixels a cycle
@@ -52,14 +50,6 @@ mob - after taking damage
grows
teleports
-tech- foam is attracted to mobs
- use a gravitational attraction model?
- could foam be attracted to other foam bullets too?
- or foam is only attracted to foam bullets that are stuck to mobs
- is this too computationally intense?
- name - static cling
- could also do bremsstrahlung radiation like damage on attachment
-
mobile requirements:
detect mobile, flip to landscape
detect no keyboard, no mouse
@@ -88,6 +78,7 @@ map: laboratory
radiation room
portal + rotor + falling blocks = perpetual motion room
a button that spawns a heal.
+ consider adding canvas path shadows to levels in level.custom for non squared lighting
lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players
@@ -320,7 +311,7 @@ possible names for tech
genetic algorithm
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity
stochastic optimization
- meta-analysis
+ electrostatic discharge
plot script: