From 514b72c76d153dffaa845588f1cdf9d3509c5bc8 Mon Sep 17 00:00:00 2001 From: landgreen Date: Mon, 10 Jan 2022 20:59:44 -0800 Subject: [PATCH] reservoir new map reservoir - still in development, but putting it out for feedback tech: optical amplifier - get 3 random laser tech, but you can't turn off your laser until you run out of energy slow light - lasers are slightly closer together at higher stacks of this tech research power ups no longer log to the "in game console" to prevent spam dynamo-bots give 6->7 more energy (upgraded 20->23) some Boss invulnerability times are very slightly shorter music tech now links to actual n-gon music https://www.youtube.com/watch?v=lEbHeSdmS-k&list=PL9Z5wjoBiPKEDhwCW2RN-VZoCpmhIojdn --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 19 ++- js/level.js | 330 ++++++++++++++++++++++++++++++++++++++++++-------- js/powerup.js | 5 +- js/spawn.js | 4 +- js/tech.js | 70 ++++++++--- todo.txt | 42 +++++-- 7 files changed, 383 insertions(+), 87 deletions(-) diff --git a/.DS_Store b/.DS_Store index 4520c6291cdf150989ac6d1017e8348dba067114..1e57cd778ae40ea4e1b6385fd3b39458c1391a7b 100644 GIT binary patch delta 22 dcmZoMXffEJ$;>RT@_e!mvmfJx&DG4EA^=aL2H^kz delta 22 dcmZoMXffEJ$;>SG(Py#_vmax?=4$3n5dcv-2GRfk diff --git a/js/bullet.js b/js/bullet.js index db996d6..bb7324f 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -3617,7 +3617,7 @@ const b = { if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250 && m.immuneCycle < m.cycle) { //give energy Matter.Body.setAngularVelocity(this, this.spin) if (this.isUpgraded) { - m.energy += 0.1 + m.energy += 0.115 simulation.drawList.push({ //add dmg to draw queue x: this.position.x, y: this.position.y, @@ -3626,7 +3626,7 @@ const b = { time: simulation.drawTime }); } else { - m.energy += 0.03 + m.energy += 0.035 simulation.drawList.push({ //add dmg to draw queue x: this.position.x, y: this.position.y, @@ -6374,10 +6374,20 @@ const b = { ammoPack: Infinity, have: false, charge: 0, + isStuckOn: false, do() {}, fire() {}, chooseFireMethod() { - this.do = () => {}; + this.do = () => { + if (tech.isStuckOn) { + if (this.isStuckOn) { + if (!input.fire) this.fire(); + if (m.energy < tech.laserFieldDrain * tech.isLaserDiode) this.isStuckOn = false + } else if (input.fire) { + this.isStuckOn = true + } + } + }; if (tech.isPulseLaser) { this.fire = () => { const drain = 0.01 * tech.isLaserDiode * (tech.isCapacitor ? 10 : 1) @@ -6455,7 +6465,6 @@ const b = { } else { this.fire = this.fireLaser } - // this.fire = this.firePhoton }, // firePhoton() { @@ -6569,7 +6578,7 @@ const b = { m.fireCDcycle = m.cycle m.energy -= m.fieldRegen + tech.laserFieldDrain * tech.isLaserDiode const dmg = 0.4 * tech.laserDamage // 3.5 * 0.55 = 200% more damage - const spacing = Math.ceil(5.2 - 0.2 * tech.historyLaser) + const spacing = Math.ceil(5.2 - 0.4 * tech.historyLaser) ctx.beginPath(); b.laser({ x: m.pos.x + 20 * Math.cos(m.angle), diff --git a/js/level.js b/js/level.js index 68f59c3..2560017 100644 --- a/js/level.js +++ b/js/level.js @@ -7,35 +7,30 @@ const level = { defaultZoom: 1400, onLevel: -1, levelsCleared: 0, - playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "ruins"], //intro, gauntlet, final are added in at the start and end of level order - // playableLevels: ["ruins", "ruins", "ruins", "ruins", "ruins", "ruins", "ruins", "ruins", "ruins", "ruins", "ruins"], //intro, gauntlet, final are added in at the start and end of level order + playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "ruins"], //see level.populateLevels: (intro, ... , reservoir, ... , gauntlet, final) added later communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"], - trainingLevels: [ - "walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", - "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", - "stack", "mine", "grenades", "harpoon" - ], + trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], levels: [], start() { if (level.levelsCleared === 0) { //this code only runs on the first level - // simulation.enableConstructMode() //used to build maps in testing mode // m.immuneCycle = Infinity //you can't take damage // localSettings.levelsClearedLastGame = 10 // level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.setField("plasma torch") - // b.giveGuns("harpoon") - // tech.giveTech("extruder") + // b.giveGuns("laser") + // for (let i = 0; i < 9; i++) tech.giveTech("slow light") // tech.giveTech("thermocouple") // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); - // for (let i = 0; i < 9; i++) tech.giveTech("annelids") + // tech.giveTech("annelids") // tech.giveTech("tinsellated flagella") // for (let i = 0; i < 2; i++) tech.giveTech("refractory metal") // tech.giveTech("antiscience") // for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // tech.tech[297].frequency = 100 - // level.ruins(); + // level.reservoir(); + // simulation.enableConstructMode() //used to build maps in testing mode if (simulation.isTraining) { level.walk(); } else { level.intro(); } // level.testing(); //not in rotation, used for testing @@ -261,6 +256,7 @@ const level = { } else { level.levels = shuffle(level.levels); //shuffles order of maps } + level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reservoir"); //add level to the back half of the randomized levels list if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech level.levels.unshift("intro"); //add level to the start of the randomized levels list level.levels.push("gauntlet"); //add level to the end of the randomized levels list @@ -451,13 +447,13 @@ const level = { }); return who }, - elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isAtTop = false) { x += width / 2 y += height / 2 maxHeight += height / 2 const yTravel = maxHeight - y force += simulation.g - const who = body[body.length] = Bodies.rectangle(x, y, width, height, { + const who = body[body.length] = Bodies.rectangle(x, isAtTop ? maxHeight : y, width, height, { collisionFilter: { category: cat.body, mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet @@ -543,10 +539,8 @@ const level = { Matter.Body.setDensity(who, 0.01) //10x density for added stability return who }, - platform(x, y, width, height, speed = 0, density = 0.001) { - x = x + width / 2 - y = y + height / 2 - const who = body[body.length] = Bodies.rectangle(x, y, width, height, { + spring(x, y, v = "-100 0 100 0 70 40 0 50 -70 40", force = 0.01, distance = 300, angle = 0) { + const who = body[body.length] = Matter.Bodies.fromVertices(x, y, Vertices.fromPath(v), { collisionFilter: { category: cat.body, mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet @@ -556,26 +550,52 @@ const level = { friction: 1, frictionStatic: 1, restitution: 0, - }); + frictionAir: 1, + density: 0.1, + isReady: true, + isResetting: false, + query() { + if (this.isReady) { + if (Matter.Query.collides(this, [player]).length) { + this.isReady = false + this.constraint.stiffness = 0 + this.constraint.damping = 0 //0.3 + this.frictionAir = 0 + Matter.Body.setVelocity(this, { x: 0, y: 0 }); + //show graphically being ready? - Matter.Body.setDensity(who, density) - const constraint = Constraint.create({ //fix rotor in place, but allow rotation + } + } else { + if (this.isResetting) { + this.constraint.stiffness += 0.0005 + if (this.constraint.stiffness > 0.1) { + this.isResetting = false + this.isReady = true + } + } else { + if (Vector.magnitudeSquared(Vector.sub(this.position, { x: x, y: y })) < distance * distance) { + this.force.y -= force * this.mass + } else { + this.constraint.damping = 1 + this.frictionAir = 1 + this.isResetting = true + Matter.Body.setVelocity(this, { x: 0, y: 0 }); + } + } + } + } + }); + who.constraint = Constraint.create({ pointA: { - x: x, - y: y + x: who.position.x, + y: who.position.y }, bodyB: who, - stiffness: 0.1, - damping: 0.3 + stiffness: 1, + damping: 1 }); - Composite.add(engine.world, constraint); - constraint.plat = { - position: who.position, - speed: speed, - } - constraint.pauseUntilCycle = 0 //to to pause platform at top and bottom - - return constraint + Composite.add(engine.world, who.constraint); + return who }, rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { @@ -1174,10 +1194,10 @@ const level = { for (let i = 0, len = powerUpCollide.length; i < len; i++) { const diameter = 2 * powerUpCollide[i].size const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter - powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g; + powerUpCollide[i].force.y -= buoyancy * 1.14 * powerUpCollide[i].mass * simulation.g; Matter.Body.setVelocity(powerUpCollide[i], { x: powerUpCollide[i].velocity.x, - y: 0.95 * powerUpCollide[i].velocity.y + y: 0.96 * powerUpCollide[i].velocity.y }); } } @@ -1188,9 +1208,22 @@ const level = { // ctx.fillRect(this.min.x, this.min.y, this.width, this.height) // } // }, - level(isFill) { + levelRise(growRate = 1) { + if (this.height < this.maxHeight && !m.isBodiesAsleep) { + this.height += growRate + this.min.y -= growRate + this.max.y = this.min.y + this.height + } + }, + levelFall(fallRate = 1) { + if (this.height > 0 && !m.isBodiesAsleep) { + this.height -= fallRate + this.min.y += fallRate + this.max.y = this.min.y + this.height + } + }, + level(isFill, growSpeed = 1) { if (!m.isBodiesAsleep) { - const growSpeed = 1 if (isFill) { if (this.height < this.maxHeight) { this.height += growSpeed @@ -2149,7 +2182,7 @@ const level = { ) }, // (x = offset.x, y = offset.y) => { - // const elevator1 = level.elevator(x + 1100, y - 200, 250, 30, -2100, 0.0015) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isTeleport = false) { + // const elevator1 = level.elevator(x + 1100, y - 200, 250, 30, -2100, 0.0015) // x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }, isTeleport = false) { // // const elevator1 = level.elevator(x + 175, y - 200, 250, 30, -1400, 0.001) // // const elevator2 = level.elevator(x + 2175, y - 200, 250, 30, -1400, 0.001) @@ -2928,6 +2961,204 @@ const level = { spawn.bodyRect(2400, -100, 100, 60); spawn.bodyRect(2500, -150, 100, 150); //exit step }, + reservoir() { + level.exit.x = 1700; + level.exit.y = -4510; + spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 25); + level.setPosToSpawn(-500, 850); //normal spawn + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.defaultZoom = 2300 + simulation.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#d8dadf"; + powerUps.spawnStartingPowerUps(-1175, -3875); + + //no debris? + // spawn.debris(750, -2200, 3700, 16); //16 debris per level + + //walls + spawn.mapRect(-3500, -5000, 1500, 6500); + spawn.mapRect(2000, -5000, 1500, 6500); + spawn.mapRect(-2500, 1100, 5000, 400); //slime floor + spawn.mapRect(-3500, -5475, 7000, 600); //top + spawn.mapRect(-1925, -4900, 175, 375); //pipe + spawn.mapRect(-1950, -4550, 225, 25); //pipe + //top floor exit + spawn.mapRect(1025, -4475, 1100, 50); + spawn.mapRect(1475, -4900, 50, 250); + + // ground + spawn.mapVertex(-687, 1060, "700 0 -700 0 -450 -300 450 -300"); //left base + spawn.mapVertex(863, 1060, "700 0 -700 0 -450 -300 450 -300"); //right base + //entrance + spawn.mapRect(-730, 525, 475, 50); + spawn.mapRect(-730, 550, 50, 150); + spawn.mapRect(-305, 550, 50, 500); + spawn.bodyRect(-717, 700, 25, 100); //door + spawn.bodyRect(-717, 800, 25, 100); //door + + //1st floor + //left + spawn.mapVertex(-1125 + 435, -50, "325 0 250 80 -250 80 -325 0 -250 -80 250 -80"); + spawn.mapRect(-1125, -100, 870, 100); + + if (Math.random() < 0.33) { + spawn.mapVertex(-687, -1000, "-100 -300 0 -350 100 -300 100 300 0 350 -100 300"); + } else if (Math.random() < 0.5) { + spawn.mapVertex(-687, -1000, "-150 -450 0 -525 150 -450 150 450 0 525 -150 450"); + } else { + spawn.mapVertex(-687, -700, "-150 0 150 0 150 450 0 525 -150 450"); + } + + const spinnerArray = [] + spinnerArray.push(level.spinner(72, -300, 40, 500, 0.003, Math.PI / 2)) + + //right + spawn.mapVertex(425 + 435, -50, "325 0 250 80 -250 80 -325 0 -250 -80 250 -80"); + spawn.mapRect(425, -100, 870, 100); + spawn.mapRect(300, 675, 250, 25); + spawn.mapRect(675, 450, 375, 25); + spawn.mapRect(1175, 225, 240, 25); + + if (Math.random() < 0.33) { + spawn.mapVertex(855, -1000, "-100 -300 0 -350 100 -300 100 300 0 350 -100 300"); + } else if (Math.random() < 0.5) { + spawn.mapVertex(855, -1000, "-150 -450 0 -525 150 -450 150 450 0 525 -150 450"); + } else { + spawn.mapVertex(855, -700, "-150 0 150 0 150 450 0 525 -150 450"); + } + + //2nd floor + spawn.mapVertex(855, -1936, "-612 50 0 100 612 50 612 -50 -612 -50"); + spawn.mapVertex(-687, -1936, "-612 50 0 100 612 50 612 -50 -612 -50"); + + //2nd floor right building + const boost1 = level.boost(800, -2000, 700) + spawn.mapRect(550, -3050, 600, 175); + spawn.mapRect(550, -2700, 150, 600); + spawn.mapRect(1000, -2700, 150, 600); + spawn.mapRect(450, -2700, 250, 25); + spawn.mapRect(1000, -2700, 250, 25); + const boost2 = level.boost(800, -3050, 1500) + spinnerArray.push(level.spinner(50, -3325, 45, 600, 0.003, Math.PI / 2)) + + //2nd floor left building + spawn.mapRect(-875, -2350, 600, 200); + spawn.mapRect(-825, -2825, 425, 275); + spawn.mapRect(-450, -3125, 50, 350); + spawn.mapRect(-750, -3150, 350, 50); + spawn.mapRect(-650, -3400, 250, 300); + spawn.mapRect(-650, -3675, 200, 50); + spawn.bodyRect(-375, -2150, 100, 150, 0.2); + //2nd floor left pillar + spawn.mapRect(-1300, -2625, 225, 25); + spawn.mapRect(-1300, -3225, 225, 25); + spawn.mapRect(-1300, -3825, 225, 25); + + const slime = level.hazard(-2000, -5000, 4000, 6060); // hazard(x, y, width, height, damage = 0.003) + slime.height -= slime.maxHeight - 60 //start slime at zero + slime.min.y += slime.maxHeight + slime.max.y = slime.min.y + slime.height + const elevator1 = level.elevator(-1625, -90, 310, 35, -2000, 0.0025, { up: 0.1, down: 0.2 }) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + elevator1.isOn = true + + level.custom = () => { + elevator1.drawTrack(); + + ctx.fillStyle = "#c0c3c9" + ctx.fillRect(-1200, -3825, 25, 1850); //small pillar background + ctx.fillStyle = "#d0d4d6" + ctx.fillRect(-1100, -1925, 825, 2925) //large pillar background + ctx.fillRect(450, -1925, 825, 2925) //large pillar background + + ctx.fillStyle = "#cff" //exit + ctx.fillRect(1475, -4900, 525, 425) + level.playerExitCheck(); + level.exit.draw(); + level.enter.draw(); + }; + let waterFallWidth = 0 + let waterFallX = 0 + let waterFallSmoothX = 0 + let isWaterfallFilling = false + const riseRate = 0.25 + Math.min(1, simulation.difficulty * 0.01) + level.customTopLayer = () => { + boost1.query(); + boost2.query(); + + if (elevator1.isOn) { + elevator1.move(); + } else if (Matter.Query.collides(elevator1, [player]).length) { + elevator1.isOn = true + elevator1.isUp = false + elevator1.removeConstraint(); + elevator1.frictionAir = 0.2 + } + + ctx.fillStyle = "#233" + ctx.beginPath(); //central dot on spinners + ctx.arc(spinnerArray[0].pointA.x, spinnerArray[0].pointA.y, 9, 0, 2 * Math.PI); + for (let i = 0, len = spinnerArray.length; i < len; i++) { + ctx.moveTo(spinnerArray[i].pointA.x, spinnerArray[i].pointA.y) + ctx.arc(spinnerArray[i].pointA.x, spinnerArray[i].pointA.y, 9, 0, 2 * Math.PI); + } + ctx.fill(); + + //shadow + ctx.fillStyle = "rgba(0,10,30,0.1)" + ctx.fillRect(550, -2900, 600, 925); + ctx.fillRect(-750, -3100, 300, 275); + ctx.fillRect(-650, -3625, 200, 225); + ctx.fillRect(-825, -2575, 425, 325); + ctx.fillRect(-875, -2150, 600, 150); + + slime.query(); + if (isWaterfallFilling) { + if (slime.height < 5500) { + //draw slime fill + waterFallWidth = 0.98 * waterFallWidth + 4.7 * Math.random() + waterFallSmoothX = 0.98 * waterFallSmoothX + 3.5 * Math.random() + waterFallX = waterFallSmoothX - 1985 + ctx.fillStyle = `hsla(160, 100%, 43%,${0.3+0.07*Math.random()})` + ctx.fillRect(waterFallX, -5050, waterFallWidth, 6175 - slime.height) + ctx.fillRect(waterFallX + waterFallWidth * Math.random(), -5050, 4, 6175 - slime.height) + //push player down if they go under waterfall + if (player.position.x > waterFallX && player.position.x < waterFallX + waterFallWidth && player.position.y < slime.height) { + Matter.Body.setVelocity(player, { + x: player.velocity.x, + y: player.velocity.y + 2 + }); + } + slime.levelRise(riseRate) + } + } else if (Vector.magnitudeSquared(Vector.sub(player.position, level.enter)) > 100000) { + isWaterfallFilling = true + } + }; + // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why + // m.immuneCycle = Infinity //you can't take damage + // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns + // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns + + spawn.randomMob(1000, -275, 0.3); + spawn.randomMob(950, -1725, 0.2); + spawn.randomMob(-725, -1775, 0.2); + spawn.randomMob(1775, 1000, 0.1); + spawn.randomMob(-200, -2075, 0.1); + spawn.randomMob(375, -2125, 0.1); + spawn.randomMob(1025, -3200, 0); + spawn.randomMob(-525, -3750, 0); + spawn.randomMob(-550, -3500, 0); + spawn.randomMob(-700, -2450, -0.1); + spawn.randomMob(-1175, -2775, -0.1); + spawn.randomMob(1350, -2075, -0.2); + spawn.randomSmallMob(-575, -2925); + spawn.randomGroup(-400, -4400, 0); + if (simulation.difficulty > 1) { + spawn.randomLevelBoss(825, -3500); + spawn.secondaryBossChance(75, -1350) + } + powerUps.addResearchToLevel() //needs to run after mobs are spawned + }, ruins() { const vanish = [] level.exit.x = -850; @@ -3005,11 +3236,6 @@ const level = { spawn.mapRect(-1050, -1800, 525, 25); spawn.mapRect(-550, -1800, 25, 200); - // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why - // m.immuneCycle = Infinity //you can't take damage - // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns - // spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns - spawn.randomMob(-1175, -1975, -0.4); spawn.randomMob(275, -1500, -0.3); spawn.randomMob(700, -1875, -0.2); @@ -4255,12 +4481,12 @@ const level = { } }, highrise() { - const elevator1 = level.elevator(-790, -190, 180, 25, -1150) //, 0.007 + const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 }, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator1.addConstraint(); // const button1 = level.button(-500, -200) const toggle1 = level.toggle(-500, -200) //(x,y,isOn,isLockOn = true/false) - const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //, 0.007 + const elevator2 = level.elevator(-3630, -1000, 180, 25, -1740) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator2.addConstraint(); // const button2 = level.button(-3100, -1330) const toggle2 = level.toggle(-3100, -1330) //(x,y,isOn, isLockOn = true/false) @@ -4295,11 +4521,10 @@ const level = { if (elevator1.isOn) { elevator1.move(); ctx.fillStyle = "#444" - ctx.fillRect(-700, -1140, 1, 975) } else { ctx.fillStyle = "#aaa" - ctx.fillRect(-700, -1140, 1, 975) } + ctx.fillRect(-700, -1140, 1, 975) toggle2.query(); // button2.draw(); @@ -4319,11 +4544,10 @@ const level = { if (elevator2.isOn) { elevator2.move(); ctx.fillStyle = "#444" - ctx.fillRect(-3540, -1720, 1, 740) } else { ctx.fillStyle = "#aaa" - ctx.fillRect(-3540, -1720, 1, 740) } + ctx.fillRect(-3540, -1720, 1, 740) ctx.fillStyle = "rgba(64,64,64,0.97)" //hidden section ctx.fillRect(-4450, -750, 800, 200) @@ -4638,7 +4862,7 @@ const level = { let elevator1, elevator2, elevator3 if (Math.random() < 0.5) { isElevators = true - elevator1 = level.elevator(-1780, 500, 260, 40, 7, 0.0003) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + elevator1 = level.elevator(-1780, 500, 260, 40, 7, 0.0003) // x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator2 = level.elevator(820, 1300, 260, 40, 607, 0.0003) elevator3 = level.elevator(-2850, 1250, 160, 40, 600, 0.007) if (simulation.isHorizontalFlipped) { @@ -8132,7 +8356,7 @@ const level = { } else { tech.addJunkTechToPool(0.49) } - spawn.randomLevelBoss(x, y, ["historyBoss"]); + // spawn.randomLevelBoss(x, y, ["historyBoss"]); } } @@ -9664,11 +9888,11 @@ const level = { b.removeAllGuns(); b.giveGuns("grenades") - const elevator1 = level.elevator(550, -100, 180, 25, -840, 0.003, { up: 0.05, down: 0.2 }) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + const elevator1 = level.elevator(550, -100, 180, 25, -840, 0.003, { up: 0.05, down: 0.2 }) // x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator1.addConstraint(); const toggle1 = level.toggle(275, 0) //(x,y,isOn,isLockOn = true/false) - const elevator2 = level.elevator(1400, -950, 180, 25, -2400, 0.0025) // elevator(x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { + const elevator2 = level.elevator(1400, -950, 180, 25, -2400, 0.0025) // x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) { elevator2.addConstraint(); const button2 = level.button(1000, -850) diff --git a/js/powerup.js b/js/powerup.js index 0a69cae..87c1e47 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -344,9 +344,10 @@ const powerUps = { powerUps.research.count += amount if (powerUps.research.count < 0) { powerUps.research.count = 0 - } else { - simulation.makeTextLog(`powerUps.research.count += ${amount}`) //
${powerUps.research.count} } + // else { + // simulation.makeTextLog(`powerUps.research.count += ${amount}`) //
${powerUps.research.count} + // } } if (tech.isRerollBots) { let delay = 0 diff --git a/js/spawn.js b/js/spawn.js index 39f6c77..7f148ba 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1127,7 +1127,7 @@ const spawn = { this.isInvulnerable = true if (this.damageReduction) this.startingDamageReduction = this.damageReduction this.damageReduction = 0 - this.invulnerabilityCountDown = simulation.difficulty * 2 + this.invulnerabilityCountDown = simulation.difficulty } me.onDeath = function() { this.isBuffBoss = false; @@ -2020,7 +2020,7 @@ const spawn = { this.cons2.length = -200; this.isInvulnerable = false - this.invulnerabilityCountDown = 45 + Math.max(0, 70 - simulation.difficulty) + this.invulnerabilityCountDown = 60 + Math.max(0, 70 - simulation.difficulty) this.damageReduction = this.startingDamageReduction for (let i = 0; i < this.babyList.length; i++) { if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction diff --git a/js/tech.js b/js/tech.js index e1b8472..7b758e9 100644 --- a/js/tech.js +++ b/js/tech.js @@ -354,22 +354,15 @@ const tech = { requires: "NOT EXPERIMENT MODE, at least 2 guns", effect() { for (let i = b.inventory.length - 1; i > -1; i--) { - //spawn a research for each gun - // powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); - //find a gun tech for this gun - const gunTechPool = [] + const gunTechPool = [] //find gun tech for this gun for (let j = 0, len = tech.tech.length; j < len; j++) { // console.log(j, tech.tech[j].isGunTech, tech.tech[j].allowed(), !tech.tech[j].isJunk, !tech.tech[j].isBadRandomOption, tech.tech[j].count < tech.tech[j].maxCount) - //set current gun to active so allowed works - const originalActiveGunIndex = b.activeGun + const originalActiveGunIndex = b.activeGun //set current gun to active so allowed works b.activeGun = b.inventory[i] //to make the .allowed work for guns that aren't active if (tech.tech[j].isGunTech && tech.tech[j].allowed() && !tech.tech[j].isJunk && !tech.tech[j].isBadRandomOption && tech.tech[j].count < tech.tech[j].maxCount) { const regex = tech.tech[j].requires.search(b.guns[b.inventory[i]].name) //get string index of gun name const not = tech.tech[j].requires.search(' not ') //get string index of ' not ' - //look for the gun name in the requirements, but the gun name needs to show up before the word ' not ' - if (regex !== -1 && (not === -1 || not > regex)) { - gunTechPool.push(j) - } + if (regex !== -1 && (not === -1 || not > regex)) gunTechPool.push(j) //look for the gun name in the requirements, but the gun name needs to show up before the word ' not ' } b.activeGun = originalActiveGunIndex } @@ -1290,7 +1283,7 @@ const tech = { { name: "dynamo-bot", link: `dynamo-bot`, - description: "a bot damages mobs while it traces your path
regen 6 energy per second when it's near", + description: "a bot damages mobs while it traces your path
regen 7 energy per second when it's near", maxCount: 9, count: 0, frequency: 1, @@ -1314,7 +1307,7 @@ const tech = { { name: "dynamo-bot upgrade", link: `dynamo-bot upgrade`, - description: "convert your current bots to dynamo-bots
increase regen to 20 energy per second", + description: "convert your current bots to dynamo-bots
increase regen to 23 energy per second", maxCount: 1, count: 0, frequency: 3, @@ -5634,6 +5627,53 @@ const tech = { // tech.isRodAreaDamage = false; // } // }, + { + name: "optical amplifier", + description: "gain 3 random laser guntech
laser only turns off if you have no energy", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + isNonRefundable: true, + allowed() { + return tech.haveGunCheck("laser") && !tech.isPulseLaser + }, + requires: "laser gun, not pulse", + effect() { + tech.isStuckOn = true + + for (let j = 0; j < 3; j++) { + const names = ["laser diode", "free-electron laser", "relativistic momentum", "specular reflection", "diffraction grating", "diffuse beam", "output coupler", "slow light"] + //convert names into indexes + const options = [] + for (let i = 0; i < names.length; i++) { + for (let k = 0; k < tech.tech.length; k++) { + if (tech.tech[k].name === names[i]) { + options.push(k) + break + } + } + } + //remove options that don't meet requirements + for (let i = options.length - 1; i > -1; i--) { + const index = options[i] + if (!(tech.tech[index].count < tech.tech[index].maxCount) || !tech.tech[index].allowed()) { + options.splice(i, 1); + } + } + //pick one option + if (options.length) { + const index = options[Math.floor(Math.random() * options.length)] + simulation.makeTextLog(`tech.giveTech("${tech.tech[index].name}") //optical amplifier`); + tech.giveTech(index) + } + } + }, + remove() { + tech.isStuckOn = false + } + }, { name: "laser diode", description: "all lasers drain 30% less energy
affects laser-gun, laser-bot, laser-mines, pulse", @@ -5844,9 +5884,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.17 + return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.17 && !tech.isStuckOn }, - requires: "laser gun, not specular reflection, diffuse, free-electron laser", + requires: "laser gun, not specular reflection, diffuse, free-electron laser, optical amplifier", effect() { tech.isPulseLaser = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun @@ -8147,7 +8187,7 @@ const tech = { allowed() { return true }, requires: "", effect() { - window.open('https://www.youtube.com/results?search_query=music', '_blank') + window.open('https://www.youtube.com/watch?v=lEbHeSdmS-k&list=PL9Z5wjoBiPKEDhwCW2RN-VZoCpmhIojdn', '_blank') }, remove() {} }, diff --git a/todo.txt b/todo.txt index 882ccd1..f7fbd6e 100644 --- a/todo.txt +++ b/todo.txt @@ -1,26 +1,45 @@ ******************************************************** NEXT PATCH ************************************************** +new map reservoir - still in development, but putting it out for feedback + +tech: optical amplifier - get 3 random laser tech, but you can't turn off your laser until you run out of energy + +slow light - lasers are slightly closer together at higher stacks of this tech +research power ups no longer log to the "in game console" to prevent spam +dynamo-bots give 6->7 more energy (upgraded 20->23) +some Boss invulnerability times are very slightly shorter +music tech now links to actual n-gon music + https://www.youtube.com/watch?v=lEbHeSdmS-k&list=PL9Z5wjoBiPKEDhwCW2RN-VZoCpmhIojdn ******************************************************** TODO ******************************************************** -set damage reduction equal to how much mana you have below 95 - override all other harm reduction effects? +reversed version of reservoir level, start at top and press buttons to lower slime -make shields not able to get radioactive +tech immune to harm after mob kill + require no other mob kill tech? + cloaking field tech? + +final boss invulnerability + until mobs are cleared? + in between phases + for all of one phase + +JUNK tech - do something to the mob display health method + +new platform element, spring + toggle to on when player touches platform + platform extends in any direction + +start toggled elevators in the high or middle state, not low wormhole tech - pause while placing the wormhole -tech requires cache - ammo automatically regenerates every second, ammo is capped even lower -new level climb - 3 vertical climb sections - use vanish elements - -ruins: mobs can see you too easily at the start +tech - set damage reduction equal to how much mana you have below 95 + override all other harm reduction effects? vanish element: grow as it returns? - option to shrink in vertical pull bullets back to player with crouch/field bullets type?: drones, spores, missiles, @@ -37,6 +56,9 @@ training reset progress to zero if you clear all training levels maybe only save progress if you made if past the trainingHeal level make the training button more obvious if the account has only played 1-2 times + larger? + position? + animated text? uses the lore voice/text code? replace all mob clear triggers with button triggers? tutorial rooms: