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: