From e30f63ad941e16c5c68455599b3037a8c8c8b81f Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 22 Jul 2020 08:50:40 -0700 Subject: [PATCH] mod bot upgrades --- js/bullet.js | 589 +++++++++++++++++++++++++------------------------- js/game.js | 48 ++-- js/index.js | 22 +- js/level.js | 157 ++++++++------ js/mob.js | 2 +- js/mods.js | 88 +++++--- js/player.js | 28 ++- js/powerup.js | 2 +- style.css | 4 +- todo.txt | 22 +- 10 files changed, 510 insertions(+), 452 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 2dbe576..f77a635 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -966,11 +966,20 @@ const b = { }; bullet[me].do = function () {}; }, + // ************************************************************************************************** + // ************************************************************************************************** + // ******************************** Bots ********************************************* + // ************************************************************************************************** + // ************************************************************************************************** + respawnBots() { + for (let i = 0; i < mod.laserBotCount; i++) b.laserBot() + for (let i = 0; i < mod.nailBotCount; i++) b.nailBot() + for (let i = 0; i < mod.foamBotCount; i++) b.foamBot() + for (let i = 0; i < mod.boomBotCount; i++) b.boomBot() + for (let i = 0; i < mod.plasmaBotCount; i++) b.plasmaBot() + }, randomBot(where = mech.pos, isKeep = true) { - if (Math.random() < 0.05) { //very low chance of plasma bot - b.plasmaBot(where) - if (isKeep) mod.plasmaBotCount++; - } else if (Math.random() < 0.25) { + if (Math.random() < 0.25) { b.nailBot(where) if (isKeep) mod.nailBotCount++; } else if (Math.random() < 0.33) { @@ -984,11 +993,12 @@ const b = { if (isKeep) mod.boomBotCount++; } }, - nailBot(position = mech.pos) { + nailBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { const me = bullet.length; const dir = mech.angle; const RADIUS = (12 + 4 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, { + isUpgraded: isUpgraded, isBot: true, angle: dir, friction: 0, @@ -997,7 +1007,8 @@ const b = { restitution: 0.6 * (1 + 0.5 * Math.random()), dmg: 0, // 0.14 //damage done in addition to the damage from momentum minDmgSpeed: 2, - lookFrequency: 56 + Math.floor(17 * Math.random()), + // lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20, + lastLookCycle: game.cycle + 60 * Math.random(), acceleration: 0.005 * (1 + 0.5 * Math.random()), range: 70 * (1 + 0.3 * Math.random()), endCycle: Infinity, @@ -1012,7 +1023,8 @@ const b = { }, onEnd() {}, do() { - if (!(game.cycle % this.lookFrequency) && !mech.isStealth) { + if (this.lastLookCycle < game.cycle) { + this.lastLookCycle = game.cycle + 65 - this.isUpgraded * 30 let target for (let i = 0, len = mob.length; i < len; i++) { const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); @@ -1026,25 +1038,22 @@ const b = { } } } - const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) if (distanceToPlayer > this.range) { //if far away move towards player this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) - // this.frictionAir = 0.1 } else { //close to player - // this.frictionAir = 0 - //add player's velocity - Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); + Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity } } }) World.add(engine.world, bullet[me]); //add bullet to world }, - foamBot(position = mech.pos) { + foamBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { const me = bullet.length; const dir = mech.angle; const RADIUS = (10 + 5 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 6, RADIUS, { + isUpgraded: isUpgraded, isBot: true, angle: dir, friction: 0, @@ -1080,12 +1089,11 @@ const b = { const radius = 6 + 7 * Math.random() const SPEED = 29 - radius * 0.5; //(mech.crouch ? 32 : 20) - radius * 0.7; const velocity = Vector.mult(Vector.normalise(Vector.sub(target, this.position)), SPEED) - b.foam(this.position, velocity, radius) + b.foam(this.position, velocity, radius + 8 * this.isUpgraded) break; } } } - const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) if (distanceToPlayer > this.range) { //if far away move towards player this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) @@ -1096,279 +1104,12 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, - plasmaBot(position = mech.pos) { - const me = bullet.length; - const dir = mech.angle; - const RADIUS = 21 - bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, { - isBot: true, - angle: dir, - friction: 0, - frictionStatic: 0, - frictionAir: 0.05, - restitution: 1, - dmg: 0, // 0.14 //damage done in addition to the damage from momentum - minDmgSpeed: 2, - lookFrequency: 25, - cd: 0, - acceleration: 0.009, - endCycle: Infinity, - classType: "bullet", - collisionFilter: { - category: cat.bullet, - mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield - }, - lockedOn: null, - onDmg() { - this.lockedOn = null - }, - onEnd() {}, - do() { - const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) - if (distanceToPlayer > 150) { //if far away move towards player - this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) - } - Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity - - //find closest - if (!(game.cycle % this.lookFrequency)) { - this.lockedOn = null; - let closeDist = mod.isPlasmaRange * 1000; - for (let i = 0, len = mob.length; i < len; ++i) { - const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (DIST < closeDist && - Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0) { - closeDist = DIST; - this.lockedOn = mob[i] - } - } - } - - //fire plasma at target - - - if (this.lockedOn && this.lockedOn.alive && mech.fieldCDcycle < mech.cycle) { - const sub = Vector.sub(this.lockedOn.position, this.position) - const DIST = Vector.magnitude(sub); - const unit = Vector.normalise(sub) - - const DRAIN = 0.0022 - if (DIST < mod.isPlasmaRange * 550 && mech.energy > DRAIN) { - mech.energy -= DRAIN; - if (mech.energy < 0) { - mech.fieldCDcycle = mech.cycle + 120; - mech.energy = 0; - } - //calculate laser collision - let best; - let range = mod.isPlasmaRange * (140 + 300 * Math.sqrt(Math.random())) - const path = [{ - x: this.position.x, - y: this.position.y - }, - { - x: this.position.x + range * unit.x, - y: this.position.y + range * unit.y - } - ]; - const vertexCollision = function (v1, v1End, domain) { - for (let i = 0; i < domain.length; ++i) { - let vertices = domain[i].vertices; - const len = vertices.length - 1; - for (let j = 0; j < len; j++) { - results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[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: vertices[j], - v2: vertices[j + 1] - }; - } - } - } - results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[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 && (!domain[i].mob || domain[i].alive)) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; - - //check for collisions - best = { - x: null, - y: null, - dist2: Infinity, - who: null, - v1: null, - v2: null - }; - vertexCollision(path[0], path[1], mob); - vertexCollision(path[0], path[1], map); - vertexCollision(path[0], path[1], body); - if (best.dist2 != Infinity) { //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; - if (best.who.alive) { - const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* - best.who.damage(dmg); - best.who.locatePlayer(); - - //push mobs away - const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) - Matter.Body.applyForce(best.who, path[1], force) - Matter.Body.setVelocity(best.who, { //friction - x: best.who.velocity.x * 0.7, - y: best.who.velocity.y * 0.7 - }); - //draw mob damage circle - game.drawList.push({ - x: path[1].x, - y: path[1].y, - radius: Math.sqrt(dmg) * 50, - color: "rgba(255,0,255,0.2)", - time: game.drawTime * 4 - }); - } else if (!best.who.isStatic) { - //push blocks away - const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass))) - Matter.Body.applyForce(best.who, path[1], force) - } - } - - //draw blowtorch laser beam - ctx.strokeStyle = "rgba(255,0,255,0.1)" - ctx.lineWidth = 14 - ctx.beginPath(); - ctx.moveTo(path[0].x, path[0].y); - ctx.lineTo(path[1].x, path[1].y); - ctx.stroke(); - ctx.strokeStyle = "#f0f"; - ctx.lineWidth = 2 - ctx.stroke(); - - //draw electricity - let x = this.position.x + 20 * unit.x; - let y = this.position.y + 20 * unit.y; - ctx.beginPath(); - ctx.moveTo(x, y); - const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 5 - for (let i = 0; i < 4; i++) { - x += step * (unit.x + 1.5 * (Math.random() - 0.5)) - y += step * (unit.y + 1.5 * (Math.random() - 0.5)) - ctx.lineTo(x, y); - } - ctx.lineWidth = 2 * Math.random(); - ctx.stroke(); - } - } - } - }) - World.add(engine.world, bullet[me]); //add bullet to world - }, - boomBot(position = mech.pos) { - const me = bullet.length; - const dir = mech.angle; - const RADIUS = (7 + 2 * Math.random()) - bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, { - isBot: true, - angle: dir, - friction: 0, - frictionStatic: 0, - frictionAir: 0.05, - restitution: 1, - dmg: 0, - minDmgSpeed: 0, - lookFrequency: 35 + Math.floor(7 * Math.random()), - acceleration: 0.005 * (1 + 0.5 * Math.random()), - range: 500 * (1 + 0.1 * Math.random()), - endCycle: Infinity, - classType: "bullet", - collisionFilter: { - category: cat.bullet, - mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield - }, - lockedOn: null, - explode: 0, - onDmg() { - if (this.lockedOn) { - const explosionRadius = Math.min(170, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30) - if (explosionRadius > 60) { - this.explode = explosionRadius - // - //push away from player, because normal explosion knock doesn't do much - // const sub = Vector.sub(this.lockedOn.position, mech.pos) - // mag = Math.min(35, 20 / Math.sqrt(this.lockedOn.mass)) - // Matter.Body.setVelocity(this.lockedOn, Vector.mult(Vector.normalise(sub), mag)) - } - this.lockedOn = null //lose target so bot returns to player - } - }, - onEnd() {}, - do() { - if (this.explode) { - b.explosion(this.position, this.explode); //makes bullet do explosive damage at end - this.explode = 0; - } - const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) - if (distanceToPlayer > 100) { //if far away move towards player - this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) - } else if (distanceToPlayer < 250) { //close to player - Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity - //find targets - if (!(game.cycle % this.lookFrequency) && !mech.isStealth) { - this.lockedOn = null; - let closeDist = this.range; - for (let i = 0, len = mob.length; i < len; ++i) { - const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (DIST < closeDist && mob[i].dropPowerUp && - Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0) { - closeDist = DIST; - this.lockedOn = mob[i] - } - } - } - } - //punch target - if (this.lockedOn && this.lockedOn.alive) { - const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); - if (DIST - this.lockedOn.radius < this.range && - Matter.Query.ray(map, this.position, this.lockedOn.position).length === 0) { - //move towards the target - this.force = Vector.add(this.force, Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), 0.012 * this.mass)) - } - } - } - }) - World.add(engine.world, bullet[me]); //add bullet to world - }, - laserBot(position = mech.pos) { + laserBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { const me = bullet.length; const dir = mech.angle; const RADIUS = (14 + 6 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 3, RADIUS, { + isUpgraded: isUpgraded, isBot: true, angle: dir, friction: 0, @@ -1430,7 +1171,7 @@ const b = { } //hit target with laser if (this.lockedOn && this.lockedOn.alive && mech.energy > 0.15) { - mech.energy -= 0.0014 * mod.isLaserDiode + mech.energy -= 0.0014 * mod.isLaserDiode - 0.0007 * this.isUpgraded //make sure you can still see vertex const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); if (DIST - this.lockedOn.radius < this.range + 150 && @@ -1438,7 +1179,6 @@ const b = { Matter.Query.ray(body, this.vertices[0], this.lockedOn.position).length === 0) { //move towards the target this.force = Vector.add(this.force, Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), 0.0013)) - //find the closest vertex let bestVertexDistance = Infinity let bestVertex = null @@ -1472,6 +1212,272 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, + boomBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + const me = bullet.length; + const dir = mech.angle; + const RADIUS = (7 + 2 * Math.random()) + bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, { + isUpgraded: isUpgraded, + isBot: true, + angle: dir, + friction: 0, + frictionStatic: 0, + frictionAir: 0.05, + restitution: 1, + dmg: 0, + minDmgSpeed: 0, + lookFrequency: 35 + Math.floor(7 * Math.random()), + acceleration: 0.005 * (1 + 0.5 * Math.random()), + range: 500 * (1 + 0.1 * Math.random()), + endCycle: Infinity, + classType: "bullet", + collisionFilter: { + category: cat.bullet, + mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield + }, + lockedOn: null, + explode: 0, + onDmg() { + if (this.lockedOn) { + const explosionRadius = Math.min(170 + 70 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30) + if (explosionRadius > 60) { + this.explode = explosionRadius + // + //push away from player, because normal explosion knock doesn't do much + // const sub = Vector.sub(this.lockedOn.position, mech.pos) + // mag = Math.min(35, 20 / Math.sqrt(this.lockedOn.mass)) + // Matter.Body.setVelocity(this.lockedOn, Vector.mult(Vector.normalise(sub), mag)) + } + this.lockedOn = null //lose target so bot returns to player + } + }, + onEnd() {}, + do() { + if (this.explode) { + b.explosion(this.position, this.explode); //makes bullet do explosive damage at end + this.explode = 0; + } + const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) + if (distanceToPlayer > 100) { //if far away move towards player + this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) + } else if (distanceToPlayer < 250) { //close to player + Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity + //find targets + if (!(game.cycle % this.lookFrequency) && !mech.isStealth) { + this.lockedOn = null; + let closeDist = this.range; + for (let i = 0, len = mob.length; i < len; ++i) { + const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; + if (DIST < closeDist && mob[i].dropPowerUp && + Matter.Query.ray(map, this.position, mob[i].position).length === 0 && + Matter.Query.ray(body, this.position, mob[i].position).length === 0) { + closeDist = DIST; + this.lockedOn = mob[i] + } + } + } + } + //punch target + if (this.lockedOn && this.lockedOn.alive) { + const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); + if (DIST - this.lockedOn.radius < this.range && + Matter.Query.ray(map, this.position, this.lockedOn.position).length === 0) { + //move towards the target + this.force = Vector.add(this.force, Vector.mult(Vector.normalise(Vector.sub(this.lockedOn.position, this.position)), 0.012 * this.mass)) + } + } + } + }) + World.add(engine.world, bullet[me]); //add bullet to world + }, + plasmaBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + const me = bullet.length; + const dir = mech.angle; + const RADIUS = 21 + bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, { + isUpgraded: isUpgraded, + isBot: true, + angle: dir, + friction: 0, + frictionStatic: 0, + frictionAir: 0.05, + restitution: 1, + dmg: 0, // 0.14 //damage done in addition to the damage from momentum + minDmgSpeed: 2, + lookFrequency: 25, + cd: 0, + acceleration: 0.009, + endCycle: Infinity, + classType: "bullet", + collisionFilter: { + category: cat.bullet, + mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield + }, + lockedOn: null, + onDmg() { + this.lockedOn = null + }, + onEnd() {}, + do() { + const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, mech.pos)) + if (distanceToPlayer > 150) { //if far away move towards player + this.force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, this.position)), this.mass * this.acceleration) + } + Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity + //find closest + if (!(game.cycle % this.lookFrequency)) { + this.lockedOn = null; + let closeDist = mod.isPlasmaRange * 1000; + for (let i = 0, len = mob.length; i < len; ++i) { + const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; + if (DIST < closeDist && + Matter.Query.ray(map, this.position, mob[i].position).length === 0 && + Matter.Query.ray(body, this.position, mob[i].position).length === 0) { + closeDist = DIST; + this.lockedOn = mob[i] + } + } + } + //fire plasma at target + if (this.lockedOn && this.lockedOn.alive && mech.fieldCDcycle < mech.cycle) { + const sub = Vector.sub(this.lockedOn.position, this.position) + const DIST = Vector.magnitude(sub); + const unit = Vector.normalise(sub) + const DRAIN = 0.0016 - 0.0008 * this.isUpgraded + if (DIST < mod.isPlasmaRange * 550 && mech.energy > DRAIN) { + mech.energy -= DRAIN; + if (mech.energy < 0) { + mech.fieldCDcycle = mech.cycle + 120; + mech.energy = 0; + } + //calculate laser collision + let best; + let range = mod.isPlasmaRange * (140 + 300 * Math.sqrt(Math.random())) + const path = [{ + x: this.position.x, + y: this.position.y + }, + { + x: this.position.x + range * unit.x, + y: this.position.y + range * unit.y + } + ]; + const vertexCollision = function (v1, v1End, domain) { + for (let i = 0; i < domain.length; ++i) { + let vertices = domain[i].vertices; + const len = vertices.length - 1; + for (let j = 0; j < len; j++) { + results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[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: vertices[j], + v2: vertices[j + 1] + }; + } + } + } + results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[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 && (!domain[i].mob || domain[i].alive)) { + best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[0], + v2: vertices[len] + }; + } + } + } + }; + //check for collisions + best = { + x: null, + y: null, + dist2: Infinity, + who: null, + v1: null, + v2: null + }; + vertexCollision(path[0], path[1], mob); + vertexCollision(path[0], path[1], map); + vertexCollision(path[0], path[1], body); + if (best.dist2 != Infinity) { //if hitting something + path[path.length - 1] = { + x: best.x, + y: best.y + }; + if (best.who.alive) { + const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* + best.who.damage(dmg); + best.who.locatePlayer(); + //push mobs away + const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) + Matter.Body.applyForce(best.who, path[1], force) + Matter.Body.setVelocity(best.who, { //friction + x: best.who.velocity.x * 0.7, + y: best.who.velocity.y * 0.7 + }); + //draw mob damage circle + game.drawList.push({ + x: path[1].x, + y: path[1].y, + radius: Math.sqrt(dmg) * 50, + color: "rgba(255,0,255,0.2)", + time: game.drawTime * 4 + }); + } else if (!best.who.isStatic) { + //push blocks away + const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass))) + Matter.Body.applyForce(best.who, path[1], force) + } + } + //draw blowtorch laser beam + ctx.strokeStyle = "rgba(255,0,255,0.1)" + ctx.lineWidth = 14 + ctx.beginPath(); + ctx.moveTo(path[0].x, path[0].y); + ctx.lineTo(path[1].x, path[1].y); + ctx.stroke(); + ctx.strokeStyle = "#f0f"; + ctx.lineWidth = 2 + ctx.stroke(); + //draw electricity + let x = this.position.x + 20 * unit.x; + let y = this.position.y + 20 * unit.y; + ctx.beginPath(); + ctx.moveTo(x, y); + const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 5 + for (let i = 0; i < 4; i++) { + x += step * (unit.x + 1.5 * (Math.random() - 0.5)) + y += step * (unit.y + 1.5 * (Math.random() - 0.5)) + ctx.lineTo(x, y); + } + ctx.lineWidth = 2 * Math.random(); + ctx.stroke(); + } + } + } + }) + World.add(engine.world, bullet[me]); //add bullet to world + }, + // ************************************************************************************************** + // ************************************************************************************************** + // ******************************** Guns ********************************************* + // ************************************************************************************************** + // ************************************************************************************************** giveGuns(gun = "random", ammoPacks = 6) { if (gun === "random") { //find what guns player doesn't have @@ -1979,8 +1985,8 @@ const b = { name: "flak", description: "fire a cluster of short range projectiles
explodes on contact or after half a second", ammo: 0, - ammoPack: 7, - defaultAmmoPack: 7, //use to revert ammoPack after mod changes drop rate + ammoPack: 6, + defaultAmmoPack: 6, //use to revert ammoPack after mod changes drop rate have: false, isEasyToAim: false, fire() { @@ -2098,12 +2104,11 @@ const b = { for (let i = 0, len = mob.length; i < len; ++i) { if (mob[i].shield) { const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (dist < this.explodeRad) mob[i].damage(Infinity); - } else if (mob[i].alive && !mob[i].isShielded) { - const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (dist < this.explodeRad) mob[i].damage(0.8 * b.dmgScale); + if (dist < this.explodeRad) mob[i].health *= 0.8 } } + const dist = Vector.magnitude(Vector.sub(this.position, player.position)) + if (dist < this.explodeRad) mech.energy = 0 //remove player energy } } bullet[me].onDmg = function () { diff --git a/js/game.js b/js/game.js index 8f1da98..ba1973f 100644 --- a/js/game.js +++ b/js/game.js @@ -200,7 +200,7 @@ const game = { if (b.inventory[0] === b.activeGun) { let lessDamage = 1 for (let i = 0, len = b.inventory.length; i < len; i++) { - lessDamage *= 0.84 // 1 - 0.16 + lessDamage *= 0.85 // 1 - 0.15 } document.getElementById("mod-entanglement").innerHTML = " " + ((1 - lessDamage) * 100).toFixed(0) + "%" } else { @@ -908,9 +908,9 @@ const game = { ctx.stroke(); }, wireFrame() { - ctx.textAlign = "center"; - ctx.textBaseline = "middle"; - ctx.fillStyle = "#999"; + // ctx.textAlign = "center"; + // ctx.textBaseline = "middle"; + // ctx.fillStyle = "#999"; const bodies = Composite.allBodies(engine.world); ctx.beginPath(); for (let i = 0; i < bodies.length; ++i) { @@ -928,17 +928,17 @@ const game = { }, testing() { //query zones - ctx.beginPath(); - for (let i = 0, len = level.queryList.length; i < len; ++i) { - ctx.rect( - level.queryList[i].bounds.max.x, - level.queryList[i].bounds.max.y, - level.queryList[i].bounds.min.x - level.queryList[i].bounds.max.x, - level.queryList[i].bounds.min.y - level.queryList[i].bounds.max.y - ); - } - ctx.fillStyle = "rgba(0, 0, 255, 0.2)"; - ctx.fill(); + // ctx.beginPath(); + // for (let i = 0, len = level.queryList.length; i < len; ++i) { + // ctx.rect( + // level.queryList[i].bounds.max.x, + // level.queryList[i].bounds.max.y, + // level.queryList[i].bounds.min.x - level.queryList[i].bounds.max.x, + // level.queryList[i].bounds.min.y - level.queryList[i].bounds.max.y + // ); + // } + // ctx.fillStyle = "rgba(0, 0, 255, 0.2)"; + // ctx.fill(); //jump ctx.beginPath(); let bodyDraw = jumpSensor.vertices; @@ -947,10 +947,10 @@ const game = { ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y); } ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y); - ctx.fillStyle = "rgba(255, 0, 0, 0.3)"; + ctx.fillStyle = "rgba(255, 0, 0, 0.5)"; ctx.fill(); - ctx.strokeStyle = "#000"; - ctx.stroke(); + // ctx.strokeStyle = "#000"; + // ctx.stroke(); //main body ctx.beginPath(); bodyDraw = playerBody.vertices; @@ -959,9 +959,9 @@ const game = { ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y); } ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y); - ctx.fillStyle = "rgba(0, 255, 255, 0.3)"; + ctx.fillStyle = "rgba(0, 255, 255, 0.25)"; ctx.fill(); - ctx.stroke(); + // ctx.stroke(); //head ctx.beginPath(); bodyDraw = playerHead.vertices; @@ -970,9 +970,9 @@ const game = { ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y); } ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y); - ctx.fillStyle = "rgba(255, 255, 0, 0.3)"; + ctx.fillStyle = "rgba(255, 255, 0, 0.4)"; ctx.fill(); - ctx.stroke(); + // ctx.stroke(); //head sensor ctx.beginPath(); bodyDraw = headSensor.vertices; @@ -981,9 +981,9 @@ const game = { ctx.lineTo(bodyDraw[j].x, bodyDraw[j].y); } ctx.lineTo(bodyDraw[0].x, bodyDraw[0].y); - ctx.fillStyle = "rgba(0, 0, 255, 0.3)"; + ctx.fillStyle = "rgba(0, 0, 255, 0.25)"; ctx.fill(); - ctx.stroke(); + // ctx.stroke(); } }, checkLineIntersection(v1, v1End, v2, v2End) { diff --git a/js/index.js b/js/index.js index c15f8b5..ac29206 100644 --- a/js/index.js +++ b/js/index.js @@ -93,20 +93,20 @@ const build = { PAUSED               press P to resume
- damage increase: ${((mod.damageFromMods()-1)*100).toFixed(0)}% -
harm reduction: ${((1-mech.harmReduction())*100).toFixed(0)}% -
fire delay decrease: ${((1-b.fireCD)*100).toFixed(0)}%
+ damage increase: ${((mod.damageFromMods()-1)*100).toFixed(0)}% +
harm reduction: ${((1-mech.harmReduction())*100).toFixed(0)}% +
fire delay decrease: ${((1-b.fireCD)*100).toFixed(0)}%
-
health: (${(mech.health*100).toFixed(0)} / ${(mech.maxHealth*100).toFixed(0)})   energy: (${(mech.energy*100).toFixed(0)} / ${(mech.maxEnergy*100).toFixed(0)}) -
mass: ${player.mass.toFixed(1)}   rerolls: ${powerUps.reroll.rerolls} +
rerolls: ${powerUps.reroll.rerolls} +
health: (${(mech.health*100).toFixed(0)} / ${(mech.maxHealth*100).toFixed(0)})   energy: (${(mech.energy*100).toFixed(0)} / ${(mech.maxEnergy*100).toFixed(0)})
position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})   velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)}) +
mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)})   mass: ${player.mass.toFixed(1)}
-
level: ${level.levelsCleared} - ${level.levels[level.onLevel]} (${level.difficultyText()}) -
${mob.length} mobs,   ${body.length} blocks,   ${bullet.length} bullets,   ${powerUp.length} power ups -
mouse: (${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)})   ${mech.cycle} cycles +
level: ${level.levelsCleared} - ${level.levels[level.onLevel]} (${level.difficultyText()})   ${mech.cycle} cycles +
${mob.length} mobs,   ${body.length} blocks,   ${bullet.length} bullets,   ${powerUp.length} power ups +
damage difficulty scale: ${(b.dmgScale*100).toFixed(2) }%
harm difficulty scale: ${(game.dmgScale*100).toFixed(0)}% -
damage difficulty scale: ${(b.dmgScale*100).toFixed(0) }% -
heal difficulty scale: ${(game.healScale*100).toFixed(0)}% +
heal difficulty scale: ${(game.healScale*100).toFixed(1)}%
`; let countGuns = 0 let countMods = 0 @@ -407,7 +407,7 @@ function setupCanvas() { canvas.width2 = canvas.width / 2; //precalculated because I use this often (in mouse look) canvas.height2 = canvas.height / 2; canvas.diagonal = Math.sqrt(canvas.width2 * canvas.width2 + canvas.height2 * canvas.height2); - ctx.font = "15px Arial"; + ctx.font = "18px Arial"; ctx.lineJoin = "round"; ctx.lineCap = "round"; // ctx.lineCap='square'; diff --git a/js/level.js b/js/level.js index bbf6c69..ea41a18 100644 --- a/js/level.js +++ b/js/level.js @@ -16,12 +16,13 @@ const level = { // game.zoomScale = 1000; // game.setZoom(); // mech.isStealth = true; - // mod.giveMod("nail-bot"); + // mod.giveMod("bot upgrades"); + // mod.nailBotCount += 10 // b.giveGuns("ice IX") // mech.setField("plasma torch") - level.intro(); //starting level // level.testing(); + level.intro(); //starting level // level.testChamber() // level.sewers(); // level.satellite(); @@ -39,17 +40,12 @@ const level = { // spawn.pickList = ["focuser", "focuser"] level[level.levels[level.onLevel]](); //picks the current map from the the levels array } - level.levelAnnounce(); game.noCameraScroll(); game.setZoom(); level.addToWorld(); //add bodies to game engine game.draw.setPaths(); - for (let i = 0; i < mod.laserBotCount; i++) b.laserBot() - for (let i = 0; i < mod.nailBotCount; i++) b.nailBot() - for (let i = 0; i < mod.foamBotCount; i++) b.foamBot() - for (let i = 0; i < mod.boomBotCount; i++) b.boomBot() - for (let i = 0; i < mod.plasmaBotCount; i++) b.plasmaBot() + b.respawnBots(); if (mod.isArmorFromPowerUps) { mech.maxHealth += 0.05 * powerUps.totalPowerUps if (powerUps.totalPowerUps) game.makeTextLog(" max health increased by " + (0.05 * powerUps.totalPowerUps * 100).toFixed(0) + "%", 300) @@ -121,6 +117,19 @@ const level = { } } } + //remove block if touching + touching = Matter.Query.collides(this, body) + if (touching.length !== 0) { + if (body.length) { + for (let i = 0; i < body.length; i++) { + if (body[i] === touching[0].bodyB) { + body.splice(i, 1); + break; + } + } + } + Matter.World.remove(engine.world, touching[0].bodyB); + } } const portalA = composite[composite.length] = Bodies.rectangle(centerA.x, centerA.y, width, height, { @@ -172,6 +181,30 @@ const level = { return [portalA, portalB, mapA, mapB] }, testChamber() { + level.setPosToSpawn(0, -50); //lower start + level.exit.y = level.enter.y - 550; + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.exit.x = level.enter.x; + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); + level.defaultZoom = 2000 + game.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#444"; + + level.fillBG.push({ //full map white + x: -375, + y: -3700, + width: 2975, + height: 3800, + color: "#ddd" + }); + + level.fillBG.push({ //exit room + x: -300, + y: -1000, + width: 650, + height: 500, + color: "#d4f4f4" + }); const portal = level.portal({ x: 2500, y: -75 @@ -188,19 +221,6 @@ const level = { y: -2150 }, -Math.PI / 2) //up - const hazard = level.hazard(175, -2050, 1050, 10, 0.15, "hsl(0, 100%, 50%)") //laser - const hazard2 = level.hazard(1775, -2550, 150, 10, 0.15, "hsl(0, 100%, 50%)") //laser - const button = level.button(2100, -2600) - - level.setPosToSpawn(0, -50); //lower start - level.exit.y = level.enter.y - 550; - level.fillBG.push({ - x: -300, - y: -1000, - width: 650, - height: 500, - color: "#d4f4f4" - }); const portal3 = level.portal({ x: 1850, y: -550 @@ -208,6 +228,9 @@ const level = { x: 2425, y: -600 }, -2 * Math.PI / 3) //up left + const hazard = level.hazard(175, -2050, 1050, 10, 0.15, "hsl(0, 100%, 50%)") //laser + const hazard2 = level.hazard(1775, -2550, 150, 10, 0.15, "hsl(0, 100%, 50%)") //laser + const button = level.button(2100, -2600) level.custom = () => { level.playerExitCheck(); @@ -245,13 +268,6 @@ const level = { portal3[2].draw(); portal3[3].draw(); }; - spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - level.exit.x = level.enter.x; - spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); - - level.defaultZoom = 2000 - game.zoomTransition(level.defaultZoom) - document.body.style.backgroundColor = "#dcdcde"; powerUps.spawnStartingPowerUps(1975, -3075); const powerUpPos = shuffle([{ //no debris on this level but 2 random spawn instead @@ -278,22 +294,24 @@ const level = { spawn.mapRect(-400, 0, 3100, 200); //floor //lower entrance /exit - spawn.mapRect(300, -550, 50, 350); //right entrance wall - spawn.mapRect(-400, -550, 1825, 50); //ceiling - spawn.bodyRect(312, -750, 25, 200); - spawn.mapRect(1075, -100, 575, 200); - spawn.bodyRect(1775, -75, 75, 75); + // spawn.mapRect(300, -550, 50, 350); //right entrance wall + // spawn.mapRect(-400, -550, 1825, 50); //ceiling + // spawn.mapRect(1075, -100, 575, 200); + // spawn.bodyRect(312, -200, 25, 200); + // spawn.bodyRect(1775, -75, 100, 100); + spawn.mapRect(1075, -375, 50, 225); + spawn.bodyRect(1087, -150, 25, 150); //upper entrance / exit spawn.mapRect(-400, -1050, 750, 50); spawn.mapRect(300, -1050, 50, 300); - spawn.bodyRect(312, -200, 25, 200); + spawn.bodyRect(312, -750, 25, 200); // spawn.mapRect(1400, -1025, 50, 300); // spawn.mapRect(1400, -1025, 50, 825); spawn.mapRect(600, -600, 275, 75); spawn.bodyRect(675, -725, 125, 125); spawn.mapRect(1075, -1050, 550, 400); - spawn.mapRect(300, -550, 1475, 250); + spawn.mapRect(-400, -550, 2175, 250); spawn.mapRect(-200, -1700, 150, 25); //platform above exit room spawn.mapRect(-200, -1325, 350, 25); @@ -332,30 +350,37 @@ const level = { spawn.mapRect(0, -1975, 175, 50); spawn.mapRect(1225, -1975, 175, 50); - spawn.mapRect(150, -2150, 50, 225); - spawn.mapRect(1200, -2150, 50, 225); + spawn.mapRect(150, -2150, 25, 225); + spawn.mapRect(1225, -2150, 25, 225); - - spawn.randomMob(1075, -3500, 0.2); - spawn.randomMob(-75, -3425, 0.2); - spawn.randomMob(1475, -225, 0.3); - spawn.randomMob(2075, -150, 0.5); - spawn.randomMob(2175, -700, 0.5); - if (game.difficulty > 40) { - spawn.randomMob(2300, -2775, 0.4); - spawn.randomMob(600, -925, 0.1); - spawn.randomMob(1550, -2750, 0.3); - spawn.randomMob(1350, -1150, 0.4); - spawn.randomMob(-75, -1475, 0.6); + //mobs + spawn.randomMob(1075, -3500, 0); + // spawn.randomMob(-75, -3425, 0.2); + spawn.randomMob(1475, -225, 0); + spawn.randomMob(2075, -150, 0); + spawn.randomMob(2175, -700, 0); + spawn.randomMob(-75, -850, 0.1); + spawn.randomMob(1300, -600, 0.1); + spawn.randomMob(550, -3400, 0.1); + if (game.difficulty > 50) { + spawn.randomMob(2300, -2775, -0.5); + spawn.randomMob(600, -925, -0.5); + spawn.randomMob(1550, -2750, -0.5); + spawn.randomMob(1350, -1150, -0.5); + spawn.randomMob(-75, -1475, 0); + spawn.randomBoss(600, -2600, 0); } - if (game.difficulty > 24) spawn.randomBoss(600, -2600, 0.4); - if (game.difficulty > 12) { - spawn.randomLevelBoss(700, -1550, ["shooterBoss", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"]); - } else { - // spawn.randomMob(700, -1650, 1); - spawn.randomMob(600, -3500, 1); - spawn.randomMob(-75, -1175, 1); + if (game.difficulty < 30) { + spawn.randomMob(700, -1650, 0); + spawn.randomMob(600, -3500, 0.2); + spawn.randomMob(-75, -1175, 0.2); powerUps.spawnBossPowerUp(-125, -1760); + } else { + if (Math.random() < 0.5) { + spawn.randomLevelBoss(700, -1550, ["shooterBoss", "launcherBoss", "laserTargetingBoss"]); + } else { + spawn.randomLevelBoss(675, -2775, ["shooterBoss", "launcherBoss", "laserTargetingBoss"]); + } } powerUps.addRerollToLevel() //needs to run after mobs are spawned }, @@ -2304,26 +2329,26 @@ const level = { // if (level.isBuildRun) num++ for (let i = 0; i < num; i++) { game.difficulty++ - game.dmgScale += 0.21; //damage done by mobs increases each level - b.dmgScale *= 0.91; //damage done by player decreases each level + game.dmgScale += 0.25; //damage done by mobs increases each level + b.dmgScale *= 0.92; //damage done by player decreases each level game.accelScale *= 1.027 //mob acceleration increases each level - game.lookFreqScale *= 0.974 //mob cycles between looks decreases each level - game.CDScale *= 0.964 //mob CD time decreases each level + game.lookFreqScale *= 0.975 //mob cycles between looks decreases each level + game.CDScale *= 0.966 //mob CD time decreases each level } - game.healScale = 1 / (1 + game.difficulty * 0.09) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; + game.healScale = 1 / (1 + game.difficulty * 0.08) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; }, difficultyDecrease(num = 1) { //used in easy mode for game.reset() for (let i = 0; i < num; i++) { game.difficulty-- - game.dmgScale -= 0.21; //damage done by mobs increases each level + game.dmgScale -= 0.25; //damage done by mobs increases each level if (game.dmgScale < 0.1) game.dmgScale = 0.1; - b.dmgScale /= 0.91; //damage done by player decreases each level + b.dmgScale /= 0.92; //damage done by player decreases each level game.accelScale /= 1.027 //mob acceleration increases each level - game.lookFreqScale /= 0.974 //mob cycles between looks decreases each level - game.CDScale /= 0.964 //mob CD time decreases each level + game.lookFreqScale /= 0.975 //mob cycles between looks decreases each level + game.CDScale /= 0.966 //mob CD time decreases each level } if (game.difficulty < 1) game.difficulty = 0; - game.healScale = 1 / (1 + game.difficulty * 0.09) + game.healScale = 1 / (1 + game.difficulty * 0.08) }, difficultyText(mode = document.getElementById("difficulty-select").value) { if (mode === "0") { diff --git a/js/mob.js b/js/mob.js index 032fc1d..f95a327 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1026,7 +1026,7 @@ const mobs = { } else if (Math.random() < 0.5 && !mod.isSuperDeterminism) { type = "reroll" } - for (let i = 0, len = 1 + Math.ceil(2 * Math.random()); i < len; i++) { + for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) { powerUps.spawn(this.position.x, this.position.y, type); if (Math.random() < mod.bayesian) powerUps.spawn(this.position.x, this.position.y, type); } diff --git a/js/mods.js b/js/mods.js index 7fdcfad..eb244d7 100644 --- a/js/mods.js +++ b/js/mods.js @@ -204,9 +204,9 @@ const mod = { maxCount: 1, count: 0, allowed() { - return true + return mech.harmReduction() < 1 }, - requires: "", + requires: "some harm reduction", effect() { mod.isHarmDamage = true; }, @@ -460,13 +460,13 @@ const mod = { }, { name: "bot fabrication", - description: "anytime you collect 3 rerolls
use them to build a random bot", + description: "anytime you collect 4 rerolls
use them to build a random bot", maxCount: 1, count: 0, allowed() { - return powerUps.reroll.rerolls > 2 || build.isCustomSelection + return powerUps.reroll.rerolls > 3 || build.isCustomSelection }, - requires: "at least 3 rerolls", + requires: "at least 4 rerolls", effect() { mod.isRerollBots = true; powerUps.reroll.changeRerolls(0) @@ -493,7 +493,23 @@ const mod = { }, { name: "perimeter defense", - description: "reduce harm by 6%
for each of your permanent bots", + description: "reduce harm by 4%
for each of your permanent bots", + maxCount: 1, + count: 0, + allowed() { + return mod.totalBots() > 4 && !mod.isEnergyHealth + }, + requires: "5 or more bots", + effect() { + mod.isBotArmor = true + }, + remove() { + mod.isBotArmor = false + } + }, + { + name: "bot upgrades", + description: "50% improved: nail fire rate, boom explosion,
foam size, laser drain, and plasma drain", maxCount: 1, count: 0, allowed() { @@ -501,10 +517,16 @@ const mod = { }, requires: "2 or more bots", effect() { - mod.isBotArmor = true + mod.isBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].isBot) bullet[i].isUpgraded = true + } }, remove() { - mod.isBotArmor = false + mod.isBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].isBot) bullet[i].isUpgraded = false + } } }, { @@ -514,9 +536,9 @@ const mod = { count: 0, // isNonRefundable: true, allowed() { - return mod.totalBots() > 1 + return mod.totalBots() > 2 }, - requires: "2 or more bots", + requires: "3 or more bots", effect() { //remove ammo for (let i = 0, len = b.guns.length; i < len; ++i) { @@ -627,9 +649,9 @@ const mod = { maxCount: 1, count: 0, allowed() { - return !mod.isEnergyHealth + return !mod.isEnergyHealth && mech.harmReduction() < 1 }, - requires: "not mass-energy equivalence", + requires: "some harm reduction", effect() { mod.isHarmArmor = true; }, @@ -677,7 +699,7 @@ const mod = { game.boldActiveGunHUD(); }, 1000); }, - description: "while your first gun is equipped
reduce harm by 16% for each of your guns", + description: "while your first gun is equipped
reduce harm by 15% for each of your guns", maxCount: 1, count: 0, allowed() { @@ -740,7 +762,7 @@ const mod = { }, requires: "not piezoelectricity
or acute stress response", effect: () => { - // mech.health = 0 + mech.health = 0 // mech.displayHealth(); document.getElementById("health").style.display = "none" document.getElementById("health-bg").style.display = "none" @@ -752,7 +774,7 @@ const mod = { document.getElementById("health").style.display = "inline" document.getElementById("health-bg").style.display = "inline" document.getElementById("dmg").style.backgroundColor = "#f67"; - mech.health = mech.energy; + mech.health = Math.min(mech.maxHealth, mech.energy); } }, { @@ -872,7 +894,7 @@ const mod = { }, { name: "negentropy", - description: "at the start of each level
heal up to 66% of maximum health", + description: `at the start of each level
heal a percent of maximum health`, maxCount: 1, count: 0, allowed() { @@ -926,7 +948,7 @@ const mod = { powerUps.reroll.changeRerolls(0) }, 1000); }, - description: "heal to full health instead of dying
consumes 1 reroll", + description: "instead of dying consume 1 reroll
heal a percent of max health", maxCount: 1, count: 0, allowed() { @@ -945,7 +967,7 @@ const mod = { }, { name: "bubble fusion", - description: "after destroying a mob's shield
spawn 2-3 heals, ammo, or rerolls", + description: "after destroying a mob's shield
spawn 1-3 heals, ammo, or rerolls", maxCount: 1, count: 0, allowed() { @@ -961,7 +983,7 @@ const mod = { }, { name: "Bayesian inference", - description: "40% chance for double power ups to drop
ammo will no longer spawn from mobs", + description: "33% chance for double power ups to drop
ammo will no longer spawn from mobs", maxCount: 1, count: 0, allowed() { @@ -969,7 +991,7 @@ const mod = { }, requires: "", effect: () => { - mod.bayesian = 0.4; + mod.bayesian = 0.33; }, remove() { mod.bayesian = 0; @@ -977,7 +999,7 @@ const mod = { }, { name: "logistics", - description: "ammo power ups add to your current gun
spawn 6 ammo", + description: "ammo power ups add to your current gun
spawn 7 ammo", maxCount: 1, count: 0, allowed() { @@ -986,7 +1008,7 @@ const mod = { requires: "at least 2 guns", effect() { mod.isAmmoForGun = true; - for (let i = 0; i < 6; i++) { + for (let i = 0; i < 7; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "ammo"); if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "ammo"); } @@ -1023,7 +1045,7 @@ const mod = { }, requires: "not mass-energy equivalence", effect: () => { - mod.isAmmoFromHealth = 0.02; + mod.isAmmoFromHealth = 0.023; }, remove() { mod.isAmmoFromHealth = 0; @@ -1047,7 +1069,7 @@ const mod = { }, { name: "gun turret", - description: "reduce harm by 50% when crouching", + description: "reduce harm by 40% when crouching", maxCount: 1, count: 0, allowed() { @@ -1640,7 +1662,7 @@ const mod = { }, { name: "electromagnetic pulse", - description: "vacuum bomb's explosion destroys shields
increase bomb damage by 20%", + description: "vacuum bomb's explosion removes
80% of shields and 100% of energy", maxCount: 1, count: 0, allowed() { @@ -1970,7 +1992,7 @@ const mod = { //************************************************** { name: "flux pinning", - description: "blocking with perfect diamagnetism
stuns mobs for 1 second", + description: "blocking with perfect diamagnetism
stuns mobs for +1 second", maxCount: 9, count: 0, allowed() { @@ -2004,7 +2026,7 @@ const mod = { }, { name: "Lorentz transformation", - description: "time dilation field has an effect while inactive
move, jump, and shoot 33% faster", + description: "move, jump, and shoot 33% faster
while time dilation is active or inactive ", maxCount: 1, count: 0, allowed() { @@ -2042,7 +2064,7 @@ const mod = { }, { name: "degenerate matter", - description: "harm reduction from negative mass field
is increased from 60% to 80%", + description: "reduce harm by 40%
while negative mass field is active", maxCount: 1, count: 0, allowed() { @@ -2051,11 +2073,10 @@ const mod = { requires: "negative mass field", effect() { mod.isHarmReduce = true - mech.fieldHarmReduction = 0.2; }, remove() { mod.isHarmReduce = false; - if (mech.fieldUpgrades[mech.fieldMode].name === "negative mass field") mech.setField("negative mass field") //reset harm reduction + // if (mech.fieldUpgrades[mech.fieldMode].name === "negative mass field") mech.setField("negative mass field") //reset harm reduction } }, { @@ -2276,7 +2297,7 @@ const mod = { { name: "rerolls", - description: "spawn 6 reroll power ups", + description: "spawn 5 reroll power ups", maxCount: 9, count: 0, isNonRefundable: true, @@ -2285,7 +2306,7 @@ const mod = { }, requires: "not superdeterminism", effect() { - for (let i = 0; i < 6; i++) { + for (let i = 0; i < 5; i++) { powerUps.spawn(mech.pos.x, mech.pos.y, "reroll"); if (Math.random() < mod.bayesian) powerUps.spawn(mech.pos.x, mech.pos.y, "reroll"); } @@ -2434,6 +2455,7 @@ const mod = { rerollHaste: null, isMineDrop: null, isRerollBots: null, - isRailTimeSlow: null + isRailTimeSlow: null, + isBotUpgrade: null // isMaxHealthRemove: null } \ No newline at end of file diff --git a/js/player.js b/js/player.js index c91127b..1fb01c1 100644 --- a/js/player.js +++ b/js/player.js @@ -441,13 +441,14 @@ const mech = { let dmg = 1 dmg *= mech.fieldHarmReduction dmg *= mod.isSlowFPS ? 0.85 : 1 - if (mod.isBotArmor) dmg *= 0.94 ** mod.totalBots() + if (mod.isHarmReduce && mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" && mech.isFieldActive) dmg *= 0.6 + if (mod.isBotArmor) dmg *= 0.95 ** mod.totalBots() if (mod.isHarmArmor && mech.lastHarmCycle + 600 > mech.cycle) dmg *= 0.5; if (mod.energyRegen === 0) dmg *= 0.5 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy - if (mod.isTurret && mech.crouch) dmg /= 2; + if (mod.isTurret && mech.crouch) dmg *= 0.6; if (mod.isEntanglement && b.inventory[0] === b.activeGun) { for (let i = 0, len = b.inventory.length; i < len; i++) { - dmg *= 0.84 // 1 - 0.16 + dmg *= 0.85 // 1 - 0.15 } } return dmg @@ -684,6 +685,7 @@ const mech = { holdingTarget: null, timeSkipLastCycle: 0, // these values are set on reset by setHoldDefaults() + isFieldActive: false, fieldRange: 155, fieldShieldingScale: 1, energy: 0, @@ -713,7 +715,7 @@ const mech = { mech.airSpeedLimit = 125 mech.drop(); mech.holdingMassScale = 0.5; - + mech.isFieldActive = false; //only being used by negative mass field mech.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.isBodiesAsleep = true; @@ -1361,21 +1363,18 @@ const mech = { }, { name: "negative mass field", - description: "use energy to nullify   gravity
reduce harm by 60%", + description: "use energy to nullify   gravity
reduce harm by 50%", fieldDrawRadius: 0, isEasyToAim: true, effect: () => { mech.fieldFire = true; mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping mech.fieldMeterColor = "#000" - if (mod.isHarmReduce) { - mech.fieldHarmReduction = 0.2; - } else { - mech.fieldHarmReduction = 0.4; - } + mech.fieldHarmReduction = 0.5; mech.hold = function () { mech.airSpeedLimit = 125 //5 * player.mass * player.mass mech.FxAir = 0.016 + mech.isFieldActive = false; if (mech.isHolding) { mech.drawHold(mech.holdingTarget); mech.holding(); @@ -1385,6 +1384,7 @@ const mech = { mech.lookForPickUp(); const DRAIN = 0.00035 if (mech.energy > DRAIN) { + mech.isFieldActive = true; //used with mod.isHarmReduce mech.airSpeedLimit = 400 // 7* player.mass * player.mass mech.FxAir = 0.005 // mech.pushMobs360(); @@ -1399,8 +1399,6 @@ const mech = { // mob[i].force.y = force.y // } // } - - //look for nearby objects to make zero-g function zeroG(who, range, mag = 1.06) { for (let i = 0, len = who.length; i < len; ++i) { @@ -1496,7 +1494,7 @@ const mech = { } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed mech.grabPowerUp(); mech.lookForPickUp(); - const DRAIN = 0.0014 + const DRAIN = 0.0017 if (mech.energy > DRAIN) { mech.energy -= DRAIN; if (mech.energy < 0) { @@ -1656,7 +1654,7 @@ const mech = { mech.grabPowerUp(); mech.lookForPickUp(180); - const DRAIN = 0.0014 + const DRAIN = 0.001 if (mech.energy > DRAIN) { mech.energy -= DRAIN; if (mech.energy < DRAIN) { @@ -1793,7 +1791,7 @@ const mech = { // game.draw.bodyFill = "transparent" // game.draw.bodyStroke = "transparent" - const DRAIN = 0.0002 + 0.0001 * player.speed + ((!mod.renormalization && mech.fireCDcycle > mech.cycle) ? 0.005 : 0.001) + const DRAIN = 0.00014 + ((!mod.renormalization && mech.fireCDcycle > mech.cycle) ? 0.007 : 0.001) if (mech.energy > DRAIN) { mech.energy -= DRAIN; // if (mech.energy < 0.001) { diff --git a/js/powerup.js b/js/powerup.js index 5facc65..ada13f8 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -56,7 +56,7 @@ const powerUps = { if (powerUps.reroll.rerolls < 0) powerUps.reroll.rerolls = 0 if (mod.isRerollBots) { - const limit = 3 + const limit = 4 for (; powerUps.reroll.rerolls > limit - 1; powerUps.reroll.rerolls -= limit) { b.randomBot() } diff --git a/style.css b/style.css index 10b798d..ab327a5 100644 --- a/style.css +++ b/style.css @@ -467,8 +467,8 @@ em { .color-harm { /* color: */ /* text-shadow: #FC0 1px 0 10px; */ - background-color: hsla(325, 100%, 85%, 0.2); - padding: 3px; + background-color: hsla(325, 100%, 85%, 0.15); + padding: 2px; border-radius: 4px; letter-spacing: 1px; } diff --git a/todo.txt b/todo.txt index bac5a9e..6d083dc 100644 --- a/todo.txt +++ b/todo.txt @@ -1,15 +1,23 @@ -determinism mod no longer lets you cancel power ups -mod: frame dragging - rail gun doesn't drain energy, and slows time while charging -mod: high caliber - minigun bullets are bigger, but fire slower - -new level: testChamber - it's a bit different, so don't hold back on feedback positive or negative +mod: upgrade all bots (current and future bots) +some difficulty scaling changes (harm ramps a bit faster at high levels) ************** TODO - n-gon ************** -testChamber +too many mods are dropping at high levels on hard + +mod: upgrade all your current bots + upgrade should be equal to a 50% increases in value for the bot + nail-bot fires faster + foam bot fires larger radius foam + larger boom-bot explosions + laser-bot does more damage + plasma-bot uses less energy + +testChamber + too much block clutter near portals make reverse path viable + removing block from button releases boss? portals: portal while holding block sometimes send player back to original portal