diff --git a/.DS_Store b/.DS_Store index 760bd30..15c8217 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/index.html b/index.html index e1eec7b..bde0b5f 100644 --- a/index.html +++ b/index.html @@ -11,14 +11,12 @@ - n-gon -
@@ -29,45 +27,7 @@
- - - - - - - - - - - - - - - -
@@ -82,7 +42,6 @@ - training
@@ -140,7 +99,8 @@
controls
- To change controls click a box
+ To change controls click a box +
and press an unused key.

@@ -203,17 +163,13 @@
updates -
+
about -
- +
- Chat about n-gon in the discord.
Let me know about ideas, - or bugs. -
-
-
+ Chat about n-gon in the discord.
Let me know about ideas, or bugs. +


@@ -238,13 +191,7 @@ - Github hosts the source code for n-gon.
It's - written in JavaScript, CSS, and HTML. - + Github hosts the source code for n-gon.
It's written in JavaScript, CSS, and HTML using the matter.js 2-D physics library.
@@ -335,17 +282,6 @@ } - - @@ -360,19 +296,10 @@ - - @@ -398,26 +325,16 @@ - - Q W E - A S D - - - @@ -431,140 +348,7 @@ fire field - - - - - @@ -576,14 +360,9 @@ - - - - \ No newline at end of file diff --git a/js/bullet.js b/js/bullet.js index 8047c00..e96b75b 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -196,9 +196,9 @@ const b = { } }, - removeGun(gun, isRemoveSelection = false) { + removeGun(gunName) { for (let i = 0; i < b.guns.length; i++) { - if (b.guns[i].name === gun) { + if (b.guns[i].name === gunName && b.guns[i].have) { b.guns[i].have = false for (let j = 0; j < b.inventory.length; j++) { if (b.inventory[j] === i) { @@ -206,13 +206,12 @@ const b = { break } } - if (b.inventory.length) { + if (b.inventory.length > 0) { b.activeGun = b.inventory[0]; } else { b.activeGun = null; } simulation.makeGunHUD(); - if (isRemoveSelection) b.guns.splice(i, 1) //also remove gun from gun pool array break } } @@ -973,7 +972,7 @@ const b = { grenadeNeutron = function(where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }, angle = m.angle, size = 1) { const me = bullet.length; bullet[me] = Bodies.polygon(where.x, where.y, 10, 4, b.fireAttributes(angle, false)); - b.fireProps((input.down ? 45 : 25) / Math.pow(0.93, tech.missileCount), input.down ? 35 : 20, angle, me); //cd , speed + b.fireProps((input.down ? 45 : 25) / Math.pow(0.92, tech.missileCount), input.down ? 35 : 20, angle, me); //cd , speed Matter.Body.setDensity(bullet[me], 0.000001); bullet[me].endCycle = Infinity; bullet[me].frictionAir = 0; @@ -1901,7 +1900,7 @@ const b = { frictionAir: 0.045, dmg: 0, //damage done in addition to the damage from momentum classType: "bullet", - endCycle: simulation.cycle + Math.floor((230 + 40 * Math.random()) * tech.isBulletsLastLonger), + endCycle: simulation.cycle + Math.floor((230 + 40 * Math.random()) * tech.isBulletsLastLonger + 120 * tech.isMissileBiggest + 60 * tech.isMissileBig), collisionFilter: { category: cat.bullet, mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield @@ -1992,7 +1991,7 @@ const b = { didExtruderDrain: false, canExtruderFire: true, extruder() { - const DRAIN = 0.0018 + const DRAIN = 0.0012 if (m.energy > DRAIN && b.canExtruderFire) { m.energy -= DRAIN if (m.energy < 0) { @@ -2011,7 +2010,7 @@ const b = { frictionAir: 0, isInHole: true, //this keeps the bullet from entering wormholes minDmgSpeed: 0, - dmg: m.dmgScale * 2.5, //damage also changes when you divide by mob.mass on in .do() + dmg: m.dmgScale * 2.7, //damage also changes when you divide by mob.mass on in .do() classType: "bullet", isBranch: false, restitution: 0, @@ -2070,7 +2069,7 @@ const b = { } }, plasma() { - const DRAIN = 0.0011 + const DRAIN = 0.00075 if (m.energy > DRAIN) { m.energy -= DRAIN; if (m.energy < 0) { @@ -2150,7 +2149,7 @@ const b = { y: best.y }; if (best.who.alive) { - const dmg = 0.8 * m.dmgScale; //********** SCALE DAMAGE HERE ********************* + const dmg = 0.9 * m.dmgScale; //********** SCALE DAMAGE HERE ********************* best.who.damage(dmg); best.who.locatePlayer(); @@ -2726,6 +2725,7 @@ const b = { dmg: tech.isMutualism ? 16.8 : 7, //bonus damage from tech.isMutualism lookFrequency: 100 + Math.floor(117 * Math.random()), classType: "bullet", + isSpore: true, collisionFilter: { category: cat.bullet, mask: cat.map | cat.mob | cat.mobBullet | cat.mobShield //no collide with body @@ -4235,7 +4235,7 @@ const b = { this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, mob[i].position)), this.mass * 0.02) if (tech.missileCount > 1) { - const countReduction = Math.pow(0.93, tech.missileCount) + const countReduction = Math.pow(0.85, tech.missileCount) const size = 0.9 * Math.sqrt(countReduction) const direction = { x: Math.cos(angle), @@ -5765,7 +5765,7 @@ const b = { fireCycle: 0, do() {}, fire() { - const countReduction = Math.pow(0.9, tech.missileCount) + const countReduction = Math.pow(0.86, tech.missileCount) // if (input.down) { // m.fireCDcycle = m.cycle + tech.missileFireCD * b.fireCDscale / countReduction; // cool down // // for (let i = 0; i < tech.missileCount; i++) { @@ -6246,13 +6246,13 @@ const b = { const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) // console.log(dot, 0.95 - Math.min(dist * 0.00015, 0.3)) if (dot > 0.95 - Math.min(dist * 0.00015, 0.3)) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target - if (this.ammo > -1) { - this.ammo-- - b.harpoon(where, input.down ? mob[i] : null, angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 }) - angle += SPREAD - targetCount++ - if (targetCount > tech.extraHarpoons) break - } + // if (this.ammo > -1) { + // this.ammo-- + b.harpoon(where, input.down ? mob[i] : null, angle, harpoonSize, false) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 }) + angle += SPREAD + targetCount++ + if (targetCount > tech.extraHarpoons) break + // } } } } @@ -6260,14 +6260,14 @@ const b = { if (targetCount < tech.extraHarpoons + 1) { const num = tech.extraHarpoons + 1 - targetCount for (let i = 0; i < num; i++) { - if (this.ammo > -1) { - this.ammo-- - b.harpoon(where, null, angle, harpoonSize, false) - angle += SPREAD - } + // if (this.ammo > -1) { + // this.ammo-- + b.harpoon(where, null, angle, harpoonSize, false) + angle += SPREAD + // } } } - this.ammo++ //make up for the ammo used up in fire() + // this.ammo++ //make up for the ammo used up in fire() simulation.updateGunHUD(); } else { //look for closest mob in player's LoS @@ -7298,7 +7298,7 @@ const b = { m.fireCDcycle = m.cycle m.energy -= m.fieldRegen + tech.laserFieldDrain * tech.isLaserDiode const dmg = 0.4 * tech.laserDamage // 3.5 * 0.55 = 200% more damage - const spacing = Math.ceil(5.2 - 0.4 * tech.historyLaser) + const spacing = Math.ceil(4 - 0.3 * tech.historyLaser) ctx.beginPath(); b.laser({ x: m.pos.x + 20 * Math.cos(m.angle), diff --git a/js/index.js b/js/index.js index 7ef6e2e..8b14fda 100644 --- a/js/index.js +++ b/js/index.js @@ -280,7 +280,7 @@ const build = {
${botText}
health: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)})   energy: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) -
gun: ${b.activeGun !== null ? b.guns[b.activeGun].name: "null"}   ammo: ${b.activeGun !== null ? b.guns[b.activeGun].ammo: "0"} +
gun: ${b.activeGun === null || b.activeGun === undefined ? "undefined":b.guns[b.activeGun].name}   ammo: ${b.activeGun === null || b.activeGun === undefined ? "0":b.guns[b.activeGun].ammo}
fire delay decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
duplication chance: ${(tech.duplicationChance()*100).toFixed(0)}%
tech: ${tech.totalCount}   research: ${powerUps.research.count} diff --git a/js/level.js b/js/level.js index 790b6cc..39e9699 100644 --- a/js/level.js +++ b/js/level.js @@ -18,13 +18,13 @@ const level = { // simulation.isHorizontalFlipped = true // m.setField("metamaterial cloaking") // b.giveGuns("missiles") - // tech.giveTech("nematodes") - // tech.giveTech("launch system") - // tech.giveTech("cruise missile") + // tech.giveTech("scrap-bot manufacturing") + // tech.giveTech("dynamo-bot upgrade") + // tech.giveTech("time crystals") // tech.giveTech("ICBM") // tech.giveTech("grappling hook") // tech.giveTech("annelids") - // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); + // for (let i = 0; i < 10; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 9; i++) tech.giveTech("annelids") // for (let i = 10; i < tech.tech.length; i++) { tech.tech[i].isBanished = true } // powerUps.research.changeRerolls(100000) @@ -35,9 +35,9 @@ const level = { // tech.giveTech("extruder") // m.immuneCycle = Infinity //you can't take damage - // level.difficultyIncrease(10) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // simulation.enableConstructMode() //used to build maps in testing mode - // level.islands(); + // level.reactor(); // level.testing(); //not in rotation, used for testing if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************ // powerUps.research.changeRerolls(3000) @@ -253,8 +253,8 @@ const level = { level.levels = shuffle(level.levels); //shuffles order of maps } // level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reservoir"); //add level to the back half of the randomized levels list - level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.4, level.levels.length)), 0, "reservoir"); //add level to the back half of the randomized levels list - level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.4, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list + level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.6, level.levels.length)), 0, "reservoir"); //add level to the back half of the randomized levels list + level.levels.splice(Math.floor(Math.seededRandom((level.levels.length) * 0.6, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list level.levels.splice(0, 2); //remove 2 levels from the start of the array if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech level.levels.unshift("intro"); //add level to the start of the randomized levels list @@ -440,6 +440,69 @@ const level = { Composite.add(engine.world, constraint); return constraint }, + rotor(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + x += width / 2 + y += height / 2 + const who = body[body.length] = Bodies.rectangle(x, y, width, height, { + collisionFilter: { + category: cat.map, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + }, + isNoSetCollision: true, + isNotHoldable: true, + frictionAir: frictionAir, + friction: 1, + frictionStatic: 1, + restitution: 0, + rotationForce: rotationForce + }); + Matter.Body.setAngle(who, angle) + Matter.Body.setAngularVelocity(who, angularVelocity); + + Matter.Body.setDensity(who, density) + const constraint = Constraint.create({ //fix rotor in place, but allow rotation + pointA: { + x: who.position.x, + y: who.position.y + }, + bodyB: who, + stiffness: 1, + damping: 1 + }); + Composite.add(engine.world, constraint); + who.center = { x: who.position.x, y: who.position.y } + who.rotate = function() { + if (!m.isBodiesAsleep) { + Matter.Body.applyForce(this, { + x: this.position.x + 100, + y: this.position.y + 100 + }, { + x: this.rotationForce * this.mass, + y: 0 + }) + } else { + Matter.Body.setAngularVelocity(this, 0); + } + } + // if (rotate) { + // rotor.rotate = function() { + // if (!m.isBodiesAsleep) { + // Matter.Body.applyForce(rotor, { + // x: rotor.position.x + 100, + // y: rotor.position.y + 100 + // }, { + // x: rotate * rotor.mass, + // y: 0 + // }) + // } else { + // Matter.Body.setAngularVelocity(rotor, 0); + // } + // } + // } + + + return who + }, boost(x, y, height = 1000) { //height is how high the player will be flung above y who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("120 40 -120 40 -50 -40 50 -40"), { collisionFilter: { @@ -473,7 +536,7 @@ const level = { query(bullet) query(powerUp) //player collision - if (Matter.Query.region([player], this.boostBounds).length > 0) { + if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) { m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts m.hardLandCD = 0 // disable hard landing if (player.velocity.y > 26) { @@ -651,77 +714,77 @@ const level = { Composite.add(engine.world, who.constraint); return who }, - rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { - const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { - density: density, - isNotHoldable: true, - isNonStick: true, - collisionFilter: { - category: cat.map, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet - }, - isNoSetCollision: true, - }); - const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, { - angle: Math.PI / 2, - density: density, - isNotHoldable: true, - isNonStick: true, - collisionFilter: { - category: cat.map, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet - }, - isNoSetCollision: true, - }); - rotor = Body.create({ //combine rotor1 and rotor2 - parts: [rotor1, rotor2], - restitution: 0, - collisionFilter: { - category: cat.map, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet - }, - isNoSetCollision: true, - }); - Matter.Body.setPosition(rotor, { - x: x, - y: y - }); - Composite.add(engine.world, [rotor]); - body[body.length] = rotor1 - body[body.length] = rotor2 + // rotor(x, y, rotate = 0, radius = 800, width = 40, density = 0.0005) { + // const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { + // density: density, + // isNotHoldable: true, + // isNonStick: true, + // collisionFilter: { + // category: cat.map, + // mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + // }, + // isNoSetCollision: true, + // }); + // const rotor2 = Matter.Bodies.rectangle(x, y, width, radius, { + // angle: Math.PI / 2, + // density: density, + // isNotHoldable: true, + // isNonStick: true, + // collisionFilter: { + // category: cat.map, + // mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + // }, + // isNoSetCollision: true, + // }); + // rotor = Body.create({ //combine rotor1 and rotor2 + // parts: [rotor1, rotor2], + // restitution: 0, + // collisionFilter: { + // category: cat.map, + // mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + // }, + // isNoSetCollision: true, + // }); + // Matter.Body.setPosition(rotor, { + // x: x, + // y: y + // }); + // Composite.add(engine.world, [rotor]); + // body[body.length] = rotor1 + // body[body.length] = rotor2 - // setTimeout(function() { - // rotor.collisionFilter.category = cat.body; - // rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map - // }, 1000); + // // setTimeout(function() { + // // rotor.collisionFilter.category = cat.body; + // // rotor.collisionFilter.mask = cat.body | cat.player | cat.bullet | cat.mob | cat.mobBullet //| cat.map + // // }, 1000); - const constraint = Constraint.create({ //fix rotor in place, but allow rotation - pointA: { - x: x, - y: y - }, - bodyB: rotor - }); - Composite.add(engine.world, constraint); + // const constraint = Constraint.create({ //fix rotor in place, but allow rotation + // pointA: { + // x: x, + // y: y + // }, + // bodyB: rotor + // }); + // Composite.add(engine.world, constraint); - if (rotate) { - rotor.rotate = function() { - if (!m.isBodiesAsleep) { - Matter.Body.applyForce(rotor, { - x: rotor.position.x + 100, - y: rotor.position.y + 100 - }, { - x: rotate * rotor.mass, - y: 0 - }) - } else { - Matter.Body.setAngularVelocity(rotor, 0); - } - } - } - composite[composite.length] = rotor - return rotor - }, + // if (rotate) { + // rotor.rotate = function() { + // if (!m.isBodiesAsleep) { + // Matter.Body.applyForce(rotor, { + // x: rotor.position.x + 100, + // y: rotor.position.y + 100 + // }, { + // x: rotate * rotor.mass, + // y: 0 + // }) + // } else { + // Matter.Body.setAngularVelocity(rotor, 0); + // } + // } + // } + // composite[composite.length] = rotor + // return rotor + // }, toggle(x, y, isOn = false, isLockOn = false) { spawn.mapVertex(x + 65, y + 2, "70 10 -70 10 -40 -10 40 -10"); //toggle platform map[map.length - 1].restitution = 0; @@ -847,7 +910,7 @@ const level = { // const block = body[body.length] = Bodies.rectangle(x, y, width, height, { collisionFilter: { category: cat.map, - mask: cat.player | cat.body | cat.bullet | cat.powerUp // | cat.mob | cat.mobBullet + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet }, isNoSetCollision: true, inertia: Infinity, //prevents rotation @@ -896,7 +959,7 @@ const level = { this.returnCount = 15 } else { this.isThere = true - this.collisionFilter.mask = cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + this.collisionFilter.mask = cat.player | cat.mob | cat.body | cat.bullet | cat.powerUp | cat.mobBullet this.fadeCount = this.fadeTime //delete any overlapping blocks const blocks = Matter.Query.collides(this, body) @@ -912,6 +975,20 @@ const level = { } } } + //delete any overlapping mobs + const mobsHits = Matter.Query.collides(this, mob) + for (let i = 0; i < mobsHits.length; i++) { + if (mobsHits[i].bodyB !== this && mobsHits[i].bodyB !== m.holdingTarget) { //dont' delete yourself <----- bug here maybe... + Matter.Composite.remove(engine.world, mobsHits[i].bodyB); + mobsHits[i].bodyB.isRemoveMeNow = true + for (let i = 1; i < mob.length; i++) { //find which index in body array it is and remove from array + if (mob[i].isRemoveMeNow) { + mob.splice(i, 1); + break + } + } + } + } } } } @@ -2554,7 +2631,7 @@ const level = { level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why m.addHealth(Infinity) - spawn.starter(1900, -500, 200) //big boy + // spawn.starter(1900, -500, 200) //big boy // for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500) // spawn.slashBoss(1900, -500) // spawn.launcherBoss(3200, -500) @@ -2563,7 +2640,7 @@ const level = { // spawn.powerUpBossBaby(3200, -500) // spawn.snakeBoss(1700, -500) // spawn.streamBoss(3200, -500) - // spawn.pulsarBoss(1700, -500) + spawn.pulsarBoss(1700, -500) // spawn.spawnerBossCulture(3200, -500) // spawn.grenadierBoss(1700, -500) // spawn.growBossCulture(3200, -500) @@ -2582,7 +2659,7 @@ const level = { // for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40); // for (let i = 0; i < 5; i++) spawn.focuser(1900, -500) - // spawn.pulsar(1900, -500) + spawn.pulsar(1900, -500) // spawn.shield(mob[mob.length - 1], 1900, -500, 1); // mob[mob.length - 1].isShielded = true // spawn.nodeGroup(1200, 0, "grenadier") @@ -2601,6 +2678,8 @@ const level = { document.body.style.backgroundColor = "#d0d5df" //"#d8dadf"; // powerUps.spawnStartingPowerUps(1475, -1175); // spawn.debris(750, -2200, 3700, 16); //16 debris per level + const button = level.button(1400, 0) + button.isUp = true spawn.mapRect(-1525, -2825, 1250, 4925); spawn.mapRect(-400, -2025, 625, 925); spawn.mapRect(-400, -750, 625, 1200); @@ -2613,7 +2692,6 @@ const level = { // spawn.bodyRect(1525, -100, 100, 100, 0.3); // spawn.bodyRect(2325, -50, 125, 50, 0.3); // spawn.bodyRect(2375, -100, 50, 50, 0.3); - for (let i = 0; i < 3; ++i) powerUps.spawn(400 + 2000 * Math.random(), -25, "ammo"); spawn.mapRect(-425, 0, 4200, 2100); spawn.mapRect(175, -1250, 50, 300); @@ -2654,22 +2732,6 @@ const level = { // player.force.y -= player.mass * simulation.g * 0.4; //float player if (isDoorsLocked) { - if (!isFightOver && !(simulation.cycle % 120)) { //once a second - let isFoundBoss = false - for (let i = 0; i < mob.length; i++) { - if (mob[i].isBoss) { - isFoundBoss = true - break - } - } - if (!isFoundBoss) { - isFightOver = true - doorIn.isClosing = false - doorOut.isClosing = false - powerUps.spawnBossPowerUp(2900, -100) - } - } - // if (mob.length > 0) { // doorIn.isClosing = true // doorOut.isClosing = true @@ -2687,25 +2749,55 @@ const level = { isDoorsLocked = true doorIn.isClosing = true doorOut.isClosing = true - if (!isSpawnedBoss) { - isSpawnedBoss = true - if (Math.random() < 0.33) { - for (let i = 0, len = Math.min(simulation.difficulty / 15, 7); i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); - } else if (Math.random() < 0.5) { - for (let i = 0, len = Math.min(simulation.difficulty / 8, 8); i < len; ++i) spawn.sprayBoss(2400 - 150 * i, -225, 30, false) - } else { - for (let i = 0, len = Math.min(simulation.difficulty / 5, 11); i < len; ++i) spawn.mineBoss(1950, -250, 50, false); - } - // for (let i = 0, len = 3 + simulation.difficulty / 20; i < len; ++i) spawn.mantisBoss(1487 + 300 * i, -1525, 35, false) - } } - doorIn.openClose(); doorOut.openClose(); ctx.fillStyle = "#d5ebef" ctx.fillRect(2750, -375, 550, 375) level.enter.draw(); level.exit.drawAndCheck(); + + button.draw(); + if (button.isUp) { + button.query(); + } else if (!isSpawnedBoss) { + for (let i = 0; i < 4; ++i) { + setTimeout(() => { powerUps.spawn(300 + 800 * Math.random(), -1700, "ammo") }, 10000 * Math.random()); + } + for (let i = 0; i < 3; ++i) { + setTimeout(() => { powerUps.spawn(1800 + 800 * Math.random(), -1700, "ammo") }, 10000 * Math.random()); + } + powerUps.spawn(300 + 800 * Math.random(), -1700, "heal"); + powerUps.spawn(1800 + 800 * Math.random(), -1700, "heal"); + isSpawnedBoss = true + const scale = Math.pow(simulation.difficulty, 0.73) //hard around 30, why around 54 + if (Math.random() < 0.3) { + for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 + } else if (Math.random() < 0.45) { + for (let i = 0, len = scale * 0.17; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15 + } else if (Math.random() < 0.9) { + for (let i = 0, len = scale * 0.23; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 + } else { + for (let i = 0, len = scale * 0.1 / 3; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); + for (let i = 0, len = scale * 0.17 / 3; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) + for (let i = 0, len = scale * 0.23 / 3; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); + } + } else if (!isFightOver && !(simulation.cycle % 120)) { //once a second look for any bosses + let isFoundBoss = false + for (let i = 0; i < mob.length; i++) { + if (mob[i].isBoss) { + isFoundBoss = true + break + } + } + if (!isFoundBoss) { + isFightOver = true + doorIn.isClosing = false + doorOut.isClosing = false + powerUps.spawnBossPowerUp(2900, -100) + powerUps.spawn(2900, -200, "tech") + } + } }; level.customTopLayer = () => { // if (isDoorsLocked) { @@ -3180,7 +3272,6 @@ const level = { } else { spawn.mapVertex(-687, -700, "-150 0 150 0 150 450 0 525 -150 450"); } - //right spawn.mapVertex(425 + 437, -50, "490 0 350 80 -350 80 -490 0 -350 -80 350 -80"); spawn.mapRect(325, -100, 1070, 100); @@ -3346,13 +3437,47 @@ const level = { spawn.mapVertex(1116, -2500, "0 0 300 0 150 600 0 600"); spawn.mapVertex(584, -2500, "0 0 300 0 300 600 150 600"); - if (Math.random() < 0.33) { + if (Math.random() < 0.1) { spinnerArray.push(level.spinner(65, -300, 40, 450, 0.003, Math.PI / 2)) - } else { + } else if (Math.random() < 0.25) { spinnerArray.push(level.spinner(65, -500, 40, 500, 0.003, 0, 0, -0.015)) // spinner(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0) { const r = 250 const hexagon = `${r} 0 ${r * Math.cos(5.236)} ${r * Math.sin(5.236)} ${r * Math.cos(4.189)} ${r * Math.sin(4.189)} ${-r} 0 ${r * Math.cos(2.0944)} ${r * Math.sin(2.0944)} ${r * Math.cos(1.0472)} ${r * Math.sin(1.0472)} ` Matter.Body.setVertices(spinnerArray[spinnerArray.length - 1].bodyB, Vertices.fromPath(hexagon)) + } else { + const W = 410; + const H = 30; + spawn.bodyRect(-120, -75, W, H, 1, spawn.propsIsNotHoldable) + let b = body[body.length - 1]; + cons[cons.length] = Constraint.create({ + pointA: { + x: b.position.x - (W / 2) + 50 - 211, + y: b.position.y - 1825 + }, + bodyB: b, + pointB: { + x: -(W / 2) + 50, + y: 0 + }, + damping: 0.01, + stiffness: 0.002, + length: 1800 + }); + cons[cons.length] = Constraint.create({ + pointA: { + x: b.position.x + (W / 2) - 50 + 211, + y: b.position.y - 1825 + }, + bodyB: b, + pointB: { + x: (W / 2) - 50, + y: 0 + }, + damping: 0.01, + stiffness: 0.002, + length: 1800 + }); + Composite.add(engine.world, [cons[cons.length - 1], cons[cons.length - 2]]) } spinnerArray.push(level.spinner(50, -3325, 45, 600, 0.003, 0, 0, 0.01)) // spinner(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0) { @@ -3846,30 +3971,29 @@ const level = { drip1.draw(); drip2.draw(); drip3.draw(); - button1.query(); button1.draw(); - - rotor.rotate(); - ctx.fillStyle = "hsl(175, 15%, 76%)" ctx.fillRect(9300, 2200, 600, 400) level.exit.drawAndCheck(); - level.enter.draw(); }; level.customTopLayer = () => { + rotor.rotate(); + ctx.fillStyle = "#233" ctx.beginPath(); - ctx.arc(balance1.pointA.x, balance1.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance2.pointA.x, balance2.pointA.y) - ctx.arc(balance2.pointA.x, balance2.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance3.pointA.x, balance3.pointA.y) - ctx.arc(balance3.pointA.x, balance3.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance4.pointA.x, balance4.pointA.y) - ctx.arc(balance4.pointA.x, balance4.pointA.y, 9, 0, 2 * Math.PI); - ctx.moveTo(balance5.pointA.x, balance5.pointA.y) - ctx.arc(balance5.pointA.x, balance5.pointA.y, 9, 0, 2 * Math.PI); + ctx.arc(balance1.center.x, balance1.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance2.center.x, balance2.center.y) + ctx.arc(balance2.center.x, balance2.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance3.center.x, balance3.center.y) + ctx.arc(balance3.center.x, balance3.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance4.center.x, balance4.center.y) + ctx.arc(balance4.center.x, balance4.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(balance5.center.x, balance5.center.y) + ctx.arc(balance5.center.x, balance5.center.y, 9, 0, 2 * Math.PI); + ctx.moveTo(rotor.center.x, rotor.center.y) + ctx.arc(rotor.center.x, rotor.center.y, 9, 0, 2 * Math.PI); ctx.fill(); hazard.query(); hazard.level(button1.isUp) @@ -3976,13 +4100,14 @@ const level = { if (simulation.isHorizontalFlipped) { //flip the map horizontally level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit - rotor = level.rotor(-5100, 2475, 0.001) //rotates other direction because flipped - balance1 = level.spinner(-300 - 25, -395, 25, 390, 0.001) //entrance - balance2 = level.spinner(-2605 - 390, 500, 390, 25, 0.001) //falling - balance3 = level.spinner(-2608 - 584, 1900, 584, 25, 0.001) //falling - balance4 = level.spinner(-9300 - 25, 2205, 25, 380, 0.001) //exit - balance5 = level.spinner(-2605 - 390, 1100, 390, 25, 0.001) //falling - + // rotor(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + // rotor = level.rotor(-5100, 2475, 0.001) //rotates other direction because flipped + rotor = level.rotor(-5600, 2390, 850, 50, 0.001, 0, 0.01, 0, 0.001) //balance(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + balance1 = level.rotor(-300 - 25, -395, 25, 390, 0.001) //entrance + balance2 = level.rotor(-2605 - 390, 500, 390, 25, 0.001) //falling + balance3 = level.rotor(-2608 - 584, 1900, 584, 25, 0.001) //falling + balance4 = level.rotor(-9300 - 25, 2205, 25, 380, 0.001) //exit + balance5 = level.rotor(-2605 - 390, 1100, 390, 25, 0.001) //falling // boost1.boostBounds.min.x = -boost1.boostBounds.min.x - 100 // boost1.boostBounds.max.x = -boost1.boostBounds.max.x + 100 // level.setPosToSpawn(300, -700); //-x // no need since 0 @@ -4008,12 +4133,13 @@ const level = { }; // level.customTopLayer = () => {}; } else { - rotor = level.rotor(5100, 2475, -0.001) - balance1 = level.spinner(300, -395, 25, 390, 0.001) //entrance - balance2 = level.spinner(2605, 500, 390, 25, 0.001) //falling - balance3 = level.spinner(2608, 1900, 584, 25, 0.001) //falling - balance4 = level.spinner(9300, 2205, 25, 380, 0.001) //exit - balance5 = level.spinner(2605, 1100, 390, 25, 0.001) //falling + // rotor = level.rotor(5100, 2475, -0.001) + rotor = level.rotor(4700, 2390, 850, 50, 0.001, 0, 0.01, 0, -0.001) //balance(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + balance1 = level.rotor(300, -395, 25, 390, 0.001) //entrance + balance2 = level.rotor(2605, 500, 390, 25, 0.001) //falling + balance3 = level.rotor(2608, 1900, 584, 25, 0.001) //falling + balance4 = level.rotor(9300, 2205, 25, 380, 0.001) //exit + balance5 = level.rotor(2605, 1100, 390, 25, 0.001) //falling } }, @@ -5540,6 +5666,8 @@ const level = { }, stronghold() { // player made level by Francois 👑 from discord + simulation.makeTextLog(`stronghold by Francois`); + const boost1 = level.boost(1470, -250, 1080) const boost2 = level.boost(-370, 0, 800) const boost3 = level.boost(4865, 0, 1800) @@ -5708,6 +5836,7 @@ const level = { powerUps.addResearchToLevel() //needs to run after mobs are spawned }, basement() { // player made level by Francois 👑 from discord + simulation.makeTextLog(`basement by Francois`); let button, door, buttonDoor, buttonPlateformEnd, doorPlateform let isLevelReversed = Math.random(); if (isLevelReversed < 0.7) { @@ -5996,320 +6125,322 @@ const level = { if (simulation.difficulty > 1) spawn.nodeGroup(2330, 1850, "spawns", 8, 20, 105); powerUps.chooseRandomPowerUp(3100, 1630); }, - detours() { //by Francois from discord - level.setPosToSpawn(0, 0); //lower start - level.exit.y = 150; - spawn.mapRect(level.enter.x, 45, 100, 20); - level.exit.x = 10625; - spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); - level.defaultZoom = 1400; - simulation.zoomTransition(level.defaultZoom) - document.body.style.backgroundColor = "#d5d5d5"; - const BGColor = "rgba(0,0,0,0.1)"; - // level.fill.push({ - // x: -150, - // y: -250, - // width: 625, - // height: 325, - // color: BGColor - // }); - // level.fill.push({ - // x: 475, - // y: -520, - // width: 5375, - // height: 875, - // color: BGColor - // }); - // level.fill.push({ - // x: 5850, - // y: -1275, - // width: 2800, - // height: 2475, - // color: BGColor - // }); - // level.fill.push({ - // x: 8650, - // y: -500, - // width: 1600, - // height: 750, - // color: BGColor - // }); - // level.fill.push({ - // x: 10250, - // y: -700, - // width: 900, - // height: 950, - // color: BGColor - // }); - const balance = level.spinner(5500, -412.5, 25, 660) //entrance - const rotor = level.rotor(7000, 580, -0.001); - const doorSortieSalle = level.door(8590, -520, 20, 800, 750) - // let buttonSortieSalle - // let portalEnBas - let portalEnHaut - // let door3isClosing = false; + // detours() { //by Francois from discord + // simulation.makeTextLog(`detours by Francois`); + // level.setPosToSpawn(0, 0); //lower start + // level.exit.y = 150; + // spawn.mapRect(level.enter.x, 45, 100, 20); + // level.exit.x = 10625; + // spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); + // level.defaultZoom = 1400; + // simulation.zoomTransition(level.defaultZoom) + // document.body.style.backgroundColor = "#d5d5d5"; + // const BGColor = "rgba(0,0,0,0.1)"; + // // level.fill.push({ + // // x: -150, + // // y: -250, + // // width: 625, + // // height: 325, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 475, + // // y: -520, + // // width: 5375, + // // height: 875, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 5850, + // // y: -1275, + // // width: 2800, + // // height: 2475, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 8650, + // // y: -500, + // // width: 1600, + // // height: 750, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 10250, + // // y: -700, + // // width: 900, + // // height: 950, + // // color: BGColor + // // }); + // const balance = level.spinner(5500, -412.5, 25, 660) //entrance + // const rotor = level.rotor(7000, 580, -0.001); + // const doorSortieSalle = level.door(8590, -520, 20, 800, 750) + // // let buttonSortieSalle + // // let portalEnBas + // let portalEnHaut + // // let door3isClosing = false; - function drawOnTheMapMapRect(x, y, dx, dy) { - spawn.mapRect(x, y, dx, dy); - len = map.length - 1 - map[len].collisionFilter.category = cat.map; - map[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; - Matter.Body.setStatic(map[len], true); //make static - Composite.add(engine.world, map[len]); //add to world - simulation.draw.setPaths() //update map graphics - } + // function drawOnTheMapMapRect(x, y, dx, dy) { + // spawn.mapRect(x, y, dx, dy); + // len = map.length - 1 + // map[len].collisionFilter.category = cat.map; + // map[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; + // Matter.Body.setStatic(map[len], true); //make static + // Composite.add(engine.world, map[len]); //add to world + // simulation.draw.setPaths() //update map graphics + // } - function drawOnTheMapBodyRect(x, y, dx, dy) { - spawn.bodyRect(x, y, dx, dy); - len = body.length - 1 - body[len].collisionFilter.category = cat.body; - body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet - Composite.add(engine.world, body[len]); //add to world - body[len].classType = "body" - } + // function drawOnTheMapBodyRect(x, y, dx, dy) { + // spawn.bodyRect(x, y, dx, dy); + // len = body.length - 1 + // body[len].collisionFilter.category = cat.body; + // body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet + // Composite.add(engine.world, body[len]); //add to world + // body[len].classType = "body" + // } - function spawnCouloirEnHaut() { - // level.fill.push({ - // x: 2575, - // y: -1150, - // width: 2550, - // height: 630, - // color: BGColor - // }); - // level.fill.push({ - // x: 1900, - // y: -2300, - // width: 1650, - // height: 1150, - // color: BGColor - // }); - // level.fill.push({ - // x: 3550, - // y: -1625, - // width: 1650, - // height: 475, - // color: BGColor - // }); - // level.fill.push({ - // x: 1800, - // y: -1120, - // width: 775, - // height: 600, - // color: BGColor - // }); - drawOnTheMapMapRect(3800, -270, 75, 75); - drawOnTheMapMapRect(3900, -895, 500, 75); - drawOnTheMapMapRect(3900, -1195, 75, 375); - drawOnTheMapMapRect(3525, -1195, 450, 75); - drawOnTheMapMapRect(3525, -1995, 50, 1575); - drawOnTheMapMapRect(3325, -1995, 50, 1575); - drawOnTheMapMapRect(3525, -1670, 1675, 75); - drawOnTheMapMapRect(5100, -1670, 100, 1250); - drawOnTheMapMapRect(1800, -1195, 1575, 75); - drawOnTheMapMapRect(1800, -1520, 375, 400); - drawOnTheMapMapRect(1800, -2370, 100, 1250); - drawOnTheMapMapRect(2375, -1845, 375, 250); - drawOnTheMapMapRect(2700, -1745, 650, 75); - drawOnTheMapMapRect(1800, -2370, 1775, 100); - drawOnTheMapMapRect(3525, -2370, 50, 775); - drawOnTheMapMapRect(4650, -1220, 550, 75); - drawOnTheMapBodyRect(3225, -1845, 100, 100); - drawOnTheMapBodyRect(3575, 1255, 125, 25); - drawOnTheMapBodyRect(2450, 2255, 25, 25); - drawOnTheMapBodyRect(3975, -945, 175, 50); - drawOnTheMapBodyRect(4825, -1295, 50, 75); - drawOnTheMapBodyRect(4850, -720, 250, 200); - drawOnTheMapBodyRect(4050, -970, 25, 25); - drawOnTheMapBodyRect(3075, -1245, 50, 50); - portalEnHaut = level.portal({ - x: 3650, - y: -1470 - }, Math.PI / 2, { - x: 3250, - y: -1473 - }, Math.PI / 2) + // function spawnCouloirEnHaut() { + // // level.fill.push({ + // // x: 2575, + // // y: -1150, + // // width: 2550, + // // height: 630, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 1900, + // // y: -2300, + // // width: 1650, + // // height: 1150, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 3550, + // // y: -1625, + // // width: 1650, + // // height: 475, + // // color: BGColor + // // }); + // // level.fill.push({ + // // x: 1800, + // // y: -1120, + // // width: 775, + // // height: 600, + // // color: BGColor + // // }); + // drawOnTheMapMapRect(3800, -270, 75, 75); + // drawOnTheMapMapRect(3900, -895, 500, 75); + // drawOnTheMapMapRect(3900, -1195, 75, 375); + // drawOnTheMapMapRect(3525, -1195, 450, 75); + // drawOnTheMapMapRect(3525, -1995, 50, 1575); + // drawOnTheMapMapRect(3325, -1995, 50, 1575); + // drawOnTheMapMapRect(3525, -1670, 1675, 75); + // drawOnTheMapMapRect(5100, -1670, 100, 1250); + // drawOnTheMapMapRect(1800, -1195, 1575, 75); + // drawOnTheMapMapRect(1800, -1520, 375, 400); + // drawOnTheMapMapRect(1800, -2370, 100, 1250); + // drawOnTheMapMapRect(2375, -1845, 375, 250); + // drawOnTheMapMapRect(2700, -1745, 650, 75); + // drawOnTheMapMapRect(1800, -2370, 1775, 100); + // drawOnTheMapMapRect(3525, -2370, 50, 775); + // drawOnTheMapMapRect(4650, -1220, 550, 75); + // drawOnTheMapBodyRect(3225, -1845, 100, 100); + // drawOnTheMapBodyRect(3575, 1255, 125, 25); + // drawOnTheMapBodyRect(2450, 2255, 25, 25); + // drawOnTheMapBodyRect(3975, -945, 175, 50); + // drawOnTheMapBodyRect(4825, -1295, 50, 75); + // drawOnTheMapBodyRect(4850, -720, 250, 200); + // drawOnTheMapBodyRect(4050, -970, 25, 25); + // drawOnTheMapBodyRect(3075, -1245, 50, 50); + // portalEnHaut = level.portal({ + // x: 3650, + // y: -1470 + // }, Math.PI / 2, { + // x: 3250, + // y: -1473 + // }, Math.PI / 2) - spawn.randomSmallMob(2500, -2070 + Math.random(), 1); - spawn.randomSmallMob(5000, -1370, 1); - spawn.randomMob(5000, -645, 0.9); - spawn.randomMob(4050, -970, 0.9); - spawn.randomSmallMob(2800, -1620, 0.7); - spawn.randomMob(2400, -1370, 0.5); - spawn.randomMob(3725, -1320, 0.3); - spawn.randomGroup(2115, -2020, 0.1) + // spawn.randomSmallMob(2500, -2070 + Math.random(), 1); + // spawn.randomSmallMob(5000, -1370, 1); + // spawn.randomMob(5000, -645, 0.9); + // spawn.randomMob(4050, -970, 0.9); + // spawn.randomSmallMob(2800, -1620, 0.7); + // spawn.randomMob(2400, -1370, 0.5); + // spawn.randomMob(3725, -1320, 0.3); + // spawn.randomGroup(2115, -2020, 0.1) - powerUps.spawn(5000, -1275, "heal"); + // powerUps.spawn(5000, -1275, "heal"); - levelCustom2(); - } - ////////////////////////////////////////// - level.custom = () => { - level.exit.drawAndCheck(); - rotor.rotate(); - // rotor2.rotate() + // levelCustom2(); + // } + // ////////////////////////////////////////// + // level.custom = () => { + // level.exit.drawAndCheck(); + // rotor.rotate(); + // // rotor2.rotate() - level.enter.draw(); - }; - level.customTopLayer = () => { - doorSortieSalle.draw(); - ctx.fillStyle = "#233" - ctx.beginPath(); - ctx.arc(balance.pointA.x, balance.pointA.y, 9, 0, 2 * Math.PI); - ctx.fill(); - }; - //////////////////////////////////////// - function levelCustom2() { - level.custom = () => { - portalEnHaut[2].query(); - portalEnHaut[3].query(); - rotor.rotate(); - doorSortieSalle.openClose(); - level.exit.drawAndCheck(); + // level.enter.draw(); + // }; + // level.customTopLayer = () => { + // doorSortieSalle.draw(); + // ctx.fillStyle = "#233" + // ctx.beginPath(); + // ctx.arc(balance.pointA.x, balance.pointA.y, 9, 0, 2 * Math.PI); + // ctx.fill(); + // }; + // //////////////////////////////////////// + // function levelCustom2() { + // level.custom = () => { + // portalEnHaut[2].query(); + // portalEnHaut[3].query(); + // rotor.rotate(); + // doorSortieSalle.openClose(); + // level.exit.drawAndCheck(); - level.enter.draw(); - }; - // ////////////////////////////////////// - level.customTopLayer = () => { - doorSortieSalle.draw(); - portalEnHaut[0].draw(); - portalEnHaut[1].draw(); - portalEnHaut[2].draw(); - portalEnHaut[3].draw(); - ctx.fillStyle = "#233" - ctx.beginPath(); - ctx.arc(balance.pointA.x, balance.pointA.y, 9, 0, 2 * Math.PI); - ctx.fill(); + // level.enter.draw(); + // }; + // // ////////////////////////////////////// + // level.customTopLayer = () => { + // doorSortieSalle.draw(); + // portalEnHaut[0].draw(); + // portalEnHaut[1].draw(); + // portalEnHaut[2].draw(); + // portalEnHaut[3].draw(); + // ctx.fillStyle = "#233" + // ctx.beginPath(); + // ctx.arc(balance.pointA.x, balance.pointA.y, 9, 0, 2 * Math.PI); + // ctx.fill(); - }; - } - //spawn box - spawn.mapRect(-200, -295, 75, 425); - spawn.mapRect(-200, 55, 700, 75); - spawn.mapRect(-200, -295, 700, 75); - spawn.bodyRect(470, -220, 25, 275); //porte spawn box - //couloir - spawn.mapRect(450, -520, 50, 300); //muret gauche haut - spawn.mapRect(450, 55, 50, 300); //muret gauche bas - spawn.mapRect(1700, -520, 50, 325); //muret 2 haut - spawn.mapRect(1700, 55, 50, 300); //muret 2 bas - spawn.mapRect(4375, 55, 50, 300); - spawn.mapRect(4575, 55, 50, 300); - spawn.bodyRect(4625, 155, 75, 100); - spawn.bodyRect(4725, 230, 50, 25); - if (Math.random() > 0.5) { - powerUps.chooseRandomPowerUp(4500, 200); - } else { - powerUps.chooseRandomPowerUp(8350, -630); - } - //blocs - spawn.bodyRect(7475, 1055, 50, 75); - spawn.bodyRect(7775, 1105, 25, 25); - spawn.bodyRect(6925, 1105, 125, 25); - spawn.bodyRect(6375, 380, 50, 50); - spawn.bodyRect(6425, -220, 125, 150); - spawn.bodyRect(6475, -245, 125, 25); - spawn.bodyRect(7675, -245, 100, 50); - spawn.bodyRect(7075, -520, 50, 100); - spawn.bodyRect(8400, -595, 100, 75); - spawn.bodyRect(1700, 5, 50, 50); - spawn.bodyRect(1700, -45, 50, 50); - spawn.bodyRect(1700, -95, 50, 50); - spawn.bodyRect(1700, -145, 50, 50); - spawn.bodyRect(1700, -195, 50, 50); - spawn.mapRect(450, -520, 1600, 100); //plafond 1 - spawn.mapRect(450, 255, 1600, 100); //sol 1 - spawn.mapRect(2250, -45, 1450, 75); //entresol - spawn.mapRect(3900, -520, 2000, 100); //plafond 2 - spawn.mapRect(3900, 255, 2000, 100); //sol 2 - //grande salle - spawn.bodyRect(5900, 830, 325, 300); //bloc en bas à gauche - spawn.mapRect(5775, -1295, 2900, 100); - spawn.mapRect(5775, 1130, 2900, 100); //plancher + sol grande salle - spawn.mapRect(5925, -70, 650, 50); //plateforme middle entrée - spawn.mapRect(7575, -520, 1100, 100); //sol salle en haut à droite - spawn.mapRect(6800, -420, 450, 50); //petite plateforme transition vers salle en haut - spawn.mapRect(7750, -1295, 75, 575); //mur gauche salle en haut à droite - spawn.mapRect(6100, 430, 375, 50); //plateforme en bas, gauche rotor - spawn.mapRect(7450, -195, 1225, 75); //longue plateforme - //murs grande salle - spawn.mapRect(5775, -1295, 125, 875); - spawn.mapRect(5775, 255, 125, 975); - spawn.mapRect(8550, -1295, 125, 875); - spawn.mapRect(8550, 180, 125, 1050); - //couloir 2 - spawn.mapRect(8875, -520, 1425, 325); - spawn.mapRect(8550, -520, 1750, 100); - spawn.mapRect(8550, 180, 2625, 100); - spawn.mapRect(10175, -745, 125, 325); - spawn.mapRect(10175, -745, 1000, 125); - spawn.mapRect(11050, -745, 125, 1025); - spawn.mapRect(8875, 80, 1425, 200); - //MOBS - spawn.randomSmallMob(900, -70, 1); - spawn.randomMob(4300, 95, 1); - spawn.randomSmallMob(6250, 630, 1); - spawn.randomMob(6255, -835, 0.9); - spawn.randomMob(8200, -900, 0.7); - spawn.randomMob(5700, -270, 0.7); - spawn.randomMob(8275, -320, 0.7); - spawn.randomMob(2700, -270, 0.7); - spawn.randomMob(7575, 950, 0.5); - spawn.randomMob(7000, -695, 0.4); - spawn.randomMob(1850, -345, 0.3); - spawn.randomMob(3600, -270, 0.3); - spawn.randomMob(1500, -270, 0.2); - spawn.randomMob(1250, 55, 0.2); - spawn.randomMob(8800, -45, 0.2); - spawn.randomGroup(8025, -845, 0.2); + // }; + // } + // //spawn box + // spawn.mapRect(-200, -295, 75, 425); + // spawn.mapRect(-200, 55, 700, 75); + // spawn.mapRect(-200, -295, 700, 75); + // spawn.bodyRect(470, -220, 25, 275); //porte spawn box + // //couloir + // spawn.mapRect(450, -520, 50, 300); //muret gauche haut + // spawn.mapRect(450, 55, 50, 300); //muret gauche bas + // spawn.mapRect(1700, -520, 50, 325); //muret 2 haut + // spawn.mapRect(1700, 55, 50, 300); //muret 2 bas + // spawn.mapRect(4375, 55, 50, 300); + // spawn.mapRect(4575, 55, 50, 300); + // spawn.bodyRect(4625, 155, 75, 100); + // spawn.bodyRect(4725, 230, 50, 25); + // if (Math.random() > 0.5) { + // powerUps.chooseRandomPowerUp(4500, 200); + // } else { + // powerUps.chooseRandomPowerUp(8350, -630); + // } + // //blocs + // spawn.bodyRect(7475, 1055, 50, 75); + // spawn.bodyRect(7775, 1105, 25, 25); + // spawn.bodyRect(6925, 1105, 125, 25); + // spawn.bodyRect(6375, 380, 50, 50); + // spawn.bodyRect(6425, -220, 125, 150); + // spawn.bodyRect(6475, -245, 125, 25); + // spawn.bodyRect(7675, -245, 100, 50); + // spawn.bodyRect(7075, -520, 50, 100); + // spawn.bodyRect(8400, -595, 100, 75); + // spawn.bodyRect(1700, 5, 50, 50); + // spawn.bodyRect(1700, -45, 50, 50); + // spawn.bodyRect(1700, -95, 50, 50); + // spawn.bodyRect(1700, -145, 50, 50); + // spawn.bodyRect(1700, -195, 50, 50); + // spawn.mapRect(450, -520, 1600, 100); //plafond 1 + // spawn.mapRect(450, 255, 1600, 100); //sol 1 + // spawn.mapRect(2250, -45, 1450, 75); //entresol + // spawn.mapRect(3900, -520, 2000, 100); //plafond 2 + // spawn.mapRect(3900, 255, 2000, 100); //sol 2 + // //grande salle + // spawn.bodyRect(5900, 830, 325, 300); //bloc en bas à gauche + // spawn.mapRect(5775, -1295, 2900, 100); + // spawn.mapRect(5775, 1130, 2900, 100); //plancher + sol grande salle + // spawn.mapRect(5925, -70, 650, 50); //plateforme middle entrée + // spawn.mapRect(7575, -520, 1100, 100); //sol salle en haut à droite + // spawn.mapRect(6800, -420, 450, 50); //petite plateforme transition vers salle en haut + // spawn.mapRect(7750, -1295, 75, 575); //mur gauche salle en haut à droite + // spawn.mapRect(6100, 430, 375, 50); //plateforme en bas, gauche rotor + // spawn.mapRect(7450, -195, 1225, 75); //longue plateforme + // //murs grande salle + // spawn.mapRect(5775, -1295, 125, 875); + // spawn.mapRect(5775, 255, 125, 975); + // spawn.mapRect(8550, -1295, 125, 875); + // spawn.mapRect(8550, 180, 125, 1050); + // //couloir 2 + // spawn.mapRect(8875, -520, 1425, 325); + // spawn.mapRect(8550, -520, 1750, 100); + // spawn.mapRect(8550, 180, 2625, 100); + // spawn.mapRect(10175, -745, 125, 325); + // spawn.mapRect(10175, -745, 1000, 125); + // spawn.mapRect(11050, -745, 125, 1025); + // spawn.mapRect(8875, 80, 1425, 200); + // //MOBS + // spawn.randomSmallMob(900, -70, 1); + // spawn.randomMob(4300, 95, 1); + // spawn.randomSmallMob(6250, 630, 1); + // spawn.randomMob(6255, -835, 0.9); + // spawn.randomMob(8200, -900, 0.7); + // spawn.randomMob(5700, -270, 0.7); + // spawn.randomMob(8275, -320, 0.7); + // spawn.randomMob(2700, -270, 0.7); + // spawn.randomMob(7575, 950, 0.5); + // spawn.randomMob(7000, -695, 0.4); + // spawn.randomMob(1850, -345, 0.3); + // spawn.randomMob(3600, -270, 0.3); + // spawn.randomMob(1500, -270, 0.2); + // spawn.randomMob(1250, 55, 0.2); + // spawn.randomMob(8800, -45, 0.2); + // spawn.randomGroup(8025, -845, 0.2); - if (simulation.difficulty > 2) { - // if (Math.random() < 0.2) { - // // tether ball - // spawn.tetherBoss(8000, 630, { x: 8550, y: 680 }) - // let me = mob[mob.length - 1]; - // me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs - // this.removeCons(); //remove constraint - // spawnCouloirEnHaut() - // doorSortieSalle.isClosing = false; - // }; - // if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105); - // } else { - spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss", "pulsarBoss"]); - spawn.secondaryBossChance(8000, 630) - //find level boss index - let me - for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i].isBoss) me = mob[i] - } - if (me) { - me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs - spawnCouloirEnHaut() - doorSortieSalle.isClosing = false; - }; - } else { - spawnCouloirEnHaut() - doorSortieSalle.isClosing = false; - } - // } - } else { - spawn.randomLevelBoss(8000, 630, ["shooterBoss"]); - let me - for (let i = 0, len = mob.length; i < len; i++) { - if (mob[i].isBoss) me = mob[i] - } - if (me) { - me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs - spawnCouloirEnHaut() - doorSortieSalle.isClosing = false; - }; - } else { - spawnCouloirEnHaut() - doorSortieSalle.isClosing = false; - } - } - }, + // if (simulation.difficulty > 2) { + // // if (Math.random() < 0.2) { + // // // tether ball + // // spawn.tetherBoss(8000, 630, { x: 8550, y: 680 }) + // // let me = mob[mob.length - 1]; + // // me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs + // // this.removeCons(); //remove constraint + // // spawnCouloirEnHaut() + // // doorSortieSalle.isClosing = false; + // // }; + // // if (simulation.difficulty > 4) spawn.nodeGroup(8000, 630, "spawns", 8, 20, 105); + // // } else { + // spawn.randomLevelBoss(8000, 630, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "spiderBoss", "laserBoss", "bomberBoss", "orbitalBoss", "pulsarBoss"]); + // spawn.secondaryBossChance(8000, 630) + // //find level boss index + // let me + // for (let i = 0, len = mob.length; i < len; i++) { + // if (mob[i].isBoss) me = mob[i] + // } + // if (me) { + // me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs + // spawnCouloirEnHaut() + // doorSortieSalle.isClosing = false; + // }; + // } else { + // spawnCouloirEnHaut() + // doorSortieSalle.isClosing = false; + // } + // // } + // } else { + // spawn.randomLevelBoss(8000, 630, ["shooterBoss"]); + // let me + // for (let i = 0, len = mob.length; i < len; i++) { + // if (mob[i].isBoss) me = mob[i] + // } + // if (me) { + // me.onDeath = function() { //please don't edit the onDeath function this causes serious bugs + // spawnCouloirEnHaut() + // doorSortieSalle.isClosing = false; + // }; + // } else { + // spawnCouloirEnHaut() + // doorSortieSalle.isClosing = false; + // } + // } + // }, house() { //by Francois from discord - const rotor = level.rotor(4315, -315, -0.0002, 120, 20, 200); + simulation.makeTextLog(`house by Francois`); + const rotor = level.rotor(4251, -325, 120, 20, 200, 0, 0.01, 0, -0.0001); const hazard = level.hazard(4350, -1000, 300, 110); const doorBedroom = level.door(1152, -1150, 25, 250, 250); const doorGrenier = level.door(1152, -1625, 25, 150, 160); @@ -6785,6 +6916,7 @@ const level = { } }, perplex() { //by Oranger from discord + simulation.makeTextLog(`perplex by Oranger`); document.body.style.backgroundColor = "#dcdcde"; level.setPosToSpawn(-600, 400); spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); @@ -6806,7 +6938,8 @@ const level = { x: 1700, y: -1700 }, -Math.PI / 2) //up - const rotor = level.rotor(-200, -1950, -0.001) + // rotor(x, y, width, height, density = 0.001, angle = 0, frictionAir = 0.001, angularVelocity = 0, rotationForce = 0.0005) { + const rotor = level.rotor(-600, -1950, 800, 50, 0.001, 0, 0.01, 0, -0.001) level.custom = () => { portal[2].query(true) @@ -6969,6 +7102,7 @@ const level = { spawn.secondaryBossChance(7725, 2275) }, coliseum() { + simulation.makeTextLog(`coliseum by iNoobBoi`); level.custom = () => { level.exit.drawAndCheck(); @@ -7119,6 +7253,8 @@ const level = { spawn.secondaryBossChance(6600, 600) }, crossfire() { + simulation.makeTextLog(`crossfire by iNoobBoi`); + //*1.5 //Level Setup const slimePitOne = level.hazard(0, 850, 3800, 120); @@ -7282,6 +7418,8 @@ const level = { spawn.debris(9300, -900, 400, debrisCount); }, vats() { // Made by Dablux#6610 on Discord + simulation.makeTextLog(`vats by Dablux`); + simulation.zoomScale = 1500; level.setPosToSpawn(4400, -1060) spawn.mapRect(level.enter.x, level.enter.y + 30, 100, 20) @@ -7304,7 +7442,10 @@ const level = { const deliverySlime2 = level.hazard(3700, -461, 100, 1141) const slimePit = level.hazard(700, 1200, 2500, 1300, 0.004, "hsla(160, 100%, 35%,0.75)") const topSlime = level.hazard(800, -460, 2900, 90, 0.004, "hsla(160, 100%, 35%,0.75)") - const rotor = level.rotor(0, -725, 0.001) + // const rotor = level.rotor(0, -725, 0.001) + const rotor = level.rotor(-400, -725, 800, 50, 0.001, 0, 0.01, 0, 0.001) + + const portal = level.portal({ x: -135, y: 800 @@ -7718,6 +7859,8 @@ const level = { } }, "n-gon"() { //make by Oranger + simulation.makeTextLog(`"n-gon" by Oranger`); + document.body.style.backgroundColor = "#dcdcde"; let needGravity = []; let s = { //mech statue @@ -8121,6 +8264,8 @@ const level = { } }, tunnel() { // by Scarlettt + simulation.makeTextLog(`tunnel by Scarlettt`); + level.custom = () => { level.exit.drawAndCheck(); @@ -8593,6 +8738,8 @@ const level = { } }, run() { + simulation.makeTextLog(`run by iNoobBoi`); + addPartToMap = (len) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually map[len].collisionFilter.category = cat.map; map[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet; @@ -8943,6 +9090,8 @@ const level = { } }, islands() { + simulation.makeTextLog(`islands by Richard0820`); + const boost1 = level.boost(58500, -18264, 1300); let portal2, portal3; // const removeIndex1 = map.length - 1; diff --git a/js/player.js b/js/player.js index ebe873d..6314461 100644 --- a/js/player.js +++ b/js/player.js @@ -522,7 +522,7 @@ const m = { if (tech.isAddBlockMass && m.isHolding) dmg *= 0.15 if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0165, 0.66) if (tech.isSlowFPS) dmg *= 0.8 - if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.4 + if (tech.isHarmReduce && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.34 if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.1 if (tech.isBotArmor) dmg *= 0.93 ** b.totalBots() if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33; @@ -956,7 +956,7 @@ const m = { m.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) m.isBodiesAsleep = true; m.wakeCheck(); - // m.setMaxEnergy(); + m.setMaxEnergy(); m.hole = { isOn: false, isReady: false, @@ -971,7 +971,7 @@ const m = { } }, setMaxEnergy() { - m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 0.5 * (m.fieldUpgrades[m.fieldMode].name === "standing wave") simulation.makeTextLog(`m.maxEnergy= ${(m.maxEnergy.toFixed(2))}`) }, fieldMeterColor: "#0cf", @@ -1336,7 +1336,7 @@ const m = { //draw electricity const step = 40 ctx.beginPath(); - for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) { + for (let i = 0, len = 1.3 * tech.blockDmg; i < len; i++) { let x = m.pos.x - 20 * unit.x; let y = m.pos.y - 20 * unit.y; ctx.moveTo(x, y); @@ -1527,7 +1527,7 @@ const m = { }, { name: "standing wave", - description: "3 oscillating shields are permanently active
deflecting protects you in every direction
deflecting has 50% less recoil", //drains energy + description: "3 oscillating shields are permanently active
deflecting protects you in every direction
increase your maxenergy by 50", //drains energy //deflecting has 50% less recoil drainCD: 0, effect: () => { m.fieldBlockCD = 0; @@ -1560,7 +1560,7 @@ const m = { m.pushMass(mob[i]); this.drainCD = m.cycle + 10 } - if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 30 + if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 20 } } } @@ -1589,7 +1589,7 @@ const m = { m.pushMass(mob[i]); this.drainCD = m.cycle + 10 } - if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 30 + if (mob[i].isShielded || mob[i].shield) m.fieldCDcycle = m.cycle + 20 } } } @@ -1660,7 +1660,7 @@ const m = { mob[i].damage(tech.blockDmg * m.dmgScale) const step = 40 ctx.beginPath(); - for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) { + for (let i = 0, len = 1.3 * tech.blockDmg; i < len; i++) { let x = m.fieldPosition.x - 20 * unit.x; let y = m.fieldPosition.y - 20 * unit.y; ctx.moveTo(x, y); @@ -1967,6 +1967,11 @@ const m = { // m.eyeFillColor = m.fieldMeterColor m.hold = function() { if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 300 && (m.cycle % 2)) { + // if (tech.isBotField) { + // b.randomBot(this.position, false) + // bullet[bullet.length - 1].endCycle = simulation.cycle + 840 //14 seconds + // m.energy -= 0.35 + // } else if (tech.isSporeField) { if (tech.isSporeWorm) { const drain = 0.16 + (Math.max(bullet.length, 130) - 130) * 0.02 @@ -2111,9 +2116,9 @@ const m = { isPopping: false, isAttached: false, isOn: false, - drain: 0.0015, + drain: 0.0011, radiusLimit: 10, - damage: 0.7, + damage: 0.8, setPositionToNose() { const nose = { x: m.pos.x + 10 * Math.cos(m.angle), y: m.pos.y + 10 * Math.sin(m.angle) } Matter.Body.setPosition(this, Vector.add(nose, Vector.mult(Vector.normalise(Vector.sub(nose, m.pos)), this.circleRadius))); @@ -2355,7 +2360,6 @@ const m = { } m.plasmaBall.setPositionToNose() - //add friction for player when holding ball, more friction in vertical // const floatScale = Math.sqrt(m.plasmaBall.circleRadius) // const friction = 0.0002 * floatScale @@ -2380,10 +2384,6 @@ const m = { } else { player.force.y -= 0.5 * player.mass * simulation.g; } - - - - } else { m.fieldCDcycle = m.cycle + 90; m.plasmaBall.fire() @@ -2402,12 +2402,8 @@ const m = { } } m.drawFieldMeter("rgba(0, 0, 0, 0.2)") - m.plasmaBall.do() } - - - } else if (tech.isExtruder) { m.hold = function() { b.isExtruderOn = false @@ -2651,7 +2647,7 @@ const m = { } else { m.fieldFire = true; m.isBodiesAsleep = false; - m.drain = 0.0005 + m.drain = 0.0003 m.hold = function() { if (m.isHolding) { m.wakeCheck(); @@ -2662,7 +2658,7 @@ const m = { m.grabPowerUp(); m.lookForPickUp(); - m.drain += 0.0000025 //also increases inside tech.isTimeSkip + m.drain += 0.000002 //also increases inside tech.isTimeSkip if (m.energy > m.drain) { m.energy -= m.drain; if (m.energy < m.drain) { diff --git a/js/powerup.js b/js/powerup.js index 6b53eb3..ecac22c 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -736,7 +736,7 @@ const powerUps = { function cycle() { count++ - if (count < 600 && simulation.isChoosing) { + if (count < tech.brainStormDelay * 5 && simulation.isChoosing) { if (!(count % tech.brainStormDelay)) { powerUps.tech.effect(); document.getElementById("choose-grid").style.pointerEvents = "auto"; //turn off the normal 500ms delay diff --git a/js/simulation.js b/js/simulation.js index 50581cb..c9d9ca0 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -823,24 +823,29 @@ const simulation = { simulation.drawList = []; if (tech.isDronesTravel && m.alive) { - console.log('hi') //count drones let count = 0 + let sporeCount = 0 + let wormCount = 0 let deliveryCount = 0 for (let i = 0; i < bullet.length; ++i) { if (bullet[i].isDrone) { count++ if (bullet[i].isImproved) deliveryCount++ + } else if (bullet[i].isSpore) { + sporeCount++ + } else if (bullet[i].wormSize) { + wormCount++ } } - // count *= 2 + //respawn drones in animation frame let respawnDrones = () => { if (count > 0) { requestAnimationFrame(respawnDrones); if (!simulation.paused && !simulation.isChoosing) { - count-- const where = { x: level.enter.x + 50, y: level.enter.y - 60 } + count-- if (tech.isDroneRadioactive) { b.droneRadioactive({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5) }, 0) } else { @@ -859,6 +864,32 @@ const simulation = { } } requestAnimationFrame(respawnDrones); + + //respawn spores in animation frame + let respawnSpores = () => { + if (sporeCount > 0) { + requestAnimationFrame(respawnSpores); + if (!simulation.paused && !simulation.isChoosing) { + sporeCount-- + const where = { x: level.enter.x + 50, y: level.enter.y - 60 } + b.spore({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }) + } + } + } + requestAnimationFrame(respawnSpores); + + //respawn worms in animation frame + let respawnWorms = () => { + if (wormCount > 0) { + requestAnimationFrame(respawnWorms); + if (!simulation.paused && !simulation.isChoosing) { + wormCount-- + const where = { x: level.enter.x + 50, y: level.enter.y - 60 } + b.worm({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 120 * (Math.random() - 0.5) }) + } + } + } + requestAnimationFrame(respawnWorms); } function removeAll(array) { diff --git a/js/spawn.js b/js/spawn.js index 8f2bfef..1f51bc9 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -2988,6 +2988,7 @@ const spawn = { }, Vector.normalise(Vector.sub(this.fireTarget, this.position))); //distance between the target and the player's location if ( + m.isCloak || dot > 0.03 || // not looking at target Matter.Query.ray(map, this.fireTarget, this.position).length || Matter.Query.ray(body, this.fireTarget, this.position).length || //something blocking line of sight Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) > 1000 // distance from player to target is very far, (this is because dot product can't tell if facing 180 degrees away) @@ -3542,6 +3543,10 @@ const spawn = { spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random(), 1) Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + + me.startingDamageReduction = me.damageReduction + me.isInvulnerable = false + me.onDeath = function() { if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; @@ -3571,8 +3576,8 @@ const spawn = { if (this.speed < 0.01) { Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(Vector.sub(player.position, this.position)), 0.1)); } else { - if (Math.abs(this.velocity.y) < 15) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.07 }); - if (Math.abs(this.velocity.x) < 11) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.07, y: this.velocity.y }); + if (Math.abs(this.velocity.y) < 13) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.07 }); + if (Math.abs(this.velocity.x) < 10) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.07, y: this.velocity.y }); } } me.noFire = function() { @@ -3582,18 +3587,32 @@ const spawn = { this.phaseCycle = -2 this.do = this.burstFire this.frictionAir = 1 - if (!this.isShielded) spawn.shield(this, this.position.x, this.position.y, 1); + this.isInvulnerable = true + this.damageReduction = 0 + // if (!this.isShielded) spawn.shield(this, this.position.x, this.position.y, 1); } }; me.burstFire = function() { this.normalDoStuff(); this.radialLines() + //draw invulnerable + ctx.beginPath(); + let vertices = this.vertices; + ctx.moveTo(vertices[0].x, vertices[0].y); + for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y); + ctx.lineTo(vertices[0].x, vertices[0].y); + ctx.lineWidth = 13 + 5 * Math.random(); + ctx.strokeStyle = `rgba(255,255,255,${0.5+0.2*Math.random()})`; + ctx.stroke(); + if (!(simulation.cycle % this.burstFireFreq)) { this.phaseCycle++ if (this.phaseCycle > this.burstTotalPhases) { //start spiral fire mode this.phaseCycle = -7 this.do = this.noFire this.frictionAir = 0; + this.isInvulnerable = false + this.damageReduction = this.startingDamageReduction Matter.Body.setVelocity(this, Vector.rotate({ x: 20, y: 0 }, 2 * Math.PI * Math.random())); if (this.isShielded) { //remove shield for (let i = 0; i < mob.length; i++) { diff --git a/js/tech.js b/js/tech.js index 666ce58..65acb1d 100644 --- a/js/tech.js +++ b/js/tech.js @@ -232,7 +232,7 @@ const tech = { if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) if (tech.isMaxEnergyTech) dmg *= 1.5 - if (tech.isEnergyNoAmmo) dmg *= 1.70 + if (tech.isEnergyNoAmmo) dmg *= 1.88 if (tech.isDamageForGuns) dmg *= 1 + 0.12 * b.inventory.length if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5 if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; @@ -250,7 +250,7 @@ const tech = { return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { - return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0)) + return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0)) }, isScaleMobsWithDuplication: false, maxDuplicationEvent() { @@ -312,7 +312,7 @@ const tech = { allowed() { return !tech.isSuperDeterminism }, - requires: "NOT EXPERIMENT MODE, not superdeterminism", + requires: "not superdeterminism", effect() { powerUps.spawn(m.pos.x, m.pos.y, "gun"); // this.count-- @@ -592,7 +592,7 @@ const tech = { }, { name: "exciton", - description: `increase damage by 70%, but
${powerUps.orb.ammo()} will no longer spawn`, + description: `increase damage by 88%, but
${powerUps.orb.ammo()} will no longer spawn`, maxCount: 1, count: 0, frequency: 1, @@ -671,7 +671,7 @@ const tech = { allowed() { return !m.isShipMode && !tech.isAlwaysFire, !tech.isGrapple }, - requires: "not ship mode, not automatic, grappling hook", + requires: "not ship mode, automatic, grappling hook", effect: () => { tech.isFireMoveLock = true; b.setFireCD(); @@ -2114,7 +2114,7 @@ const tech = { allowed() { //&& (m.fieldUpgrades[m.fieldMode].name !== "molecular assembler" || m.maxEnergy > 1) return m.maxEnergy > 0.99 && m.fieldUpgrades[m.fieldMode].name !== "standing wave" && !tech.isEnergyHealth && !tech.isRewindField //&& !tech.isRewindGun }, - requires: "not standing wave, mass-energy, max energy reduction", + requires: "not standing wave, mass-energy, max energy reduction, retrocausality", effect() { tech.isRewindAvoidDeath = true; }, @@ -2910,7 +2910,7 @@ const tech = { allowed() { return (powerUps.research.count > 3 || build.isExperimentSelection) && !tech.isSuperDeterminism }, - requires: "at least 4 research and not superdeterminism", + requires: "at least 4 research, not superdeterminism", effect() { tech.renormalization = true; }, @@ -3008,7 +3008,7 @@ const tech = { effect() { tech.isBrainstorm = true tech.isBrainstormActive = false - tech.brainStormDelay = 120 + tech.brainStormDelay = 145 - simulation.difficultyMode * 10 }, remove() { tech.isBrainstorm = false @@ -3134,7 +3134,7 @@ const tech = { allowed() { return true }, - requires: "not superdeterminism", + requires: "", effect() { tech.isPauseSwitchField = true; for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); @@ -3148,7 +3148,7 @@ const tech = { }, { name: "paradigm shift", - description: `clickingtech while paused ejects them
10% chance to convert that tech into ${powerUps.orb.research(1)}`, + description: `clickingtech while paused ejects them
10% chance to convert that tech into ${powerUps.orb.research(1)}`, maxCount: 1, count: 0, frequency: 1, @@ -3193,7 +3193,7 @@ const tech = { allowed() { return (build.isExperimentSelection || powerUps.research.count > 3) && !tech.isDuplicateBoss }, - requires: "at least 4 research and not parthenogenesis", + requires: "at least 4 research, not parthenogenesis", effect() { tech.isResearchBoss = true; //abiogenesis }, @@ -3253,7 +3253,7 @@ const tech = { allowed() { return level.onLevel > 1 && !tech.isEnergyHealth }, - requires: "past levels 1, not mass-energy", + requires: "past level 1, not mass-energy", effect() { tech.isNoHeals = true; level.difficultyDecrease(simulation.difficultyMode * 2) @@ -3605,7 +3605,7 @@ const tech = { allowed() { return !tech.isSuperDeterminism }, - requires: "NOT EXPERIMENT MODE, not superdeterminism", + requires: "not superdeterminism", effect() { powerUps.spawn(m.pos.x, m.pos.y, "field"); for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); @@ -3767,7 +3767,7 @@ const tech = { allowed() { return ((tech.haveGunCheck("nail gun") && tech.isNeedles) || (tech.isNeedles && tech.haveGunCheck("shotgun"))) && !tech.isNeedleIce }, - requires: "needle gun, not needle ice", + requires: "nail gun, needle gun, not needle ice", effect() { tech.needleTunnel = true }, @@ -3825,7 +3825,7 @@ const tech = { allowed() { return ((tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate) || (tech.haveGunCheck("shotgun") && !tech.isNailShot && !tech.isFoamShot && !tech.isSporeWorm)) && !tech.isNeedles && !tech.isIceCrystals && !tech.isIceShot }, - requires: "nail gun shot gun, not ice crystal, needles, or pneumatic actuator", + requires: "nail gun, shot gun, not ice crystal, needles, or pneumatic actuator", effect() { tech.isRivets = true for (i = 0, len = b.guns.length; i < len; i++) { //find which gun @@ -4040,7 +4040,7 @@ const tech = { allowed() { return (tech.isNailShot || tech.isNeedles || tech.nailBotCount > 1 || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary }, - requires: "needles, nails, rivets, not incendiary", + requires: "nail gun, needles, nails, rivets, not incendiary", effect() { tech.isNailCrit = true }, @@ -4060,7 +4060,7 @@ const tech = { allowed() { return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) + tech.isNeedles + tech.isNailShot) * 2 > 1 }, - requires: "nail gun, nails, rivets, not ceramic needles", + requires: "nail gun, nails, rivets, mine, not ceramic needles", effect() { tech.isNailRadiation = true; }, @@ -4080,7 +4080,7 @@ const tech = { allowed() { return tech.isNailRadiation && !tech.isFastRadiation }, - requires: "irradiated nails, not 1s half-life", + requires: "nail gun, mine, irradiated nails, not 1s half-life", effect() { tech.isSlowRadiation = true; }, @@ -4100,7 +4100,7 @@ const tech = { allowed() { return tech.isNailRadiation && !tech.isSlowRadiation }, - requires: "irradiated nails, not 6s half-life", + requires: "nail gun, mine, irradiated nails, not 6s half-life", effect() { tech.isFastRadiation = true; }, @@ -4249,16 +4249,16 @@ const tech = { }, { name: "incendiary ammunition", - description: "rivets, super balls, and drones
are loaded with explosives", + description: "shotgun, rivets, super balls, and drones
are loaded with explosives", isGunTech: true, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return tech.haveGunCheck("super balls") || (tech.isRivets && !tech.isNailCrit) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) + return tech.haveGunCheck("shotgun") || tech.haveGunCheck("super balls") || (tech.isRivets && !tech.isNailCrit) || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isForeverDrones && !tech.isDroneRadioactive && !tech.isDroneTeleport) }, - requires: "super balls, rivets, drones, not irradiated drones or burst drones", + requires: "shotgun, super balls, rivets, drones, not irradiated drones or burst drones", effect() { tech.isIncendiary = true }, @@ -4581,7 +4581,7 @@ const tech = { isBot: true, isBotTech: true, allowed() { - return tech.haveGunCheck("missiles", false) + return tech.haveGunCheck("missiles", false) && tech.missileFireCD === 45 }, requires: "missiles", effect() { @@ -4778,7 +4778,7 @@ const tech = { }, { name: "MIRV", - description: "fire +1missile and grenade per shot
decrease explosionradius up to 10%", + description: "fire +1missile and grenade per shot
decrease explosionradius up to 12%", isGunTech: true, maxCount: 9, count: 0, @@ -5012,7 +5012,7 @@ const tech = { allowed() { return tech.haveGunCheck("spores") }, - requires: "spore gun", + requires: "spores", effect() { tech.isSporeGrowth = true }, @@ -5032,7 +5032,7 @@ const tech = { allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField }, - requires: "spore gun, spores", + requires: "spores", effect() { tech.isFastSpores = true }, @@ -5052,7 +5052,7 @@ const tech = { allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm }, - requires: "spore gun, spores or worms", + requires: "spores", effect() { tech.isSporeFreeze = true }, @@ -5071,7 +5071,7 @@ const tech = { allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isSporeWorm }, - requires: "spore gun, spores or worms", + requires: "spores", effect() { tech.isSporeFollow = true }, @@ -5090,7 +5090,7 @@ const tech = { allowed() { return (tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField) && !tech.isEnergyHealth || tech.isSporeWorm }, - requires: "spore gun, spores, worms, not mass-energy", + requires: "spores, not mass-energy", effect() { tech.isMutualism = true }, @@ -5129,7 +5129,7 @@ const tech = { allowed() { return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || (tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isRivets && !tech.isIceShot && !tech.isFoamShot && !tech.isNeedles && !tech.isNailShot) }, - requires: "spore gun, spores", + requires: "spores", effect() { tech.isSporeWorm = true }, @@ -5148,7 +5148,7 @@ const tech = { allowed() { return tech.isSporeWorm }, - requires: "spore gun, shotgun, worms", + requires: "spores, shotgun, worms", effect() { tech.wormSize++ }, @@ -5156,6 +5156,25 @@ const tech = { tech.wormSize = 0 } }, + { + name: "path integration", + description: "drones, spores, and worms
travel with you through levels", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (tech.haveGunCheck("spores") && tech.isSporeFollow) || tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField)) + }, + requires: "spores, diplochory, drones", + effect() { + tech.isDronesTravel = true + }, + remove() { + tech.isDronesTravel = false + } + }, { name: "anti-shear topology", link: `anti-shear topology`, @@ -5218,7 +5237,7 @@ const tech = { allowed() { return !tech.isExtraMaxEnergy && (tech.haveGunCheck("drones") || tech.isForeverDrones || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) }, - requires: "drones, not permittivity", + requires: "drones, not weak interaction", effect() { tech.isDroneGrab = true }, @@ -5247,25 +5266,6 @@ const tech = { tech.isDroneRespawn = false } }, - { - name: "autonomous navigation", - description: "drones travel with you through levels
and reset their durability", - isGunTech: true, - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)) - }, - requires: "drones", - effect() { - tech.isDronesTravel = true - }, - remove() { - tech.isDronesTravel = false - } - }, { name: "brushless motor", description: "drones rapidly rush towards their target
increase drone collision damage by 33%", @@ -5351,7 +5351,7 @@ const tech = { allowed() { return tech.isDroneRadioactive }, - requires: "drones irradiated drones", + requires: "drones, irradiated drones", effect() { tech.droneRadioDamage = 2 }, @@ -5606,7 +5606,7 @@ const tech = { allowed() { return tech.haveGunCheck("harpoon") && !tech.isFilament && !tech.isHarpoonPowerUp && !tech.isGrapple }, - requires: "harpoon, not filament, toggling harpoon, grappling hook", + requires: "harpoon, not UHMWPE, induction furnace, grappling hook", ammoBonus: 8, effect() { tech.isRailGun = true; @@ -5730,7 +5730,7 @@ const tech = { allowed() { return tech.haveGunCheck("harpoon") && !tech.isImmuneGrapple }, - requires: "railgun, not Bose–Einstein statistics", + requires: "harpoon, not bulk modulus", effect() { tech.isRailEnergyGain = true; }, @@ -5749,7 +5749,7 @@ const tech = { allowed() { return (!tech.isLargeHarpoon && tech.haveGunCheck("harpoon")) || tech.isNeedles }, - requires: "nail gun, needle gun, needle, harpoon, not Bessemer process", + requires: "needle gun, harpoon, not Bessemer process", effect() { tech.isShieldPierce = true }, @@ -5768,7 +5768,7 @@ const tech = { allowed() { return tech.haveGunCheck("harpoon") && !tech.isShieldPierce }, - requires: "harpoon not ceramics", + requires: "harpoon, not ceramics", effect() { tech.isLargeHarpoon = true; }, @@ -5778,8 +5778,9 @@ const tech = { }, { name: "smelting", + // description: `forge 3ammo into a new harpoon
fire +1harpoon with each shot`, + descriptionFunction() { return `forge ${(tech.isRailGun ?5:3)*(2+this.count)}ammo into a new harpoon
fire +1harpoon with each shot` }, // description: `spend ${powerUps.orb.ammo(2)}to upgrade the harpoon
fire +1harpoon with each shot`, - description: `forge 3ammo into a new harpoon
fire +1harpoon with each shot`, // descriptionFunction() { return `forge ${tech.isRailGun? 10: 2}ammo into a new harpoon
fire +1harpoon with each shot` }, isGunTech: true, maxCount: 9, @@ -5787,28 +5788,28 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') > 2 + this.count * 3 + return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') >= (tech.isRailGun ? 5 : 3) * (1 + this.count) }, requires: "harpoon", effect() { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "harpoon") { - b.guns[i].ammo -= 3 + this.count * 3 - console.log(3 + this.count * 3) + b.guns[i].ammo -= (tech.isRailGun ? 5 : 3) * (1 + this.count) + // console.log(3 + this.count * 3) if (b.guns[i].ammo < 0) b.guns[i].ammo = 0 simulation.updateGunHUD(); tech.extraHarpoons++; break } } - this.description = `forge ${3+(this.count+1)*3}ammo into a new harpoon
fire +1harpoon with each shot` + // this.description = `forge ${3+(this.count+1)*3}ammo into a new harpoon
fire +1harpoon with each shot` }, remove() { if (tech.extraHarpoons) { - this.description = `forge ${2}ammo into a new harpoon
fire +1harpoon with each shot` + // this.description = `forge ${2}ammo into a new harpoon
fire +1harpoon with each shot` for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "harpoon") { - b.guns[i].ammo += 2 + b.guns[i].ammo += (tech.isRailGun ? 5 : 3) simulation.updateGunHUD(); break } @@ -6081,8 +6082,8 @@ const tech = { isGunTech: true, maxCount: 9, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isWideLaser }, @@ -6239,7 +6240,7 @@ const tech = { }, requires: "standing wave, perfect diamagnetism", effect() { - tech.blockDmg += 1.75 //if you change this value also update the for loop in the electricity graphics in m.pushMass + tech.blockDmg += 2 //if you change this value also update the for loop in the electricity graphics in m.pushMass }, remove() { tech.blockDmg = 0; @@ -6354,7 +6355,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3) + return m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" }, requires: "negative mass, pilot wave", effect() { @@ -6460,7 +6461,7 @@ const tech = { allowed() { return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" }, - requires: "molecular assembler or pilot wave", + requires: "molecular assembler, pilot wave, standing wave", effect: () => { tech.isMassEnergy = true // used in m.grabPowerUp m.energy += 2 @@ -6653,6 +6654,32 @@ const tech = { } }, // { + // name: "scrap-bot manufacturing", + // link: `manufacturing`, + // description: `use ${powerUps.orb.research(1)}to repurpose molecular assembler
excess energy used to condense scrap bot `, + // isFieldTech: true, + // maxCount: 1, + // count: 0, + // frequency: 3, + // frequencyDefault: 3, + // allowed() { + // return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isIceField || tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel) + // }, + // requires: "molecular assembler, no other manufacturing, no drone tech", + // effect() { + // if (!build.isExperimentSelection) { + // for (let i = 0; i < 1; i++) { + // if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + // } + // } + // tech.isBotField = true; + // }, + // remove() { + // tech.isBotField = false; + // if (this.count > 0) powerUps.research.changeRerolls(1) + // } + // }, + // { // name: "thermal reservoir", // description: "increase your plasmadamage by 100%
plasma temporarily lowers health not energy", // isFieldTech: true, @@ -6672,7 +6699,7 @@ const tech = { // }, { name: "degenerate matter", - description: "reduce harm by 60% while your field is active", + description: "reduce harm by 66% while your field is active", isFieldTech: true, maxCount: 1, count: 0, @@ -6681,7 +6708,7 @@ const tech = { allowed() { return (m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isEnergyHealth }, - requires: "perfect diamagnetism, pilot wave, plasma, not mass-energy", + requires: "plasma torch, perfect diamagnetism, pilot wave, not mass-energy", effect() { tech.isHarmReduce = true }, @@ -6722,7 +6749,7 @@ const tech = { allowed() { return m.fieldUpgrades[m.fieldMode].name === "plasma torch" && (build.isExperimentSelection || powerUps.research.count > 0) && !tech.isPlasmaBall && !tech.isExtruder }, - requires: "plasma torch", + requires: "plasma torch, not extruder, plasma ball", effect() { tech.plasmaBotCount++; b.plasmaBot(); @@ -6861,9 +6888,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "time dilation" && !m.isShipMode && !tech.isRewindAvoidDeath && !tech.isEnergyHealth && !tech.isTimeSkip && !tech.isFreezeMobs + return m.fieldUpgrades[m.fieldMode].name === "time dilation" && !m.isShipMode && !tech.isRewindAvoidDeath && !tech.isEnergyHealth && !tech.isTimeSkip }, - requires: "time dilation, not CPT symmetry, mass-energy, timelike, Bose Einstein condensate", + requires: "time dilation, not CPT symmetry, mass-energy, timelike", effect() { tech.isRewindField = true; m.fieldUpgrades[m.fieldMode].set() @@ -7113,7 +7140,7 @@ const tech = { }, { name: "discrete optimization", - description: "increase damage by 40%
40% increased delay after firing", + description: "increase damage by 35%
35% increased delay after firing", isFieldTech: true, maxCount: 1, count: 0, @@ -7124,7 +7151,7 @@ const tech = { }, requires: "metamaterial cloaking, molecular assembler, plasma torch or pilot wave", effect() { - tech.aimDamage = 1.40 + tech.aimDamage = 1.35 b.setFireCD(); }, remove() { @@ -7174,18 +7201,18 @@ const tech = { }, { name: "virtual particles", - description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
12% chance to duplicate spawned power ups`, + description: `use ${powerUps.orb.research(4)}to exploit your field for a
12% chance to duplicate spawned power ups`, isFieldTech: true, maxCount: 1, count: 0, frequency: 3, frequencyDefault: 3, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 3) + return (m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "wormhole") && (build.isExperimentSelection || powerUps.research.count > 3) }, - requires: "wormhole", + requires: "wormhole, time dilation", effect() { - tech.wormDuplicate = 0.12 + tech.fieldDuplicate = 0.12 powerUps.setDupChance(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.13); for (let i = 0; i < 4; i++) { @@ -7193,7 +7220,7 @@ const tech = { } }, remove() { - tech.wormDuplicate = 0 + tech.fieldDuplicate = 0 powerUps.setDupChance(); //needed after adjusting duplication chance if (this.count > 0) powerUps.research.changeRerolls(4) } @@ -9748,7 +9775,7 @@ const tech = { isLongitudinal: null, is360Longitudinal: null, isShotgunReversed: null, - wormDuplicate: null, + fieldDuplicate: null, isCloakingDamage: null, harmonicEnergy: null, isFieldHarmReduction: null, @@ -9807,5 +9834,6 @@ const tech = { isFlipFlopHealth: null, isRelayEnergy: null, coyoteTime: null, - missileFireCD: null + missileFireCD: null, + isBotField: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 5855d8f..e4ae920 100644 --- a/todo.txt +++ b/todo.txt @@ -1,30 +1,58 @@ ******************************************************** NEXT PATCH ************************************************** -nematodes now wiggle their tail. it's horrible -tech: transdimensional spores renamed transdimensional worms - spawns spores -> worms +automonous navigation -> path integration + sends spores and worms and drones to the next level with you +MIRV gives 10->12% smaller radius and damage +laser tech slow light has 33% less spacing +tech exciton gives 70%->88% damage +discrete optimization: 40%->35% damage and fire delay +degenerate matter 60->66% harm reduction while field is active +virtual particles 15% duplication is now allowed for time dilation +railgun no longer uses extra ammo when firing multiple bullets with smelting + smelting now costs more ammo with railgun +plasma torch, ball, extruder all use 33% less energy, do 15% more damage +bremsstrahlung does 15% more damage +standing wave field gives 50 energy + it's cooldown for blocking shields in now 0.5->0.33 s -missiles: - 20% more ammo - no longer fire rapidly on crouch - instead crouch gives missile initial forward velocity - no crouch makes the missiles recoil back before they accelerate forward - tech: launch system - fire missiles 500% more rapidly, gives 25% ammo - doesn't work with cruse missile - tech: ICBM - cruse missile is even bigger and slower +reactor + fight now starts when you press a button, so you can prep + spawns more ammo 4->7, heals 0->2 + will no longer show up on levels 2,3,4 + fewer bosses spawn at high difficulty levels + has a small chance to spawn all 3 boss types + sprayBoss is 25% slower, but it goes immune while spraying instead of shielding -pavilion has been added back to the map rotation - this will make the game end at 13 again, and feel harder - let me know if it's absence resulted in less NaN game crashes +community maps have a short message onload giving credit to the author +new level element balance - it's basically spinners and rotors combined + I'm replacing all rotors to fix potential BUGS + sewers, house, perplex, vats -reactor sprayBoss is now harder to kill - -bug fixes +requirement text bug fixes ******************************************************** TODO ******************************************************** -bugs: requirement text man discord messages - make sure guns are listed to work with gun tech randomization +make player collisions with mobs do no harm while standing wave is active + +Mobs bypass the [shrinking thing] on pavilion + either make this for all mobs or remove it + mobs only ignore it before it has been touched and returned + +fix issues with rotor + maybe fixes NaN + vats, sewers + replace with code powered spinner + +portal: + convert graphics to bitmaps + this seems to clip the edges + issues with + the end + platformer + player doesn't fling fast enough, unless arrows are held + player can't stand on blocks + but they can jump on blocks + bring back: the old phase decoherence field