From 38d993154cf2d8f4baab2624a17e9ff822611026 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sat, 24 Feb 2024 15:09:35 -0800 Subject: [PATCH] laserLayer mob: laserLayer - leaves behind lasers that persist for a few seconds ghoster mobs do 66% less damage, but they eject your ammo grappling hook tech rupture renamed swarf fires several nails at nearby mobs, not explosions grappling hook 6->9 energy per second CIWS 18->10 energy reel +40->75 energy reeling blocks wormhole 5->7% duplication cloaking no longer drains energy, this fixes a can't cloak bug dazzler no longer drains energy dazzler range reduced by 15% dazzler stuns for 3->2 seconds zero point energy 100->166 max energy expansion 40->77 max energy annihilation -33% of max energy -> 10 energy dynamical systems is no longer a field tech 35->30 damage tessellation is no longer a field tech 50->35 defense yield stress removed topological defect 80->111% damage brittle 80->111% damage commodities exchange 6-12 -> 10-14 power ups heat engine 50->40% damage flame test grenades clusters explode 40% faster alternator uses 10->0% energy for harpoon finally made a shared vertexCollision function this might cause some bugs with laser-like effects... --- img/{rupture.webp => swarf.webp} | Bin img/topological defect.webp | Bin 56516 -> 58264 bytes img/yield stress.webp | Bin 58264 -> 0 bytes js/bullet.js | 496 ++---------- js/engine.js | 4 +- js/index.js | 90 +++ js/level.js | 92 ++- js/mob.js | 197 ++--- js/player.js | 98 +-- js/powerup.js | 2 +- js/spawn.js | 1217 ++++++------------------------ js/tech.js | 226 +++--- todo.txt | 70 +- 13 files changed, 684 insertions(+), 1808 deletions(-) rename img/{rupture.webp => swarf.webp} (100%) delete mode 100644 img/yield stress.webp diff --git a/img/rupture.webp b/img/swarf.webp similarity index 100% rename from img/rupture.webp rename to img/swarf.webp diff --git a/img/topological defect.webp b/img/topological defect.webp index c81a53c01699f20fab6e0d6470ca7f2ece3bfeb5..a4be7c938ce04bdc4845215e167dc12076510d8a 100644 GIT binary patch literal 58264 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 literal 56516 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 z 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 diff --git a/img/yield stress.webp b/img/yield stress.webp deleted file mode 100644 index a4be7c938ce04bdc4845215e167dc12076510d8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 58264 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 diff --git a/js/bullet.js b/js/bullet.js index 674bfd5..b1bc458 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -558,46 +558,6 @@ const b = { y: where.y + range * Math.sin(angle) } ]; - 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 = simulation.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 = simulation.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, @@ -607,28 +567,8 @@ const b = { v1: null, v2: null }; - // if (tech.isPulseAim && !m.crouch) { //find mobs in line of sight - // let dist = 2200 - // for (let i = 0, len = mob.length; i < len; i++) { - // const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position)) - // if ( - // explosionRadius < newDist && - // newDist < dist && - // !mob[i].isBadTarget && - // Matter.Query.ray(map, path[0], mob[i].position).length === 0 && - // Matter.Query.ray(body, path[0], mob[i].position).length === 0 && - // !mob[i].isInvulnerable - // ) { - // dist = newDist - // best.who = mob[i] - // path[path.length - 1] = mob[i].position - // } - // } - // } if (!best.who) { - vertexCollision(path[0], path[1], mob); - vertexCollision(path[0], path[1], map); - vertexCollision(path[0], path[1], body); + best = vertexCollision(path[0], path[1], [mob, map, body]); if (best.dist2 != Infinity) { //if hitting something path[path.length - 1] = { x: best.x, @@ -678,135 +618,20 @@ const b = { }); } }, - // photon(where, angle = m.angle) { - // let best; - // const path = [{ - // x: m.pos.x + 20 * Math.cos(angle), - // y: m.pos.y + 20 * Math.sin(angle) - // }, - // { - // x: m.pos.x + range * Math.cos(angle), - // y: m.pos.y + range * Math.sin(angle) - // } - // ]; - // 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 = simulation.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 = simulation.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 - // }; - // if (tech.isPulseAim) { //find mobs in line of sight - // let dist = 2200 - // for (let i = 0, len = mob.length; i < len; i++) { - // const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position)) - // if (explosionRadius < newDist && - // newDist < dist && - // Matter.Query.ray(map, path[0], mob[i].position).length === 0 && - // Matter.Query.ray(body, path[0], mob[i].position).length === 0) { - // dist = newDist - // best.who = mob[i] - // path[path.length - 1] = mob[i].position - // } - // } - // } - // if (!best.who) { - // 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) b.explosion(path[1], explosionRadius) - - // //draw laser beam - // ctx.beginPath(); - // ctx.moveTo(path[0].x, path[0].y); - // ctx.lineTo(path[1].x, path[1].y); - // ctx.strokeStyle = "rgba(255,0,0,0.13)" - // ctx.lineWidth = 60 * energy / 0.2 - // ctx.stroke(); - // ctx.strokeStyle = "rgba(255,0,0,0.2)" - // ctx.lineWidth = 18 - // ctx.stroke(); - // ctx.strokeStyle = "#f00"; - // ctx.lineWidth = 4 - // ctx.stroke(); - - // //draw little dots along the laser path - // const sub = Vector.sub(path[1], path[0]) - // const mag = Vector.magnitude(sub) - // for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) { - // const dist = Math.random() - // simulation.drawList.push({ - // x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5), - // y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5), - // radius: 1 + 4 * Math.random(), - // color: "rgba(255,0,0,0.5)", - // time: Math.floor(2 + 33 * Math.random() * Math.random()) - // }); - // } - // }, - fireworks(where, size) { //can occur after grenades detonate + clusterExplode(where, size) { //can occur after grenades detonate const cycle = () => { if (m.alive) { if (simulation.paused || m.isBodiesAsleep) { requestAnimationFrame(cycle) } else { count++ - if (count < 130) requestAnimationFrame(cycle); - if (!(count % 10)) { + if (count < 84) requestAnimationFrame(cycle); + if (!(count % 7)) { const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random()) - b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.02 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end + b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.03 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end } } } @@ -884,7 +709,7 @@ const b = { } else if (tech.isPetalsExplode) { b.fireFlower(this.position, this.explodeRad) } else if (tech.isClusterExplode) { - b.fireworks(this.position, this.explodeRad) + b.clusterExplode(this.position, this.explodeRad) } else { b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end } @@ -1501,7 +1326,7 @@ const b = { drawStringControlMagnitude: 1000 + 1000 * Math.random(), drawStringFlip: (Math.round(Math.random()) ? 1 : -1), attached: false, - glowColor: tech.isHookExplosion ? "rgba(200,0,0,0.07)" : tech.isHarmReduce ? "rgba(50,100,255,0.1)" : "rgba(0,200,255,0.07)", + glowColor: tech.hookNails ? "rgba(200,0,0,0.07)" : tech.isHarmReduce ? "rgba(50,100,255,0.1)" : "rgba(0,200,255,0.07)", collisionFilter: { category: cat.bullet, mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield, @@ -1598,14 +1423,20 @@ const b = { }); } if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs - if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end + if (tech.hookNails) { + // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles + // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end + b.targetedNail(this.position, tech.hookNails) + const ANGLE = 2 * Math.PI * Math.random() //make a few random ones + for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2) + } // if (this.powerUpDamage) this.density = 2 * 0.004 //double damage after pick up power up for 8 seconds if (tech.isHarpoonPowerUp && simulation.cycle - 480 < tech.harpoonPowerUpCycle) { Matter.Body.setDensity(this, 1.8 * 0.004); //+90% damage after pick up power up for 8 seconds } else if (tech.isHarpoonFullHealth && who.health === 1) { - Matter.Body.setDensity(this, 1.9 * 0.004); //+90% damage if mob has full health do + Matter.Body.setDensity(this, 2.11 * 0.004); //+90% damage if mob has full health do simulation.ephemera.push({ name: "grapple outline", count: 3, //cycles before it self removes @@ -1688,7 +1519,7 @@ const b = { if (this.pickUpTarget) { if (tech.isReel && this.blockDist > 150) { // console.log(0.0003 * Math.min(this.blockDist, 1000)) - m.energy += 0.00044 * Math.min(this.blockDist, 800) //max 0.352 energy + m.energy += 0.0009 * Math.min(this.blockDist, 800) //max 0.352 energy simulation.drawList.push({ //add dmg to draw queue x: m.pos.x, y: m.pos.y, @@ -1758,10 +1589,15 @@ const b = { if (blocks.length) { // console.log(blocks) for (let i = 0; i < blocks.length; i++) { - if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && !blocks[0].bodyA.mass < 60) { + if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && blocks[0].bodyA.mass < 60) { this.retract() - if (tech.isHookExplosion) { - b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end + if (tech.hookNails) { + // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles + // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end + b.targetedNail(this.position, 3 * tech.hookNails) + const ANGLE = 2 * Math.PI * Math.random() //make a few random ones + for (let i = 0; i < 13; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2) + const blockVertices = blocks[i].bodyA.vertices Composite.remove(engine.world, blocks[i].bodyA) body.splice(body.indexOf(blocks[i].bodyA), 1) @@ -1785,12 +1621,20 @@ const b = { this.pickUpTarget = blocks[i].bodyA this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos)) } - } else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && !blocks[0].bodyB.mass < 60) { - this.retract() - this.pickUpTarget = blocks[i].bodyB - this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos)) - if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end } + // else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && blocks[0].bodyB.mass < 60) { + // this.retract() + // this.pickUpTarget = blocks[i].bodyB + // this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos)) + // if (tech.hookNails) { + // // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles + // // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end + // b.targetedNail(this.position, tech.hookNails) + // const ANGLE = 2 * Math.PI * Math.random() //make a few random ones + // for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2) + + // } + // } } // if (blocks[0].bodyA.mass > 2.5 && blocks[0].bodyA.mass > 15) { @@ -1855,7 +1699,14 @@ const b = { if (input.field && Matter.Query.collides(this, map).length) { Matter.Body.setPosition(this, Vector.add(this.position, { x: -20 * Math.cos(this.angle), y: -20 * Math.sin(this.angle) })) if (Matter.Query.collides(this, map).length) { - if (tech.isHookExplosion) b.explosion(this.position, 150 + 50 * Math.random()); //makes bullet do explosive damage at end + if (tech.hookNails) { + // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles + // b.explosion(this.position, 200 + 150 * Math.random()); //makes bullet do explosive damage at end + b.targetedNail(this.position, tech.hookNails) + const ANGLE = 2 * Math.PI * Math.random() //make a few random ones + for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2) + + } this.attached = true Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Sleeping.set(this, true) @@ -1976,7 +1827,7 @@ const b = { friction: 1, frictionAir: 0.4, // thrustMag: 0.1, - drain: tech.isRailEnergy ? 0.0006 : 0.006, + drain: tech.isRailEnergy ? 0 : 0.006, turnRate: isReturn ? 0.1 : 0.03, //0.015 drawStringControlMagnitude: 3000 + 5000 * Math.random(), drawStringFlip: (Math.round(Math.random()) ? 1 : -1), @@ -2022,7 +1873,7 @@ const b = { if (tech.isHarpoonPowerUp && simulation.cycle - 480 < tech.harpoonPowerUpCycle) { Matter.Body.setDensity(this, 1.8 * tech.harpoonDensity); //+90% damage after pick up power up for 8 seconds } else if (tech.isHarpoonFullHealth && who.health === 1) { - Matter.Body.setDensity(this, 1.9 * tech.harpoonDensity); //+90% damage if mob has full health do + Matter.Body.setDensity(this, 2.11 * tech.harpoonDensity); //+90% damage if mob has full health do simulation.ephemera.push({ name: "harpoon outline", count: 2, //cycles before it self removes @@ -2435,7 +2286,6 @@ const b = { } //calculate laser collision - let best; let range = tech.isPlasmaRange * (120 + (m.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(m.cycle * 0.3); // const dir = m.angle // + 0.04 * (Math.random() - 0.5) const path = [{ @@ -2447,49 +2297,8 @@ const b = { y: m.pos.y + range * Math.sin(m.angle) } ]; - 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 = simulation.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 = simulation.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 = { + let best = { x: null, y: null, dist2: Infinity, @@ -2497,14 +2306,9 @@ const b = { v1: null, v2: null }; - vertexCollision(path[0], path[1], mob); - vertexCollision(path[0], path[1], map); - vertexCollision(path[0], path[1], body); + best = vertexCollision(path[0], path[1], [mob, map, body]); if (best.dist2 != Infinity) { //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; + path[path.length - 1] = { x: best.x, y: best.y }; if (best.who.alive) { const dmg = 0.9 * m.dmgScale; //********** SCALE DAMAGE HERE ********************* best.who.damage(dmg); @@ -2571,6 +2375,7 @@ const b = { }, dmg = tech.laserDamage, reflections = tech.laserReflections, isThickBeam = false, push = 1) { const reflectivity = 1 - 1 / (reflections * 3) let damage = m.dmgScale * dmg + let best = { x: 1, y: 1, @@ -2586,59 +2391,9 @@ const b = { x: whereEnd.x, y: whereEnd.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 = simulation.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 = simulation.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] - }; - } - } - } - }; const checkForCollisions = function () { - best = { - x: 1, - y: 1, - dist2: Infinity, - who: null, - v1: 1, - v2: 1 - }; - vertexCollision(path[path.length - 2], path[path.length - 1], mob); - vertexCollision(path[path.length - 2], path[path.length - 1], map); - vertexCollision(path[path.length - 2], path[path.length - 1], body); + best = vertexCollision(path[path.length - 2], path[path.length - 1], [mob, map, body]); }; const laserHitMob = function () { if (best.who.alive) { @@ -2895,7 +2650,7 @@ const b = { } else if (tech.isSuperMine) { b.targetedBall(this.position, 22 + 2 * tech.extraSuperBalls) } else { - b.targetedNail(this.position, 22, 40 + 10 * Math.random(), 1200, true, 2.2) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) { + b.targetedNail(this.position, 22, 40 + 10 * Math.random(), 1200, 2.2) } } }, @@ -2993,7 +2748,7 @@ const b = { if (Math.random() < 0.33) b.targetedBall(this.position, 1, 42 + 12 * Math.random(), 1200, false) } } else { - this.shots -= b.targetedNail(this.position, 1, 45 + 5 * Math.random(), 1100, false, 2.3) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) { + this.shots -= b.targetedNail(this.position, 1, 45 + 5 * Math.random(), 1100, 2.3) } if (this.shots < 0) this.endCycle = 0 if (!(simulation.cycle % (this.lookFrequency * 6))) { @@ -3508,10 +3263,7 @@ const b = { } requestAnimationFrame(respawnDrones); }, - drone(where = { - x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), - y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) - }, speed = 1) { + drone(where = { x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) }, speed = 1) { const me = bullet.length; const THRUST = 0.0015 const dir = m.angle + 0.2 * (Math.random() - 0.5); @@ -3688,7 +3440,7 @@ const b = { for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up if ( Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && - (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -3719,7 +3471,7 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isSuperDeterminism) // &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { @@ -3748,8 +3500,7 @@ const b = { } //look for power ups to lock onto if ( - Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 && - Matter.Query.ray(body, this.position, powerUp[i].position).length === 0 + Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 //&& Matter.Query.ray(body, this.position, powerUp[i].position).length === 0 ) { const TARGET_VECTOR = Vector.sub(this.position, powerUp[i].position) const DIST = Vector.magnitude(TARGET_VECTOR); @@ -4545,7 +4296,7 @@ const b = { Matter.Body.setVelocity(who, velocity); } }, - targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) { + targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, damage = 1.4) { let shotsFired = 0 const targets = [] //target nearby mobs for (let i = 0, len = mob.length; i < len; i++) { @@ -4570,7 +4321,7 @@ const b = { } b.nail(position, Vector.mult(Vector.normalise(Vector.sub(WHERE, position)), speed), damage) shotsFired++ - } else if (isRandomAim) { // aim in random direction + } else { // aim in random direction const ANGLE = 2 * Math.PI * Math.random() b.nail(position, { x: speed * Math.cos(ANGLE), @@ -5634,59 +5385,9 @@ const b = { const perp2 = Vector.mult(Vector.rotate({ x: 1, y: 0 }, m.angle + Math.PI / 2), 0.6 * this.lockedOn.radius * Math.sin(simulation.cycle / this.lookFrequency)) const path = [{ x: this.vertices[0].x, y: this.vertices[0].y }, Vector.add(this.lockedOn.position, perp2)]; - 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 = simulation.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 = simulation.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] - }; - } - } - } - }; - const checkForCollisions = function () { - best = { - x: 1, - y: 1, - dist2: Infinity, - who: null, - v1: 1, - v2: 1 - }; - vertexCollision(path[path.length - 2], path[path.length - 1], mob); - vertexCollision(path[path.length - 2], path[path.length - 1], map); - vertexCollision(path[path.length - 2], path[path.length - 1], body); + best = { x: 1, y: 1, dist2: Infinity, who: null, v1: 1, v2: 1 }; + best = vertexCollision(path[path.length - 2], path[path.length - 1], [mob, map, body]); }; const laserHitMob = function () { if (best.who.alive) { @@ -5717,19 +5418,13 @@ const b = { } if (tech.isLaserPush) { //push mobs away const index = path.length - 1 - Matter.Body.setVelocity(best.who, { - x: best.who.velocity.x * 0.97, - y: best.who.velocity.y * 0.97 - }); + Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 }); const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass)) Matter.Body.applyForce(best.who, path[index], force) } } else if (tech.isLaserPush && best.who.classType === "body") { const index = path.length - 1 - Matter.Body.setVelocity(best.who, { - x: best.who.velocity.x * 0.97, - y: best.who.velocity.y * 0.97 - }); + Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 }); const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass)) Matter.Body.applyForce(best.who, path[index], force) } @@ -5746,20 +5441,14 @@ const b = { let lastBestOdd let lastBestEven = best.who //used in hack below if (best.dist2 !== Infinity) { //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; + path[path.length - 1] = { x: best.x, y: best.y }; laserHitMob(); for (let i = 0; i < tech.laserReflections; i++) { reflection(); checkForCollisions(); if (best.dist2 !== Infinity) { //if hitting something lastReflection = best - path[path.length - 1] = { - x: best.x, - y: best.y - }; + path[path.length - 1] = { x: best.x, y: best.y }; damage *= reflectivity laserHitMob(); //I'm not clear on how this works, but it gets rid of a bug where the laser reflects inside a block, often vertically. @@ -5947,51 +5636,9 @@ const b = { let best; let range = tech.isPlasmaRange * (120 + 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 = simulation.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 = simulation.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); + best = vertexCollision(path[0], path[1], [mob, map, body]); if (best.dist2 != Infinity) { //if hitting something path[path.length - 1] = { x: best.x, y: best.y }; if (best.who.alive) { @@ -6001,12 +5648,7 @@ const b = { //push mobs away const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.007 * Math.min(5, best.who.mass)) Matter.Body.applyForce(best.who, path[1], force) - if (best.who.speed > 2.5) { - Matter.Body.setVelocity(best.who, { //friction - x: best.who.velocity.x * 0.75, - y: best.who.velocity.y * 0.75 - }); - } + if (best.who.speed > 2.5) Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.75, y: best.who.velocity.y * 0.75 }); //draw mob damage circle if (best.who.damageReduction) { simulation.drawList.push({ @@ -7729,7 +7371,7 @@ const b = { charge: 0, railDo() { if (this.charge > 0) { - const DRAIN = (tech.isRailEnergy ? 0.0002 : 0.002) + const DRAIN = (tech.isRailEnergy ? 0 : 0.002) //exit railgun charging without firing if (m.energy < DRAIN) { // m.energy += 0.025 + this.charge * 22 * this.drain diff --git a/js/engine.js b/js/engine.js index 3eecee3..9c79988 100644 --- a/js/engine.js +++ b/js/engine.js @@ -229,8 +229,8 @@ function collisionChecks(event) { y: mob[k].velocity.y - 8 * Math.sin(angle) }); - if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy && mob[k].damageReduction > 0) { - m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy + if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) { + m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage mob[k].death(); simulation.drawList.push({ //add dmg to draw queue diff --git a/js/index.js b/js/index.js index a2eb61b..5c22bad 100644 --- a/js/index.js +++ b/js/index.js @@ -39,6 +39,96 @@ function shuffle(array) { } return array; } +// function vertexCollision(v1, v1End, domain, best) { +// let results +// 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 = simulation.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 = simulation.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) { +// best = { +// x: results.x, +// y: results.y, +// dist2: dist2, +// who: domain[i], +// v1: vertices[0], +// v2: vertices[len] +// }; +// } +// } +// } +// return best +// } +//this function is used for finding the point where a ray hits things, used for lasers mostly +function vertexCollision(v1, v1End, domains) { //= [map, body, [playerBody, playerHead]] //m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]] + let results + let best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; + for (let j = 0; j < domains.length; j++) { + let domain = domains[j] + 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 = simulation.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 = simulation.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) { + best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[0], + v2: vertices[len] + }; + } + } + } + } + return best +} + //collision groups // cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet | cat.mobShield | cat.phased diff --git a/js/level.js b/js/level.js index 5292830..4e72d84 100644 --- a/js/level.js +++ b/js/level.js @@ -19,26 +19,26 @@ const level = { // simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode // simulation.isHorizontalFlipped = true // tech.giveTech("performance") - // level.difficultyIncrease(8 * 2) //30 is near max on hard //60 is near max on why - // m.maxHealth = m.health = 1 + // level.difficultyIncrease(3 * 2) //30 is near max on hard //60 is near max on why + // m.maxHealth = m.health = 100000000 // m.maxEnergy = m.energy = 10000000 // tech.isRerollDamage = true // powerUps.research.changeRerolls(99999) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 // m.couplingChange(10) - // m.setField("metamaterial cloaking") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook + // m.setField("plasma torch") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook // m.energy = 0 // tech.isHookWire = true // m.energy = 0 // simulation.molecularMode = 2 // m.damage(0.1); - // b.giveGuns("super balls") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser + // b.giveGuns("drones") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.guns[8].ammo = 100000000 // requestAnimationFrame(() => { tech.giveTech("Higgs mechanism") }); - // for (let i = 0; i < 1; ++i) tech.giveTech("optical amplifier") - // for (let i = 0; i < 1; ++i) tech.giveTech("depolarization") + // for (let i = 0; i < 1; ++i) tech.giveTech("flame test") + // for (let i = 0; i < 1; ++i) tech.giveTech("dazzler") // for (let i = 0; i < 1; ++i) tech.giveTech("mass production") // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) tech.giveTech("orbital-bot") }); // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) }); @@ -46,26 +46,30 @@ const level = { // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") // m.lastKillCycle = m.cycle - // for (let i = 0; i < 1; ++i) tech.giveTech("depolarization") + // for (let i = 0; i < 1; ++i) tech.giveTech("swarf") // for (let i = 0; i < 1; ++i) tech.giveTech("CPT symmetry") // for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); - // level.arena(); + // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing + // level.testing(); - // for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500) - // for (let i = 0; i < 4; ++i) spawn.stinger(1900, -500) - // for (let i = 0; i < 1; ++i) spawn.timeSkipBoss(1900, -2500) + // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) + // Matter.Body.setPosition(player, { x: -200, y: -3330 }); + // for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random()) + // for (let i = 0; i < 3; ++i) spawn.laser(1900, -500) + // for (let i = 0; i < 1; ++i) spawn.laserBombingBoss(1900, -2500) // spawn.beetleBoss(1900, -500, 25) - // spawn.slasher2(2000, -1150) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) // tech.addJunkTechToPool(2) // tech.tech[322].frequency = 100 // spawn.tetherBoss(1900, -500, { x: 1900, y: -500 }) // for (let i = 0; i < 40; ++i) tech.giveTech() + level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** + // for (let i = 0; i < 2; i++) spawn.ghoster(1300, -500) //ghosters need to spawn after the map loads // spawn.bodyRect(2425, -120, 200, 200); // console.log(body[body.length - 1].mass) // simulation.isAutoZoom = false; //look in close @@ -289,8 +293,8 @@ const level = { simulation.updateTechHUD(); simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map - //pop up new level info screen for a few seconds - if (!localSettings.isHideHUD && !simulation.isChoosing && !simulation.isCheating && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor" || level.levels[level.onLevel] === "subway")) { + //pop up new level info screen for a few seconds //|| level.levels[level.onLevel] === "subway" + if (!localSettings.isHideHUD && !simulation.isCheating && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor")) { //pause if (!simulation.paused) { simulation.paused = true; @@ -325,7 +329,7 @@ const level = { simulation.draw.cons(); simulation.draw.body(); level.customTopLayer(); - let count = countMax = simulation.testing ? 0 : 180 + let count = countMax = simulation.testing ? 0 : 240 let newLevelDraw = () => { count-- if (count > 0) { @@ -346,40 +350,46 @@ const level = { simulation.wipe(); m.look(); simulation.camera(); - // if (count < 30) { - // } - // if (count < 60) { - // simulation.draw.cons(); - // simulation.draw.body(); - // level.customTopLayer(); - // simulation.draw.body(); - // simulation.draw.drawMapPath(); - // mobs.draw(); - // } else - // if (count < 240) { - - // ctx.lineDashOffset = 900 * Math.random() - // ctx.setLineDash([3, -8 + 0.5 * count]); - - const scale = 10 + const scale = 15 ctx.setLineDash([scale * (countMax - count), scale * count]); simulation.draw.wireFrame(); ctx.setLineDash([]); - - - // } - // else if (count === 91) { //hide text boss - // document.getElementById("choose-grid").style.opacity = "0" - // setTimeout(() => { - // document.getElementById("choose-grid").style.visibility = "hidden" - // }, 1000); - // } ctx.restore(); simulation.drawCursor(); } requestAnimationFrame(newLevelDraw); - } + // else { + // //pause + // if (!simulation.paused) { + // simulation.paused = true; + // simulation.isChoosing = true; //stops p from un pausing on key down + // } + // let count = countMax = simulation.testing ? 0 : 60 + // let newLevelDraw = () => { + // count-- + // if (count > 0) { + // requestAnimationFrame(newLevelDraw); + // } else { //unpause + // // if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles + // if (simulation.paused) requestAnimationFrame(cycle); + // if (m.alive) simulation.paused = false; + // simulation.isChoosing = false; //stops p from un pausing on key down + // build.unPauseGrid() + // } + // //draw + // simulation.wipe(); + // m.look(); + // simulation.camera(); + // const scale = 30 + // ctx.setLineDash([scale * (countMax - count), scale * count]); + // simulation.draw.wireFrame(); + // ctx.setLineDash([]); + // ctx.restore(); + // simulation.drawCursor(); + // } + // requestAnimationFrame(newLevelDraw); + // } } }, unPause() { diff --git a/js/mob.js b/js/mob.js index 6f5b85c..349d687 100644 --- a/js/mob.js +++ b/js/mob.js @@ -505,89 +505,48 @@ const mobs = { ctx.fill(); } }, - laser() { - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; - if (this.seePlayer.recall && !this.isSlowed) { - const seeRange = 2500; - best = { - x: null, - y: null, - dist2: Infinity, - who: null, - v1: null, - v2: null - }; - const look = { - x: this.position.x + seeRange * Math.cos(this.angle), - y: this.position.y + seeRange * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); - vertexCollision(this.position, look, body); - if (!m.isCloak) vertexCollision(this.position, look, [player]); - // hitting player - if (best.who === player) { - if (m.immuneCycle < m.cycle) { - const dmg = 0.0014 * simulation.dmgScale; - m.damage(dmg); - ctx.fillStyle = "#f00"; //draw damage - ctx.beginPath(); - ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI); - ctx.fill(); - } - } - //draw beam - if (best.dist2 === Infinity) { - best = look; - } - ctx.beginPath(); - ctx.moveTo(this.position.x, this.position.y); - ctx.lineTo(best.x, best.y); - ctx.strokeStyle = "#f00"; // Purple path - ctx.lineWidth = 1; - ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); - ctx.stroke(); // Draw it - ctx.setLineDash([]); - } - }, + // laser() { + // if (this.seePlayer.recall && !this.isSlowed) { + // const seeRange = 2500; + // best = { + // x: null, + // y: null, + // dist2: Infinity, + // who: null, + // v1: null, + // v2: null + // }; + // const look = { + // x: this.position.x + seeRange * Math.cos(this.angle), + // y: this.position.y + seeRange * Math.sin(this.angle) + // }; + // best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [player]]); + + // // hitting player + // if (best.who === player) { + // if (m.immuneCycle < m.cycle) { + // const dmg = 0.0014 * simulation.dmgScale; + // m.damage(dmg); + // ctx.fillStyle = "#f00"; //draw damage + // ctx.beginPath(); + // ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI); + // ctx.fill(); + // } + // } + // //draw beam + // if (best.dist2 === Infinity) { + // best = look; + // } + // ctx.beginPath(); + // ctx.moveTo(this.position.x, this.position.y); + // ctx.lineTo(best.x, best.y); + // ctx.strokeStyle = "#f00"; // Purple path + // ctx.lineWidth = 1; + // ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + // ctx.stroke(); // Draw it + // ctx.setLineDash([]); + // } + // }, wing(a, radius = 250, ellipticity = 0.4, dmg = 0.0006) { const minorRadius = radius * ellipticity const perp = { x: Math.cos(a), y: Math.sin(a) } // @@ -658,47 +617,6 @@ const mobs = { ctx.fillStyle = "rgba(0,0,0,0.07)"; ctx.fill(); //spring to random place on map - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; - //move to a random location if (!(simulation.cycle % (this.seePlayerFreq * 4))) { best = { x: null, @@ -713,8 +631,7 @@ const mobs = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) }; - vertexCollision(this.position, look, map); - vertexCollision(this.position, look, body); + best = vertexCollision(this.position, look, [map, body]); if (best.dist2 != Infinity) { if (Math.random() > 0.5) { this.springTarget.x = best.x; @@ -1135,32 +1052,8 @@ const mobs = { dmg *= tech.damageFromTech() if (this.isDropPowerUp) { if (this.health === 1) { - if (tech.isMobFullHealth) { - dmg *= 1.55 - - simulation.ephemera.push({ - name: "damage outline", - count: 5, //cycles before it self removes - vertices: this.vertices, - do() { - this.count-- - if (this.count < 0) simulation.removeEphemera(this.name) - //draw body - ctx.beginPath(); - const vertices = this.vertices; - ctx.moveTo(vertices[0].x, vertices[0].y); - for (let j = 1, len = vertices.length; j < len; ++j) { - ctx.lineTo(vertices[j].x, vertices[j].y); - } - ctx.lineTo(vertices[0].x, vertices[0].y); - ctx.lineWidth = 3 //60 * (0.25 - this.damageReductionGoal) - ctx.strokeStyle = `#f05` //"rgba(150,150,225,0.5)"; - ctx.stroke(); - }, - }) - } else if (tech.isMobFullHealthCloak) { - dmg *= 1.88 - + if (tech.isMobFullHealthCloak) { + dmg *= 2.11 simulation.ephemera.push({ name: "damage outline", count: 7, //cycles before it self removes diff --git a/js/player.js b/js/player.js index 5a9876d..e0df3d5 100644 --- a/js/player.js +++ b/js/player.js @@ -559,7 +559,7 @@ const m = { // 1.25 + Math.sin(m.cycle * 0.01) if (tech.isDiaphragm) dmg *= 0.56 + 0.36 * Math.sin(m.cycle * 0.0075); if (tech.isZeno) dmg *= 0.15 - if (tech.isFieldHarmReduction) dmg *= 0.5 + if (tech.isFieldHarmReduction) dmg *= 0.65 if (tech.isHarmMACHO) dmg *= 0.4 if (tech.isImmortal) dmg *= 0.7 if (tech.energyRegen === 0) dmg *= 0.34 @@ -2192,7 +2192,7 @@ const m = { } }, setMaxEnergy(isMessage = true) { - m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.4 * tech.isStandingWaveExpand + m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand if (isMessage) simulation.makeTextLog(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`) }, fieldMeterColor: "#0cf", @@ -2243,6 +2243,8 @@ const m = { m.fieldRegen = 0.001667 //10 energy per second plasma torch } else if (m.fieldMode === 8) { m.fieldRegen = 0.001667 //10 energy per second pilot wave + } else if (m.fieldMode === 10) { + m.fieldRegen = 0.0015 //9 energy per second grappling hook } else { m.fieldRegen = 0.001 //6 energy per second } @@ -3631,15 +3633,9 @@ const m = { // if (!this.isAttached && !mob[i].isMobBullet) this.isPopping = true mob[i].damage(dmg); if (mob[i].speed > 5) { - Matter.Body.setVelocity(mob[i], { //friction - x: mob[i].velocity.x * 0.6, - y: mob[i].velocity.y * 0.6 - }); + Matter.Body.setVelocity(mob[i], { x: mob[i].velocity.x * 0.6, y: mob[i].velocity.y * 0.6 }); } else { - Matter.Body.setVelocity(mob[i], { //friction - x: mob[i].velocity.x * 0.93, - y: mob[i].velocity.y * 0.93 - }); + Matter.Body.setVelocity(mob[i], { x: mob[i].velocity.x * 0.93, y: mob[i].velocity.y * 0.93 }); } } else if (sub < dischargeRange + mob[i].radius && Matter.Query.ray(map, mob[i].position, this.position).length === 0) { arcList.push(mob[i]) //populate electrical arc list @@ -3684,10 +3680,7 @@ const m = { //slowly slow down if too fast if (this.speed > 10) { const scale = 0.998 - Matter.Body.setVelocity(this, { - x: scale * this.velocity.x, - y: scale * this.velocity.y - }); + Matter.Body.setVelocity(this, { x: scale * this.velocity.x, y: scale * this.velocity.y }); } //graphics @@ -3703,10 +3696,7 @@ const m = { ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI); ctx.fill(); //draw arcs - const unit = Vector.rotate({ - x: 1, - y: 0 - }, Math.random() * 6.28) + const unit = Vector.rotate({ x: 1, y: 0 }, Math.random() * 6.28) let len = 8 const step = this.circleRadius / len let x = this.position.x @@ -3761,13 +3751,6 @@ const m = { // m.plasmaBall.reset() } - // const scale = 0.7 - // Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast - // if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) { - // m.plasmaBall.isAttached = true - // m.plasmaBall.isOn = true - // m.plasmaBall.setPositionToNose() - // } } else if (m.energy > m.plasmaBall.drain) { //charge up when attached if (tech.isCapacitor) { m.energy -= m.plasmaBall.drain * 2; @@ -4233,16 +4216,14 @@ const m = { //not shooting (or using field) enable cloak if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle if (m.fireCDcycle + 10 < m.cycle && !input.fire) { //automatically cloak if not firing - const drain = 0.02 - if (!m.isCloak && m.energy > drain + 0.03) { - m.energy -= drain + // const drain = 0.02 + if (!m.isCloak) { //&& m.energy > drain + 0.03 + // m.energy -= drain m.isCloak = true //enter cloak m.fieldHarmReduction = 0.33; //66% reduction m.enterCloakCycle = m.cycle if (tech.isCloakHealLastHit && m.lastHit > 0) { const heal = Math.min(0.75 * m.lastHit, m.energy) - // if (m.energy > heal) { - // m.energy -= heal * 0.8 m.addHealth(heal); //heal from last hit m.lastHit = 0 simulation.drawList.push({ //add dmg to draw queue @@ -4252,7 +4233,6 @@ const m = { color: "rgba(0,255,200,0.6)", time: 16 }); - // } } if (tech.isIntangible) { for (let i = 0; i < bullet.length; i++) { @@ -4272,26 +4252,26 @@ const m = { } if (tech.isCloakStun) { //stun nearby mobs after exiting cloak let isMobsAround = false - const stunRange = m.fieldDrawRadius * 1.5 - const drain = 0.1 - if (m.energy > drain) { - for (let i = 0, len = mob.length; i < len; ++i) { - if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) { - isMobsAround = true - mobs.statusStun(mob[i], 180) - } - } - if (isMobsAround) { - m.energy -= drain - simulation.drawList.push({ - x: m.pos.x, - y: m.pos.y, - radius: stunRange, - color: "hsla(0,50%,100%,0.7)", - time: 7 - }); + const stunRange = m.fieldDrawRadius * 1.25 + // const drain = 0.01 + // if (m.energy > drain) { + for (let i = 0, len = mob.length; i < len; ++i) { + if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) { + isMobsAround = true + mobs.statusStun(mob[i], 120) } } + // if (isMobsAround) { + // m.energy -= drain + // simulation.drawList.push({ + // x: m.pos.x, + // y: m.pos.y, + // radius: stunRange, + // color: "hsla(0,50%,100%,0.7)", + // time: 7 + // }); + // } + // } } } @@ -4580,13 +4560,13 @@ const m = { { name: "wormhole", //wormholes attract blocks and power ups
- description: "use energy to tunnel through a wormhole
+5% chance to duplicate spawned power ups
generate 6 energy per second", //
bullets may also traverse wormholes + description: "use energy to tunnel through a wormhole
+7% chance to duplicate spawned power ups
generate 6 energy per second", //
bullets may also traverse wormholes drain: 0, effect: function () { m.fieldMeterColor = "#bbf" //"#0c5" m.eyeFillColor = m.fieldMeterColor - m.duplicateChance = 0.05 + m.duplicateChance = 0.07 m.fieldRange = 0 powerUps.setPowerUpMode(); //needed after adjusting duplication chance @@ -4639,10 +4619,7 @@ const m = { if (dist2 < 600000) { //&& !(m.health === m.maxHealth && powerUp[i].name === "heal") powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity - Matter.Body.setVelocity(powerUp[i], { //extra friction - x: powerUp[i].velocity.x * 0.05, - y: powerUp[i].velocity.y * 0.05 - }); + Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.05, y: powerUp[i].velocity.y * 0.05 }); if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough // if (true) { //AoE radiation effect @@ -4811,10 +4788,7 @@ const m = { this.drain = tech.isFreeWormHole ? 0 : 0.05 + 0.005 * Math.sqrt(mag) } const unit = Vector.perp(Vector.normalise(sub)) - const where = { - x: m.pos.x + 30 * Math.cos(m.angle), - y: m.pos.y + 30 * Math.sin(m.angle) - } + const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025)) const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame) const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame) @@ -5135,7 +5109,7 @@ const m = { { name: "grappling hook", // description: `use energy to pull yourself towards the map
generate 6 energy per second`, - description: `use energy to fire a hook that pulls player
damages mobs and grabs blocks
generate 6 energy per second`, + description: `use energy to fire a hook that pulls player
damages mobs and grabs blocks
generate 9 energy per second`, effect: () => { m.fieldFire = true; // m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping @@ -5159,7 +5133,7 @@ const m = { m.grabPowerUp(); } else { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) - if (tech.isHookDefense && m.energy > 0.33 && m.fieldCDcycle < m.cycle) { + if (tech.isHookDefense && m.energy > 0.15 && m.fieldCDcycle < m.cycle) { const range = 300 for (let i = 0; i < mob.length; i++) { if (!mob[i].isBadTarget && @@ -5167,7 +5141,7 @@ const m = { Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 ) { - m.energy -= 0.18 + m.energy -= 0.1 if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30 const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x); b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { diff --git a/js/powerup.js b/js/powerup.js index 5292b4d..c836f6e 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -332,7 +332,7 @@ const powerUps = { simulation.circleFlare(0.043); } if (tech.isCancelRerolls) { - for (let i = 0, len = 6 + 6 * Math.random(); i < len; i++) { + for (let i = 0, len = 10 + 4 * Math.random(); i < len; i++) { let spawnType if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) { spawnType = "ammo" diff --git a/js/spawn.js b/js/spawn.js index a13550e..9f7c1df 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -26,16 +26,17 @@ const spawn = { "springer", "springer", "springer", "stinger", "stinger", "stinger", "flutter", "flutter", + "striker", "striker", "shooter", "shooter", "grenadier", "grenadier", - "striker", "striker", - "laser", "laser", "pulsar", "pulsar", + "laser", "laser", + "laserLayer", "laserLayer", "sneaker", "launcher", "launcherOne", "exploder", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", "focuser" ], mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed mobTypeSpawnIndex: 0, //increases as the mob type cycles - allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter", "stinger"], + allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter", "stinger", "laserLayer"], setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level spawn.pickList.splice(0, 1); const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length] @@ -892,43 +893,6 @@ const spawn = { }; } me.lasers = function (where, angle, dmg = 0.1 * simulation.dmgScale) { - 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 = simulation.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 = simulation.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) best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - }; - const seeRange = 7000; best = { x: null, @@ -942,10 +906,7 @@ const spawn = { x: where.x + seeRange * Math.cos(angle), y: where.y + seeRange * Math.sin(angle) }; - // vertexCollision(where, look, mob); - vertexCollision(where, look, map); - vertexCollision(where, look, body); - if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { if (m.immuneCycle < m.cycle + 60 + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 60 + m.collisionImmuneCycles; //player is immune to damage extra time m.damage(dmg); @@ -1101,499 +1062,6 @@ const spawn = { } }; }, - // finalBoss(x, y, radius = 300) { - // mobs.spawn(x, y, 6, radius, "rgb(150,150,255)"); - // let me = mob[mob.length - 1]; - // setTimeout(() => { //fix mob in place, but allow rotation - // me.constraint = Constraint.create({ - // pointA: { - // x: me.position.x, - // y: me.position.y - // }, - // bodyB: me, - // stiffness: 1, - // damping: 1 - // }); - // Composite.add(engine.world, me.constraint); - // }, 2000); //add in a delay in case the level gets flipped left right - // me.isBoss = true; - // me.isFinalBoss = true; - // me.frictionAir = 0.01; - // me.memory = Infinity; - // me.hasRunDeathScript = false - // me.locatePlayer(); - // // const density = 0.2 - // Matter.Body.setDensity(me, 0.2); //extra dense //normal is 0.001 //makes effective life much larger - // // spawn.shield(me, x, y, 1); - // me.onDamage = function() {}; - // me.cycle = 660; - // me.endCycle = 780; - // me.totalCycles = 0 - // me.mode = 0; - // me.damageReduction = 0.25 //reset on each new mode - // me.pushAway = function(magX = 0.13, magY = 0.05) { - // for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally - // body[i].force.x += magX * body[i].mass * (body[i].position.x > this.position.x ? 1 : -1) - // body[i].force.y -= magY * body[i].mass - // } - // for (let i = 0, len = bullet.length; i < len; ++i) { //push blocks away horizontally - // bullet[i].force.x += magX * bullet[i].mass * (bullet[i].position.x > this.position.x ? 1 : -1) - // bullet[i].force.y -= magY * bullet[i].mass - // } - // for (let i = 0, len = powerUp.length; i < len; ++i) { //push blocks away horizontally - // powerUp[i].force.x += magX * powerUp[i].mass * (powerUp[i].position.x > this.position.x ? 1 : -1) - // powerUp[i].force.y -= magY * powerUp[i].mass - // } - // player.force.x += magX * player.mass * (player.position.x > this.position.x ? 1 : -1) - // player.force.y -= magY * player.mass - // } - // me.do = function() { - // this.modeDo(); //this does different things based on the mode - // this.checkStatus(); - // this.cycle++; //switch modes÷ if time isn't paused - // this.totalCycles++; - // if (this.health > 0.3) { - // if (this.cycle > this.endCycle) { - // this.showHealthBar = true - // this.cycle = 0; - // this.mode++ - // this.damageReduction = 0.25 - // if (this.totalCycles > 180) this.pushAway(); - // if (this.mode > 3) { - // this.mode = 0; - // this.fill = "#50f"; - // this.rotateVelocity = Math.abs(this.rotateVelocity) * (player.position.x > this.position.x ? 1 : -1) //rotate so that the player can get away - // this.modeDo = this.modeLasers - // //push blocks and player away, since this is the end of suck, and suck causes blocks to fall on the boss and stun it - // Matter.Body.scale(this, 1000, 1000); - // if (!this.isShielded) spawn.shield(this, this.position.x, this.position.y, 1); // regen shield to also prevent stun - // } else if (this.mode === 1) { - // this.fill = "#50f"; // this.fill = "rgb(150,150,255)"; - // this.modeDo = this.modeSpawns - // } else if (this.mode === 2) { - // this.fill = "#50f"; - // this.modeDo = this.modeBombs - // } else if (this.mode === 3) { - // for (let i = 0; i < mob.length; i++) { - // if (mob[i].isMine) mob[i].isExploding = true //explode the mines at the start of new round - // } - // this.fill = "#000"; - // this.modeDo = this.modeSuck - // Matter.Body.scale(this, 0.001, 0.001); - // this.damageReduction = 0.000025 - // this.showHealthBar = false - // } - - // if (tech.isGunCycle) { - // b.inventoryGun++; - // if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0; - // simulation.switchGun(); - // } - // } - // } else if (this.mode !== 3) { //all three modes at once , this runs once - // this.showHealthBar = true - // this.pushAway(); - // this.cycle = 0; - // this.endCycle = Infinity - // this.damageReduction = 0.15 - // if (this.mode === 2) { - // Matter.Body.scale(this, 500, 500); - // } else { - // Matter.Body.scale(this, 0.5, 0.5); - // } - // this.mode = 3 - // this.fill = "#000"; - // this.eventHorizon = 750 - // this.spawnInterval = 600 - // this.rotateVelocity = 0.001 * (player.position.x > this.position.x ? 1 : -1) //rotate so that the player can get away - // // if (!this.isShielded) spawn.shield(this, x, y, 1); //regen shield here ? - // this.modeDo = this.modeAll - // this.eventHorizonRadius = 700 - // if (tech.isGunCycle) { - // b.inventoryGun++; - // if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0; - // simulation.switchGun(); - // } - // } - // // } - // }; - // me.modeDo = function() {} - // me.modeAll = function() { - // this.modeBombs() - // this.modeSpawns() - // this.modeSuck() - // this.modeLasers() - // } - // me.bombInterval = 36 - 0.5 * simulation.difficultyMode * simulation.difficultyMode - // me.modeBombs = function() { - // if (!(this.cycle % 20)) { - // if (m.pos.x < 750) { - // spawn.mine(m.pos.x + 200 * (Math.random() - 0.5), -500) - // } else { - // spawn.mine(Math.min(Math.max(770, m.pos.x + 200 * (Math.random() - 0.5)), 5350), -1500) - // } - // } - // if (!(this.cycle % 10)) spawn.mine(800 + 4550 * Math.random(), -1500) - - // //mines fall - // for (let i = 0; i < mob.length; i++) { - // // if (mob[i].isMine && mob[i].position.y < -5) Matter.Body.setPosition(mob[i], { x: mob[i].position.x, y: mob[i].position.y + 5 }) - // if (mob[i].isMine && mob[i].position.y < -14) mob[i].force.y += mob[i].mass * 0.03; - // } - - // } - // me.spawnInterval = 395 - // me.modeSpawns = function() { - // if (!(this.cycle % this.spawnInterval) && mob.length < 40) { - // if (this.mode !== 3) Matter.Body.setAngularVelocity(this, 0.1) - // //fire a bullet from each vertex - // const whoSpawn = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]; - // for (let i = 0, len = 2 + this.totalCycles / 1000; i < len; i++) { - // const vertex = this.vertices[i % 6] - // spawn[whoSpawn](vertex.x + 50 * (Math.random() - 0.5), vertex.y + 50 * (Math.random() - 0.5)); - // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, vertex))), -18) //give the mob a rotational velocity as if they were attached to a vertex - // Matter.Body.setVelocity(mob[mob.length - 1], { - // x: this.velocity.x + velocity.x, - // y: this.velocity.y + velocity.y - // }); - // } - // if (!(this.cycle % 2 * this.spawnInterval) && mob.length < 40) { - // const len = (this.totalCycles / 1000 + simulation.difficulty / 2 - 30) / 15 - // for (let i = 0; i < len; i++) { - // spawn.randomLevelBoss(3000 * (simulation.isHorizontalFlipped ? -1 : 1) + 2000 * (Math.random() - 0.5), -1100 + 200 * (Math.random() - 0.5)) - // } - // } - // } - // } - // me.eventHorizon = 0 - // me.eventHorizonRadius = 1300 - // me.modeSuck = function() { - // if (!(this.cycle % 30)) { - // const index = Math.floor((this.cycle % 360) / 60) - // spawn.seeker(this.vertices[index].x, this.vertices[index].y, 20 * (0.5 + Math.random()), 9); //give the bullet a rotational velocity as if they were attached to a vertex - // const who = mob[mob.length - 1] - // Matter.Body.setDensity(who, 0.00003); //normal is 0.001 - // who.timeLeft = 720 + 10 * simulation.difficulty //* (0.8 + 0.4 * Math.random()); - // who.accelMag = 0.0003 * simulation.accelScale; //* (0.8 + 0.4 * Math.random()) - // who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random()); - // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -7) - // Matter.Body.setVelocity(who, { - // x: this.velocity.x + velocity.x, - // y: this.velocity.y + velocity.y - // }); - // } - - // //eventHorizon waves in and out - // if (this.cycle + 30 > this.endCycle) { //shrink fast in last bit of cycle - // this.eventHorizon = 0.93 * this.eventHorizon - // } else { - // this.eventHorizon = 0.97 * this.eventHorizon + 0.03 * (this.eventHorizonRadius * (1 - 0.5 * Math.cos(this.cycle * 0.015))) - // } - // //draw darkness - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.2, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,20,40,0.6)"; - // ctx.fill(); - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.4, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,20,40,0.4)"; - // ctx.fill(); - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.6, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,20,40,0.3)"; - // ctx.fill(); - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.8, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,20,40,0.2)"; - // ctx.fill(); - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,0,0,0.05)"; - // ctx.fill(); - // //when player is inside event horizon - // if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) { - // if (m.immuneCycle < m.cycle) { - // if (m.energy > 0) m.energy -= 0.02 - // if (m.energy < 0.05 && m.immuneCycle < m.cycle) m.damage(0.0004 * simulation.dmgScale); - // } - // const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x); - // player.force.x -= 0.0017 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1); - // player.force.y -= 0.0017 * Math.sin(angle) * player.mass; - // //draw line to player - // ctx.beginPath(); - // ctx.moveTo(this.position.x, this.position.y); - // ctx.lineTo(m.pos.x, m.pos.y); - // ctx.lineWidth = Math.min(60, this.radius * 2); - // ctx.strokeStyle = "rgba(0,0,0,0.5)"; - // ctx.stroke(); - // ctx.beginPath(); - // ctx.arc(m.pos.x, m.pos.y, 40, 0, 2 * Math.PI); - // ctx.fillStyle = "rgba(0,0,0,0.3)"; - // ctx.fill(); - // } - // this.curl(this.eventHorizon); - // } - // me.rotateVelocity = 0.0025 - // me.rotateCount = 0; - // me.lasers = function(where, angle, dmg = 0.14 * simulation.dmgScale) { - // 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 = simulation.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 = simulation.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) best = { - // x: results.x, - // y: results.y, - // dist2: dist2, - // who: domain[i], - // v1: vertices[0], - // v2: vertices[len] - // }; - // } - // } - // }; - - // const seeRange = 7000; - // best = { - // x: null, - // y: null, - // dist2: Infinity, - // who: null, - // v1: null, - // v2: null - // }; - // const look = { - // x: where.x + seeRange * Math.cos(angle), - // y: where.y + seeRange * Math.sin(angle) - // }; - // // vertexCollision(where, look, mob); - // vertexCollision(where, look, map); - // vertexCollision(where, look, body); - // if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); - // if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { - // if (m.immuneCycle < m.cycle + 60 + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 60 + m.collisionImmuneCycles; //player is immune to damage extra time - // m.damage(dmg); - // simulation.drawList.push({ //add dmg to draw queue - // x: best.x, - // y: best.y, - // radius: dmg * 1500, - // color: "rgba(80,0,255,0.5)", - // time: 20 - // }); - // } - // //draw beam - // if (best.dist2 === Infinity) best = look; - // ctx.moveTo(where.x, where.y); - // ctx.lineTo(best.x, best.y); - // } - // me.modeLasers = function() { - // if (!this.isStunned) { - // let slowed = false //check if slowed - // for (let i = 0; i < this.status.length; i++) { - // if (this.status[i].type === "slow") { - // slowed = true - // break - // } - // } - // if (!slowed) { - // this.rotateCount++ - // Matter.Body.setAngle(this, this.rotateCount * this.rotateVelocity) - // Matter.Body.setAngularVelocity(this, 0) - // Matter - // } - // } - // if (this.cycle < 240) { //damage scales up over 2 seconds to give player time to move - // const scale = this.cycle / 240 - // const dmg = (this.cycle < 120) ? 0 : 0.14 * simulation.dmgScale * scale - // ctx.beginPath(); - // this.lasers(this.vertices[0], this.angle + Math.PI / 6, dmg); - // this.lasers(this.vertices[1], this.angle + 3 * Math.PI / 6, dmg); - // this.lasers(this.vertices[2], this.angle + 5 * Math.PI / 6, dmg); - // this.lasers(this.vertices[3], this.angle + 7 * Math.PI / 6, dmg); - // this.lasers(this.vertices[4], this.angle + 9 * Math.PI / 6, dmg); - // this.lasers(this.vertices[5], this.angle + 11 * Math.PI / 6, dmg); - // ctx.strokeStyle = "#50f"; - // ctx.lineWidth = 1.5 * scale; - // ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); - // ctx.stroke(); // Draw it - // ctx.setLineDash([]); - // ctx.lineWidth = 20; - // ctx.strokeStyle = `rgba(80,0,255,${0.07 * scale})`; - // ctx.stroke(); // Draw it - // } else { - // ctx.beginPath(); - // this.lasers(this.vertices[0], this.angle + Math.PI / 6); - // this.lasers(this.vertices[1], this.angle + 3 * Math.PI / 6); - // this.lasers(this.vertices[2], this.angle + 5 * Math.PI / 6); - // this.lasers(this.vertices[3], this.angle + 7 * Math.PI / 6); - // this.lasers(this.vertices[4], this.angle + 9 * Math.PI / 6); - // this.lasers(this.vertices[5], this.angle + 11 * Math.PI / 6); - // ctx.strokeStyle = "#50f"; - // ctx.lineWidth = 1.5; - // ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]); - // ctx.stroke(); // Draw it - // ctx.setLineDash([]); - // ctx.lineWidth = 20; - // ctx.strokeStyle = "rgba(80,0,255,0.07)"; - // ctx.stroke(); // Draw it - // } - // } - // me.onDeath = function() { - // if (!this.hasRunDeathScript) { - // this.hasRunDeathScript = true - // //make a block body to replace this one - // //this body is too big to leave behind in the normal way mobs.replace() - // const len = body.length; - // const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure - // body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v); - // Matter.Body.setVelocity(body[len], { x: 0, y: -3 }); - // Matter.Body.setAngularVelocity(body[len], this.angularVelocity); - // body[len].collisionFilter.category = cat.body; - // body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; - // body[len].classType = "body"; - // Composite.add(engine.world, body[len]); //add to world - // const expand = function(that, massLimit) { - // const scale = 1.05; - // Matter.Body.scale(that, scale, scale); - // if (that.mass < massLimit) setTimeout(expand, 20, that, massLimit); - // }; - // expand(body[len], 200) - - // function unlockExit() { - // if (simulation.isHorizontalFlipped) { - // level.exit.x = -5500 - 100; - // } else { - // level.exit.x = 5500; - // } - // level.exit.y = -330; - // Matter.Composite.remove(engine.world, map[map.length - 1]); - // map.splice(map.length - 1, 1); - // simulation.draw.setPaths(); //redraw map draw path - // // level.levels.push("null") - // } - - // //add lore level as next level if player took lore tech earlier in the game - // if (lore.techCount > (lore.techGoal - 1) && !simulation.isCheating) { - // simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`, 360); - // setTimeout(function() { - // simulation.makeTextLog(`level.levels.push("null")`, 720); - // unlockExit() - // level.levels.push("null") - // }, 4000); - // //remove block map element so exit is clear - // } else { //reset game - // let count = 0 - - // function loop() { - // if (!simulation.paused && !simulation.onTitlePage) { - // count++ - // if (count < 660) { - // if (count === 1) simulation.makeTextLog(`//enter testing mode to set level.levels.length to Infinite`); - // if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${((count / 60 - Math.random()) * 0.1).toFixed(3)}`); - // } else if (count === 660) { - // simulation.makeTextLog(`simulation.analysis = 1 //analysis complete`); - // } else if (count === 780) { - // simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`) - // } else if (count === 1020) { - // simulation.makeTextLog(`Engine.clear(engine) //simulation successful`); - // } else if (count === 1260) { - // // tech.isImmortal = false; - // // m.death() - // // m.alive = false; - // // simulation.paused = true; - // // m.health = 0; - // // m.displayHealth(); - // document.getElementById("health").style.display = "none" - // document.getElementById("health-bg").style.display = "none" - // document.getElementById("text-log").style.opacity = 0; //fade out any active text logs - // document.getElementById("fade-out").style.opacity = 1; //slowly fades out - // // build.shareURL(false) - // setTimeout(function() { - // if (!simulation.onTitlePage) { - // simulation.paused = true; - // // simulation.clearMap(); - // // Matter.Composite.clear(composite, keepStatic, [deep = false]) - // // Composite.clear(engine.composite); - // engine.world.bodies.forEach((body) => { Matter.Composite.remove(engine.world, body) }) - // Engine.clear(engine); - // simulation.splashReturn(); - // } - // }, 6000); - // return - // } - // } - // if (simulation.testing) { - // unlockExit() - // setTimeout(function() { - // simulation.makeTextLog(`level.levels.length = Infinite`); - // }, 1500); - // } else { - // if (!simulation.onTitlePage) requestAnimationFrame(loop); - // } - // } - // requestAnimationFrame(loop); - // } - // // for (let i = 0; i < 3; i++) - // level.difficultyIncrease(simulation.difficultyMode) //ramp up damage - // //remove power Ups, to avoid spamming console - // function removeAll(array) { - // for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]); - // } - // removeAll(powerUp); - // powerUp = []; - - // //pull in particles - // for (let i = 0, len = body.length; i < len; ++i) { - // const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65) - // const pushUp = Vector.add(velocity, { x: 0, y: -0.5 }) - // Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp)); - // } - // //damage all mobs - // for (let j = 0; j < 8; j++) { //in case some mobs leave things after they die - // for (let i = 0, len = mob.length; i < len; ++i) { - // if (mob[i] !== this) { - // if (mob[i].isInvulnerable) { //disable invulnerability - // mob[i].isInvulnerable = false - // mob[i].damageReduction = 1 - // } - // mob[i].damage(Infinity, true); - // } - // } - // } - - // //draw stuff - // for (let i = 0, len = 22; i < len; i++) { - // simulation.drawList.push({ //add dmg to draw queue - // x: this.position.x, - // y: this.position.y, - // radius: (i + 1) * 150, - // color: `rgba(255,255,255,0.17)`, - // time: 5 * (len - i + 1) - // }); - // } - // } - // }; - // }, zombie(x, y, radius, sides, color) { //mob that attacks other mobs mobs.spawn(x, y, sides, radius, color); let me = mob[mob.length - 1]; @@ -2229,7 +1697,7 @@ const spawn = { me.isInvulnerable = true me.startingDamageReduction = me.damageReduction me.damageReduction = 0 - me.invulnerabilityCountDown = 40 + simulation.difficulty + me.invulnerabilityCountDown = 25 + simulation.difficulty me.onHit = function () { //run this function on hitting player if (powerUps.ejectTech()) { powerUps.ejectGraphic("150, 138, 255"); @@ -2276,10 +1744,7 @@ const spawn = { for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) { powerUp[i].collisionFilter.mask = 0 Matter.Body.setPosition(powerUp[i], this.vertices[i]) - Matter.Body.setVelocity(powerUp[i], { - x: 0, - y: 0 - }) + Matter.Body.setVelocity(powerUp[i], { x: 0, y: 0 }) } } this.seePlayerByHistory(50); @@ -2294,7 +1759,7 @@ const spawn = { me.frictionAir = 0.01 me.seeAtDistance2 = 1000000; me.accelMag = 0.0002 + 0.0004 * simulation.accelScale; - Matter.Body.setDensity(me, 0.00035); //normal is 0.001 + Matter.Body.setDensity(me, 0.0003); //normal is 0.001 me.collisionFilter.mask = cat.bullet | cat.player //| cat.body me.memory = Infinity; me.seePlayerFreq = 30 @@ -2308,7 +1773,7 @@ const spawn = { me.foundPlayer(); } - me.damageReduction = 0.16 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.isInvulnerable = true // me.startingDamageReduction = me.damageReduction // me.damageReduction = 0 @@ -3215,10 +2680,7 @@ const spawn = { me.seePlayerFreq = 31; const springStiffness = 0.00003; //simulation.difficulty const springDampening = 0.0002; - me.springTarget = { - x: me.position.x, - y: me.position.y - }; + me.springTarget = { x: me.position.x, y: me.position.y }; const len = cons.length; cons[len] = Constraint.create({ pointA: me.springTarget, @@ -3314,47 +2776,6 @@ const spawn = { } else { this.torque = this.lookTorque * this.inertia; //spring to random place on map - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; - //move to a random location if (!(simulation.cycle % (this.seePlayerFreq))) { best = { x: null, @@ -3365,11 +2786,8 @@ const spawn = { v2: null }; const seeRange = 3000; - const look = { - x: this.position.x + seeRange * Math.cos(this.angle), - y: this.position.y + seeRange * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); + const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) }; + best = vertexCollision(this.position, look, [map]); if (best.dist2 != Infinity) { this.springTarget.x = best.x; this.springTarget.y = best.y; @@ -3899,46 +3317,6 @@ const spawn = { const seeRange = 550 + 35 * simulation.difficultyMode; if (this.distanceToPlayer() < seeRange) { - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; best = { x: null, y: null, @@ -3948,13 +3326,8 @@ const spawn = { v2: null }; const seeRangeRandom = seeRange - 200 - 150 * Math.random() - const look = { - x: this.position.x + seeRangeRandom * Math.cos(this.angle), - y: this.position.y + seeRangeRandom * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); - vertexCollision(this.position, look, body); - if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]); + const look = { x: this.position.x + seeRangeRandom * Math.cos(this.angle), y: this.position.y + seeRangeRandom * Math.sin(this.angle) }; + best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); // hitting player if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { @@ -4272,46 +3645,6 @@ const spawn = { this.torque -= 0.000004 * this.inertia; } if (simulation.cycle % this.laserInterval > this.laserInterval / 2) { - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; const seeRange = 8000; best = { x: null, @@ -4321,13 +3654,8 @@ const spawn = { v1: null, v2: null }; - const look = { - x: this.position.x + seeRange * Math.cos(this.angle), - y: this.position.y + seeRange * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); - vertexCollision(this.position, look, body); - if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]); + const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) }; + best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); // hitting player if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { @@ -4390,26 +3718,6 @@ const spawn = { me.targetingCount = 0; me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty) me.do = function () { - - // //wings - // const wing = (simulation.cycle % 9) > 4 ? this.vertices[0] : this.vertices[2] //Vector.add(this.position, { x: 100, y: 0 }) - // const radius = 200 - // //draw - // ctx.beginPath(); - // ctx.arc(wing.x, wing.y, radius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay - // ctx.fillStyle = "rgba(0,235,255,0.3)"; - // ctx.fill(); - // //check damage - // const hitPlayer = Matter.Query.ray([player], this.position, wing, radius) - // if (hitPlayer.length && m.immuneCycle < m.cycle) { - // m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage - // m.damage(0.02 * simulation.dmgScale); - // } - - - - - this.seePlayerByLookingAt(); this.checkStatus(); this.attraction(); @@ -4427,46 +3735,6 @@ const spawn = { } else if (c < -threshold) { this.torque -= 0.000004 * this.inertia; } - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; const seeRange = 8000; best = { @@ -4477,12 +3745,8 @@ const spawn = { v1: null, v2: null }; - const look = { - x: this.position.x + seeRange * Math.cos(this.angle), - y: this.position.y + seeRange * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); - if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]); + const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) }; + best = vertexCollision(this.position, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]); // hitting player if (best.who === playerBody || best.who === playerHead) { @@ -4844,6 +4108,152 @@ const spawn = { } }; }, + laserLayer(x, y, radius = 18 + Math.floor(6 * Math.random())) { + const color = "#f09" + mobs.spawn(x, y, 4, radius, color); + let me = mob[mob.length - 1]; + me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front + for (let i = 0; i < 4; i += 2) { + let spike = Vector.mult(Vector.normalise(Vector.sub(me.vertices[i], me.position)), radius * 2) + me.vertices[i].x = me.position.x + spike.x + me.vertices[i].y = me.position.y + spike.y + } + Matter.Body.rotate(me, Math.random() * Math.PI * 2); + me.accelMag = 0.0002 * simulation.accelScale; + // me.frictionAir = 1 + + me.lasers = [] //keeps track of static laser beams + me.laserLimit = simulation.difficultyMode < 3 ? 1 : 2 + me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) + me.cycle = 0 + me.laserDelay = 150 + Math.floor(Math.random() * 120) + me.addLaser = function () { + if (this.cycle > this.laserDelay) { + this.cycle = 0 + const seeRange = 6000; + const angle = this.angle + Math.PI / 4 + const v1 = { x: this.position.x + seeRange * Math.cos(angle), y: this.position.y + seeRange * Math.sin(angle) }; + const v2 = { x: this.position.x + seeRange * Math.cos(angle + Math.PI), y: this.position.y + seeRange * Math.sin(angle + Math.PI) }; + //find where v1,v2 hit walls and make them stop there + let best1 = vertexCollision(this.position, v1, [map]); + let best2 = vertexCollision(this.position, v2, [map]); + if (best2.who === null) { + best2.x = v2.x + best2.y = v2.y + } + if (best1.who === null) { //if the path never hits the map , just stop at seeRange + best1.x = v1.x + best1.y = v1.y + } + if (best1.y > best2.y) { //make laser beams always fire from top to bottom so they are predicable, and not stopped by blocks on the ground + const save1X = best1.x + const save1Y = best1.y + best1.x = best2.x + best1.y = best2.y + best2.x = save1X + best2.y = save1Y + } + + this.lasers.push({ a: { x: best1.x, y: best1.y }, b: { x: best2.x, y: best2.y }, fade: 0 }) + //friction to animate the mob dropping something + Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.05)); + Matter.Body.setAngularVelocity(this, this.angularVelocity * 0.05) + // simulation.drawList.push({ x: best1.x, y: best1.y, radius: 10, color: "rgba(255,0,100,0.3)", time: simulation.drawTime * 2 }); + // simulation.drawList.push({ x: best2.x, y: best2.y, radius: 10, color: "rgba(255,0,100,0.3)", time: simulation.drawTime * 2 }); + + if (this.lasers.length > this.laserLimit) this.lasers.shift() //cap total lasers + if (!this.seePlayer.recall && (Vector.magnitude(Vector.sub(this.position, this.driftGoal)) < 200 || 0.3 > Math.random())) { + //used in drift when can't find player + const radius = Math.random() * 1000; + const angle = Math.random() * 2 * Math.PI; + this.driftGoal = Vector.add(this.driftCenter, { x: radius * Math.cos(angle), y: radius * Math.sin(angle) }) + } + } + } + me.fireLaser = function () { + for (let i = 0; i < this.lasers.length; i++) { //fire all lasers in the array + let best = vertexCollision(this.lasers[i].a, this.lasers[i].b, m.isCloak ? [body] : [body, [playerBody, playerHead]]); //not checking map to fix not hitting player bug, this might make some lasers look strange when the map changes + if (this.lasers[i].fade > 0.99) { + if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player + m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit + const dmg = 0.05 * simulation.dmgScale; + m.damage(dmg); + simulation.drawList.push({ //add dmg to draw queue + x: best.x, + y: best.y, + radius: dmg * 1500, + color: "rgba(255,0,100,0.5)", + time: 20 + }); + this.lasers.splice(i, 1) //remove this laser node + if (this.distanceToPlayer < 1000) { //mob jumps away from player + const forceMag = 0.03 * this.mass; + const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); + this.force.x -= 2 * forceMag * Math.cos(angle); + this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity + } + } else if (best.who && best.who.classType === "body") { //hitting block + ctx.beginPath(); + ctx.moveTo(best.x, best.y); + ctx.lineTo(this.lasers[i].a.x, this.lasers[i].a.y); + ctx.strokeStyle = `rgb(255,0,100)`; + ctx.lineWidth = 2; + ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + ctx.stroke(); + ctx.setLineDash([]); + } else { //hitting nothing + ctx.beginPath(); + ctx.moveTo(this.lasers[i].b.x, this.lasers[i].b.y); + ctx.lineTo(this.lasers[i].a.x, this.lasers[i].a.y); + ctx.strokeStyle = `rgb(255,0,100)`; + ctx.lineWidth = 2; + ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + ctx.stroke(); + ctx.setLineDash([]); + } + } else {//fade in warning + this.lasers[i].fade += 0.01 + ctx.beginPath(); + ctx.moveTo(this.lasers[i].a.x, this.lasers[i].a.y); + ctx.lineTo(this.lasers[i].b.x, this.lasers[i].b.y); + ctx.lineWidth = 5 + 5 * this.lasers[i].fade; + ctx.strokeStyle = `rgba(255,0,100,${0.02 + 0.1 * this.lasers[i].fade})`; + ctx.stroke(); + } + } + } + me.driftCenter = { ...me.position }; //copy position with out reference so it doesn't change as mob moves + const r = Math.random() * 100; + const a = Math.random() * 2 * Math.PI; + me.driftGoal = Vector.add(me.driftCenter, { x: r * Math.cos(a), y: r * Math.sin(a) }) //updated in addLaser() + me.drift = function () { + //accelerate towards the player + if (this.seePlayer.recall) { + const force = Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position, this.position)), this.accelMag * this.mass) + this.force.x += force.x; + this.force.y += force.y; + } else { //drift + const force = Vector.mult(Vector.normalise(Vector.sub(this.driftGoal, this.position)), 0.00002 * this.mass) + // const force = Vector.mult(this.driftGoal, 0.0001 * this.mass) + this.force.x += force.x; + this.force.y += force.y; + } + }, + me.do = function () { + this.cycle++ + this.torque = this.lookTorque * this.inertia * 0.6; + this.seePlayerCheck(); + this.checkStatus(); + this.drift(); + //add new laser to lasers array + this.addLaser() + this.fireLaser() + // if (this.seePlayer.recall) { + // //set direction to turn to fire + // if (!(simulation.cycle % this.seePlayerFreq)) this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); + // } + }; + }, laser(x, y, radius = 30) { const color = "#f00" mobs.spawn(x, y, 3, radius, color); @@ -4866,46 +4276,6 @@ const spawn = { if (!(simulation.cycle % this.seePlayerFreq)) this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); if (simulation.cycle % this.laserInterval > this.laserInterval / 2) { - 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 = simulation.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 = simulation.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) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; const seeRange = 8000; best = { x: null, @@ -4915,13 +4285,8 @@ const spawn = { v1: null, v2: null }; - const look = { - x: this.position.x + seeRange * Math.cos(this.angle), - y: this.position.y + seeRange * Math.sin(this.angle) - }; - vertexCollision(this.position, look, map); - vertexCollision(this.position, look, body); - if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]); + const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) }; + best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); // hitting player if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { @@ -4963,10 +4328,7 @@ const spawn = { setTimeout(() => { //fix mob in place, but allow rotation me.constraint = Constraint.create({ - pointA: { - x: me.position.x, - y: me.position.y - }, + pointA: { x: me.position.x, y: me.position.y }, bodyB: me, stiffness: 1, damping: 1 @@ -4988,7 +4350,6 @@ const spawn = { me.do = function () { this.fill = '#' + Math.random().toString(16).substr(-6); //flash colors this.checkStatus(); - if (!this.isStunned) { //check if slowed let slowed = false @@ -5003,7 +4364,6 @@ const spawn = { Matter.Body.setAngle(this, this.count * this.rotateVelocity) Matter.Body.setAngularVelocity(this, 0) } - ctx.beginPath(); this.lasers(this.vertices[0], this.angle + Math.PI / 3); this.lasers(this.vertices[1], this.angle + Math.PI); @@ -5017,53 +4377,8 @@ const spawn = { ctx.strokeStyle = "rgba(80,0,255,0.07)"; ctx.stroke(); // Draw it } - - - // Matter.Body.setVelocity(this, { - // x: 0, - // y: 0 - // }); - // Matter.Body.setPosition(this, this.startingPosition); - }; me.lasers = function (where, angle) { - 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 = simulation.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 = simulation.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) best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - }; - const seeRange = 7000; best = { x: null, @@ -5073,14 +4388,9 @@ const spawn = { v1: null, v2: null }; - const look = { - x: where.x + seeRange * Math.cos(angle), - y: where.y + seeRange * Math.sin(angle) - }; - // vertexCollision(where, look, mob); - vertexCollision(where, look, map); - vertexCollision(where, look, body); - if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); + const look = { x: where.x + seeRange * Math.cos(angle), y: where.y + seeRange * Math.sin(angle) }; + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); + if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second const dmg = 0.14 * simulation.dmgScale; @@ -5115,9 +4425,6 @@ const spawn = { me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.player //can't touch other mobs Matter.Body.rotate(me, Math.PI * 0.1); spawn.shield(me, x, y); - // me.onDamage = function () {}; - // me.onHit = function() { //run this function on hitting player - // }; me.onDeath = function () { if (this.spikeLength > 4) { this.spikeLength = 4 @@ -5157,11 +4464,6 @@ const spawn = { } else { if (this.isSpikeGrowing) { this.spikeLength += Math.pow(this.spikeGrowth += 0.02, 8) - // if (this.spikeLength < 2) { - // this.spikeLength += 0.035 - // } else { - // this.spikeLength += 1 - // } if (this.spikeLength > spikeMax) { this.isSpikeGrowing = false; this.spikeGrowth = 0 @@ -5182,7 +4484,6 @@ const spawn = { } }; }, - striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) { mobs.spawn(x, y, 5, radius, "rgb(221,102,119)"); let me = mob[mob.length - 1]; @@ -5306,33 +4607,9 @@ const spawn = { } }; me.laserSword = function (where, angle, length) { - 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 = simulation.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 = simulation.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) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[0], v2: vertices[len] }; - } - } - }; best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }; const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) }; - // vertexCollision(where, look, body); // vertexCollision(where, look, mob); - vertexCollision(where, look, map); - if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]); + best = vertexCollision(where, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second m.damage(this.swordDamage); @@ -5934,33 +5211,11 @@ const spawn = { 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]); + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); + if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.damage(this.swordDamage); @@ -6056,33 +5311,9 @@ const spawn = { } } 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]); + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.damage(this.swordDamage); @@ -6172,33 +5403,9 @@ const spawn = { } } 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]); + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second m.damage(this.swordDamage); @@ -6306,33 +5513,10 @@ const spawn = { } } me.laserSpear = 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]); + best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]); + if (best.who && (best.who === playerBody || best.who === playerHead)) { this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player @@ -6543,10 +5727,10 @@ const spawn = { mobs.spawn(x, y, 7, radius, "transparent"); let me = mob[mob.length - 1]; me.seeAtDistance2 = 300000; - me.accelMag = 0.00004 + 0.00015 * simulation.accelScale; + me.accelMag = 0.00007 + 0.0001 * simulation.accelScale; if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search - // Matter.Body.setDensity(me, 0.0015); //normal is 0.001 - me.damageReduction = 0.5 + Matter.Body.setDensity(me, 0.0002); //normal is 0.001 + me.damageReduction = 0.1 me.stroke = "transparent"; //used for drawGhost me.alpha = 1; //used in drawGhost me.isNotCloaked = false; //used in drawGhost @@ -6555,14 +5739,35 @@ const spawn = { me.collisionFilter.mask = cat.bullet //| cat.body me.showHealthBar = false; me.memory = 600; - me.do = function () { - //cap max speed to avoid getting launched by deflection, explosion - if (this.speed > 7) { - Matter.Body.setVelocity(this, { - x: this.velocity.x * 0.8, - y: this.velocity.y * 0.8 - }); + me.delay = 60 + me.cd = 0; + me.onHit = function () { + if (this.cd < simulation.cycle) { + this.cd = simulation.cycle + this.delay; + //dislodge ammo + if (b.inventory.length) { + let isRemovedAmmo = false + const numRemoved = 3 + for (let j = 0; j < numRemoved; j++) { + for (let i = 0; i < b.inventory.length; i++) { + const gun = b.guns[b.inventory[i]] + if (gun.ammo > 0 && gun.ammo !== Infinity) { + gun.ammo -= Math.ceil((0.6 * Math.random() + 0.6 * Math.random()) * gun.ammoPack) //Math.ceil(Math.random() * target.ammoPack) + if (gun.ammo < 0) gun.ammo = 0 + isRemovedAmmo = true + } + } + } + if (isRemovedAmmo) { + simulation.updateGunHUD(); + for (let j = 0; j < numRemoved; j++) powerUps.directSpawn(this.position.x + 10 * Math.random(), this.position.y + 10 * Math.random(), "ammo"); + powerUps.ejectGraphic(); + } + } } + }; + me.do = function () { + if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion this.seePlayerCheckByDistance(); this.checkStatus(); this.attraction(); @@ -6586,9 +5791,7 @@ const spawn = { ctx.beginPath(); const vertices = this.vertices; ctx.moveTo(vertices[0].x, vertices[0].y); - for (let j = 1, len = vertices.length; j < len; ++j) { - ctx.lineTo(vertices[j].x, vertices[j].y); - } + for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y); ctx.lineTo(vertices[0].x, vertices[0].y); // ctx.lineWidth = 1; ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`; diff --git a/js/tech.js b/js/tech.js index 7900dfa..a62ab72 100644 --- a/js/tech.js +++ b/js/tech.js @@ -218,7 +218,7 @@ const tech = { } }, hasExplosiveDamageCheck() { - return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isHookExplosion + return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) }, damage: 1, //used for tech changes to player damage that don't have complex conditions damageFromTech() { @@ -1215,6 +1215,38 @@ const tech = { b.setFireCD(); } }, + { + name: "dynamical systems", + description: `use ${powerUps.orb.research(2)}
+30% damage`, + // isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return powerUps.research.count > 1 || build.isExperimentSelection + }, + requires: "", + // allowed() { + // return (m.fieldMode === 5 || m.fieldMode === 7 || m.fieldMode === 8) && (build.isExperimentSelection || powerUps.research.count > 1) + // }, + // requires: "cloaking, pilot wave, or plasma torch", + damage: 1.3, + effect() { + tech.damage *= this.damage + tech.isCloakingDamage = true + for (let i = 0; i < 2; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + } + }, + remove() { + tech.isCloakingDamage = false + if (this.count > 0) { + tech.damage /= this.damage + powerUps.research.changeRerolls(2) + } + } + }, { name: "heuristics", description: "+22% fire rate
spawn a gun", @@ -1412,24 +1444,24 @@ const tech = { tech.healSpawn = 0; } }, - { - name: "yield stress", - description: "+55% damage
to mobs at maximum health", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return m.fieldMode !== 7 && tech.mobSpawnWithHealth === 0 - }, - requires: "not cloaking, reaction inhibitor", - effect() { - tech.isMobFullHealth = true - }, - remove() { - tech.isMobFullHealth = false - } - }, + // { + // name: "yield stress", + // description: "+55% damage
to mobs at maximum health", + // maxCount: 1, + // count: 0, + // frequency: 1, + // frequencyDefault: 1, + // allowed() { + // return m.fieldMode !== 7 && tech.mobSpawnWithHealth === 0 + // }, + // requires: "not cloaking, reaction inhibitor", + // effect() { + // tech.isMobFullHealth = true + // }, + // remove() { + // tech.isMobFullHealth = false + // } + // }, { name: "cascading failure", description: "+222% damage
to mobs below 25% health", @@ -1456,7 +1488,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isMobFullHealth + return !tech.isMobFullHealthCloak }, requires: "not topological defect", effect() { @@ -2676,6 +2708,34 @@ const tech = { tech.isHarmArmor = false; } }, + { + name: "tessellation", + description: `use ${powerUps.orb.research(2)}
+35% defense`, + // description: "use 4 research
reduce defense by 50%", + // isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return powerUps.research.count > 1 || build.isExperimentSelection + }, + requires: "", + // allowed() { + // return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 3) + // }, + // requires: "perfect diamagnetism, negative mass, grappling hook, pilot wave", + effect() { + tech.isFieldHarmReduction = true + for (let i = 0; i < 2; i++) { + if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) + } + }, + remove() { + tech.isFieldHarmReduction = false + if (this.count > 0) powerUps.research.changeRerolls(2) + } + }, { name: "Pauli exclusion", description: `after mob collisions
become invulnerable for +3.5 seconds`, @@ -2796,14 +2856,14 @@ const tech = { }, { name: "heat engine", - description: `+50% damage
–50 maximum energy`, + description: `+40% damage
–50 maximum energy`, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed: () => true, requires: "not CPT", - damage: 1.5, + damage: 1.4, effect() { tech.damage *= this.damage tech.isMaxEnergyTech = true; @@ -4184,7 +4244,7 @@ const tech = { { name: "commodities exchange", descriptionFunction() { - return `clicking cancel for a field, tech, or gun
spawns 6-12 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` + return `clicking cancel for a field, tech, or gun
spawns 10-14 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` }, maxCount: 1, count: 0, @@ -4912,7 +4972,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isFoamMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 + return tech.hookNails + tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isFoamMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 }, requires: "nails, nail gun, rivets, shotgun, super balls, mine", effect() { @@ -4951,7 +5011,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || ((tech.isMineDrop || tech.haveGunCheck("mine")) && !(tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot)) + return tech.isNailBotUpgrade || tech.hookNails || tech.fragments || tech.nailsDeathMob || ((tech.isMineDrop || tech.haveGunCheck("mine")) && !(tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot)) }, requires: "nail gun, nails, rivets, mine, not ceramic needles", effect() { @@ -5842,7 +5902,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || tech.isHookExplosion || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) + return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) }, requires: "an explosive damage source, not rocket propelled grenade", effect() { @@ -6123,7 +6183,7 @@ const tech = { frequencyDefault: 2, allowed() { // return (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("mines")) - return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles) + return tech.isMineDrop || tech.isNailBotUpgrade || tech.hookNails || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles) }, // requires: "nail gun, not rotary cannon, rivets, or needles", @@ -7074,7 +7134,7 @@ const tech = { // }, { name: "alternator", - description: "+90% harpoon energy efficiency", + description: "harpoon no longer uses any energy", isGunTech: true, maxCount: 1, count: 0, @@ -7113,7 +7173,7 @@ const tech = { { name: "Bessemer process", descriptionFunction() { - return `+${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}% harpoon size and damage
(1/10 √ harpoon ammo)` + return `+${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}% harpoon size and damage
(effect scales by 1/10 √ harpoon ammo)` }, isGunTech: true, maxCount: 1, @@ -7179,7 +7239,7 @@ const tech = { { name: "UHMWPE", descriptionFunction() { - return `+${(b.guns[9].ammo * 1.25).toFixed(0)}% harpoon rope length
(1/80 of harpoon ammo)` + return `+${(b.guns[9].ammo * 1.25).toFixed(0)}% harpoon rope length
(effect scales by 1/80 of harpoon ammo)` }, isGunTech: true, maxCount: 1, @@ -7219,7 +7279,7 @@ const tech = { }, { name: "brittle", - description: "+88% harpoon/grapple damage
to mobs at maximum health", + description: "+111% harpoon/grapple damage
to mobs at maximum health", isGunTech: true, maxCount: 1, count: 0, @@ -7673,7 +7733,7 @@ const tech = { }, { name: "zero point energy", - description: `use ${powerUps.orb.research(2)}
+100 maximum energy`, + description: `use ${powerUps.orb.research(2)}
+166 maximum energy`, isFieldTech: true, maxCount: 1, count: 0, @@ -7684,7 +7744,7 @@ const tech = { }, requires: "standing wave, pilot wave, time dilation", effect() { - tech.harmonicEnergy = 1 + tech.harmonicEnergy = 1.66 m.setMaxEnergy() for (let i = 0; i < 2; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) @@ -7698,7 +7758,7 @@ const tech = { }, { name: "expansion", - description: "using standing wave field expands its radius
+40 maximum energy", + description: "using standing wave field expands its radius
+77 maximum energy", isFieldTech: true, maxCount: 1, count: 0, @@ -7860,30 +7920,6 @@ const tech = { tech.isBigField = false; } }, - { - name: "tessellation", - description: `use ${powerUps.orb.research(2)}
+50% defense`, - // description: "use 4 research
reduce defense by 50%", - isFieldTech: true, - maxCount: 1, - count: 0, - frequency: 3, - frequencyDefault: 3, - allowed() { - return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 3) - }, - requires: "perfect diamagnetism, negative mass, grappling hook, pilot wave", - effect() { - tech.isFieldHarmReduction = true - for (let i = 0; i < 2; i++) { - if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - } - }, - remove() { - tech.isFieldHarmReduction = false - if (this.count > 0) powerUps.research.changeRerolls(2) - } - }, { name: "radiative equilibrium", descriptionFunction() { @@ -7978,7 +8014,7 @@ const tech = { }, { name: "annihilation", - description: "after colliding with non-boss mobs
they are annihilated and –33% energy", + description: "after colliding with non-boss mobs
they are annihilated and –10 energy", isFieldTech: true, maxCount: 1, count: 0, @@ -8291,9 +8327,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return m.fieldMode === 5 || m.fieldMode === 6 || m.fieldMode === 7 || m.fieldMode === 8 || m.fieldMode === 4 + return m.fieldMode === 6 || m.fieldMode === 7 || m.fieldMode === 8 }, - requires: "cloaking, molecular assembler, plasma torch, pilot wave", + requires: "time dilation, cloaking, pilot wave", damage: 1.35, effect() { tech.damage *= this.damage @@ -8315,9 +8351,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10) && !tech.isPrinter && !tech.isReel && !tech.isHookExplosion + return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10) && !tech.isPrinter && !tech.isReel && !tech.hookNails }, - requires: "plasma torch, molecular assembler, grappling hook, not printer, reel, rupture", + requires: "plasma torch, molecular assembler, grappling hook, not printer, reel, swarf", effect() { tech.isTokamak = true; }, @@ -8705,7 +8741,7 @@ const tech = { { name: "dazzler", link: `
dazzler`, - description: "after decloaking stun nearby mobs
and drain –10 energy", + description: "after decloaking
stun nearby mobs for 2 second", isFieldTech: true, maxCount: 1, count: 0, @@ -8724,16 +8760,16 @@ const tech = { }, { name: "topological defect", - description: "+88% damage
to mobs at maximum health", + description: "+111% damage
to mobs at maximum health", isFieldTech: true, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return (m.fieldMode === 8 || m.fieldMode === 7) && tech.mobSpawnWithHealth === 0 && !tech.isMobFullHealth + return (m.fieldMode === 8 || m.fieldMode === 7) && tech.mobSpawnWithHealth === 0 }, - requires: "cloaking, pilot wave, not reaction inhibitor, yield stress", + requires: "cloaking, pilot wave, not reaction inhibitor", effect() { tech.isMobFullHealthCloak = true }, @@ -8760,34 +8796,6 @@ const tech = { // tech.sneakAttackDmg = 4.33 //333% + 100% // } // }, - { - name: "dynamical systems", - description: `use ${powerUps.orb.research(2)}
+35% damage`, - isFieldTech: true, - maxCount: 1, - count: 0, - frequency: 3, - frequencyDefault: 3, - allowed() { - return (m.fieldMode === 5 || m.fieldMode === 7 || m.fieldMode === 8) && (build.isExperimentSelection || powerUps.research.count > 1) - }, - requires: "cloaking, pilot wave, or plasma torch", - damage: 1.35, - effect() { - tech.damage *= this.damage - tech.isCloakingDamage = true - for (let i = 0; i < 2; i++) { - if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) - } - }, - remove() { - tech.isCloakingDamage = false - if (this.count > 0) { - tech.damage /= this.damage - powerUps.research.changeRerolls(2) - } - } - }, { name: "WIMPs", description: `at the end of each level spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly chases you`, @@ -8818,9 +8826,9 @@ const tech = { frequency: 3, frequencyDefault: 3, allowed() { - return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 2) + return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2) }, - requires: "wormhole, time dilation, negative mass, pilot wave, grappling hook", + requires: "wormhole, time dilation, negative mass, pilot wave", effect() { tech.fieldDuplicate = 0.11 powerUps.setPowerUpMode(); //needed after adjusting duplication chance @@ -8988,7 +8996,7 @@ const tech = { }, { name: "CIWS", - description: "grappling hook uses 18 energy
to fire harpoons at nearby mobs", + description: "grappling hook uses 10 energy
to fire harpoons at nearby mobs", isFieldTech: true, maxCount: 1, count: 0, @@ -9006,10 +9014,11 @@ const tech = { } }, { - name: "rupture", - description: "after grappling hook impacts solid objects
generate an explosion", + name: "swarf", + // description: "after grappling hook impacts solid objects generate an explosion and become briefly invulnerable", + description: "after grappling hook impacts something
eject nails splinters towards nearby mobs", isFieldTech: true, - maxCount: 1, + maxCount: 3, count: 0, frequency: 2, frequencyDefault: 2, @@ -9018,24 +9027,24 @@ const tech = { }, requires: "grappling hook, not reel, tokamak", effect() { - tech.isHookExplosion = true + tech.hookNails += 4 }, remove() { - tech.isHookExplosion = false + tech.hookNails = 0 } }, { name: "reel", - description: "+400% block collision damage
+30 energy when reeling in far away blocks", + description: "+400% block collision damage
up to +75 energy after reeling in blocks", isFieldTech: true, maxCount: 1, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return m.fieldMode === 10 && !tech.isTokamak && tech.blockDamage === 0.075 && !tech.isHookExplosion + return m.fieldMode === 10 && !tech.isTokamak && tech.blockDamage === 0.075 && !tech.hookNails }, - requires: "grappling hook, not mass driver, rupture, tokamak", + requires: "grappling hook, not mass driver, swarf, tokamak", effect() { tech.blockDamage = 0.375 tech.isReel = true @@ -11910,7 +11919,7 @@ const tech = { isFastFoam: null, isSporeGrowth: null, isStimulatedEmission: null, - nailGun: null, + // nailGun: null, nailInstantFireRate: null, isCapacitor: null, isEnergyNoAmmo: null, @@ -12148,12 +12157,11 @@ const tech = { isPrinter: null, // isHookWire: null, isHookDefense: null, - isHookExplosion: null, + hookNails: null, isHarpoonDefense: null, isReel: null, harpoonPowerUpCycle: null, isHarpoonFullHealth: null, - isMobFullHealth: null, isMobFullHealthCloak: null, isMobLowHealth: null, isDamageCooldown: null, diff --git a/todo.txt b/todo.txt index 3bf436e..30494eb 100644 --- a/todo.txt +++ b/todo.txt @@ -1,16 +1,71 @@ ******************************************************** NEXT PATCH ************************************************** -tech: hyperpolarization - reduce the CD on depolarization by 1 second +mob: laserLayer - leaves behind lasers that persist for a few seconds +ghoster mobs do 66% less damage, but they eject your ammo -metamaterial absorber 22->25% chance to get power up for mobs not killed -symbiosis -0.5 -> 0.25 max health after killing a mob -dazzler -15->10 energy after decloaking and stunning mobs -Hilbert space 142->300% damage +grappling hook tech rupture renamed swarf + fires several nails at nearby mobs, not explosions +grappling hook 6->9 energy per second +CIWS 18->10 energy +reel +40->75 energy reeling blocks +wormhole 5->7% duplication +cloaking no longer drains energy, this fixes a can't cloak bug + dazzler no longer drains energy + dazzler range reduced by 15% + dazzler stuns for 3->2 seconds +zero point energy 100->166 max energy +expansion 40->77 max energy +annihilation -33% of max energy -> 10 energy +dynamical systems is no longer a field tech 35->30 damage +tessellation is no longer a field tech 50->35 defense +yield stress removed + topological defect 80->111% damage + brittle 80->111% damage +commodities exchange 6-12 -> 10-14 power ups +heat engine 50->40% damage +flame test grenades clusters explode 40% faster +alternator uses 10->0% energy for harpoon + +finally made a shared vertexCollision function + this might cause some bugs with laser-like effects... -fixed bug with 1000x more frequent enthalpy *********************************************************** TODO ***************************************************** +increase damage for each not picked up power up on the level + +make a laserLayerBoss + add lasers on player's history + +button/switch input ideas from Cocoon game + pick up blocks that have a rubber band attached to a sliding switch + as player moves the vector direction of the rubber band will move the slider left or right + use this to open doors, move larger blocks, ... + switches that toggle left, right when player presses input.field while standing nearby + replace laser off on switch? + platform that rises up when player presses input.field while standing + How to instruct player to use field on these? + color with field #0ff + draw field effect + make it still functional without the field button + +tech: - getting a new gun also gives you 2 random tech for that gun + or a field? + can these guntech tech be converted into a player choice? + +tech: interest - research and ammo increases by 10% at the start of each level? + spawn research and ammo at start of new level + extend to current health? + +how to reduce the number of clicks and keypresses + auto fire mode + player shoots at whatever is nearby + should player have to look towards mobs? + increase ammo? + +animate egg laying mobs + just draw a circle when it happens? + improve new player experience training is too long to be a tutorial before nail gun level offer player option to continue or switch to normal game @@ -51,7 +106,7 @@ make grappling hook of different shapes longer circular with spikes indicate tech upgrades? - rupture, reel, tokamak + swarf, reel, tokamak do this in draw or in verticies? draw can have different colors @@ -1097,6 +1152,7 @@ possible names for tech Pyroelectricity - voltage from temp changes - upgrade from piezoelectricity Unruh effect - accelerating makes heat/thermal particles configuration space - holds the position of everything + stress–energy tensor ******************************************************** CARS IMAGES ********************************************************