From 1fde74d65aa518a331c3d33758a9380228f0db34 Mon Sep 17 00:00:00 2001 From: landgreen Date: Tue, 12 Nov 2024 20:16:17 -0800 Subject: [PATCH] substructure new level substructure featured element - motion triggered lasers futures exchange 5->6% duplication per cancel plasma torch coupling 0.015->0.025x damage per coupling Gibbs free energy 1.005->1.006x damage per missing energy compound lens arc adds 25->30 degrees instability 2->2.5x damage when damage taken is 1x constraint: after 30->40 seconds spawn WIMPs constraint: 0.1->0.3x damage after getting power ups renamed holographic principle -> charmed baryons updates to community map: downpour updated lasers in labs and testChamber to the new more realistic laser bugs returning to the old console.log system from last patch I rather read bugs in the browser console not the n-gon console bots properly follow player when level flips vertically community map: arena's sword is properly removed at end of level rewrote shaped charge to be better at protecting you from all explosions pause correctly lists both mobs types for the level for quasiparticles "boost" replaces ammo in more edge cases bug with removing surfactant setting b.activeGun false and crashing game with checking active gun not sure if this is fixed or not? --- ...aryons.webp => holographic principle.webp} | Bin js/bullet.js | 27 +- js/index.js | 6 +- js/level.js | 1215 +++++++++++++---- js/player.js | 3 +- js/powerup.js | 9 +- js/simulation.js | 297 ++-- js/spawn.js | 5 +- js/tech.js | 63 +- todo.txt | 105 +- 10 files changed, 1254 insertions(+), 476 deletions(-) rename img/{charmed baryons.webp => holographic principle.webp} (100%) diff --git a/img/charmed baryons.webp b/img/holographic principle.webp similarity index 100% rename from img/charmed baryons.webp rename to img/holographic principle.webp diff --git a/js/bullet.js b/js/bullet.js index 93f4e75..188deef 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -23,7 +23,7 @@ const b = { }, fire() { }, fireNormal() { - if (b.inventory.length && b.activeGun !== null) { + if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) { if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire)) { if (b.guns[b.activeGun].ammo > 0) { b.fireWithAmmo() @@ -36,7 +36,7 @@ const b = { } }, fireNotMove() { //added && player.speed < 0.5 && m.onGround - if (b.inventory.length && b.activeGun !== null) { + if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) { if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire) && player.speed < 2.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) { if (b.guns[b.activeGun].ammo > 0) { b.fireWithAmmo() @@ -49,7 +49,7 @@ const b = { } }, fireAlwaysFire() { //added && player.speed < 0.5 && m.onGround //removed input.fire && (!input.field || m.fieldFire) - if (b.inventory.length && b.activeGun !== null) { + if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) { if (m.fireCDcycle < m.cycle && player.speed < 0.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) { if (b.guns[b.activeGun].ammo > 0) { b.fireWithAmmo() @@ -60,7 +60,7 @@ const b = { } }, fireFloat() { //added && player.speed < 0.5 && m.onGround - if (b.inventory.length && b.activeGun !== null) { + if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) { if (input.fire && (!input.field || m.fieldFire)) { if (m.fireCDcycle < m.cycle) { if (b.guns[b.activeGun].ammo > 0) { @@ -116,7 +116,7 @@ const b = { } }, refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to - if (tech.crouchAmmoCount && m.crouch && b.activeGun !== null) { + if (tech.crouchAmmoCount && m.crouch && (b.activeGun !== null && b.activeGun !== undefined)) { tech.crouchAmmoCount-- if ((tech.crouchAmmoCount) % 2) { b.guns[b.activeGun].ammo++; @@ -377,7 +377,7 @@ const b = { explosion(where, radius, color = "rgba(255,25,0,0.6)", reducedKnock = 1) { // typically explode is used for some bullets with .onEnd radius *= tech.explosiveRadius - let dist, sub, knock; + let knock; let dmg = radius * 0.019 if (tech.isExplosionHarm) radius *= 1.7 // 1/sqrt(2) radius -> area if (tech.isSmallExplosion) { @@ -385,10 +385,13 @@ const b = { radius *= 0.7 dmg *= 1.7 } + let sub = Vector.sub(where, player.position); + let dist = Vector.magnitude(sub); + if (tech.isSmartRadius && radius > dist - 50) radius = Math.max(dist - 50, 1) if (tech.isExplodeRadio) { //radiation explosion radius *= 1.25; //alert range - if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1) + // if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1) color = "rgba(25,139,170,0.25)" simulation.drawList.push({ //add dmg to draw queue x: where.x, @@ -425,7 +428,7 @@ const b = { } } } else { //normal explosions - if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1) + // if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1) simulation.drawList.push({ //add dmg to draw queue x: where.x, y: where.y, @@ -444,9 +447,6 @@ const b = { //player damage and knock back if (m.immuneCycle < m.cycle) { - sub = Vector.sub(where, player.position); - dist = Vector.magnitude(sub); - if (dist < radius) { if (simulation.dmgScale) { const harm = tech.isExplosionHarm ? 0.067 : 0.05 @@ -7716,10 +7716,7 @@ const b = { } else { m.fireCDcycle = m.cycle m.energy -= drain - const where = { - x: m.pos.x + 20 * Math.cos(m.angle), - y: m.pos.y + 20 * Math.sin(m.angle) - } + const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) } b.laser(where, { x: where.x + 3000 * Math.cos(m.angle), y: where.y + 3000 * Math.sin(m.angle) diff --git a/js/index.js b/js/index.js index 19ee488..c1d793b 100644 --- a/js/index.js +++ b/js/index.js @@ -13,7 +13,9 @@ Math.hash = s => { // document.getElementById("seed").placeholder = Math.initialSeed = Math.floor(Date.now() % 100000) //random every time: just the time in milliseconds UTC window.addEventListener('error', error => { - simulation.inGameConsole(`ERROR: ${error.message} ${error.filename}:${error.lineno}`) + // simulation.inGameConsole(`ERROR: ${error.message} ${error.filename}:${error.lineno}`) + simulation.inGameConsole(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); + }); document.getElementById("seed").placeholder = Math.initialSeed = String(Math.floor(Date.now() % 100000)) @@ -512,7 +514,7 @@ ${botText} mouse (${simulation.mouseInGame.x.toFixed(0)}, ${simulation.mouseInGame.y.toFixed(0)})
cycles ${m.cycle} velocity (${player.velocity.x.toFixed(2)}, ${player.velocity.y.toFixed(2)}) -
mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[0]}) +
mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[1]}) blocks ${body.length}
bullets ${bullet.length} power ups ${powerUp.length} diff --git a/js/level.js b/js/level.js index 1b71906..c72f1f0 100644 --- a/js/level.js +++ b/js/level.js @@ -8,8 +8,9 @@ const level = { defaultZoom: 1400, onLevel: -1, levelsCleared: 0, + isFlipped: false, uniqueLevels: ["initial", "reservoir", "factory", "interferometer", "reactor", "subway", "final"], //see level.populateLevels: (initial, ... , (reservoir, factory, or interferometer), reactor, ... , subway, final) added later - playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron"], + playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron", "substructure"], communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft", "flappyGon", "rings", "trial"], trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], levels: [], @@ -47,7 +48,7 @@ const level = { // requestAnimationFrame(() => { tech.giveTech("non-renewables") }); // tech.giveTech("dark matter") // tech.addJunkTechToPool(0.5) - // for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds") + // for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot") // for (let i = 0; i < 1; ++i) tech.giveTech("quantum immortality") // m.skin.egg(); @@ -59,7 +60,7 @@ const level = { // for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "warp"); // for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false); // spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing - // level.interferometer(); + // level.substructure(); level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** @@ -167,7 +168,7 @@ const level = { tech.tokamakHealCount = 0 tech.buffedGun++ if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0; - if (tech.isGunCycle && b.activeGun !== null && b.inventory.length) { + if (tech.isGunCycle && (b.activeGun !== null && b.activeGun !== undefined) && b.inventory.length) { b.inventoryGun = tech.buffedGun; simulation.switchGun(); } @@ -398,7 +399,7 @@ const level = { } }, { - description: "after 30 seconds spawn WIMPs", + description: "after 40 seconds spawn WIMPs", effect() { simulation.ephemera.push({ name: "WIMPS", @@ -407,7 +408,7 @@ const level = { do() { this.time++ if (level.levels[level.onLevel] === this.levelName) { - if (this.time > 1800 && !(this.time % 360)) spawn.WIMP(level.enter.x, level.enter.y) + if (this.time > 2400 && !(this.time % 420)) spawn.WIMP(level.enter.x, level.enter.y) } else { simulation.removeEphemera(this.name); } @@ -419,7 +420,7 @@ const level = { } }, { - description: "0.1x damage after getting power ups", + description: "0.3x damage after getting power ups", effect() { level.isNoDamage = true level.noDamageCycle = 0 @@ -2242,11 +2243,47 @@ const level = { ctx.setLineDash([50 + 200 * Math.random(), 50 * Math.random()]); ctx.stroke(); ctx.setLineDash([]); + }, + countDown: 0, + countTotal: 480, + countDelay: 440, + motionQuery() { + let best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null } + best = vertexCollision(this.position, this.look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, 3, 0, 2 * Math.PI); - // ctx.fillStyle = this.color;; - // ctx.fill(); + if (this.countDown === 0) { + if ((best.who === playerBody || best.who === playerHead)) this.countDown = this.countTotal // hitting player + ctx.strokeStyle = `rgba(255,255,255,0.4)`; + ctx.lineWidth = 8 + 3 * Math.sin(simulation.cycle * 0.3); + } else if (this.countDown > this.countDelay) { + ctx.strokeStyle = `rgba(255,255,255,0.8)`; + ctx.lineWidth = 11; + this.countDown-- + } else { + this.countDown-- + if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player + m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second + const dmg = damage * simulation.dmgScale; + m.damage(dmg); + simulation.drawList.push({ //add dmg to draw queue + x: best.x, + y: best.y, + radius: dmg * 1500, + color: "rgba(255,0,0,0.5)", + time: 20 + }); + } + ctx.strokeStyle = this.color; + ctx.lineWidth = 5; + ctx.setLineDash([50 + 200 * Math.random(), 50 * Math.random()]); + } + //draw + if (best.dist2 === Infinity) best = this.look; + ctx.beginPath(); + ctx.moveTo(this.position.x, this.position.y); + ctx.lineTo(best.x, best.y); + ctx.stroke(); + ctx.setLineDash([]); }, } }, @@ -4981,8 +5018,8 @@ const level = { towers() { // simulation.isHorizontalFlipped = true level.announceMobTypes() - const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false - if (isFlipped) { + const isFlippedHorizontal = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false + if (isFlippedHorizontal) { level.setPosToSpawn(9150 + 50, -2230 - 25); level.exit.x = 400 - 50; level.exit.y = -50 + 25; @@ -4997,7 +5034,7 @@ const level = { spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance level.fallMode = "position"; //must set level.fallModeBounds in this mode to prevent player getting stuck left or right level.fallModeBounds = { left: level.enter.x, right: level.exit.x } //used with level.fallMode = "position"; - if (isFlipped) level.fallModeBounds = { left: level.exit.x, right: level.enter.x } //used with level.fallMode = "position"; + if (isFlippedHorizontal) level.fallModeBounds = { left: level.exit.x, right: level.enter.x } //used with level.fallMode = "position"; simulation.fallHeight = 5000 //level.enter.y - 4000 spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit level.defaultZoom = 2300 @@ -5075,7 +5112,7 @@ const level = { portal2[3].query() ctx.fillStyle = "#cff" - if (isFlipped) { + if (isFlippedHorizontal) { ctx.fillRect(150, -300, 525, 325); //entrance typically } else { ctx.fillRect(8925, -2575, 525, 400) //exit typically @@ -5090,7 +5127,7 @@ const level = { ctx.fillRect(5400, 875, 1800, 650); ctx.fillRect(2950, -2200, 875, 1050); ctx.fillRect(5900, -1025, 800, 450); - if (isFlipped) { + if (isFlippedHorizontal) { ctx.fillRect(8925, -2575, 575, 400) //exit typically } else { ctx.fillRect(150, -300, 525, 325); //entrance typically @@ -5139,7 +5176,7 @@ const level = { spawn.mapVertex(6856, -1425, "300 -90 -350 -90 -400 -40 -400 40 -350 90 300 90"); //exit housing spawn.mapRect(8925, -2575, 575, 75); - if (isFlipped) { + if (isFlippedHorizontal) { spawn.mapRect(8925, -2550, 75, 400); spawn.mapRect(9425, -2550, 75, 125); spawn.mapRect(9425, -2215, 75, 50); @@ -5558,24 +5595,29 @@ const level = { let hazard1 if (Math.random() > 0.5) { spawn.mapRect(x + 550, y - 750, 1500, 50); //entrance shelf - hazard1 = level.hazard(x + 850, y - 920, 600, 10, 0.4) //laser + // hazard1 = level.hazard(x + 850, y - 920, 600, 10, 0.4) //laser + hazard1 = level.laser({ x: x + 870, y: y - 915 }, { x: x + 1450, y: y - 915 }) spawn.mapRect(x + 860, y - 925, 10, 20); //laser nose spawn.mapRect(x + 660, y - 975, 200, 120); //laser body } else { spawn.mapRect(x + 1350, y - 750, 700, 50); //entrance shelf - hazard1 = level.hazard(x + 1040, y - 660, 1000, 10, 0.4) //laser + // hazard1 = level.hazard(x + 1040, y - 660, 1000, 10, 0.4) //laser + hazard1 = level.laser({ x: x + 1060, y: y - 655 }, { x: x + 2000, y: y - 655 }) spawn.mapRect(x + 1050, y - 665, 10, 20); //laser nose spawn.mapRect(x + 650, y - 705, 400, 100); //laser body } - const hazard2 = level.hazard(x, y - 330, 450, 10, 0.4) //laser + // const hazard2 = level.hazard(x, y - 330, 450, 10, 0.4) //laser + const hazard2 = level.laser({ x: x + 5, y: y - 325 }, { x: x + 455, y: y - 325 }) spawn.mapRect(x + 440, y - 335, 10, 20); //laser nose spawn.mapRect(x + 450, y - 375, 400, 100); //laser body - //exit hazards const Xoffset = Math.floor(400 * Math.random()) - const hazard3 = level.hazard(x + Xoffset, y - 1300, 10, 1300, 0.4) //laser + //level.hazard(x + Xoffset, y - 1300, 10, 1300, 0.4) //laser + const hazard3 = level.laser({ x: x + Xoffset + 5, y: y - 1290 }, { x: x + Xoffset + 5, y: y }) spawn.mapRect(x + Xoffset - 5, y - 1310, 20, 20); //laser nose const Xoffset2 = 1650 + Math.floor(300 * Math.random()) - const hazard4 = level.hazard(x + Xoffset2, y - 240, 10, 250, 0.4) //laser + // const hazard4 = level.hazard(x + Xoffset2, y - 240, 10, 250, 0.4) //laser + hazard4 = level.laser({ x: x + Xoffset2 + 5, y: y - 230 }, { x: x + Xoffset2 + 5, y: y - 230 + 250 }) + spawn.mapRect(x + Xoffset2 - 5, y - 250, 20, 20); //laser nose spawn.randomMob(x + 150, y + -1100, mobSpawnChance); spawn.randomMob(x + 175, y + -775, mobSpawnChance); @@ -5587,26 +5629,15 @@ const level = { doCustomTopLayer.push( () => { toggle.query(); - hazard1.isOn = toggle.isOn - hazard2.isOn = toggle.isOn - hazard3.isOn = toggle.isOn - hazard4.isOn = toggle.isOn - if ((simulation.cycle % 120) > 60) { - hazard1.opticalQuery(); - hazard2.opticalQuery(); - } else { - hazard3.opticalQuery(); - hazard4.opticalQuery(); + if (toggle.isOn) { + if ((simulation.cycle % 120) > 60) { + hazard1.query(); + hazard2.query(); + } else { + hazard3.query(); + hazard4.query() + } } - // if (!isSpawnedMobs && !toggle.isOn) { - // isSpawnedMobs = true - // spawn.randomMob(x + 150, y + -1100, mobSpawnChance); - // spawn.randomMob(x + 175, y + -775, mobSpawnChance); - // spawn.randomMob(x + 150, y + -350, mobSpawnChance); - // spawn.randomMob(x + 150, y + -75, mobSpawnChance); - // spawn.randomMob(x + 650, y + -125, mobSpawnChance); - // spawn.randomMob(x + 1200, y + -75, mobSpawnChance); - // } } ) }, @@ -6072,14 +6103,14 @@ const level = { spawn.mapRect(x + 550, y + -10 - 640, 900, 25); //raised floor spawn.mapRect(x + 450, y + -20 - 640, 1100, 25); spawn.mapRect(x + 450, y + -675 - 640, 1100, 25); //chamber ceiling - powerUps.directSpawn(x + 998, y - 333 - 640, "tech", false); + powerUps.spawn(x + 998, y - 333 - 640, "tech", false); spawn.mapVertex(x + 1000, y + -0, "575 0 -575 0 -450 -100 450 -100"); //base } else { //lower chamber spawn.mapRect(x + 400, y + -10, 1200, 50); //raised floor spawn.mapRect(x + 450, y + -20, 1100, 50); spawn.mapRect(x + 450, y + -675, 1100, 25); //chamber ceiling spawn.mapRect(x + 550, y + -685, 900, 25); - powerUps.directSpawn(x + 998, y - 333, "tech", false); + powerUps.spawn(x + 998, y - 333, "tech", false); } const powerUp1 = powerUp[powerUp.length - 1] if (powerUp1) powerUp1.holdPosition = { x: powerUp1.position.x, y: powerUp1.position.y } @@ -6319,9 +6350,9 @@ const level = { for (let i = 0, numberOfMapElementsAdded = map.length - mapStartingLength; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i]) simulation.draw.setPaths() //update map graphics //mobs go here - powerUps.directSpawn(x + 50, y - 1525, "ammo"); - powerUps.directSpawn(x + 1950, y - 1525, "ammo"); - powerUps.directSpawn(x + 1900, y - 1525, "ammo"); + powerUps.spawn(x + 50, y - 1525, "ammo"); + powerUps.spawn(x + 1950, y - 1525, "ammo"); + powerUps.spawn(x + 1900, y - 1525, "ammo"); spawn.hopMotherBoss(x + 800, y + -2200) for (let i = 0; i < 4; ++i) spawn.hopBullet(x + 150 + 750 * Math.random(), y + -1600) for (let i = 0; i < 4; ++i) spawn.hopBullet(x + 1100 + 750 * Math.random(), y + -1600) @@ -6813,9 +6844,19 @@ const level = { spawn.mapRect(1225, -1955, 175, 30); const removeIndex2 = map.length - 1 //so much work to catch blocks caught at the bottom of the vertical portals let portal, portal2, portal3 - const hazard = level.hazard((simulation.isHorizontalFlipped ? -350 - 700 : 350), -2025, 700, 10, 0.4) //laser + // const hazard = level.hazard((simulation.isHorizontalFlipped ? -350 - 700 : 350), -2025, 700, 10, 0.4) //laser + // const hazard2 = level.hazard((simulation.isHorizontalFlipped ? -1775 - 150 : 1775), -2550, 150, 10, 0.4) //laser + // const hazard = level.laser({ x: (simulation.isHorizontalFlipped ? -350 - 700 : 350), y: -2025 }, { x: 700 + (simulation.isHorizontalFlipped ? -350 - 700 : 350), y: -2025 }) ////x, y, width, height, damage = 0.002) + // const hazard2 = level.laser({ x: 145 + (simulation.isHorizontalFlipped ? -1775 - 150 : 1775), y: -2545 }, { x: (simulation.isHorizontalFlipped ? -1775 - 150 : 1775), y: -2545 }) ////x, y, width, height, damage = 0.002) + let hazard, hazard2 + if (simulation.isHorizontalFlipped) { + hazard = level.laser({ x: -360, y: -2020 }, { x: -1050, y: -2020 }) ////x, y, width, height, damage = 0.002) + hazard2 = level.laser({ x: - 1920, y: -2545 }, { x: -1775, y: -2545 }) ////x, y, width, height, damage = 0.002) + } else { + hazard = level.laser({ x: 360, y: -2020 }, { x: 700 + 360, y: -2020 }) ////x, y, width, height, damage = 0.002) + hazard2 = level.laser({ x: 145 + 1775, y: -2545 }, { x: 1775, y: -2545 }) ////x, y, width, height, damage = 0.002) + } spawn.mapRect(340, -2032.5, 20, 25); //laser nose - const hazard2 = level.hazard((simulation.isHorizontalFlipped ? -1775 - 150 : 1775), -2550, 150, 10, 0.4) //laser spawn.mapRect(1920, -2557.5, 20, 25); //laser nose const button = level.button(2100, -2600) const buttonDoor = level.button(600, -550) @@ -6860,14 +6901,6 @@ const level = { portal2[3].query() portal3[2].query() portal3[3].query() - - if (button.isUp) { - hazard.isOn = false; - hazard2.isOn = false; - } else { - hazard.isOn = true; - hazard2.isOn = true; - } button.query(); button.draw(); @@ -6879,8 +6912,11 @@ const level = { }; level.customTopLayer = () => { door.draw(); - hazard.opticalQuery(); - hazard2.opticalQuery(); + if (!button.isUp) { + hazard.query(); + hazard2.query(); + } + portal[0].draw(); portal[1].draw(); portal[2].draw(); @@ -7072,7 +7108,7 @@ const level = { let buttons = [] let lasers = [] let balance = [] - let isFlipped = false; + level.isFlipped = false; let isFlipping = false; let isSpawned = false const flipAnimationCycles = 120 @@ -7099,7 +7135,7 @@ const level = { move() { this.force.y -= this.mass * simulation.g; //undo gravity if (!m.isBodiesAsleep) { - if (isFlipped) { + if (level.isFlipped) { ctx.fillStyle = "#ccc" ctx.fillRect(this.holdX, -this.maxHeight, 5, this.maxHeight - this.minHeight) //draw path @@ -7400,9 +7436,9 @@ const level = { buttons[i].queryPlayer(); if (!buttons[i].isUp) { isFlipping = true - if (isFlipped) { + if (level.isFlipped) { const normalMap = function () { - isFlipped = false + level.isFlipped = false flipAndRemove() buildMapOutline() buildNormalMap(); //rewrite flipped version of map @@ -7412,7 +7448,7 @@ const level = { simulation.unFlipCameraVertical(flipAnimationCycles, normalMap) } else { const flipMap = function () { - isFlipped = true + level.isFlipped = true flipAndRemove() buildMapOutline() buildVerticalFLippedMap(); //rewrite flipped version of map @@ -7446,7 +7482,7 @@ const level = { } } - if (isFlipped) { + if (level.isFlipped) { //background structure ctx.fillStyle = "#c3c7c7" ctx.fillRect(1487, -75 - 1925, 25, 1925); @@ -7503,7 +7539,7 @@ const level = { } ctx.fill(); ctx.fillStyle = `rgba(255,255,255,${0 + 0.3 * Math.random()})` - if (isFlipped) { + if (level.isFlipped) { ctx.fillRect(-2025, 2025 - 450, 400, 450); //shadows ctx.fillStyle = "rgba(0,0,0,0.08)" @@ -7598,7 +7634,7 @@ const level = { color.map = "#444" let buttons = [] - let isFlipped = false; + level.isFlipped = false; let isFlipping = false; const flipAnimationCycles = 60 @@ -7732,7 +7768,7 @@ const level = { spawn.mapRect(3750, -210, 100, 25); } let flipAndRemove = function () { - simulation.translatePlayerAndCamera({ x: player.position.x, y: -player.position.y }) + level.enter.y = -level.enter.y level.exit.y = -level.exit.y for (let i = body.length - 1; i > -1; i--) { @@ -7747,6 +7783,7 @@ const level = { removeAll(buttons); buttons = [] + simulation.translatePlayerAndCamera({ x: player.position.x, y: -player.position.y }, false) function invertVertical(array) { for (let i = 0; i < array.length; ++i) { Matter.Body.setPosition(array[i], { x: array[i].position.x, y: -array[i].position.y }) @@ -7756,6 +7793,7 @@ const level = { invertVertical(powerUp); invertVertical(bullet); invertVertical(mob); + //fields if (m.fieldMode === 9 && m.hole.isOn) { m.hole.pos1.y *= -1 @@ -7831,9 +7869,9 @@ const level = { buttons[i].queryPlayer(); if (!buttons[i].isUp) { isFlipping = true - if (isFlipped) { + if (level.isFlipped) { const normalMap = function () { - isFlipped = false + level.isFlipped = false flipAndRemove() buildMapOutline() buildNormalMap(); //rewrite flipped version of map @@ -7843,7 +7881,7 @@ const level = { simulation.unFlipCameraVertical(flipAnimationCycles, normalMap) } else { const flipMap = function () { - isFlipped = true + level.isFlipped = true flipAndRemove() buildMapOutline() buildVerticalFLippedMap(); //rewrite flipped version of map @@ -7858,7 +7896,7 @@ const level = { } ctx.fillStyle = "#d4f4f4" ctx.fillRect(3575, -300, 475, 575); - if (isFlipped) { + if (level.isFlipped) { //draw flipped entrance ctx.beginPath(); ctx.moveTo(level.enter.x, level.enter.y - 30); @@ -7929,6 +7967,196 @@ const level = { spawn.secondaryBossChance(2675, -125) powerUps.addResearchToLevel() //needs to run after mobs are spawned }, + substructure() { + // simulation.fallHeight = 4000 + level.announceMobTypes() + level.setPosToSpawn(-3800, -750); + level.exit.x = 3750 + level.exit.y = -625 + level.defaultZoom = 2000 + simulation.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#d0d5d5"; + color.map = "#444" + + const boost1 = level.boost(-2225, 1000, 1750) + const boost2 = level.boost(3400, 1000, 1750) + + const lasers = [] + const center = { x: 2800, y: 300 } + map[map.length] = Matter.Bodies.polygon(center.x, center.y, 20, 100) //center circle with lasers + lasers.push(level.laser({ x: center.x, y: center.y }, { x: center.x, y: center.y })) //oscillating laser + lasers[lasers.length - 1].oscillate = function () { + const angle = Math.PI / 2 - 1.55 * Math.sin(0.02 * simulation.cycle) //oscillate around circle + this.position = { + x: center.x + 102 * Math.cos(angle), + y: center.y + 102 * Math.sin(angle) + } + this.look = { + x: center.x + 2000 * Math.cos(angle), + y: center.y + 2000 * Math.sin(angle) + } + } + lasers.push(level.laser({ x: center.x, y: center.y }, { x: center.x, y: center.y })) //oscillating laser + lasers[lasers.length - 1].oscillate = function () { + const angle = -Math.PI / 2 + 1.55 * Math.sin(0.02 * simulation.cycle) //oscillate around circle + this.position = { + x: center.x + 102 * Math.cos(angle), + y: center.y + 102 * Math.sin(angle) + } + this.look = { + x: center.x + 2000 * Math.cos(angle), + y: center.y + 2000 * Math.sin(angle) + } + } + + lasers.push(level.laser({ x: -1500, y: -963 }, { x: -1500, y: 0 })) //oscillating laser + lasers[lasers.length - 1].oscillate = function () { + // if (this.countDown === 0) {} + const angle = Math.PI / 2 + 0.6 * Math.sin(simulation.cycle * 0.02) //oscillate around down + this.look = { + x: this.position.x + 600 * Math.cos(angle), + y: this.position.y + 600 * Math.sin(angle) + } + } + + lasers.push(level.laser({ x: 600, y: 580 }, { x: 600, y: 1000 })) //scrolling laser + lasers[lasers.length - 1].oscillate = function () { + this.position.x = 600 + 200 * Math.sin(simulation.cycle * 0.03) + this.look.x = 600 + 400 * Math.sin(simulation.cycle * 0.03) + } + + lasers.push(level.laser({ x: -115, y: -853 }, { x: 600, y: -50 })) + if (Math.random() < 0.33) { + lasers[lasers.length - 1].oscillate = function () { this.look.x = 300 + Math.abs(600 * Math.sin(simulation.cycle * 0.017)) } + } else if (Math.random() < 0.5) { + lasers[lasers.length - 1].oscillate = function () { this.look.x = 600 + 300 * Math.sin(simulation.cycle * 0.017) } + } else { + lasers[lasers.length - 1].oscillate = function () { this.look.x = 300 + (4 * simulation.cycle % 600) } + } + lasers.push(level.laser({ x: 2375, y: -876 }, { x: 2375, y: -300 })) //exit top + lasers[lasers.length - 1].oscillate = function () { + const angle = 1.4 + 1.15 * Math.sin(simulation.cycle * 0.021) //oscillate around down + this.look = { + x: this.position.x + 2000 * Math.cos(angle), + y: this.position.y + 2000 * Math.sin(angle) + } + } + lasers.push(level.laser({ x: 2375, y: -876 }, { x: 2375, y: -876 })) //exit top + lasers[lasers.length - 1].oscillate = function () { + const angle = 1.4 + 1.15 * Math.cos(simulation.cycle * 0.021) //oscillate around down + this.look = { + x: this.position.x + 2000 * Math.cos(angle), + y: this.position.y + 2000 * Math.sin(angle) + } + } + + lasers.push(level.laser({ x: -3565, y: -915 }, { x: -3565, y: -710 })) //entrance door + lasers.push(level.laser({ x: 3535, y: -915 }, { x: 3535, y: -575 })) //exit door + + if (Math.random() < 0.33) { + lasers.push(level.laser({ x: -400, y: -713 }, { x: -400, y: -295 })) //pillar top + } else if (Math.random() < 0.5) { + lasers.push(level.laser({ x: -400, y: -250 }, { x: -400, y: 200 })) //pillar mid + } else { + lasers.push(level.laser({ x: -400, y: 250 }, { x: -400, y: 750 })) //pillar low + } + + level.custom = () => { + boost1.query(); + boost2.query(); + + ctx.fillStyle = "#cacfcf" + ctx.fillRect(2787, -425, 25, 800); + ctx.fillRect(-600, -1050, 400, 1800); + + level.exit.drawAndCheck(); + level.enter.draw(); + }; + level.customTopLayer = () => { + ctx.fillStyle = "rgba(0,255,255,0.1)" //"#d4f4f4" //exit + ctx.fillRect(3535, -1050, 500, 475); + + //shadows + ctx.fillStyle = "rgba(0,20,60,0.09)" + ctx.fillRect(-4025, -1050, 1750, 2275); + ctx.fillRect(-2025, -1050, 1050, 2175); + ctx.fillRect(200, 0, 800, 975); + ctx.fillRect(1400, -150, 650, 1175); + ctx.fillRect(2200, -425, 1175, 1475); + + //rotate angle of lasers + for (let i = 0; i < 7; i++) lasers[i].oscillate() + for (let i = 0; i < lasers.length; i++) { + lasers[i].motionQuery() + } + }; + //boxes center on zero,zero with deep walls to hide background + spawn.mapRect(4000, -2000, 2000, 4000); //right map wall + spawn.mapRect(-6000, -2000, 2000, 4000); //left map wall + spawn.mapRect(-6000, -4000, 12000, 3000); //map ceiling + spawn.mapRect(-6000, 1000, 12000, 3000); //floor + //entrance + spawn.mapRect(-4000, -710, 450, 1800); + spawn.mapVertex(-3565, -1013, "-140 0 -8 150 8 150 140 0"); //entrance door + spawn.mapVertex(-3975, -975, "0 0 100 0 0 100"); //triangle at corner + spawn.mapVertex(-2900, 268, "-650 0 0 -40 650 0 650 2000 -650 2000 "); //angled floating structure + spawn.mapVertex(-2900, -990, "-600 0 0 40 600 0"); //wide ceiling triangle + //pillar 1 + spawn.mapVertex(-1500, -350, "-550 0 0 -40 550 0 550 350 0 390 -550 350 "); + spawn.mapVertex(-1500, 535, "-550 0 0 -40 550 0 550 500 0 540 -550 500 "); + spawn.mapVertex(-1500, -990, "-600 0 0 40 600 0"); + spawn.mapVertex(-1500, 990, "-550 0 0 -40 550 0 550 20 -550 20"); + //pillar 2 + spawn.mapVertex(-400, -875, "225 0 -225 0 -350 -300 350 -300"); + spawn.mapRect(-600, 200, 400, 50); + spawn.mapRect(-600, -300, 400, 50); + spawn.mapVertex(-400, 900, "350 0 -350 0 -225 -300 225 -300"); + //pillar 3 + spawn.mapVertex(600, 1000, "575 0 -575 0 -450 -100 450 -100"); + spawn.mapVertex(600, 500, "325 0 250 80 -250 80 -325 0 -250 -80 250 -80"); + spawn.mapRect(175, 450, 850, 100); + spawn.mapVertex(600, 0, "425 -20 425 20 390 50 -390 50 -425 20 -425 -20 -390 -50 390 -50"); + //far right building + spawn.mapRect(1600, 990, 450, 100); + spawn.mapRect(2200, 990, 1175, 100); + spawn.mapVertex(1500, 1015, "200 0 -200 0 -100 -100 100 -100"); + spawn.mapVertex(1500, 200, "-100 100 0 0 100 0 100 1000 -100 1000"); //left wall + spawn.mapRect(1550, -300, 500, 200); + spawn.mapVertex(2303.5, -350, "-100 100 0 0 100 0 100 500 -100 500"); //left wall + spawn.mapRect(2350, -600, 1025, 200); + spawn.mapVertex(2375, -975, "-140 0 -8 150 8 150 140 0"); //laser mount + //exit + spawn.mapRect(3525, -600, 550, 1675); + spawn.mapRect(3750, -610, 100, 50); + spawn.mapVertex(3535, -1013, "-140 0 -8 150 8 150 140 0"); //entrance door + spawn.mapVertex(3975, -990, "0 0 100 0 100 100"); //triangle at corner + + spawn.randomMob(-1150, 900, 0.1); + spawn.randomMob(675, 750, 0.1); + spawn.randomMob(3100, 875, 0.2); + spawn.randomMob(2975, -775, 0.2); + spawn.randomMob(1675, -550, 0.3); + spawn.randomMob(700, -300, 0.3); + spawn.randomMob(-325, -425, 0.4); + spawn.randomMob(-1375, -675, 0.4); + spawn.randomMob(-1425, 100, 0.5); + spawn.randomMob(-500, 75, 0.6); + spawn.randomMob(625, 250, 0.7); + spawn.randomMob(2125, 375, 0.7); + spawn.randomMob(-500, 600, 0.8); + spawn.randomMob(-1950, 875, 0.8); + spawn.randomMob(800, -400, 0.9); + spawn.randomMob(1675, -600, 0.9); + spawn.randomMob(2825, 75, 0.9); + spawn.randomLevelBoss(2400, 600); + spawn.secondaryBossChance(800, -300) + powerUps.spawnStartingPowerUps(600, 375); + powerUps.addResearchToLevel() //needs to run after mobs are spawned + powerUps.directSpawn(2825, 175, "heal"); + powerUps.directSpawn(2475, -650, "heal"); + powerUps.directSpawn(2100, 925, "heal"); + powerUps.directSpawn(625, -100, "heal"); + }, lock() { level.announceMobTypes() level.setPosToSpawn(0, -65); //lower start @@ -21613,74 +21841,296 @@ const level = { }, downpour() { simulation.inGameConsole(`Downpour by DesBoot`); - let mobsspawned = 0 - const laser = level.hazard(7492, -2612, 10, 500, 0.3) //laserintro - //5381, -3268, 10, 0.4 + /* NEW CHANGES: + Added lights in the buildings + activate when lever is flicked + Changed lightning: + now has a chance to strike twice in a row + Small map changes + Slight rework of the start + Added sounds: + thunder + buzz from lights + */ + + + //BUILD EVERYTHING + const laser = level.hazard(7492, -2612, 10, 500, 0.3) //laserintro spawn.mapRect(340, -2032.5, 20, 25); //laser nose //laserintro const laserbutton = level.button(5485, -2510) const doorbutton = level.button(7618, -3204) const doortoggle = level.toggle(5088.4, 1226.7) + const mutetoggle = level.toggle(100, 0) const door = level.door(6500, -1200, 100, 350, 100) const bunkerdoor = level.door(10700, -2500, 100, 500, 200) - const boost1 = level.boost(7300, 1209, 2200) const boost2 = level.boost(6232.6, -832.8, 1400) const portal = level.portal({ x: 4886.4, y: 1050.7 }, 2 * Math.PI, { x: 7686, y: -2121 }, 2 * Math.PI) - //let portal const slime = level.hazard(-1800, 10, 4200, 400); const slime2 = level.hazard(2400, -2100, 200, 2100); const slime3 = level.hazard(2600, -2100, 3600, 200); const slime4 = level.hazard(6400, -2100, 3600, 200); + const slime5 = level.hazard(-2000, 10, 200, 3000); + const drip1 = level.drip(1750, -700, 0, 70) + const oldOnLevel = level.levelsCleared; + + let whereToDrip = Math.random() * 2; + + const mainDropRange = (min, max) => Math.random() * (max - min) + min + const amount = Math.round(15 + 20 * Math.random()) + const drips = [] + for (let i = 0; i < amount; i++) { + if (whereToDrip < 1.25) { + const locX = mainDropRange(3800, 6000)//2200, 2300 + drips.push(level.drip(locX, -1700, -800, 200 + Math.random() * 500)) + } else { + const locX = mainDropRange(4900, 7100)//2200, 2300 + drips.push(level.drip(locX, 200, 1200, 200 + Math.random() * 500)) + } + whereToDrip = Math.random() * 2; + } + + + //ADD MORE + + // simulation.enableConstructMode() + //LEVEL SETUP AND VARIABLES level.setPosToSpawn(0, -50); //normal spawn level.exit.x = 13130.3; - let rainCount = 1 level.exit.y = -370; - spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance - spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit level.defaultZoom = 1800 + let rainCount = 1 + let hasDoubleFlashed = false; + let lightningTime = 0; + let canBePushed = false; + let rainXtemp1 = 0; + let rainXtemp2 = 0; let stopcycle = 0 let flashcycle = Math.round(Math.random() * 25 + 260) + let mobsspawned = 0 + let distanceToLight1 = 0; + let distanceToLight2 = 0; + let customExitTimer = 0; + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit simulation.zoomTransition(level.defaultZoom) document.body.style.backgroundColor = "#2e416e";//d8dadf // color.map = "#444" //custom map color + + //SOUNDS + let thunder1 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/thunder1.mp3?raw=true'); + let chemicalLove = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/Chemical%20Love%20thunder.mp3?raw=true'); + chemicalLove.play(); + let thunder2 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/thunder2.mp3?raw=true'); + let thunder3 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/thunder3.wav?raw=true'); + let thunder4 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/thunder4.wav?raw=true'); + let ambiance1 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/buzz%20(1).wav?raw=true'); + let rain1 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/light-rain-109591.mp3?raw=true'); + let rain3 = new Audio('https://github.com/des-boot/n-gon-downpour-sound-effects/blob/main/8mb.video-ggm-Jd62jXAH.m4a?raw=true'); + rain1.volume = 0.125; + rain3.volume = 0.125; + thunder1.volume = 0.25; + thunder2.volume = 0.25; + thunder3.volume = 0.25; + thunder4.volume = 0.25; + + + + //simulation.inGameConsole(stopcycle) level.custom = () => { + for (const drip of drips) drip.draw() + drip1.draw(); + // drip1.x = Math.random() * 500 + 1630 + // if (false) { + // rain1.pause(); + // rain2.pause(); + // rain3.pause(); + // thunder1.pause(); + // thunder2.pause(); + // thunder3.pause(); + // thunder4.pause(); + // ambiance1.pause(); + // } + + ctx.fillStyle = "rgba(0,0,0,0.5)" + ctx.beginPath() + ctx.moveTo(10800, -2400)//slope of -1/3 + ctx.lineTo(10800, -340) + ctx.lineTo(12980, -340) + ctx.lineTo(12980, -700) + ctx.lineTo(13465, -700) + ctx.lineTo(13541, -1737) + ctx.lineTo(11864.6, -1967.0) + ctx.lineTo(11003, -2400) + ctx.fill() + ctx.fillRect(6100, -2000, 400, 50) + // do { + if (simulation.paused) { + rain1.pause(); + // rain2.pause(); + rain3.pause(); + thunder1.pause(); + thunder2.pause(); + thunder3.pause(); + thunder4.pause(); + } else { + // if (!mutetoggle.isOn) + rain3.play(); + if (player.position.x > 3100 && player.position.y > -1700) { + rain1.pause(); + // rain2.pause(); + rain3.volume = 0.025; + } else { + if (player.position.x > 2600 && player.position.x < 3200) { + rain1.volume = (3200 - player.position.x) / 4000 + // rain2.volume = (3100 - player.position.x) / 2000 + rain3.volume = (3200 - player.position.x) / 4000 + } + if (player.position.y > -2000 && player.position.y < -1700) { + // rain1.volume = -1 * (1700 + player.position.y) / 3000 + rain1.volume = (-3 * player.position.y) / 68000 - 0.05 + // rain2.volume = (3100 - player.position.x) / 2000 + rain3.volume = -1 * (1700 + player.position.y) / 3000 + } + // if (!mutetoggle.isOn) + rain1.play(); + // rain2.play(); + } + } + distanceToLight1 = Math.sqrt((player.position.x - 6300) * (player.position.x - 6300) + (player.position.y - 212) * (player.position.y - 212)) + distanceToLight2 = Math.sqrt((player.position.x - 4877) * (player.position.x - 4877) + (player.position.y + 1690) * (player.position.y + 1690)) + + if (doortoggle.isOn) { + if (simulation.paused) { //is it paused + ambiance1.pause(); + } else { + if (distanceToLight1 < 2000 || distanceToLight2 < 2000) { // is M close enough + // if (!mutetoggle.isOn) + ambiance1.play(); + if (distanceToLight2 < distanceToLight1) { // check for distance and set volume + ambiance1.volume = (1 - ((distanceToLight2) / 2000)) + } else { + ambiance1.volume = (1 - ((distanceToLight1) / 2000)) + + } + } else { + ambiance1.pause(); + } + } + + + } + + if (mutetoggle.isOn) { + // simulation.inGameConsole(isMuted) + muteAll(); + + } else { + // simulation.inGameConsole(isMuted) + rain1.muted = false + ambiance1.muted = false + rain3.muted = false + thunder1.muted = false + thunder2.muted = false + thunder3.muted = false + thunder4.muted = false + + } + + //mute volumes + // rain1.volume = rain1.volume * ismuted; + // // simulation.inGameConsole(ismuted) + // ambiance1.volume = ambiance1.volume * ismuted; + // rain3.volume = rain3.volume * ismuted; + // thunder1.volume = thunder1.volume * ismuted; + // thunder2.volume = thunder2.volume * ismuted; + // thunder3.volume = thunder3.volume * ismuted; + // thunder4.volume = thunder4.volume * ismuted; do { + + + ctx.fillStyle = "rgba(242, 255, 0, 0.3})" + ctx.fillStyle = `rgba(242,255,0,${(Math.round(Math.random + 0.3)) / 3})` + ctx.fillStyle = "rgba(242,255,0,0.3)" + + if (doortoggle.isOn) { + ctx.beginPath() + ctx.moveTo(6325, 212) + ctx.lineTo(6325 - 75, 212) + ctx.lineTo((6325 - 75) - 338, 212 + 338) + ctx.lineTo(6325 + 10, 212 + 338) + ctx.lineTo(6325 + 29.97, 212 + 1018) + ctx.lineTo(6325 + 597.4443, 212 + 1018) //at an angle to the right platform + ctx.lineTo((6325 + 75) + 375, 212 + 763) + ctx.lineTo((6325 + 75) + 375, 212 + 688) + ctx.lineTo((6325 + 75) + 688, 212 + 688) + ctx.lineTo((6325 + 75) + 100, 212 + 100) + ctx.lineTo(6325 + 75, 212) + ctx.fill() + //4875, -1688 + ctx.beginPath() + ctx.moveTo(4875, -1688)//middle + ctx.lineTo(4875 - 75, -1688)//right side + ctx.lineTo((4875 - 75) - 638, -1688 + 638)//middle of left platform + ctx.lineTo((4875 - 75) - 638 + 150, -1688 + 638) + ctx.lineTo((4875 - 75) - 315, -1688 + 448) + ctx.lineTo(4875 + 75 + 135, -1688 + 445)//right side of right platofrm + ctx.lineTo(4875 + 75 + 135 + 445, -1688 + 445 + 445) + ctx.lineTo(5460, -880) + ctx.lineTo(4875 + 75 + 538, -1688 + 538) + ctx.lineTo(4875 + 75, -1688)//left side + ctx.fill() + } + + //rain + // if (!mutetoggle.isOn) { ctx.beginPath() ctx.fillStyle = "rgba(30,150,117,255)" - ctx.rect(Math.random() * 4500 - 2000, -5000, Math.random() * 3 + 2.5, 5000) - ctx.rect(Math.random() * 4500 - 2000, -5000, Math.random() * 3 + 2.5, 5000) - ctx.rect(Math.random() * 4500 - 2000, -5000, Math.random() * 3 + 2.5, 5000) - ctx.rect(Math.random() * 2000 + 2500, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 2000 + 2500, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1300 + 4500, -5000, Math.random() * 3 + 2.5, 2500) - ctx.rect(Math.random() * 1300 + 7500, -5000, Math.random() * 3 + 2.5, 1800) - ctx.rect(Math.random() * 1800 + 5700, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 5700, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 8400, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 8400, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 4500 - 2000, -5000, Math.random() * 3 + 2.5, 5000) - ctx.rect(Math.random() * 1800 + 10200, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 10200, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 12000, -5000, Math.random() * 3 + 2.5, 3000) - ctx.rect(Math.random() * 1800 + 12000, -5000, Math.random() * 3 + 2.5, 3000) + ctx.rect(Math.random() * 4500 - 2000, -5000, 3 + 2.5, 5030) + ctx.rect(Math.random() * 4500 - 2000, -5000, 3 + 2.5, 5030) + ctx.rect(Math.random() * 4500 - 2000, -5000, 3 + 2.5, 5030) + ctx.rect(Math.random() * 2000 + 2500, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 2000 + 2500, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 1300 + 4500, -5000, 3 + 2.5, 2500) + ctx.rect(Math.random() * 1300 + 7500, -5000, 3 + 2.5, 1800) + ctx.rect(Math.random() * 1800 + 5700, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 1800 + 5700, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 1800 + 8400, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 1800 + 8400, -5000, 3 + 2.5, 3000) + ctx.rect(Math.random() * 4500 - 2000, -5000, 3 + 2.5, 5030) ctx.fillStyle = "rgba(30,150,117,255)" ctx.fill() - // } - // if (rainCount > 12) { - // rainCount = 1 - // simulation.inGameConsole(rainCount) + //rain on shed + rainXtemp1 = Math.random() * 900 + 11100 + rainXtemp2 = Math.random() * 900 + 10200 + if (rainXtemp2 < 10800) { + ctx.rect(rainXtemp2, -5000, Math.random() * 3 + 2.5, 3000) + } else { + ctx.rect(rainXtemp2, -5000, Math.random() * 3 + 2.5, 2600) + } + ctx.rect(rainXtemp1, -5000, Math.random() * 3 + 2.5, 5000 + 0.5468 * rainXtemp1 - 8507) + + // ctx.rect(Math.random() * 900 + 10200, -5000, Math.random() * 3 + 2.5, 3000) + // ctx.rect(Math.random() * 900 + 11100, -5000, Math.random() * 3 + 2.5, 5000 + 0.5468 * this.x - 8507) + ctx.rect(Math.random() * 1800 + 12000, -5000, Math.random() * 3 + 2.5, 3000) + ctx.rect(Math.random() * 1800 + 12000, -5000, Math.random() * 3 + 2.5, 3000) + ctx.rect(Math.random() * 1500 - 3500, -5000, Math.random() * 3 + 2.5, 10030) + ctx.fillStyle = "rgba(30,150,117,255)" + ctx.fill() + - // } else { - // rainCount = rainCount + 1 - // simulation.inGameConsole(rainCount) // } - } while (Math.random() < 0.8); + + } while (Math.random() < 0.5); //this is really important, keep it + + + //simulation.inGameConsole(stopcycle) //simulation.inGameConsole(m.cycle) // ctx.fillStyle = "rgba(228,255,0,0.8)" @@ -21689,20 +22139,137 @@ const level = { // stopcycle = m.cycle + Math.random * 600; //stopcycle = m.cycles + Math.random * 600 - if (stopcycle > 300) { - stopcycle = 0 - flashcycle = Math.round(Math.random() * 25 + 260) + + //LIGHTNING + //flash cycle gets set to a random number 260-295 + //stop cycle increases until it is bigger than flash cycle + //lightning effect starts + //stop cycle continues increasing until it reaches 300 + //repeat + // simulation.inGameConsole(stopcycle) + if (stopcycle > 300) { //reset + if (Math.random() > 0.8 && hasDoubleFlashed == false) { + flashcycle = Math.round(Math.random() * 10 + 275) + stopcycle = flashcycle - 20 + hasDoubleFlashed = true + } else { + flashcycle = Math.round(Math.random() * 25 + 260) + stopcycle = Math.random() * -100 + hasDoubleFlashed = false + } document.body.style.backgroundColor = "#2e416e"; + playRandomThunder() } else { if (stopcycle > flashcycle) { document.body.style.backgroundColor = "#7391ff"; - for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], Math.random() * 20 + 30) + for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 300 - flashcycle)//Math.random() * 20 + 20 + lightningTime = flashcycle - 300 + } stopcycle = stopcycle + 1 } + + //mute button + ctx.textAlign = "start" + ctx.fillStyle = "#00ffff"; + // ctx.fillText("Waste Discharge Interruption:", 2910, -3870); + // ctx.fillText("Owner 'Scarlet' not found", 2910, -3830); + // ctx.fillText("Detected user: 'm'", 2910, -3790); + ctx.font = "27px monospace"; + ctx.fillText("Audio:", 150, -270); + ctx.font = "54px monospace"; + ctx.textAlign = "right"; + ctx.fillText(mutetoggle.isOn ? "Muted" : "Unmuted", 250, -210); + + //mute symbol + if (mutetoggle.isOn) { + ctx.strokeStyle = "#ff0400"; + } else { + ctx.strokeStyle = "#00ff00"; + } + + // ctx.beginPath(); + // ctx.rect(80 + 50, -187.5, 20, 25) + // ctx.stroke(); + ctx.lineWidth = 10; + + ctx.beginPath(); + ctx.moveTo(130, -167.5) //top left + ctx.lineTo(130 + 15 * 2, -167.5) //top mid + ctx.lineTo(130 + 30 * 2, -167.5 - 10 * 2) //top right + ctx.lineTo(130 + 30 * 2, -167.5 + 35 * 2) //bottom right + ctx.lineTo(130 + 15 * 2, -167.5 + 22 * 2) //bottom mid + ctx.lineTo(130, -167.5 + 22 * 2) // bottom left + ctx.lineTo(130, -167.5) //top left + ctx.stroke(); + + // canvas.width += 5 + // ctx.strokeSyle() + if (mutetoggle.isOn) { + ctx.lineWidth = 9; + ctx.moveTo(230, -185) + ctx.lineTo(140, -95) + ctx.stroke(); + ctx.lineWidth = 5; + ctx.stroke(); + ctx.beginPath(); + ctx.arc(170, -145, 45, 1.75 * Math.PI, 0.25 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(170, -145, 60, 1.75 * Math.PI, 0.25 * Math.PI); + ctx.stroke(); + } else { + ctx.stroke(); + ctx.beginPath(); + ctx.arc(170, -145, 45, 1.75 * Math.PI, 0.25 * Math.PI); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(170, -145, 60, 1.75 * Math.PI, 0.25 * Math.PI); + ctx.stroke(); + } + + + // ctx.arc(130, -175, 8, 0, 2 * Math.PI); + ctx.lineWidth = 4; + ctx.stroke(); + ctx.textAlign = "center"; + ctx.fillStyle = "#00ffff"; + // if (isMuted = 0) { + // ctx.fillText("Muted", 360, -230); + // } else { + // ctx.fillText("Unmuted", 360, -190); + // } + + // ctx.strokeStyle = "#00ff00"; + // ctx.beginPath(); + // ctx.arc(3300, -3730, 60, 0, 2 * Math.PI); + // ctx.stroke(); + // ctx.arc(3330, -3730, 8, 0, 2 * Math.PI); + // ctx.lineWidth = 4; + // ctx.stroke(); + // ctx.textAlign = "center"; + // ctx.fillStyle = "#00ffff"; + // ctx.font = "30px monospace"; + // ctx.fillText("n-gon inc", 3300, -3630); + + ctx.font = "25px Arial"; + + ctx.fillStyle = "#d4f4f4" ctx.fillRect(12984, -704, 420, 450) + //windows + + //scrapped, but i might work on this again + // if (stopcycle > flashcycle) { + // ctx.fillStyle = "rgba(255, 255, 255, 1)" + // ctx.fillRect(4703, -2362, 100, 100) + // ctx.fillRect(5053, -2362, 100, 100) + // ctx.fillRect(5403, -2362, 100, 100) + // ctx.fillRect(4703, -2062, 100, 100) + // ctx.fillRect(5053, -2062, 100, 100) + // ctx.fillRect(5403, -2062, 100, 100) + // } else { ctx.fillStyle = "rgba(0,0,0,0.5)" ctx.fillRect(4703, -2362, 100, 100) ctx.fillRect(5053, -2362, 100, 100) @@ -21710,47 +22277,44 @@ const level = { ctx.fillRect(4703, -2062, 100, 100) ctx.fillRect(5053, -2062, 100, 100) ctx.fillRect(5403, -2062, 100, 100) + // } + + ctx.fillStyle = "rgba(0,0,0,0.5)" ctx.fillRect(4523, -2512, 1150, 800) ctx.fillRect(4735, -1233, 100, 500)//tree ctx.beginPath() + ctx.moveTo(4487, -1195)//slope of -1/3 ctx.lineTo(4736, -792) ctx.lineTo(4736, -852) ctx.lineTo(4527, -1195) - ctx.moveTo(5087, -1195)//slope of -1/3 ctx.lineTo(4836, -792) ctx.lineTo(4836, -852) ctx.lineTo(5047, -1195) ctx.fill() + ctx.moveTo(5252.4, -2483.5) ctx.lineTo(5141.2, -2507.8) ctx.lineTo(5209.2, -2625.2) ctx.lineTo(5290.2, -2626.6) - ctx.lineTo(5361.2, -2697.9) ctx.lineTo(5410.6, -2717.0) - ctx.lineTo(5680.2, -2648.7) ctx.lineTo(5687.7, -2471.5) - ctx.fill() //building 2 spawn.mapRect(8473, -2513, 50, 50); ctx.fillRect(8673, -2137, 50, 175) - ctx.fillRect(7630, -2540, 100, 100) ctx.fillRect(7930, -2540, 100, 100) ctx.fillRect(8230, -2540, 100, 100) - ctx.fillRect(8530, -2765, 100, 100) - ctx.fillRect(7630, -2990, 100, 100) ctx.fillRect(7930, -2990, 100, 100) - ctx.fillRect(8230, -2990, 100, 100) @@ -21769,7 +22333,7 @@ const level = { - //stairs spawn.mapRect(7523, -2313, 800, 75); + //stairs ctx.fillRect(8523, -2563, 50, 50) ctx.fillRect(8473, -2613, 50, 50) ctx.fillRect(8423, -2663, 50, 50) @@ -21800,17 +22364,17 @@ const level = { //bunker ctx.fillStyle = "rgba(0,0,0,0.5)" - ctx.beginPath() - ctx.moveTo(10800, -2400)//slope of -1/3 - ctx.lineTo(10800, -340) - ctx.lineTo(12980, -340) - ctx.lineTo(12980, -700) - ctx.lineTo(13465, -700) - ctx.lineTo(13541, -1737) - ctx.lineTo(11864.6, -1967.0) - ctx.lineTo(11003, -2400) - ctx.fill() - ctx.fillRect(6100, -2000, 400, 50) + // ctx.beginPath() + // ctx.moveTo(10800, -2400)//slope of -1/3 + // ctx.lineTo(10800, -340) + // ctx.lineTo(12980, -340) + // ctx.lineTo(12980, -700) + // ctx.lineTo(13465, -700) + // ctx.lineTo(13541, -1737) + // ctx.lineTo(11864.6, -1967.0) + // ctx.lineTo(11003, -2400) + // ctx.fill() + // ctx.fillRect(6100, -2000, 400, 50) // -2000 -> 2500 // Math.random() * 5000 -2500 @@ -21831,6 +22395,27 @@ const level = { ctx.lineTo(6500, -1200) ctx.fill() + //rocks in river + ctx.fillStyle = "rgba(50,50,50,0.6)" + + ctx.beginPath() + ctx.moveTo(-2050, 0) + ctx.lineTo(1725, 0) + ctx.lineTo(1980, 88) + ctx.lineTo(2118, 257) + ctx.lineTo(2167, 491) + ctx.lineTo(-1800, 3000) + + ctx.lineTo(-2050, 3000) + + // ctx.moveTo(6500, -1200) + // ctx.lineTo(7600, -1200) + // ctx.lineTo(8000, 1400) + // ctx.lineTo(4600, 1500) + // ctx.lineTo(4500.5, 0) + // ctx.lineTo(6500, -200) + // ctx.lineTo(6500, -1200) + ctx.fill() @@ -21844,8 +22429,16 @@ const level = { ctx.fillStyle = "rgba(0,0,0,0.6)" - ctx.fillRect(2113, -791, 500, 75) + ctx.fillRect(2013, -791, 600, 75) ctx.fillRect(1766, -1091, 250, 310) + ctx.beginPath() + ctx.moveTo(1816, -781) + ctx.lineTo(1816, 32) + ctx.lineTo(1966, 84) + ctx.lineTo(1966, -781) + ctx.fill() + // ctx.fillRect(1816, -781, 150, 2000) + ctx.fillRect(4473, -2912, 50, 1000) ctx.fillRect(5673, -2712, 50, 800) ctx.fillStyle = "rgba(0,0,0,0.2)" @@ -21854,16 +22447,64 @@ const level = { ctx.fillRect(5273, -2212, 400, 75) + // if (level.levelsCleared > oldOnLevel) { + // simulation.inGameConsole("muted bc next level"); + // console.log("muted bc next level"); + // rain1.muted = true + // ambiance1.muted = true + // rain3.muted = true + // thunder1.muted = true + // thunder2.muted = true + // thunder3.muted = true + // thunder4.muted = true + // } + if (player.position.x > level.exit.x && player.position.x < level.exit.x + 100 && player.position.y > level.exit.y - 150 && player.position.y < level.exit.y - 0 && player.velocity.y < 0.15) { + // level.exitCount += input.down ? 8 : 2 + customExitTimer += 3 + } else if (customExitTimer > 0) { + customExitTimer -= 3 + } + // simulation.inGameConsole(customExitTimer); + + if (customExitTimer > 80) { + // simulation.inGameConsole("muted bc next level"); + // console.log("muted bc next level"); + muteAll(); + } level.exit.drawAndCheck(); + + addEventListener("keydown", function (event) { + if (event.key == "u") { + muteAll(); + } + }) + + // if (simulation.testing) { + // if (key.toLowerCase = "o") { + // rain1.muted = true + // ambiance1.muted = true + // rain3.muted = true + // thunder1.muted = true + // thunder2.muted = true + // thunder3.muted = true + // thunder4.muted = true + // } + // } slime.query(); slime2.query(); slime3.query(); slime4.query(); + slime5.query(); + // spawn.mapRect(4873, -2512, 800, 75); // spawn.mapRect(4473, -2212, 800, 75); //setTimeout(function(){/*YourCode*/},1000); + + + + //water falling/flowing effect ctx.fillStyle = `hsla(160, 100%, 26%,${0.5 + 0.07 * Math.random()})`//lower river ctx.fillRect(-1800 + Math.random() * 100, 10 + 400 * Math.random(), 3900, 5) @@ -21872,12 +22513,14 @@ const level = { ctx.fillRect(2400 + 200 * Math.random(), Math.random() * - 100 - 2000, 5, 2000)//first waterfall ctx.fillRect(6100 + 100 * Math.random(), Math.random() * - 100 - 1900, 5, 1050)//twin waterfalls ctx.fillRect(6400 + 100 * Math.random(), Math.random() * - 100 - 1900, 5, 1050) + ctx.fillRect(-2000 + 200 * Math.random(), Math.random() * 100, 5, 2000)//far left waterfall ctx.fillRect(7200 + 100 * Math.random(), -800 - 50 * Math.random(), 5, 2032) level.enter.draw(); laserbutton.query(); laserbutton.draw(); doortoggle.query(); + mutetoggle.query(); if (!doortoggle.isOn) { door.isClosing = true bunkerdoor.isClosing = true @@ -21907,120 +22550,117 @@ const level = { door.draw(); bunkerdoor.draw(); + //lights in basement + + // if (doortoggle.isOn) { + // ctx.beginPath() + // ctx.moveTo(6325, 212) + // ctx.lineTo(6325 - 75, 212) + // ctx.lineTo((6325 - 75) - 338, 212 + 338) + // ctx.lineTo(6325 + 10, 212 + 338) + // ctx.lineTo(6325 + 29.97, 212 + 1018) + // ctx.lineTo(6325 + 597.4443, 212 + 1018) //at an angle to the right platform + // ctx.lineTo((6325 + 75) + 375, 212 + 763) + // ctx.lineTo((6325 + 75) + 375, 212 + 688) + // ctx.lineTo((6325 + 75) + 688, 212 + 688) + // ctx.lineTo((6325 + 75) + 100, 212 + 100) + // ctx.lineTo(6325 + 75, 212) + // ctx.fillStyle = `rgba(242, 255, 0, 0.3})` + + // ctx.fill() + // } + spawn.mapRect(6250, 200, 150, 12); + + laser.opticalQuery(); - if (player.position.y > -70 && player.position.x < 2785) { - if (m.onGround) { - Matter.Body.setVelocity(player, { - x: player.velocity.x - (2 + m.pos.y / 150), - y: player.velocity.y - }); - } else { - Matter.Body.setVelocity(player, { - x: player.velocity.x - (1 + m.pos.y / 150), - y: player.velocity.y - }); - } - - } - if (player.position.x > 2400 && player.position.x < 2600) { + if (checkForPush(m.pos.x, m.pos.y)) { Matter.Body.setVelocity(player, { - x: player.velocity.x, - y: player.velocity.y + 4 + x: player.velocity.x + checkForWaterXSpeed(m.pos.x, m.pos.y), + y: player.velocity.y + checkForWaterYSpeed(m.pos.x, m.pos.y) }); - - } + + + + //push stuff + for (let i = 0, len = body.length; i < len; ++i) { //push blocks away + if (checkForPush(body[i].position.x, body[i].position.y)) { + if (checkForWaterYSpeed(body[i].position.x, body[i].position.y) == 0) { + body[i].force.x += checkForWaterXSpeed(body[i].position.x, body[i].position.y) / 300; + body[i].force.y += checkForWaterYSpeed(body[i].position.x, body[i].position.y) / 1000 - 0.001; + } else { + body[i].force.x += checkForWaterXSpeed(body[i].position.x, body[i].position.y) / 300; + body[i].force.y += checkForWaterYSpeed(body[i].position.x, body[i].position.y) / 1000; + } + } + for (let i = 0, len = powerUp.length; i < len; ++i) { //push blocks away + if (checkForPush(powerUp[i].position.x, powerUp[i].position.y - 50)) { + powerUp[i].force.x += checkForWaterXSpeed(powerUp[i].position.x, powerUp[i].position.y) / 800; + powerUp[i].force.y += checkForWaterYSpeed(powerUp[i].position.x, powerUp[i].position.y) / 800; + powerUp[i].position.x -= 0.1; + } + } + } + // for (let i = 0, len = powerUp.length; i < len; ++i) { //push blocks away + // if (checkForPush(powerUp[i].position.x, powerUp[i].position.y)) { + // powerUp[i].force.x += checkForWaterXSpeed(powerUp[i].position.x, powerUp[i].position.y) / 1000; + // powerUp[i].force.y += checkForWaterYSpeed(powerUp[i].position.x, powerUp[i].position.y) / 1000; + // } + // } + for (let i = 0, len = mob.length; i < len; ++i) { //push blocks away + if (checkForPush(mob[i].position.x, mob[i].position.y)) { + mob[i].force.x += checkForWaterXSpeed(mob[i].position.x, mob[i].position.y) / 2000; + mob[i].force.y += checkForWaterYSpeed(mob[i].position.x, mob[i].position.y) / 2000; + } + } + for (let i = 0, len = bullet.length; i < len; ++i) { //push blocks away + if (checkForPush(bullet[i].position.x, bullet[i].position.y)) { + if (b.activeGun == 0 || b.activeGun == 1 || b.activeGun == 2 || b.activeGun == 4 || b.activeGun == 7) { + bullet[i].velocity.x += checkForWaterXSpeed(bullet[i].position.x, bullet[i].position.y) * 100; + bullet[i].velocity.y += checkForWaterYSpeed(bullet[i].position.x, bullet[i].position.y) * 100; + } + } + } + // for (let i = 0, len = bullet.length; i < len; ++i) { //push bullets away vertically + // if (bullet[i].position.x > -7625 && bullet[i].position.x < -7075 && bullet[i].position.y > -2975 - 100 && bullet[i].position.y < -625) { + // bullet[i].force.y -= simulation.g * bullet[i].mass; + // } + // } + // for (let i = 0, len = powerUp.length; i < len; ++i) { //push powerups away + // if (powerUp[i].position.x > -7625 && powerUp[i].position.x < -7075 && powerUp[i].position.y > -2975 - 100 && powerUp[i].position.y < -625) { + // powerUp[i].force.y -= simulation.g * powerUp[i].mass + 0.12; + // } + // } + + // for (let i = 0, len = mob.length; i < len; ++i) { //push mobs away + // if (mob[i].position.x > -7625 && mob[i].position.x < -7075 && mob[i].position.y > -2975 - 100 && mob[i].position.y < -625) { + // mob[i].force.y -= simulation.g * mob[i].mass + 0.0012; + // } + // } + + + + + boost1.query(); boost2.query(); - if (player.position.x > 2600 && player.position.x < 4500 && player.position.y < -1900 && player.position.y > -2121.3) { - Matter.Body.setVelocity(player, { - x: player.velocity.x - 2, - y: player.velocity.y - }); - } - if (player.position.x > 4500 && player.position.x < 6000 && player.position.y < -1900 && player.position.y > -2121.3) { - if (input.left) { - Matter.Body.setVelocity(player, { - x: player.velocity.x + 0.1, - y: player.velocity.y - }); - } else { - Matter.Body.setVelocity(player, { - x: player.velocity.x + 0.5, - y: player.velocity.y - }); - } - } - if (player.position.x > 6500 && player.position.x < 7500 && player.position.y < -1900 && player.position.y > -2121.3) { - Matter.Body.setVelocity(player, { - x: player.velocity.x - 1, - y: player.velocity.y - }); - } - if (player.position.x > 7500 && player.position.x < 10000 && player.position.y < -1900 && player.position.y > -2121.3) { - Matter.Body.setVelocity(player, { - x: player.velocity.x - 1, - y: player.velocity.y - }); - } - if (player.position.x > 2600 && player.position.x < 6100 && player.position.y < -650 && player.position.y > -920) { - if (input.right) { - Matter.Body.setVelocity(player, { - x: player.velocity.x - 0.2, - y: player.velocity.y - }); - } else { - Matter.Body.setVelocity(player, { - x: player.velocity.x - 0.4, - y: player.velocity.y - }); - } - } - if (player.position.x > 6500 && player.position.x < 7300 && player.position.y < -650 && player.position.y > -920 && m.onGround) { - if (input.left) { - Matter.Body.setVelocity(player, { - x: player.velocity.x + 0.2, - y: player.velocity.y - }); - } else { - Matter.Body.setVelocity(player, { - x: player.velocity.x + 0.4, - y: player.velocity.y - }); - } - } - if (player.position.x > 7200 && player.position.x < 7350 && player.position.y > -950 && player.position.y < 1250) { - Matter.Body.setVelocity(player, { - x: player.velocity.x, - y: player.velocity.y + 0.8 - }); - } - if (player.position.x > 6100 && player.position.x < 6200 && player.position.y < -800 && player.position.y > -2000) { - Matter.Body.setVelocity(player, { - x: player.velocity.x, - y: player.velocity.y + 0.3 - }); - } - if (player.position.x > 6400 && player.position.x < 6500 && player.position.y < -800 && player.position.y > -2000) { - Matter.Body.setVelocity(player, { - x: player.velocity.x, - y: player.velocity.y + 0.3 - }); - } // ctx.fillRect(7200, -650, 100, 1900) - portal[0].draw(); portal[1].draw(); portal[2].draw(); portal[3].draw(); - - }; + //little block to stop push + spawn.mapRect(50, -10, 250, 20) + + spawn.mapRect(4800, -1700, 150, 12); + + spawn.mapRect(-100, 0, 1000, 100); spawn.mapRect(-1800, 400, 4400, 1300); - spawn.mapRect(-1800, 0, 100, 400); + // spawn.mapRect(-1800, 0, 100, 400); spawn.mapRect(2600, -2000, 3500, 300); spawn.mapRect(2600, -2000, 500, 800); spawn.mapRect(2955, -1779, 800, 300); @@ -22029,36 +22669,34 @@ const level = { spawn.mapVertex(965, 67, "0 -100 220 0 0 0"); spawn.mapVertex(-185, 67, "0 -100 -420 0 0 0"); spawn.mapVertex(1210, 365, "0 -400 300 0 0 0"); - spawn.mapRect(217.5, -358.5, 50, 360); - spawn.mapRect(-83, -358.5, 300, 50); + spawn.mapRect(257.5, -358.5, 50, 360); + spawn.mapRect(-83, -358.5, 350, 50); //blocks in river/waterfall - spawn.mapRect(1275, 0, 450, 75); spawn.mapRect(2027, -388, 600, 75); - spawn.mapRect(1666, -791, 450, 75); - spawn.mapRect(1666, -1091, 450, 75); - //buildings + spawn.mapRect(1726, -791, 330, 19); + spawn.mapRect(1696, -772, 390, 19); + spawn.mapRect(1666, -753, 450, 19); + spawn.mapRect(1636, -734, 510, 19); + spawn.mapRect(1666, -1091, 450, 75); + + //buildings spawn.mapRect(4873, -2512, 800, 75); spawn.mapRect(4473, -2212, 800, 75); spawn.mapRect(4473, -2912, 50, 800); spawn.mapRect(5673, -2712, 50, 575); - spawn.mapRect(6671.5, -2401.4, 500, 50); spawn.mapRect(6105.1, -2354.1, 400, 50); - spawn.mapRect(4473, -2952, 8, 75);//1,3,2 spawn.mapRect(4493, -3032, 15, 150); spawn.mapRect(4513, -2982, 7, 75); - spawn.mapRect(5673, -2742, 12, 50); spawn.mapRect(5703, -2772, 8, 100); //building 2 - // ctx.fillRect(8323, -2363, 50, 50) - spawn.mapRect(7473, -3412, 50, 800); spawn.mapRect(7473, -2312, 50, 500); spawn.mapRect(8673, -3212, 50, 1075); @@ -22074,10 +22712,12 @@ const level = { spawn.mapRect(8373, -2413, 50, 50); spawn.mapRect(8423, -2463, 50, 50); spawn.mapRect(8473, -2513, 250, 50); + //stairs 2 spawn.mapRect(8523, -3013, 50, 50)//make block spawn.mapRect(8473, -3063, 50, 50)//make block spawn.mapRect(8423, -3113, 50, 50)//make block + //trees in tunnel spawn.mapRect(4485, -1243, 600, 50) spawn.mapRect(3967, -1056, 400, 50) @@ -22095,6 +22735,10 @@ const level = { spawn.mapRect(5834, 549, 500, 80); spawn.mapRect(6756, 897, 400, 80); + //light + spawn.mapRect(6250, 200, 150, 12); + + //extra boss spawn.mapRect(9196, -11492, 500, 100); @@ -22106,7 +22750,7 @@ const level = { spawn.mapRect(11600, -340, 1800, 2600); spawn.mapRect(13400, -2000, 1800, 3600); spawn.mapRect(10800, -2500, 200, 100); - spawn.mapVertex(11400, -2235, "0 10 900 510 800 510 750 510 0 110"); + spawn.mapVertex(11400, -2233, "0 10 900 510 800 510 750 510 0 110"); spawn.mapVertex(10100, -2000, "0 0 0 -250 400 0"); spawn.mapRect(12945.0, -741.9, 600, 50); @@ -22128,7 +22772,7 @@ const level = { //mobs //spawn.tetherBoss(6480, 992, { x: 6480, y: 210 }) - if (Math.random() < 0.5) { + if (Math.random() < 0.15) { spawn.tetherBoss(6480, 992, { x: 6480, y: 210 }) } else { spawn.randomLevelBoss(5977, 992) @@ -22168,7 +22812,7 @@ const level = { spawn.bodyRect(6457.9, -2541.5, 300, 25, 0.9); //spawn.bodyRect(5685, -2140, 25, 140, 0.9); - spawn.bodyRect(4473, -2110, 50, 110, 0.9); + spawn.bodyRect(4473, -2110, 50, 110, 1, 1); //spawn.bodyRect(5292.1, -2617.2, 50, 50, 0.9); spawn.bodyRect(6370.1, -2408.4, 50, 50, 0.9); //spawn.bodyRect(5467, -1400, 25, 250, 0.9); @@ -22182,6 +22826,8 @@ const level = { spawn.bodyRect(5582.1, 1061.7, 110, 70, 0.9); //spawn.bodyRect(5582.1, 961.7, 50, 30, 0.9); + //button block + spawn.bodyRect(4900 + Math.random() * 400, -2600, 70, 70, 1); @@ -22199,6 +22845,89 @@ const level = { // if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300); // spawn.secondaryBossChance(100, -1500) powerUps.addResearchToLevel() //needs to run after mobs are spawned + + function muteAll() { + rain1.muted = true + ambiance1.muted = true + rain3.muted = true + thunder1.muted = true + thunder2.muted = true + thunder3.muted = true + thunder4.muted = true + } + + + function checkForWaterXSpeed(objectX, objectY) { + let waterXForce = 0; + + if (objectY > -70 && objectX < 2785) { + waterXForce = -1 * (2 + objectY / 150) + } + if (objectX > 2600 && objectX < 4500 && objectY < -1900 && objectY > -2121.3) { + waterXForce = -2 + } + if (objectX > 4500 && objectX < 6000 && objectY < -1900 && objectY > -2121.3) { + waterXForce = 0.4 + } + if (objectX > 6500 && objectX < 10000 && objectY < -1900 && objectY > -2121.3) { + waterXForce = -1 + } + if (objectX > 2600 && objectX < 6100 && objectY < -650 && objectY > -920) { + waterXForce = -0.4 + } + if (objectX > 6500 && objectX < 7300 && objectY < -650 && objectY > -920 && m.onGround) { + waterXForce = 0.2 + } + return waterXForce; + } + + function checkForWaterYSpeed(objectX, objectY) { + let waterYForce = 0; + if (objectX > 2400 && objectX < 2600) { + waterYForce = 4 + } + if (player.position.x > 7200 && player.position.x < 7350 && player.position.y > -950 && player.position.y < 1250) { + waterYForce = 0.8 + } + if (player.position.x > 6100 && player.position.x < 6200 && player.position.y < -800 && player.position.y > -2000) { + waterYForce = 0.3 + } + if (player.position.x > 6400 && player.position.x < 6500 && player.position.y < -800 && player.position.y > -2000) { + waterYForce = 0.3 + } + return waterYForce; + } + + function checkForPush(objectX, objectY) { + return (objectY > -70 && objectX < 2785 || objectX > 2400 && objectX < 2600 || objectX > 2600 && objectX < 6000 && objectY < -1900 && objectY > -2121.3 || objectX > 6500 && objectX < 10000 && objectY < -1900 && objectY > -2121.3 || objectX > 2600 && objectX < 6100 && objectY < -650 && objectY > -920 || objectX > 6500 && objectX < 7300 && objectY < -650 && objectY > -920 || objectX > 7200 && objectX < 7350 && objectY > -950 && objectY < 1250 || objectX > 6100 && objectX < 6200 && objectY < -800 && objectY > -2000 || objectX > 6400 && objectX < 6500 && objectY < -800 && objectY > -2000); + } + + function playRandomThunder() { + let tempRandom = Math.floor(4 * Math.random()) + switch (tempRandom) { + case 1: + // simulation.inGameConsole(`thunder1`) + thunder1.play(); + break; + case 2: + // simulation.inGameConsole(`thunder2`) + thunder2.play(); + break; + case 3: + // simulation.inGameConsole(`thunder3`) + thunder3.play(); + break; + case 4: + // simulation.inGameConsole(`thunder4`) + thunder4.play(); + break; + default: + // simulation.inGameConsole(`thunder5`) + thunder4.play(); + break; + + } + } }, dungeon() { let destroyed = false; @@ -34451,6 +35180,7 @@ const level = { door2.isClosing = false; index++; } + const oldLevel = level.onLevel; level.exit.drawAndCheck(); @@ -34482,7 +35212,8 @@ const level = { player.force.y -= 0.03; } - if (player.position.x > level.exit.x && player.position.x < level.exit.x + 100 && player.position.y > level.exit.y - 150 && player.position.y < level.exit.y - 0 && player.velocity.y < .15 && index2 == 0 && !isUsingSwordMod) { + // if (player.position.x > level.exit.x && player.position.x < level.exit.x + 100 && player.position.y > level.exit.y - 150 && player.position.y < level.exit.y - 0 && player.velocity.y < .15 && index2 == 0 && !isUsingSwordMod) { + if (level.onLevel !== oldLevel && simulation.clearNow && !isUsingSwordMod) { b.removeGun("sword"); //completely removing the stuff (if you leave properly through the door) for (let i = 0, len = b.guns.length; i < len; i++) { if (b.guns[i].name === "sword") { diff --git a/js/player.js b/js/player.js index e204643..f489624 100644 --- a/js/player.js +++ b/js/player.js @@ -455,6 +455,7 @@ const m = { ctx.fillRect(0, 0, canvas.width, canvas.height); } spawn.setSpawnList(); //new mob types + level.isFlipped = false simulation.clearNow = true; //triggers a map reset m.switchWorlds() @@ -3389,7 +3390,7 @@ const m = { case 4: //assembler return `+${(0.6 * couple).toFixed(1)} energy per second` case 5: //plasma - return `${(1 + 0.015 * couple).toFixed(3)}x damage` + return `${(1 + 0.025 * couple).toFixed(3)}x damage` case 6: //time dilation return `+${(1 + 0.05 * couple).toFixed(2)}x longer stopped time` //movement, jumping, and case 7: //cloaking diff --git a/js/powerup.js b/js/powerup.js index 6fedd09..343f90f 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -285,7 +285,7 @@ const powerUps = { endDraft(type, isCanceled = false) { //type should be a gun, tech, or field if (isCanceled) { if (tech.isCancelDuplication) { - const value = 0.05 + const value = 0.06 tech.duplication += value simulation.inGameConsole(`tech.duplicationChance() += ${value}`) simulation.circleFlare(value); @@ -883,7 +883,7 @@ const powerUps = { const couplingExtraAmmo = (m.fieldMode === 10 || m.fieldMode === 0) ? 1 + 0.04 * m.coupling : 1 if (b.inventory.length > 0) { powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)') - if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics + if (tech.isAmmoForGun && (b.activeGun !== null && b.activeGun !== undefined)) { //give extra ammo to one gun only with tech logistics const name = b.guns[b.activeGun] if (name.ammo !== Infinity) { if (tech.ammoCap) { @@ -1618,7 +1618,7 @@ const powerUps = { powerUps.spawn(x, y - 40, "heal", false) } if (tech.isResearchReality) powerUps.spawnDelay("research", 6) - if (tech.isBanish) powerUps.spawnDelay("research", 2) + if (tech.isBanish) powerUps.spawnDelay("research", 3) if (tech.isCouplingNoHit) powerUps.spawnDelay("coupling", 9) // if (tech.isRerollDamage) powerUps.spawnDelay("research", 1) } @@ -1735,9 +1735,10 @@ const powerUps = { } //count big power ups and small power ups - let options = ["heal", "research", "ammo"] + let options = ["heal", "research", tech.isBoostReplaceAmmo ? "boost" : "ammo"] if (m.coupling) options.push("coupling") if (tech.isBoostPowerUps) options.push("boost") + let bigIndexes = [] let smallIndexes = [] for (let i = 0; i < powerUp.length; i++) { diff --git a/js/simulation.js b/js/simulation.js index 3ba0920..98c919a 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -2,152 +2,152 @@ //********************************************************************* const simulation = { loop() { }, //main game loop, gets set to normal or testing loop - normalLoop() { - try { - simulation.gravity(); - Engine.update(engine, simulation.delta); - simulation.wipe(); - simulation.textLog(); - if (m.onGround) { - m.groundControl() - } else { - m.airControl() - } - m.move(); - m.look(); - simulation.camera(); - level.custom(); - powerUps.do(); - mobs.draw(); - simulation.draw.cons(); - simulation.draw.body(); - if (!m.isBodiesAsleep) mobs.loop(); - mobs.healthBar(); - m.draw(); - m.hold(); - level.customTopLayer(); - simulation.draw.drawMapPath(); - b.fire(); - b.bulletRemove(); - b.bulletDraw(); - if (!m.isBodiesAsleep) b.bulletDo(); - simulation.drawCircle(); - simulation.runEphemera(); - ctx.restore(); - } catch (error) { - simulation.inGameConsole(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); - } finally { - simulation.drawCursor(); - } - }, - testingLoop() { - try { - simulation.gravity(); - Engine.update(engine, simulation.delta); - simulation.wipe(); - simulation.textLog(); - if (m.onGround) { - m.groundControl() - } else { - m.airControl() - } - m.move(); - m.look(); - simulation.camera(); - level.custom(); - m.draw(); - m.hold(); - level.customTopLayer(); - simulation.draw.wireFrame(); - if (input.fire && m.fireCDcycle < m.cycle) { - m.fireCDcycle = m.cycle + 15; //fire cooldown - for (let i = 0, len = mob.length; i < len; i++) { - if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) { - console.log(mob[i]) - } - } - } - simulation.draw.cons(); - simulation.draw.testing(); - simulation.drawCircle(); - simulation.runEphemera(); - simulation.constructCycle() - } catch (error) { - simulation.inGameConsole(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); - } finally { - ctx.restore(); - simulation.testingOutput(); - simulation.drawCursor(); - } - }, // normalLoop() { - // simulation.gravity(); - // Engine.update(engine, simulation.delta); - // simulation.wipe(); - // simulation.textLog(); - // if (m.onGround) { - // m.groundControl() - // } else { - // m.airControl() + // try { + // simulation.gravity(); + // Engine.update(engine, simulation.delta); + // simulation.wipe(); + // simulation.textLog(); + // if (m.onGround) { + // m.groundControl() + // } else { + // m.airControl() + // } + // m.move(); + // m.look(); + // simulation.camera(); + // level.custom(); + // powerUps.do(); + // mobs.draw(); + // simulation.draw.cons(); + // simulation.draw.body(); + // if (!m.isBodiesAsleep) mobs.loop(); + // mobs.healthBar(); + // m.draw(); + // m.hold(); + // level.customTopLayer(); + // simulation.draw.drawMapPath(); + // b.fire(); + // b.bulletRemove(); + // b.bulletDraw(); + // if (!m.isBodiesAsleep) b.bulletDo(); + // simulation.drawCircle(); + // simulation.runEphemera(); + // ctx.restore(); + // } catch (error) { + // simulation.inGameConsole(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); + // } finally { + // simulation.drawCursor(); // } - // m.move(); - // m.look(); - // simulation.camera(); - // level.custom(); - // powerUps.do(); - // mobs.draw(); - // simulation.draw.cons(); - // simulation.draw.body(); - // if (!m.isBodiesAsleep) mobs.loop(); - // mobs.healthBar(); - // m.draw(); - // m.hold(); - // level.customTopLayer(); - // simulation.draw.drawMapPath(); - // b.fire(); - // b.bulletRemove(); - // b.bulletDraw(); - // if (!m.isBodiesAsleep) b.bulletDo(); - // simulation.drawCircle(); - // simulation.runEphemera(); - // ctx.restore(); - // simulation.drawCursor(); // }, // testingLoop() { - // simulation.gravity(); - // Engine.update(engine, simulation.delta); - // simulation.wipe(); - // simulation.textLog(); - // if (m.onGround) { - // m.groundControl() - // } else { - // m.airControl() - // } - // m.move(); - // m.look(); - // simulation.camera(); - // level.custom(); - // m.draw(); - // m.hold(); - // level.customTopLayer(); - // simulation.draw.wireFrame(); - // if (input.fire && m.fireCDcycle < m.cycle) { - // m.fireCDcycle = m.cycle + 15; //fire cooldown - // for (let i = 0, len = mob.length; i < len; i++) { - // if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) { - // console.log(mob[i]) + // try { + // simulation.gravity(); + // Engine.update(engine, simulation.delta); + // simulation.wipe(); + // simulation.textLog(); + // if (m.onGround) { + // m.groundControl() + // } else { + // m.airControl() + // } + // m.move(); + // m.look(); + // simulation.camera(); + // level.custom(); + // m.draw(); + // m.hold(); + // level.customTopLayer(); + // simulation.draw.wireFrame(); + // if (input.fire && m.fireCDcycle < m.cycle) { + // m.fireCDcycle = m.cycle + 15; //fire cooldown + // for (let i = 0, len = mob.length; i < len; i++) { + // if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) { + // console.log(mob[i]) + // } // } // } + // simulation.draw.cons(); + // simulation.draw.testing(); + // simulation.drawCircle(); + // simulation.runEphemera(); + // simulation.constructCycle() + // } catch (error) { + // simulation.inGameConsole(`ERROR: ${(error.stack && error.stack.replace(/\n/g, "
")) || (error.message + ` ${error.filename}:${error.lineno}`)}`); + // } finally { + // ctx.restore(); + // simulation.testingOutput(); + // simulation.drawCursor(); // } - // simulation.draw.cons(); - // simulation.draw.testing(); - // simulation.drawCircle(); - // simulation.runEphemera(); - // simulation.constructCycle() - // ctx.restore(); - // simulation.testingOutput(); - // simulation.drawCursor(); // }, + normalLoop() { + simulation.gravity(); + Engine.update(engine, simulation.delta); + simulation.wipe(); + simulation.textLog(); + if (m.onGround) { + m.groundControl() + } else { + m.airControl() + } + m.move(); + m.look(); + simulation.camera(); + level.custom(); + powerUps.do(); + mobs.draw(); + simulation.draw.cons(); + simulation.draw.body(); + if (!m.isBodiesAsleep) mobs.loop(); + mobs.healthBar(); + m.draw(); + m.hold(); + level.customTopLayer(); + simulation.draw.drawMapPath(); + b.fire(); + b.bulletRemove(); + b.bulletDraw(); + if (!m.isBodiesAsleep) b.bulletDo(); + simulation.drawCircle(); + simulation.runEphemera(); + ctx.restore(); + simulation.drawCursor(); + }, + testingLoop() { + simulation.gravity(); + Engine.update(engine, simulation.delta); + simulation.wipe(); + simulation.textLog(); + if (m.onGround) { + m.groundControl() + } else { + m.airControl() + } + m.move(); + m.look(); + simulation.camera(); + level.custom(); + m.draw(); + m.hold(); + level.customTopLayer(); + simulation.draw.wireFrame(); + if (input.fire && m.fireCDcycle < m.cycle) { + m.fireCDcycle = m.cycle + 15; //fire cooldown + for (let i = 0, len = mob.length; i < len; i++) { + if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) { + console.log(mob[i]) + } + } + } + simulation.draw.cons(); + simulation.draw.testing(); + simulation.drawCircle(); + simulation.runEphemera(); + simulation.constructCycle() + ctx.restore(); + simulation.testingOutput(); + simulation.drawCursor(); + }, isTimeSkipping: false, timeSkip(cycles = 60) { simulation.isTimeSkipping = true; @@ -712,7 +712,7 @@ const simulation = { mouseMove = mouseMoveDefault } }, - translatePlayerAndCamera(where) { + translatePlayerAndCamera(where, isTranslateBots = true) { //infinite falling. teleport to sky after falling const before = { x: player.position.x, y: player.position.y, } Matter.Body.setPosition(player, { x: where.x, y: where.y }); @@ -728,14 +728,15 @@ const simulation = { //is there a reason to update m.pos here? // m.pos.x = player.position.x; // m.pos.y = playerBody.position.y - m.yOff; - - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].botType) { - if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player - Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) })); - Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); - } else { //close bots maintain relative distance to player on teleport - Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change)); + if (isTranslateBots) { + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType) { + if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player + Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) })); + Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); + } else { //close bots maintain relative distance to player on teleport + Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change)); + } } } } @@ -996,7 +997,7 @@ const simulation = { simulation.makeGunHUD(); simulation.lastLogTime = 0; mobs.mobDeaths = 0 - + level.isFlipped = false level.onLevel = 0; level.levelsCleared = 0; level.updateDifficulty() diff --git a/js/spawn.js b/js/spawn.js index 02ae7db..27a7dc5 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -42,6 +42,7 @@ const spawn = { spawn.pickList.splice(0, 1); const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length] spawn.pickList.push(push); + // if (spawn.mobTypeSpawnIndex > spawn.mobTypeSpawnOrder.length) spawn.mobTypeSpawnIndex = 0 //each level has 2 mobs: one new mob and one from the last level // spawn.pickList.splice(0, 1); @@ -116,8 +117,8 @@ const spawn = { secondaryBossChance(x, y) { if (simulation.difficultyMode > 2 && level.levelsCleared > 1) { spawn.randomLevelBoss(x, y); - powerUps.directSpawn(x - 30, y, "ammo"); - powerUps.directSpawn(x + 30, y, "ammo"); + powerUps.spawn(x - 30, y, "ammo"); + powerUps.spawn(x + 30, y, "ammo"); } else { return false } diff --git a/js/tech.js b/js/tech.js index 0073bf4..6bed21e 100644 --- a/js/tech.js +++ b/js/tech.js @@ -249,18 +249,7 @@ const tech = { } }, haveGunCheck(name, needActive = true) { - // if ( - // !build.isExperimentSelection && - // b.inventory.length > 2 && - // name !== b.guns[b.activeGun].name && - // Math.random() > 2 - b.inventory.length * 0.5 - // ) { - // return false - // } - // for (i = 0, len = b.inventory.length; i < len; i++) { - // if (b.guns[b.inventory[i]].name === name) return true - // } - // return false + if (b.activeGun === null || b.activeGun === undefined) return false if (build.isExperimentSelection || !needActive) { for (i = 0, len = b.inventory.length; i < len; i++) { if (b.guns[b.inventory[i]].name === name) return true @@ -269,6 +258,15 @@ const tech = { } else { //must be holding gun, this is the standard while playing return b.inventory.length > 0 && b.guns[b.activeGun].name === name } + + // if (build.isExperimentSelection || !needActive) { + // for (i = 0, len = b.inventory.length; i < len; i++) { + // if (b.guns[b.inventory[i]].name === name) return true + // } + // return false + // } else { //must be holding gun, this is the standard while playing + // return b.inventory.length > 0 && b.guns[b.activeGun].name === name + // } }, hasExplosiveDamageCheck() { return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) @@ -276,9 +274,9 @@ const tech = { damage: 1, //used for tech changes to player damage that don't have complex conditions damageFromTech() { let dmg = tech.damage * m.fieldDamage - if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.1 + if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.3 if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 1.5 - if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2 + if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2.5 if (tech.isImmunityDamage && m.immuneCycle > m.cycle) dmg *= 3 if (tech.isPowerUpDamage) dmg *= 1 + 0.07 * powerUp.length if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.4 : 4 @@ -288,7 +286,7 @@ const tech = { if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01) if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage - if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.015 * m.coupling + if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.025 * m.coupling if (tech.isVerlet) dmg *= 3 if (tech.isTechDebt) dmg *= tech.totalCount > 20 ? Math.pow(0.85, tech.totalCount - 20) : 4 - 0.15 * tech.totalCount if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828 @@ -299,7 +297,7 @@ const tech = { if (tech.isRerollDamage) dmg *= 1 + Math.max(0, 0.05 * powerUps.research.count) if (tech.isBotDamage) dmg *= 1 + 0.04 * b.totalBots() if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage - if (tech.isLowEnergyDamage) dmg *= 1 + 0.5 * Math.max(0, m.maxEnergy - m.energy) + if (tech.isLowEnergyDamage) dmg *= 1 + 0.6 * Math.max(0, m.maxEnergy - m.energy) if (tech.energyDamage) dmg *= 1 + m.energy * 0.23 * tech.energyDamage; if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.01 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 @@ -2874,7 +2872,7 @@ const tech = { { name: "Gibbs free energy", descriptionFunction() { - return `1.005x damage for each missing energy
(${(1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)` + return `1.006x damage for each missing energy
(${(1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3086,7 +3084,7 @@ const tech = { { name: "instability", descriptionFunction() { - return `2x damage while your damage taken is 1.00x
(current damage taken = ${(m.defense()).toFixed(2)}x)` + return `2.5x damage while your damage taken is 1.00x
(current damage taken = ${(m.defense()).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3597,7 +3595,7 @@ const tech = { }, { name: "decoherence", - description: `after a boss dies spawn ${powerUps.orb.research(2)}
${powerUps.orb.tech()} options you don't choose won't reoccur`, + description: `after a boss dies spawn ${powerUps.orb.research(3)}
${powerUps.orb.tech()} options you don't choose won't reoccur`, maxCount: 1, count: 0, frequency: 1, @@ -3606,7 +3604,6 @@ const tech = { return !tech.isSuperDeterminism }, requires: "not, superdeterminism", - bonusResearch: 7, effect() { tech.isBanish = true }, @@ -3626,8 +3623,8 @@ const tech = { description: `after observing a ${powerUps.orb.tech()} choice
that choice is available for all all future ${powerUps.orb.tech()}`, maxCount: 1, count: 0, - frequency: 1, - frequencyDefault: 1, + frequency: 3, + frequencyDefault: 3, allowed() { return tech.isBanish }, @@ -4301,7 +4298,7 @@ const tech = { }, { name: "futures exchange", - description: `clicking cancel for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
gives +5% power up duplication chance`, + description: `clicking cancel for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}
gives +6% power up duplication chance`, maxCount: 1, count: 0, frequency: 1, @@ -7448,7 +7445,7 @@ const tech = { }, { name: "compound lens", - description: "1.4x laser lens damage
+25° lens arc", + description: "1.4x laser lens damage
+30° lens arc", isGunTech: true, maxCount: 9, count: 0, @@ -7459,7 +7456,7 @@ const tech = { }, requires: "lens", effect() { - b.guns[11].arcRange += 25 * Math.PI / 180 / 2 + b.guns[11].arcRange += 30 * Math.PI / 180 / 2 b.guns[11].lensDamageOn += 0.4 }, remove() { @@ -8763,7 +8760,7 @@ const tech = { }, { name: "vacuum fluctuation", - description: `use ${powerUps.orb.research(3)}
+11% chance to duplicate spawned power ups`, + description: `use ${powerUps.orb.research(2)}
+11% chance to duplicate spawned power ups`, isFieldTech: true, maxCount: 1, count: 0, @@ -8777,14 +8774,16 @@ const tech = { tech.fieldDuplicate = 0.11 powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11); - for (let i = 0; i < 3; i++) { + for (let i = 0; i < 2; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) } }, remove() { tech.fieldDuplicate = 0 - if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance - if (this.count > 0) powerUps.research.changeRerolls(3) + if (this.count) { + powerUps.setPowerUpMode(); //needed after adjusting duplication chance + powerUps.research.changeRerolls(2) + } } }, { @@ -8900,7 +8899,7 @@ const tech = { } }, { - name: "charmed baryons", + name: "holographic principle", description: `0.8x movement and jumping
wormholes cost zero energy`, isFieldTech: true, maxCount: 1, @@ -9694,7 +9693,7 @@ const tech = { effect() { for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].isDropPowerUp) { - powerUps.directSpawn(mob[i].position.x, mob[i].position.y, "ammo"); + powerUps.spawn(mob[i].position.x, mob[i].position.y, "ammo"); mob[i].death(); } } @@ -11701,7 +11700,7 @@ const tech = { bc.activated = false bc.onmessage = function (ev) { - if (ev.data === 'tech') powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); + if (ev.data === 'tech') powerUps.spawn(m.pos.x, m.pos.y, "tech"); if (ev.data === 'death') { m.death() bc.close(); //end session diff --git a/todo.txt b/todo.txt index f521596..31fdb8d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,16 +1,30 @@ ******************************************************** NEXT PATCH ************************************************** -tech: Halbach array - throwing a block will also throw other nearby blocks +new level substructure + featured element - motion triggered lasers -tech non-renewables now spawns ammo, but ammo can't be picked up -grenade tech that cause multiple explosions have less knock back for mobs -constraint: 0->0.5x healing -wormhole 7->8% duplication -many worlds takes a few frames between each tech given +futures exchange 5->6% duplication per cancel +plasma torch coupling 0.015->0.025x damage per coupling +Gibbs free energy 1.005->1.006x damage per missing energy +compound lens arc adds 25->30 degrees +instability 2->2.5x damage when damage taken is 1x +constraint: after 30->40 seconds spawn WIMPs +constraint: 0.1->0.3x damage after getting power ups +renamed holographic principle -> charmed baryons -bug fixes - harpoon ammo gain on autonomous defense fixed - constraints are properly randomized again +updates to community map: downpour +updated lasers in labs and testChamber to the new more realistic laser + +bugs + returning to the old console.log system from last patch + I rather read bugs in the browser console not the n-gon console + bots properly follow player when level flips vertically + community map: arena's sword is properly removed at end of level + rewrote shaped charge to be better at protecting you from all explosions + pause correctly lists both mobs types for the level + for quasiparticles "boost" replaces ammo in more edge cases + bug with removing surfactant setting b.activeGun false and crashing game with checking active gun + not sure if this is fixed or not? ******************************************************** BUGS ******************************************************** @@ -50,14 +64,39 @@ player can become crouched while not touching the ground if they exit the ground *********************************************************** TODO ***************************************************** +rework focuser mobs to fire blue laser instead of charging player + like in classic 7-1-2017 + this makes more sense that a bean is focusing + + +!!conformal - similar rules for small and big scales linked to holographic principle +!!holonomy - parallel transport of a vector leads to movement (applies to curved space) + when far away from your wormhole regenerate 1% of your max energy per second + when far away from your wormhole reduce damage taken + heal last hit damage after enter wormhole +!!quasar - plasma torch from both ends + only after wormhole eats a block fire? + or just increase plasma length after eating block? + + +new level element - motion trigger for laser +new level heist + above - a building with rooms and doors like office/warehouse + below - long indoor tunnels like sewers + dark colors + narrow branching paths + elements + motion triggered lasers + doors opened by buttons + button that opens 1 door, but closes another when down + make the button down state easier, have extra power ups + + make a text orb for JUNK text to make JUNK more clear extended vertical flip to edge cases: !!stored circular graphics simulation.drawList.push -new level based laser element - !!update new version into other levels - procedural animation https://www.youtube.com/watch?v=qlfh_rv6khY @@ -839,9 +878,6 @@ mob/boss that fires a laser at player, but give player time to avoid they target where player was 1 second ago they turn to face player? -tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage - require electric reactive armor? - Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement. maybe reduce gravity to really low then apply a vector away from mouse direction @@ -851,17 +887,6 @@ auto-gon - auto battler with n-gon mob AI and tech similar research and tech system to n-gon some mobs can fire player weapons -tech: relativistic jets: - small particles that shot out from front and back poles and end up in a wide variety of spirals - slow trickle when charging and several more when firing - -Tech: Make player smol - -adapt the cloaking graphics to make a flashlight cone visual effect - put code in level.do? - -be nice if block throwing had a projected path - Pilot wave tech Energy use is increased, but you can now shape blocks using pressure Grouping blocks will merge them into a massive ball @@ -1234,11 +1259,8 @@ look up sci-fi science ideas here https://projectrho.com/public_html/rocket/ possible names for tech sidereal - with respect to the stars (an extra rotation for time keeping) - holonomy - parallel transport of a vector leads to movement (applies to curved space) - holographic - 2-D surface can predict the 3-D space behind it? I think entropic gravity - gravity is emergent in a holographic way (maybe a field tech for negative mass) - conformal - similar rules for small and big scales linked to holographic principle hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other. swarm intelligence - for a drone tech 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 @@ -1307,8 +1329,11 @@ possible names for tech cork - used as a heat shield for rockets P = NP - something with speeding up calculation times transistivity - something where a>b and b>c -> a>c - lenticular - looks different from different angles (lasers?) + lenticular - looks different from different angles (lasers?, cloaking?) + every few seconds pick a random skin tech? De Sitter space - simple model of universe related to general relativity (mass-energy?) + active optics - something with lasers? maybe something with diffuse beam getting smaller + Quintessence - related to dark energy ******************************************************* DESIGN ****************************************************** @@ -1333,3 +1358,23 @@ list of powerful synergies electronegativity and high energy? electronegativity + anyon + duplication + Maxwells demon + interest + pair production chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level + + +************************************************* COMMUNITY LINKS ************************************************* + +load old commits + www.cornbread2100.com/n-gon-loader + +n-gon fork + kgurchiek.github.io/n-gon-portal-gun + 3xiondev.github.io/n-gon-upgraded + coaldeficit.github.io/c-gon + c-rxxp-y.github.io/n-gon-enhanced + +bookmarlet + github.com/Whyisthisnotavalable/n-scythe + github.com/kgurchiek/n-gon-mobile + github.com/kgurchiek/n-gon-controller +text + ngon.fandom.com/wiki/N-gon + github.com/3xionDev/n-docs \ No newline at end of file