From 694ff23f611c1c3cd6ef05d3ab1c026effab7dfe Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 16 Jan 2022 08:22:31 -0800 Subject: [PATCH] slashBoss new boss: slashBoss - same as slash mob, but it's get invulnerability of course if you have upgraded bots then random bot will that type being inside slime reduces gravity by 50% through buoyancy difficulty increase for mobs harm is 2% lower per level boson composite no longer lets you pass through elevators and rotors NAND gate damage 50 -> 55.5% --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 112 ++++++++++++++++++++-------------- js/level.js | 81 ++++++++++++++----------- js/spawn.js | 166 ++++++++++++++++++++++++++++++++++++++++++++++++++- js/tech.js | 37 +++++++++--- todo.txt | 57 +++++++----------- 6 files changed, 327 insertions(+), 126 deletions(-) diff --git a/.DS_Store b/.DS_Store index 0940df6d76be908b6c6e57ac79c2ffcafc184275..0509efd49f13460447b3c8822a61a0b90165e872 100644 GIT binary patch delta 21 ccmZoMXffEJ#mp4;cd`z%A7jDhYUWN608V`d>Hq)$ delta 21 ccmZoMXffEJ#muBPXR;2nAEU$OYUWN607l6MF#rGn diff --git a/js/bullet.js b/js/bullet.js index bb7324f..486255c 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -2906,7 +2906,7 @@ const b = { // } }, onEnd() { - if (tech.isDroneRespawn) { + if (tech.isDroneRespawn && b.inventory.length) { const who = b.guns[b.activeGun] if (who.name === "drones" && who.ammo > 0 && mob.length) { b.droneRadioactive({ x: this.position.x, y: this.position.y }, 0) @@ -3320,55 +3320,57 @@ const b = { // bullet[me].turnRate = 0.005 * (Math.random() - 0.5) bullet[me].isInMap = false bullet[me].do = function() { - const whom = Matter.Query.collides(this, mob) - if (whom.length && this.speed > 20) { //if touching a mob - for (let i = 0, len = whom.length; i < len; i++) { - who = whom[i].bodyA - if (who && who.mob) { - let immune = false - for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already - if (this.immuneList[i] === who.id) { - immune = true - break + if (!m.isBodiesAsleep) { + const whom = Matter.Query.collides(this, mob) + if (whom.length && this.speed > 20) { //if touching a mob + for (let i = 0, len = whom.length; i < len; i++) { + who = whom[i].bodyA + if (who && who.mob) { + let immune = false + for (let i = 0; i < this.immuneList.length; i++) { //check if this needle has hit this mob already + if (this.immuneList[i] === who.id) { + immune = true + break + } } - } - if (!immune) { - if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) { - b.explosion(this.position, 220 * tech.nailSize + 50 * Math.random()); //makes bullet do explosive damage at end - } - this.immuneList.push(who.id) //remember that this needle has hit this mob once already - let dmg = this.dmg * tech.nailSize * b.dmgScale - if (tech.isNailRadiation) { - mobs.statusDoT(who, (tech.isFastRadiation ? 6 : 2) * tech.nailSize, tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles - dmg *= 0.25 - } - if (tech.isCrit && who.isStunned) dmg *= 4 - who.damage(dmg, tech.isShieldPierce); - if (who.alive) who.foundPlayer(); - if (who.damageReduction) { - simulation.drawList.push({ //add dmg to draw queue - x: this.position.x, - y: this.position.y, - radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3, - color: simulation.playerDmgColor, - time: simulation.drawTime - }); + if (!immune) { + if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.94) { + b.explosion(this.position, 220 * tech.nailSize + 50 * Math.random()); //makes bullet do explosive damage at end + } + this.immuneList.push(who.id) //remember that this needle has hit this mob once already + let dmg = this.dmg * tech.nailSize * b.dmgScale + if (tech.isNailRadiation) { + mobs.statusDoT(who, (tech.isFastRadiation ? 6 : 2) * tech.nailSize, tech.isSlowRadiation ? 360 : (tech.isFastRadiation ? 60 : 180)) // one tick every 30 cycles + dmg *= 0.25 + } + if (tech.isCrit && who.isStunned) dmg *= 4 + who.damage(dmg, tech.isShieldPierce); + if (who.alive) who.foundPlayer(); + if (who.damageReduction) { + simulation.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: Math.log(dmg + 1.1) * 40 * who.damageReduction + 3, + color: simulation.playerDmgColor, + time: simulation.drawTime + }); + } } } } + } else if (Matter.Query.collides(this, map).length) { //penetrate walls + if (!this.isInMap) { //turn after entering the map, but only turn once + this.isInMap = true + Matter.Body.setVelocity(this, Vector.rotate(this.velocity, 0.25 * (Math.random() - 0.5))); + Matter.Body.setAngle(this, Math.atan2(this.velocity.y, this.velocity.x)) + } + Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.98))) //move back 1/2 your velocity = moving at 1/2 speed + } else if (Matter.Query.collides(this, body).length) { //penetrate blocks + Matter.Body.setAngularVelocity(this, 0) + Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.94))) //move back 1/2 your velocity = moving at 1/2 speed + } else if (this.speed < 30) { + this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming } - } else if (Matter.Query.collides(this, map).length) { //penetrate walls - if (!this.isInMap) { //turn after entering the map, but only turn once - this.isInMap = true - Matter.Body.setVelocity(this, Vector.rotate(this.velocity, 0.25 * (Math.random() - 0.5))); - Matter.Body.setAngle(this, Math.atan2(this.velocity.y, this.velocity.x)) - } - Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.98))) //move back 1/2 your velocity = moving at 1/2 speed - } else if (Matter.Query.collides(this, body).length) { //penetrate blocks - Matter.Body.setAngularVelocity(this, 0) - Matter.Body.setPosition(this, Vector.add(this.position, Vector.mult(this.velocity, -0.94))) //move back 1/2 your velocity = moving at 1/2 speed - } else if (this.speed < 30) { - this.force.y += this.mass * 0.001; //no gravity until it slows down to improve aiming } }; } else { @@ -3541,7 +3543,25 @@ const b = { } }, randomBot(where = player.position, isKeep = true, isLaser = true) { - if (Math.random() < 0.166 && isLaser) { + if (tech.isNailBotUpgrade) { //check for upgrades first + b.nailBot(where, isKeep) + if (isKeep) tech.nailBotCount++; + } else if (tech.isFoamBotUpgrade) { + b.foamBot(where, isKeep) + if (isKeep) tech.foamBotCount++; + } else if (tech.isBoomBotUpgrade) { + b.boomBot(where, isKeep) + if (isKeep) tech.boomBotCount++; + } else if (tech.isLaserBotUpgrade) { + b.laserBot(where, isKeep) + if (isKeep) tech.laserBotCount++; + } else if (tech.isOrbitBotUpgrade) { + b.orbitBot(where, isKeep); + if (isKeep) tech.orbitBotCount++; + } else if (tech.isDynamoBotUpgrade) { + b.dynamoBot(where, isKeep) + if (isKeep) tech.dynamoBotCount++; + } else if (Math.random() < 0.166 && isLaser) { //random b.laserBot(where, isKeep) if (isKeep) tech.laserBotCount++; } else if (Math.random() < 0.2) { diff --git a/js/level.js b/js/level.js index 4ff657e..6aca0a9 100644 --- a/js/level.js +++ b/js/level.js @@ -17,10 +17,10 @@ const level = { // localSettings.levelsClearedLastGame = 10 // level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true - // m.setField("wormhole") - // b.giveGuns("laser") + // m.setField("metamaterial cloaking") + // b.giveGuns("harpoon") // for (let i = 0; i < 9; i++) tech.giveTech("slow light") - // tech.giveTech("invariant") + // tech.giveTech("boson composite") // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // tech.giveTech("charmed baryons") // tech.giveTech("tinsellated flagella") @@ -41,7 +41,7 @@ const level = { // for (let i = 0; i < 3; i++) tech.giveTech("undefined") // lore.techCount = 3 // simulation.isCheating = false //true; - // localSettings.loreCount = 1; //this sets what conversation is heard + // localSettings.loreCount = 0; //this sets what conversation is heard // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.null() @@ -137,7 +137,7 @@ const level = { if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level } - simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level + simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; // console.log(`CD = ${simulation.CDScale}`) }, @@ -149,7 +149,7 @@ const level = { if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level } if (simulation.difficulty < 1) simulation.difficulty = 0; - simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level + simulation.dmgScale = 0.4 * simulation.difficulty //damage done by mobs increases each level if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1; simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) }, @@ -241,7 +241,6 @@ const level = { level.levels.push("gauntlet"); //add level to the end of the randomized levels list level.levels.push("final"); //add level to the end of the randomized levels list } - console.log(level.levels) } }, flipHorizontal() { @@ -341,9 +340,10 @@ const level = { y += height / 2 const who = body[body.length] = Bodies.rectangle(x, y, width, height, { collisionFilter: { - category: cat.body, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + category: cat.map, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet }, + isNoSetCollision: true, isNotHoldable: true, frictionAir: frictionAir, friction: 1, @@ -435,9 +435,10 @@ const level = { force += simulation.g const who = body[body.length] = Bodies.rectangle(x, isAtTop ? maxHeight : y, width, height, { collisionFilter: { - category: cat.body, - mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet + category: cat.map, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet }, + isNoSetCollision: true, inertia: Infinity, //prevents rotation isNotHoldable: true, friction: 1, @@ -581,21 +582,32 @@ const level = { const rotor1 = Matter.Bodies.rectangle(x, y, width, radius, { density: density, isNotHoldable: true, - isNonStick: 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 + 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.body, - mask: cat.body | cat.mob | cat.mobBullet | cat.mobShield | cat.powerUp | cat.player | cat.bullet + category: cat.map, + mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet }, + isNoSetCollision: true, }); Matter.Body.setPosition(rotor, { x: x, @@ -605,10 +617,10 @@ const level = { 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: { @@ -794,8 +806,6 @@ const level = { this.isTouched = false this.collisionFilter.mask = 0 //cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet this.returnCount = this.returnTime - const size = 1 - // const vertices = [{ x: x * size, y: y, index: 0, isInternal: false }, { x: (x + width) * size, y: y, index: 1, isInternal: false }, { x: (x + width) * size, y: y + height, index: 4, isInternal: false }, { x: x * size, y: y + height, index: 3, isInternal: false }] Matter.Body.setVertices(this, this.shrinkVertices(1)) //take on harpoon shape Matter.Body.setVertices(this, vertices) //take on harpoon shape } @@ -818,7 +828,7 @@ const level = { //delete any overlapping blocks const blocks = Matter.Query.collides(this, body) for (let i = 0; i < blocks.length; i++) { - if (blocks[i].bodyB !== this) { //dont' delete yourself + if (blocks[i].bodyB !== this && blocks[i].bodyB !== m.holdingTarget) { //dont' delete yourself <----- bug here maybe... Matter.Composite.remove(engine.world, blocks[i].bodyB); blocks[i].bodyB.isRemoveMeNow = true for (let i = 1; i < body.length; i++) { //find which index in body array it is and remove from array @@ -1168,6 +1178,9 @@ const level = { x: Math.max(0.95, 1 - 0.036 * Math.abs(player.velocity.x)) * player.velocity.x, y: slowY * player.velocity.y }); + //undo 1/2 of gravity + player.force.y -= 0.5 * player.mass * simulation.g; + } //float power ups powerUpCollide = Matter.Query.region(powerUp, this) @@ -2427,16 +2440,16 @@ const level = { button.query(); button.draw(); vanish1.query(); - vanish2.query(); - vanish3.query(); - vanish4.query(); - vanish5.query(); + // vanish2.query(); + // vanish3.query(); + // vanish4.query(); + // vanish5.query(); }; const vanish1 = level.vanish(1400, -200, 200, 50) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it - const vanish2 = level.vanish(1825, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it - const vanish3 = level.vanish(1975, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it - const vanish4 = level.vanish(1825, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it - const vanish5 = level.vanish(1975, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + // const vanish2 = level.vanish(1825, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + // const vanish3 = level.vanish(1975, -150, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + // const vanish4 = level.vanish(1825, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it + // const vanish5 = level.vanish(1975, -300, 150, 150) //x, y, width, height, hide = { x: 0, y: 0 } //hide should just be somewhere behind the map so the player can't see it level.setPosToSpawn(0, -450); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); level.exit.x = 6500; @@ -2489,11 +2502,11 @@ const level = { spawn.mapRect(4850, -275, 50, 175); //??? - level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why + level.difficultyIncrease(15) //30 is near max on hard //60 is near max on why m.addHealth(Infinity) // spawn.starter(1900, -500, 200) //big boy - + spawn.slashBoss(1900, -500) // spawn.launcherBoss(3200, -500) // spawn.laserTargetingBoss(1700, -500) // spawn.powerUpBoss(3200, -500) @@ -2519,7 +2532,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") @@ -8598,7 +8611,7 @@ const level = { //Boss Spawning if (simulation.difficulty > 5) { - spawn.randomLevelBoss(-2200, -700, ["historyBoss", "powerUpBossBaby", "blockBoss", "revolutionBoss"]); + spawn.randomLevelBoss(-2200, -700, ["powerUpBossBaby", "blockBoss", "revolutionBoss"]); setTimeout(() => { simulation.makeTextLog("UNKNOWN: \"They are coming for you.\"", 600); diff --git a/js/spawn.js b/js/spawn.js index ba4b229..ca1a078 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -5,7 +5,7 @@ const spawn = { randomLevelBoss(x, y, options = [ "shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", - "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss" + "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "mantisBoss", "slashBoss" ]) { spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, @@ -3514,6 +3514,170 @@ const spawn = { ctx.setLineDash([]); } }, + slashBoss(x, y, radius = 80) { + mobs.spawn(x, y, 5, radius, "rgb(201,202,225)"); + let me = mob[mob.length - 1]; + Matter.Body.rotate(me, 2 * Math.PI * Math.random()); + me.isBoss = true; + me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + me.startingDamageReduction = me.damageReduction + me.isInvulnerable = false + me.frictionAir = 0.01 + me.seeAtDistance2 = 1000000; + me.accelMag = 0.001 + 0.0003 * simulation.accelScale; + Matter.Body.setDensity(me, 0.0005); //normal is 0.001 + me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map + me.memory = Infinity; + me.seePlayerFreq = 20 + me.lockedOn = null; + + me.torqueMagnitude = 0.00024 * me.inertia * (Math.random() > 0.5 ? -1 : 1); + me.delay = 120 * simulation.CDScale; + me.cd = 0; + me.swordRadius = 0; + me.swordVertex = 1 + me.swordRadiusMax = 1100 + 20 * simulation.difficulty; + me.swordRadiusGrowRate = me.swordRadiusMax * (0.005 + 0.0003 * simulation.difficulty) + me.isSlashing = false; + me.swordDamage = 0.07 * simulation.dmgScale + me.laserAngle = 3 * Math.PI / 5 + const seeDistance2 = 200000 + spawn.shield(me, x, y); + me.onDamage = function() {}; + me.onDeath = function() { + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + }; + me.do = function() { + this.seePlayerByHistory(); + this.attraction(); + this.checkStatus(); + if (!m.isBodiesAsleep) this.sword() //does various things depending on what stage of the sword swing + + // ctx.beginPath(); //hide map + // ctx.arc(this.position.x, this.position.y, 3000, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay + // ctx.fillStyle = "#444"; + // ctx.fill(); + }; + me.swordWaiting = function() { + if ( + this.seePlayer.recall && + this.cd < simulation.cycle && + this.distanceToPlayer2() < seeDistance2 && + Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 && + Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 + ) { + //find vertex farthest away from player + let dist = 0 + for (let i = 0, len = this.vertices.length; i < len; i++) { + const D = Vector.magnitudeSquared(Vector.sub({ x: this.vertices[i].x, y: this.vertices[i].y }, m.pos)) + if (D > dist) { + dist = D + this.swordVertex = i + } + } + this.laserAngle = this.swordVertex / 5 * 2 * Math.PI + 0.6283 + this.sword = this.swordGrow + Matter.Body.setVelocity(this, { x: 0, y: 0 }); + Matter.Body.setAngularVelocity(this, 0) + this.accelMag = 0 + this.damageReduction = 0 + this.isInvulnerable = true + this.frictionAir = 1 + } + } + me.sword = me.swordWaiting //base function that changes during different aspects of the sword swing + me.swordGrow = function() { + this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle); + this.swordRadius += this.swordRadiusGrowRate + if (this.swordRadius > this.swordRadiusMax) { + this.sword = this.swordSlash + this.spinCount = 0 + } + + 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 = 20; + ctx.strokeStyle = "rgba(255,255,255,0.7)"; + ctx.stroke(); + } + me.swordSlash = function() { + this.laserSword(this.vertices[this.swordVertex], this.angle + this.laserAngle); + this.torque += this.torqueMagnitude; + this.spinCount++ + if (this.spinCount > 80) { + this.sword = this.swordWaiting + this.swordRadius = 0 + this.accelMag = 0.001 * simulation.accelScale; + this.cd = simulation.cycle + this.delay; + this.damageReduction = this.startingDamageReduction + this.isInvulnerable = false + this.frictionAir = 0.01 + } + 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 = 20; + ctx.strokeStyle = "rgba(255,255,255,0.7)"; + ctx.stroke(); + } + me.laserSword = function(where, angle) { + const vertexCollision = function(v1, v1End, domain) { + for (let i = 0; i < domain.length; ++i) { + let v = domain[i].vertices; + const len = v.length - 1; + for (let j = 0; j < len; j++) { + results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] }; + } + } + results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] }; + } + } + }; + best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; + const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) }; + vertexCollision(where, look, body); // vertexCollision(where, look, mob); + vertexCollision(where, look, map); + if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); + if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { + m.immuneCycle = m.cycle + tech.collisionImmuneCycles + 60; //player is immune to damage for an extra second + m.damage(this.swordDamage); + simulation.drawList.push({ //add dmg to draw queue + x: best.x, + y: best.y, + radius: this.swordDamage * 1500, + color: "rgba(80,0,255,0.5)", + time: 20 + }); + } + if (best.dist2 === Infinity) best = look; + ctx.beginPath(); //draw beam + ctx.moveTo(where.x, where.y); + ctx.lineTo(best.x, best.y); + ctx.strokeStyle = "rgba(100,100,255,0.1)"; // Purple path + ctx.lineWidth = 25; + ctx.stroke(); + ctx.strokeStyle = "rgba(100,100,255,0.5)"; // Purple path + ctx.lineWidth = 5; + ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); + ctx.stroke(); // Draw it + ctx.setLineDash([]); + } + }, slasher(x, y, radius = 36 + Math.ceil(Math.random() * 25)) { mobs.spawn(x, y, 5, radius, "rgb(201,202,225)"); let me = mob[mob.length - 1]; diff --git a/js/tech.js b/js/tech.js index 89b3ca6..0bd7f03 100644 --- a/js/tech.js +++ b/js/tech.js @@ -214,7 +214,7 @@ const tech = { if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction()) if (tech.OccamDamage) dmg *= tech.OccamDamage if (tech.isCloakingDamage) dmg *= 1.35 - if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5 + if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599 if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg if (tech.isTechDamage) dmg *= 1.9 @@ -1016,7 +1016,7 @@ const tech = { { name: "nail-bot upgrade", link: `nail-bot upgrade`, - description: "convert your current bots to nail-bots
+500% fire rate and +40% nail velocity", + description: "convert your bots to nail-bots
+500% fire rate and +40% nail velocity", maxCount: 1, count: 0, frequency: 3, @@ -1072,7 +1072,7 @@ const tech = { { name: "foam-bot upgrade", link: `foam-bot upgrade`, - description: "convert your current bots to foam-bots
300% increased foam size and fire rate", + description: "convert your bots to foam-bots
300% increased foam size and fire rate", maxCount: 1, count: 0, frequency: 3, @@ -1128,7 +1128,7 @@ const tech = { { name: "boom-bot upgrade", link: `boom-bot upgrade`, - description: "convert your current bots to boom-bots
300% increased explosion damage and size", + description: "convert your bots to boom-bots
300% increased explosion damage and size", maxCount: 1, count: 0, frequency: 3, @@ -1186,7 +1186,7 @@ const tech = { { name: "laser-bot upgrade", link: `laser-bot upgrade`, - description: "convert your current bots to laser-bots
100% improved damage, efficiency, and range", // 400% increased laser-bot laser damage", + description: "convert your bots to laser-bots
100% improved damage, efficiency, and range", // 400% increased laser-bot laser damage", maxCount: 1, count: 0, frequency: 3, @@ -1242,7 +1242,7 @@ const tech = { { name: "orbital-bot upgrade", link: `orbital-bot upgrade`, - description: "convert your current bots to orbital-bots
increase damage by 300% and radius by 50%", + description: "convert your bots to orbital-bots
increase damage by 300% and radius by 50%", maxCount: 1, count: 0, frequency: 3, @@ -1307,7 +1307,7 @@ const tech = { { name: "dynamo-bot upgrade", link: `dynamo-bot upgrade`, - description: "convert your current bots to dynamo-bots
increase regen to 23 energy per second", + description: "convert your bots to dynamo-bots
increase regen to 23 energy per second", maxCount: 1, count: 0, frequency: 3, @@ -1748,7 +1748,7 @@ const tech = { }, { name: "NAND gate", - description: "if in the ON state
do 50% more damage", + description: "if in the ON state
do 55.5% more damage", maxCount: 1, count: 0, frequency: 4, @@ -6116,6 +6116,25 @@ const tech = { if (this.count > 0) powerUps.research.changeRerolls(2) } }, + { + name: "radiative equilibrium", + description: "for 10 seconds after receiving harm
increase damage by 200%", + isFieldTech: true, + maxCount: 1, + count: 0, + 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) + }, + requires: "negative mass, pilot wave", + effect() { + tech.isHarmDamage = true; + }, + remove() { + tech.isHarmDamage = false; + } + }, { name: "neutronium", description: `reduce harm by 90% when your field is active
move and jump 33% slower`, @@ -6223,7 +6242,7 @@ const tech = { }, { name: "bot manufacturing", - description: `use molecular assembler and ${powerUps.orb.research(2)}
to build 3 random bots`, + description: `use ${powerUps.orb.research(2)} to build
3 random bots`, isFieldTech: true, maxCount: 1, count: 0, diff --git a/todo.txt b/todo.txt index 35c9e3a..2ba44f6 100644 --- a/todo.txt +++ b/todo.txt @@ -1,22 +1,33 @@ ******************************************************** NEXT PATCH ************************************************** -the level list now has 2 levels randomly removed to bring the total back to 13 - 15 level play session felt too long +new boss: slashBoss - same as slash mob, but it's get invulnerability of course -tech: invariant - use energy to pause time while placing your wormhole +if you have upgraded bots then random bot will that type +being inside slime reduces gravity by 50% through buoyancy +difficulty increase for mobs harm is 2% lower per level +boson composite no longer lets you pass through elevators and rotors -reservoir level has wider platforms, and some other changes - -Zeno's paradox 83->85% harm reduction -supply chain no longer gives 5% JUNK -vector field renamed -> tensor field: also gives 7 research +NAND gate damage 50 -> 55.5% ******************************************************** TODO ******************************************************** +if you have upgraded bots then random bot will that type + might have to nerf upgraded bots in the future, but let's try it out + +variant of Occam's razor - remove 50% of your tech for each removed get: + 2 bots? + 50 energy max + +animate going to next level? + door fills in with color that climbs up vertically through the door graphic the longer you stand on door + hold crouch on door? or automatically + +make ship mode more playable and a fun option for people with trackpads joystick support? make a new boss with similar movement to powerUpBossBaby bossBaby power up boss has really smart movement + like slasher mob since it's kinda the best mob reversed version of reservoir level, start at top and press buttons to lower slime @@ -35,15 +46,6 @@ new platform element, spring toggle to on when player touches platform platform extends in any direction -vanish element: - grow as it returns? - -pull bullets back to player with crouch/field - spores? - extend to all bullets? - write custom code based on bullet type - bad for: laser, harpoon?, missile and grenade? - boss that gives nearby mobs invulnerability invulnerability needs to toggle off and on boss is only mildly aggressive @@ -102,10 +104,6 @@ make a line of constrained mobs move like a snake tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health) tech: maintenance - heals no longer spawn, but using research heals you 100% -tech reversed regression - mobs take less damage after each time you hit them, but you get +100% damage - maybe a gun tech only? - what gun? - foam tech - make it move slower, last much longer, and push away other foam bullets not sure about bouncing off walls, but that might be fun too @@ -149,21 +147,11 @@ 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: open a new tab for n-gon, spawn things in the original game based on events in new game - if you die in new die in original? - new is n-gon classic? - make a JUNK tech? -if you die in original open a tab with a new n-gon that starts on a random level with a random load out. if you clear the level you come back to life in the original? - bug - death while paused crashes game? tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage require electric reactive armor? -animate going to next level? - door fills in with color that climbs up vertically through the door graphic the longer you stand on door - hold crouch on door? or automatically - 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 @@ -357,6 +345,8 @@ n-gon outreach ideas ******************************************************** BUGS ******************************************************** +vanish element bug, crashes on touching element, happens for 1 person maybe with junk tech? + safari issues once: can't pick up blocks fixed on new map @@ -409,11 +399,6 @@ is there a way to check if the player is stuck inside the map or block ******************************************************** LEVELS ******************************************************** -new late game level that is easier if you can: platform well, jump high, immune to slime, wormhole through walls, fly fast - climb vertically to avoid rising slime - populate with multiple boss mobs that can't drop tech - bosses spawn in pairs - map: observatory button controls rotation of telescope laser beam shoots out of telescope