diff --git a/.DS_Store b/.DS_Store index bfc7e5e..8271bdb 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 38c63ee..53a46cf 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -352,13 +352,11 @@ const b = { explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd radius *= tech.explosiveRadius - // radius = Math.max(0, Math.min(radius, (distanceToPlayer - 70) / b.explosionRange())) - let dist, sub, knock; let dmg = radius * 0.019 * (tech.isExplosionStun ? 0.7 : 1); //* 0.013 * (tech.isExplosionStun ? 0.7 : 1); if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area if (tech.isSmallExplosion) { - color = "rgba(255,0,30,0.7)" + // color = "rgba(255,0,30,0.7)" radius *= 0.66 dmg *= 1.66 } @@ -432,18 +430,18 @@ const b = { m.energy -= 0.15 m.damage(0.01 * harm); //remove 99% of the damage 1-0.99 // console.log(Math.max(0, Math.min(0.15 - 0.01 * player.speed, 0.15))) - knock = Vector.mult(Vector.normalise(sub), -0.6 * player.mass * Math.max(0, Math.min(0.15 - 0.002 * player.speed, 0.15))); + knock = Vector.mult(Vector.normalise(sub), 0.6 * player.mass * Math.max(0, Math.min(0.15 - 0.002 * player.speed, 0.15)) * tech.implosion); player.force.x = knock.x; // not += so crazy forces can't build up with MIRV player.force.y = knock.y - 0.3; //some extra vertical kick } else { if (simulation.dmgScale) m.damage(harm); - knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * player.mass * 0.013 * tech.implosion); player.force.x += knock.x; player.force.y += knock.y; } } } else if (dist < alertRange) { - knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * player.mass * 0.005 * tech.implosion); player.force.x += knock.x; player.force.y += knock.y; } @@ -455,7 +453,7 @@ const b = { sub = Vector.sub(where, body[i].position); dist = Vector.magnitude(sub); if (dist < radius) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * body[i].mass * 0.022 * tech.implosion); body[i].force.x += knock.x; body[i].force.y += knock.y; if (tech.isBlockExplode) { @@ -470,7 +468,7 @@ const b = { }, 150 + 300 * Math.random()); } } else if (dist < alertRange) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * body[i].mass * 0.011 * tech.implosion); body[i].force.x += knock.x; body[i].force.y += knock.y; } @@ -482,11 +480,11 @@ const b = { sub = Vector.sub(where, powerUp[i].position); dist = Vector.magnitude(sub); if (dist < radius) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * powerUp[i].mass * 0.013 * tech.implosion); powerUp[i].force.x += knock.x; powerUp[i].force.y += knock.y; } else if (dist < alertRange) { - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007); + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg) * powerUp[i].mass * 0.007 * tech.implosion); powerUp[i].force.x += knock.x; powerUp[i].force.y += knock.y; } @@ -503,18 +501,28 @@ const b = { if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way mob[i].damage(dmg * damageScale * m.dmgScale); mob[i].locatePlayer(); - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01); - mob[i].force.x += knock.x; - mob[i].force.y += knock.y; - if (tech.isExplosionStun) mobs.statusStun(mob[i], 120) + if (tech.isExplosionStun) { + mobs.statusStun(mob[i], 120) + knock *= 0.1 + } + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.005 : 0.01) * tech.implosion); + if (!mob[i].isInvulnerable) { + mob[i].force.x += knock.x; + mob[i].force.y += knock.y; + } radius *= 0.95 //reduced range for each additional explosion target damageScale *= 0.87 //reduced damage for each additional explosion target } else if (!mob[i].seePlayer.recall && dist < alertRange) { mob[i].locatePlayer(); - knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006); - mob[i].force.x += knock.x; - mob[i].force.y += knock.y; - if (tech.isExplosionStun) mobs.statusStun(mob[i], 60) + knock = Vector.mult(Vector.normalise(sub), Math.sqrt(dmg * damageScale) * mob[i].mass * (mob[i].isBoss ? 0.002 : 0.006) * tech.implosion); + if (tech.isExplosionStun) { + mobs.statusStun(mob[i], 60) + knock *= 0.1 + } + if (!mob[i].isInvulnerable) { + mob[i].force.x += knock.x; + mob[i].force.y += knock.y; + } } } } @@ -761,6 +769,37 @@ const b = { // }); // } // }, + fireworks(where, size) { //can occur after grenades detonate + const cycle = () => { + if (simulation.paused || m.isBodiesAsleep) { requestAnimationFrame(cycle) } else { + count++ + if (count < 60 && m.alive) requestAnimationFrame(cycle); + if (!(count % 8)) { + const unit = Vector.rotate({ x: 1, y: 0 }, 6.28 * Math.random()) + b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.011 + 0.03 * Math.random()))), size * (0.5 + Math.random() * 0.35), `hsla(${360*Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end + } + } + } + let count = 7 + requestAnimationFrame(cycle); + }, + starburst(where, size) { //can occur after grenades detonate + const color = `hsla(${360*Math.random()},100%,66%,0.6)` + const cycle = () => { + if (simulation.paused || m.isBodiesAsleep) { requestAnimationFrame(cycle) } else { + count++ + if (count < 21 && m.alive) requestAnimationFrame(cycle); + if (count % 2) { + const unit = Vector.rotate({ x: 1, y: 0 }, curl * 6.28 * count / 18 + off) + b.explosion(Vector.add(where, Vector.mult(unit, size * 0.8)), size * 0.75, color); //makes bullet do explosive damage at end + } + } + } + const off = 6 * Math.random() + const curl = Math.random() < 0.5 ? -1 : 1; + let count = 0 + requestAnimationFrame(cycle); + }, grenade() { }, @@ -769,9 +808,15 @@ const b = { const me = bullet.length; bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false)); Matter.Body.setDensity(bullet[me], 0.0003); - bullet[me].explodeRad = 300 * size; + bullet[me].explodeRad = (tech.implosion ? 375 : 300) * size + 100 * tech.isBlockExplode; bullet[me].onEnd = function() { - b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end + if (tech.isCircleExplode) { + b.starburst(this.position, this.explodeRad) + } else if (tech.isClusterExplode) { + b.fireworks(this.position, this.explodeRad) + } else { + b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end + } if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random())) } bullet[me].minDmgSpeed = 1; @@ -794,8 +839,13 @@ const b = { const me = bullet.length; bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false)); Matter.Body.setDensity(bullet[me], 0.0003); - bullet[me].explodeRad = 305 * size; + bullet[me].explodeRad = (tech.implosion ? 375 : 300) * size + 100 * tech.isBlockExplode; bullet[me].onEnd = function() { + if (tech.isCircleExplode) { + b.starburst(this.position, this.explodeRad) + } else if (tech.isClusterExplode) { + b.fireworks(this.position, this.explodeRad) + } b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random())) } @@ -829,8 +879,13 @@ const b = { const me = bullet.length; bullet[me] = Bodies.circle(where.x, where.y, 15, b.fireAttributes(angle, false)); Matter.Body.setDensity(bullet[me], 0.0003); - bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 110 + bullet[me].explodeRad = (tech.implosion ? 425 : 350) * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100 bullet[me].onEnd = function() { + if (tech.isCircleExplode) { + b.starburst(this.position, this.explodeRad) + } else if (tech.isClusterExplode) { + b.fireworks(this.position, this.explodeRad) + } b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random())) } @@ -862,7 +917,7 @@ const b = { for (i = 0, len = who.length; i < len; i++) { const sub = Vector.sub(that.position, who[i].position); const dist = Vector.magnitude(sub); - if (dist < radius && dist > 150) { + if (dist < radius && dist > 150 && !who.isInvulnerable) { knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist)); who[i].force.x += knock.x; who[i].force.y += knock.y; @@ -906,8 +961,13 @@ const b = { const me = bullet.length; bullet[me] = Bodies.circle(where.x, where.y, 20, b.fireAttributes(angle, false)); Matter.Body.setDensity(bullet[me], 0.0002); - bullet[me].explodeRad = 350 * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100 + bullet[me].explodeRad = (tech.implosion ? 425 : 350) * size + Math.floor(Math.random() * 50) + tech.isBlockExplode * 100 bullet[me].onEnd = function() { + if (tech.isCircleExplode) { + b.starburst(this.position, this.explodeRad) + } else if (tech.isClusterExplode) { + b.fireworks(this.position, this.explodeRad) + } b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end if (tech.fragments) b.targetedNail(this.position, tech.fragments * Math.floor(2 + 1.5 * Math.random())) } @@ -926,7 +986,7 @@ const b = { for (i = 0, len = who.length; i < len; i++) { const sub = Vector.sub(that.position, who[i].position); const dist = Vector.magnitude(sub); - if (dist < radius && dist > 150) { + if (dist < radius && dist > 150 && !who.isInvulnerable) { knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist)); who[i].force.x += knock.x; who[i].force.y += knock.y; @@ -1099,7 +1159,7 @@ const b = { } } //aoe damage to mobs - const dmg = m.dmgScale * 0.11 * tech.radioactiveDamage + let dmg = m.dmgScale * 0.11 * tech.radioactiveDamage for (let i = 0, len = mob.length; i < len; i++) { if (Vector.magnitude(Vector.sub(mob[i].position, this.position)) < this.damageRadius + mob[i].radius) { if (Matter.Query.ray(map, mob[i].position, this.position).length > 0) dmg *= 0.25 //reduce damage if a wall is in the way @@ -1140,21 +1200,12 @@ const b = { } } - - let gunIndex = null - for (let i = 0, len = b.guns.length; i < len; i++) { - if (b.guns[i].name === "grenades") { - gunIndex = i - } - } - - if (tech.isNeutronBomb) { b.grenade = grenadeNeutron if (tech.isRPG) { - b.guns[gunIndex].do = function() {} + b.guns[5].do = function() {} } else { - if (gunIndex) b.guns[gunIndex].do = function() { + b.guns[5].do = function() { if (!input.field && input.down) { const cycles = 80 const speed = input.down ? 35 : 20 //input.down ? 43 : 32 @@ -1172,7 +1223,7 @@ const b = { } } } else if (tech.isRPG) { - b.guns[gunIndex].do = function() {} + b.guns[5].do = function() {} if (tech.isVacuumBomb) { b.grenade = grenadeRPGVacuum } else { @@ -1180,7 +1231,7 @@ const b = { } } else if (tech.isVacuumBomb) { b.grenade = grenadeVacuum - if (gunIndex) b.guns[gunIndex].do = function() { + b.guns[5].do = function() { if (!input.field && input.down) { const cycles = Math.floor(input.down ? 50 : 30) //30 const speed = input.down ? 44 : 35 @@ -1197,7 +1248,7 @@ const b = { } } else { b.grenade = grenadeDefault - if (gunIndex) b.guns[gunIndex].do = function() { + b.guns[5].do = function() { if (!input.field && input.down) { const cycles = Math.floor(input.down ? 120 : 80) //30 const speed = input.down ? 43 : 32 @@ -1374,7 +1425,7 @@ const b = { minDmgSpeed: 4, lookFrequency: Math.floor(7 + Math.random() * 3), density: tech.harpoonDensity, //0.001 is normal for blocks, 0.004 is normal for harpoon, 0.004*6 when buffed - drain: 0.004, + drain: tech.isRailEnergyGain ? 0.002 : 0.006, beforeDmg(who) { if (tech.isShieldPierce && who.isShielded) { //disable shields who.isShielded = false @@ -1467,7 +1518,7 @@ const b = { } } } else { - if (!tech.isRailEnergyGain && m.energy > 0.005) m.energy -= 0.005 + if (m.energy > this.drain) m.energy -= this.drain const sub = Vector.sub(this.position, m.pos) const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass) @@ -1556,13 +1607,13 @@ const b = { dist = 0 player.force.y += 5 * player.mass * simulation.g; } - if (m.energy > this.drain || tech.isRailEnergyGain) { + if (m.energy > this.drain) { Matter.Body.setVelocity(player, { x: player.velocity.x * 0.8, y: player.velocity.y * 0.8 }); const pull = Vector.mult(Vector.normalise(sub), 0.0008 * Math.min(Math.max(15, dist), 200)) player.force.x += pull.x player.force.y += pull.y - if (!tech.isRailEnergyGain && dist > 500) { + if (dist > 500) { m.energy -= this.drain if (m.energy < 0) { this.endCycle = 0; @@ -1626,6 +1677,7 @@ const b = { friction: 1, frictionAir: 0.4, thrustMag: 0.1, + drain: tech.isRailEnergyGain ? 0.002 : 0.006, turnRate: isReturn ? 0.1 : 0.03, //0.015 drawStringControlMagnitude: 3000 + 5000 * Math.random(), drawStringFlip: (Math.round(Math.random()) ? 1 : -1), @@ -1747,7 +1799,7 @@ const b = { } } } else { - if (!tech.isRailEnergyGain && m.energy > 0.005) m.energy -= 0.005 + if (m.energy > this.drain) m.energy -= this.drain const sub = Vector.sub(this.position, m.pos) const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass) @@ -2621,7 +2673,7 @@ const b = { }, worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death() const bIndex = bullet.length; - const wormSize = 6 + tech.wormSize * 6 * Math.random() + const wormSize = 6 + tech.wormSize * 4.2 * Math.random() if (bIndex < 500) { //can't make over 500 spores bullet[bIndex] = Bodies.polygon(where.x, where.y, 3, 3, { inertia: Infinity, @@ -4858,8 +4910,20 @@ const b = { // ******************************** Guns ********************************************* // ************************************************************************************************** // ************************************************************************************************** + //0 nail gun + //1 shotgun + //2 super balls + //3 matter wave + //4 missiles + //5 grenades + //6 spores + //7 drones + //8 foam + //9 harpoon + //10 mine + //11 laser guns: [{ - name: "nail gun", + name: "nail gun", // 0 description: "use compressed air to fire a stream of nails
delay after firing decreases as you shoot", ammo: 0, ammoPack: 50, @@ -5133,7 +5197,7 @@ const b = { }, }, { - name: "shotgun", + name: "shotgun", //1 description: "fire a wide burst of short range bullets", ammo: 0, ammoPack: 3.5, @@ -5336,10 +5400,10 @@ const b = { } } }, { - name: "super balls", + name: "super balls", //2 description: "fire 3 balls in a wide arc
balls bounce with no momentum loss", ammo: 0, - ammoPack: 10, + ammoPack: 9, have: false, // num: 5, do() {}, @@ -5491,7 +5555,7 @@ const b = { fire() {} }, { - name: "matter wave", + name: "matter wave", //3 description: "emit a wave packet of oscillating particles
that propagates through solids", ammo: 0, ammoPack: 115, @@ -5830,7 +5894,7 @@ const b = { fire() {} }, { - name: "missiles", + name: "missiles", //6 description: "launch homing missiles that explode", ammo: 0, ammoPack: 5, @@ -5923,7 +5987,7 @@ const b = { } } }, { - name: "grenades", + name: "grenades", //5 description: "lob a single bouncy projectile
explodes on contact or after one second", ammo: 0, ammoPack: 7, @@ -5941,7 +6005,7 @@ const b = { } }, }, { - name: "spores", + name: "spores", //6 description: "fire a sporangium that discharges spores
spores seek out nearby mobs", ammo: 0, ammoPack: 2.6, @@ -6072,7 +6136,7 @@ const b = { } } }, { - name: "drones", + name: "drones", //7 description: "deploy drones that crash into mobs
crashes reduce their lifespan by 1 second", ammo: 0, ammoPack: 16, @@ -6100,7 +6164,7 @@ const b = { } }, { - name: "foam", + name: "foam", //8 description: "spray bubbly foam that sticks to mobs
slows mobs and does damage over time", ammo: 0, ammoPack: 24, @@ -6206,7 +6270,7 @@ const b = { do() {}, }, { - name: "harpoon", + name: "harpoon", //9 description: "fire a self-steering harpoon that uses energy
to retract and refund its ammo cost", ammo: 0, ammoPack: 0.6, //update this in railgun tech @@ -6228,9 +6292,11 @@ const b = { charge: 0, railDo() { if (this.charge > 0) { + const DRAIN = (tech.isRailEnergyGain ? 0.0005 : 0.002) //exit railgun charging without firing - if (m.energy < 0.005 && !tech.isRailEnergyGain) { - m.energy += 0.025 + this.charge * 0.11 + if (m.energy < DRAIN) { + // m.energy += 0.025 + this.charge * 22 * this.drain + // m.energy -= this.drain m.fireCDcycle = m.cycle + 120; // cool down if out of energy this.endCycle = 0; this.charge = 0 @@ -6365,7 +6431,8 @@ const b = { if (input.down) smoothRate *= 0.995 this.charge = this.charge * smoothRate + 1 - smoothRate - m.energy += (this.charge - previousCharge) * ((tech.isRailEnergyGain ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen + if (m.energy > DRAIN) m.energy -= DRAIN + // m.energy += (this.charge - previousCharge) * ((tech.isRailEnergyGain ? 0.5 : -0.3)) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen //draw magnetic field const X = m.pos.x @@ -6722,7 +6789,7 @@ const b = { // } // }, }, { - name: "mine", + name: "mine", //10 description: "toss a proximity mine that sticks to walls
refund undetonated mines on exiting a level", //fires nails at mobs within range ammo: 0, ammoPack: 1.25, @@ -6765,393 +6832,8 @@ const b = { } } }, - // { - // name: "railgun", - // description: "use energy to launch a high-speed dense rod
hold left mouse to charge, release to fire", - // ammo: 0, - // ammoPack: 3.8, - // have: false, - // do() {}, - // fire() { - // function pushAway(range) { //push away blocks when firing - // for (let i = 0, len = mob.length; i < len; ++i) { - // const SUB = Vector.sub(mob[i].position, m.pos) - // const DISTANCE = Vector.magnitude(SUB) - // if (DISTANCE < range) { - // const DEPTH = Math.min(range - DISTANCE, 1500) - // const FORCE = Vector.mult(Vector.normalise(SUB), 0.001 * Math.sqrt(DEPTH) * mob[i].mass) - // mob[i].force.x += FORCE.x; - // mob[i].force.y += FORCE.y; - // } - // } - // for (let i = 0, len = body.length; i < len; ++i) { - // const SUB = Vector.sub(body[i].position, m.pos) - // const DISTANCE = Vector.magnitude(SUB) - // if (DISTANCE < range) { - // const DEPTH = Math.min(range - DISTANCE, 500) - // const FORCE = Vector.mult(Vector.normalise(SUB), 0.002 * Math.sqrt(DEPTH) * body[i].mass) - // body[i].force.x += FORCE.x; - // body[i].force.y += FORCE.y - body[i].mass * simulation.g * 1.5; //kick up a bit to give them some arc - // } - // } - // } - - // if (tech.isCapacitor) { - // if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle - // m.energy += 0.16 * (tech.isRailEnergyGain ? 2.5 : -1) - // m.fireCDcycle = m.cycle + Math.floor(40 * b.fireCDscale); - // const me = bullet.length; - // bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, { - // density: 0.005, //0.001 is normal - // restitution: 0, - // frictionAir: 0, - // angle: m.angle, - // dmg: 0, //damage done in addition to the damage from momentum - // classType: "bullet", - // collisionFilter: { - // category: cat.bullet, - // mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield - // }, - // minDmgSpeed: 5, - // endCycle: simulation.cycle + 140, - // beforeDmg(who) { - // if (who.shield) { - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks - // Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10)); - // break - // } - // } - // Matter.Body.setVelocity(this, { - // x: -0.5 * this.velocity.x, - // y: -0.5 * this.velocity.y - // }); - // // Matter.Body.setDensity(this, 0.001); - // } - // if (tech.fragments && this.speed > 10) { - // b.targetedNail(this.position, tech.fragments * 13) - // this.endCycle = 0 //triggers despawn - // } - // }, - // onEnd() {}, - // drawCycle: Math.floor(10 * b.fireCDscale), - // do() { - // this.force.y += this.mass * 0.0003; // low gravity that scales with charge - // if (this.drawCycle > 0) { - // this.drawCycle-- - // //draw magnetic field - // const X = m.pos.x - // const Y = m.pos.y - // // const unitVector = Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) - // const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) } - // const unitVectorPerp = Vector.perp(unitVector) - - // function magField(mag, arc) { - // ctx.moveTo(X, Y); - // ctx.bezierCurveTo( - // X + unitVector.x * mag, Y + unitVector.y * mag, - // X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc, - // X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc) - // ctx.bezierCurveTo( - // X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc, - // X - unitVector.x * mag, Y - unitVector.y * mag, - // X, Y) - // } - // ctx.fillStyle = `rgba(50,0,100,0.05)`; - // for (let i = 3; i < 7; i++) { - // const MAG = 8 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random()) - // const ARC = 6 * i * i * (0.93 + 0.07 * Math.random()) * (0.95 + 0.1 * Math.random()) - // ctx.beginPath(); - // magField(MAG, ARC) - // magField(MAG, -ARC) - // ctx.fill(); - // } - // } - // } - // }); - // Composite.add(engine.world, bullet[me]); //add bullet to world - - // const speed = 67 - // Matter.Body.setVelocity(bullet[me], { - // x: m.Vx / 2 + speed * Math.cos(m.angle), - // y: m.Vy / 2 + speed * Math.sin(m.angle) - // }); - - // //knock back - // const KNOCK = (input.down ? 0.08 : 0.34) - // player.force.x -= KNOCK * Math.cos(m.angle) - // player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps - // pushAway(800) - // } else { - // b.refundAmmo() - // m.fireCDcycle = m.cycle + Math.floor(120); - // } - // } else { - // const me = bullet.length; - // bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, { - // density: 0.008, //0.001 is normal - // restitution: 0, - // frictionAir: 0, - // dmg: 0, //damage done in addition to the damage from momentum - // classType: "bullet", - // collisionFilter: { - // category: 0, - // mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield - // }, - // minDmgSpeed: 5, - // beforeDmg(who) { - // if (who.shield) { - // for (let i = 0, len = mob.length; i < len; i++) { - // if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks - // Matter.Body.setVelocity(mob[i], Vector.mult(Vector.normalise(this.velocity), 10)); - // break - // } - // } - // Matter.Body.setVelocity(this, { - // x: -0.5 * this.velocity.x, - // y: -0.5 * this.velocity.y - // }); - // } - // if (tech.fragments && this.speed > 10) { - // b.targetedNail(this.position, tech.fragments * 17) - // this.endCycle = 0 //triggers despawn - // } - // }, - // onEnd() {} - // }); - // m.fireCDcycle = Infinity; // cool down - // Composite.add(engine.world, bullet[me]); //add bullet to world - // bullet[me].endCycle = Infinity - // bullet[me].charge = 0; - // bullet[me].do = function() { - // if (m.energy < 0.005 && !tech.isRailEnergyGain) { - // m.energy += 0.05 + this.charge * 0.2 - // m.fireCDcycle = m.cycle + 120; // cool down if out of energy - // this.endCycle = 0; - // b.refundAmmo() - // return - // } - - // if ((!input.fire && this.charge > 0.6)) { //fire on mouse release or on low energy - // m.fireCDcycle = m.cycle + 2; // set fire cool down - // //normal bullet behavior occurs after firing, overwrites this function - // Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it) - // this.endCycle = simulation.cycle + 140 - // this.collisionFilter.category = cat.bullet - // Matter.Body.setPosition(this, { - // x: m.pos.x, - // y: m.pos.y - // }) - // Matter.Body.setAngle(this, m.angle) - // const speed = 90 - // Matter.Body.setVelocity(this, { - // x: m.Vx / 2 + speed * this.charge * Math.cos(m.angle), - // y: m.Vy / 2 + speed * this.charge * Math.sin(m.angle) - // }); - - // if (tech.isRodAreaDamage) { - // this.auraRadius = 800 - // this.semiMinor = 0.5 - // this.where = { x: m.pos.x, y: m.pos.y } - // this.velocityAura = { x: this.velocity.x, y: this.velocity.y } - // this.angleAura = this.angle - // this.do = function() { - // this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge - // this.velocityAura.y += 0.085 / this.charge; - // this.where = Vector.add(this.where, this.velocityAura) - - // //draw damage aura - // this.semiMinor = this.semiMinor * 0.99 - // this.auraRadius = this.auraRadius * 0.99 - // let where = Vector.add(Vector.mult(this.velocityAura, -0.5), this.where) - // ctx.beginPath(); - // ctx.ellipse(where.x, where.y, this.auraRadius * 0.25, this.auraRadius * 0.15 * this.semiMinor, this.angleAura, 0, 2 * Math.PI) - // ctx.fillStyle = "rgba(255,100,0,0.75)"; - // ctx.fill(); - // where = Vector.add(Vector.mult(this.velocity, -1), where) - // ctx.beginPath(); - // ctx.ellipse(where.x, where.y, this.auraRadius * 0.5, this.auraRadius * 0.5 * this.semiMinor, this.angleAura, 0, 2 * Math.PI) - // ctx.fillStyle = "rgba(255,50,0,0.35)"; - // ctx.fill(); - // where = Vector.add(Vector.mult(this.velocity, -1), where) - // ctx.beginPath(); - // ctx.ellipse(where.x, where.y, this.auraRadius * 0.75, this.auraRadius * 0.7 * this.semiMinor, this.angleAura, 0, 2 * Math.PI) - // ctx.fillStyle = "rgba(255,0,0,0.15)"; - // ctx.fill(); - // where = Vector.add(Vector.mult(this.velocity, -1), where) - // ctx.beginPath(); - // ctx.ellipse(where.x, where.y, this.auraRadius, this.auraRadius * this.semiMinor, this.angleAura, 0, 2 * Math.PI) - // ctx.fillStyle = "rgba(255,0,0,0.03)"; - // ctx.fill(); - // //damage mobs in a circle based on this.semiMinor radius - // if (this.auraRadius > 200) { - // for (let i = 0, len = mob.length; i < len; ++i) { - // const dist = Vector.magnitude(Vector.sub(mob[i].position, where)) - // if (dist < mob[i].radius + this.auraRadius) { - // //push mob in direction of bullet - // const mag = 0.0001 - // mob[i].force.x += mag * this.velocity.x; - // mob[i].force.y += mag * this.velocity.y; - // //damage mob - // const damage = m.dmgScale * 0.002 * dist - // mob[i].damage(damage); - // mob[i].locatePlayer(); - // simulation.drawList.push({ //add dmg to draw queue - // x: mob[i].position.x, - // y: mob[i].position.y, - // radius: Math.log(2 * damage + 1.1) * 40, - // color: "rgba(255,0,0,0.25)", - // time: simulation.drawTime - // }); - // } - // } - // } - // //push blocks power ups and mobs to the direction the rod is moving - - // } - // } else { - // this.do = function() { - // this.force.y += this.mass * 0.0003 / this.charge; // low gravity that scales with charge - // } - // } - - // //knock back - // const KNOCK = ((input.down) ? 0.1 : 0.5) * this.charge * this.charge - // player.force.x -= KNOCK * Math.cos(m.angle) - // player.force.y -= KNOCK * Math.sin(m.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps - // pushAway(1200 * this.charge) - // } else { // charging on mouse down - // if (tech.isFireMoveLock) { - // Matter.Body.setVelocity(player, { - // x: 0, - // y: -55 * player.mass * simulation.g //undo gravity before it is added - // }); - // player.force.x = 0 - // player.force.y = 0 - // } - - // m.fireCDcycle = Infinity //can't fire until mouse is released - // const previousCharge = this.charge - // let smoothRate = Math.min(0.998, (input.down ? 0.98 : 0.985) * (0.98 + 0.02 * b.fireCDscale)) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot - // this.charge = this.charge * smoothRate + 1 - smoothRate - // m.energy += (this.charge - previousCharge) * (tech.isRailEnergyGain ? 1 : -0.33) //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen - // //draw targeting - // let best; - // let range = 3000 - // const dir = m.angle - // const path = [{ - // x: m.pos.x + 20 * Math.cos(dir), - // y: m.pos.y + 20 * Math.sin(dir) - // }, - // { - // x: m.pos.x + range * Math.cos(dir), - // y: m.pos.y + range * Math.sin(dir) - // } - // ]; - // 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) { - // 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] - // }; - // } - // } - // } - // }; - - // //check for collisions - // best = { - // x: null, - // y: null, - // dist2: Infinity, - // who: null, - // v1: null, - // v2: null - // }; - // vertexCollision(path[0], path[1], mob); - // vertexCollision(path[0], path[1], map); - // vertexCollision(path[0], path[1], body); - // if (best.dist2 != Infinity) { //if hitting something - // path[path.length - 1] = { - // x: best.x, - // y: best.y - // }; - // } - - // //draw beam - // ctx.beginPath(); - // ctx.moveTo(path[0].x, path[0].y); - // ctx.lineTo(path[1].x, path[1].y); - // ctx.strokeStyle = `rgba(100,0,180,0.7)`; - // ctx.lineWidth = this.charge * 1 - // ctx.setLineDash([10, 20]); - // ctx.stroke(); - // ctx.setLineDash([]); - - // //draw magnetic field - // const X = m.pos.x - // const Y = m.pos.y - // const unitVector = { x: Math.cos(m.angle), y: Math.sin(m.angle) } - // //Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)) - // const unitVectorPerp = Vector.perp(unitVector) - - // function magField(mag, arc) { - // ctx.moveTo(X, Y); - // ctx.bezierCurveTo( - // X + unitVector.x * mag, Y + unitVector.y * mag, - // X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc, - // X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc) - // ctx.bezierCurveTo( - // X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc, - // X - unitVector.x * mag, Y - unitVector.y * mag, - // X, Y) - // } - // ctx.fillStyle = `rgba(50,0,100,0.05)`; - // for (let i = 3; i < 7; i++) { - // const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random()) - // const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random()) - // ctx.beginPath(); - // magField(MAG, ARC) - // magField(MAG, -ARC) - // ctx.fill(); - // } - // } - // } - // } - // } - // }, { - name: "laser", + name: "laser", //11 description: "emit a beam of collimated coherent light
drains energy instead of ammunition", ammo: 0, ammoPack: Infinity, @@ -7409,47 +7091,4 @@ const b = { // }, }, ], - // gunRewind: { //this gun is added with a tech - // name: "CPT gun", - // description: "use energy to rewind your health, velocity,
and position up to 10 seconds", - // ammo: 0, - // ammoPack: Infinity, - // have: false, - // isRewinding: false, - // lastFireCycle: 0, - // holdCount: 0, - // activeGunIndex: null, - // do() {}, - // fire() { - // if (this.lastFireCycle === m.cycle - 1) { //button has been held down - // this.rewindCount += 8; - // const DRAIN = 0.01 - // let history = m.history[(m.cycle - this.rewindCount) % 600] - // if (this.rewindCount > 599 || m.energy < DRAIN || history.activeGun !== this.activeGunIndex) { - // this.rewindCount = 0; - // m.resetHistory(); - // m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCDscale); // cool down - // } else { - // m.energy -= DRAIN - // if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 5 cycles - // Matter.Body.setPosition(player, history.position); - // Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y }); - // if (m.health !== history.health) { - // m.health = history.health - // m.displayHealth(); - // } - // m.yOff = history.yOff - // if (m.yOff < 48) { - // m.doCrouch() - // } else { - // m.undoCrouch() - // } - // } - // } else { //button is held the first time - // this.rewindCount = 0; - // this.activeGunIndex = b.activeGun - // } - // this.lastFireCycle = m.cycle; - // } - // } }; \ No newline at end of file diff --git a/js/engine.js b/js/engine.js index d183e02..6129600 100644 --- a/js/engine.js +++ b/js/engine.js @@ -198,6 +198,7 @@ function collisionChecks(event) { const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)); if (v > 9) { if (tech.blockDmg) { //electricity + console.log("hi") Matter.Body.setVelocity(mob[k], { x: 0.5 * mob[k].velocity.x, y: 0.5 * mob[k].velocity.y }); if (tech.isBlockRadiation && !mob[k].isShielded && !mob[k].isMobBullet) { mobs.statusDoT(mob[k], tech.blockDmg * m.dmgScale * 4 / 12, 360) //200% increase -> x (1+2) //over 7s -> 360/30 = 12 half seconds -> 3/12 diff --git a/js/index.js b/js/index.js index 2d5723d..55c5bc6 100644 --- a/js/index.js +++ b/js/index.js @@ -927,6 +927,10 @@ window.addEventListener("keydown", function(event) { break case input.key.testing: if (m.alive && localSettings.loreCount > 0) { + if (simulation.difficultyMode > 4) { + simulation.makeTextLog("testing mode disabled for this difficulty"); + break + } if (simulation.testing) { simulation.testing = false; simulation.loop = simulation.normalLoop diff --git a/js/level.js b/js/level.js index ff6ea08..4822128 100644 --- a/js/level.js +++ b/js/level.js @@ -17,11 +17,11 @@ const level = { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.isHorizontalFlipped = true // m.setField("perfect diamagnetism") - // b.giveGuns("shotgun") - // tech.giveTech("bremsstrahlung") - // tech.giveTech("cherenkov radiation") - // tech.giveTech("enthalpy") + // b.giveGuns("grenades") // tech.giveTech("rule 30") + // tech.giveTech("cherenkov radiation") + // tech.giveTech("flame test") + // tech.giveTech("pyrotechnics") // for (let i = 0; i < 10; i++) tech.giveTech("replication") // tech.giveTech("decoherence") // tech.giveTech("pneumatic actuator") @@ -39,7 +39,7 @@ const level = { // m.immuneCycle = Infinity //you can't take damage // level.difficultyIncrease(15) //30 is near max on hard //60 is near max on why // simulation.enableConstructMode() //used to build maps in testing mode - // level.warehouse(); + // level.temple(); // level.testing(); //not in rotation, used for testing if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************ // powerUps.research.changeRerolls(3000) @@ -2644,11 +2644,11 @@ const level = { spawn.mapRect(4850, -275, 50, 175); //??? - level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why m.addHealth(Infinity) // spawn.starter(1900, -500, 200) //big boy - for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500) + // for (let i = 0; i < 10; ++i) spawn.launcher(1900, -500) // spawn.slashBoss(1900, -500) // spawn.launcherBoss(3200, -500) // spawn.laserTargetingBoss(1700, -500) @@ -2663,7 +2663,7 @@ const level = { // spawn.blinkBoss(1700, -500) // spawn.snakeSpitBoss(3200, -500) // spawn.laserBombingBoss(1700, -500) - // spawn.launcherBoss(3200, -500) + spawn.launcherBoss(3200, -500) // spawn.blockBoss(1700, -500) // spawn.blinkBoss(3200, -500) // spawn.spiderBoss(1700, -500) @@ -9511,22 +9511,14 @@ const level = { me.attackCycle = 0; me.lastAttackCycle = 0; - Matter.Body.setDensity(me, 0.014); // extra dense, normal is 0.001 // makes effective life much larger + Matter.Body.setDensity(me, 0.012); // extra dense, normal is 0.001 // makes effective life much larger me.onDeath = function() { // applying forces to player doesn't seem to work inside this method, not sure why powerUps.spawn(this.position.x + 20, this.position.y, "ammo"); if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo"); if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5)); - if (simulation.difficulty > 5) { - // fling player to center - const SUB = V.sub(this.position, player.position) - const DISTANCE = V.magnitude(SUB) - if (DISTANCE < this.eventHorizon) { - Matter.Body.setVelocity(player, V.mult(SUB, 5e4 / (100 + DISTANCE) / (100 + DISTANCE))) - } - } }; - me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); me.do = function() { // keep it slow, to stop issues from explosion knock backs if (this.speed > 1) { @@ -9650,12 +9642,13 @@ const level = { me.isBoss = true; me.stroke = "transparent"; - me.eventHorizon = 1000; + me.eventHorizon = 950; me.collisionFilter.mask = cat.player | cat.bullet | cat.body; me.memory = Infinity; me.attackCycle = 0; me.lastAttackCycle = 0; + me.spawnCycle = 0; Matter.Body.setDensity(me, 0.08); //extra dense //normal is 0.001 //makes effective life much larger me.onDeath = function() { for (let j = 0; j < 8; j++) { //in case some mobs leave things after they die @@ -9763,14 +9756,16 @@ const level = { } } me.periodicSpawns = function() { + if (this.isInvulnerable) return; + this.spawnCycle++; // Spawn annoying purple thing(s) that chases the player - if (!(simulation.cycle % 180)) { + if (!(this.spawnCycle % 180)) { spawn.seeker(this.position.x, this.position.y, 15 * (0.7 + 0.5 * Math.random()), 7); spawn.seeker(this.position.x, this.position.y, 4 * (0.7 + 0.5 * Math.random()), 7); spawn.seeker(this.position.x, this.position.y, 4 * (0.7 + 0.5 * Math.random()), 7); } // Spawn the annoying pink (now blue) exploder that doesn't chase the player - if (!(simulation.cycle % 300)) { + if (!(this.spawnCycle % 300)) { for (let i = 0; i < 3; i++) { mobGrenade(1100 + 700 * i, -13030, undefined, Math.min(700, 300 + simulation.difficulty * 4), 10); setVel(mob[mob.length - 1], { x: 0, y: -10 }); @@ -9779,19 +9774,30 @@ const level = { } } // Spawn a bunch of mobs - if (!(simulation.cycle % 600)) { - spawn.nodeGroup(this.position.x, this.position.y, "focuser", 3); + if (!(this.spawnCycle % 600)) { + // This is just ripped off of spawn.nodeGroup because I don't want the shield + const nodes = 3; + const radius = Math.ceil(Math.random() * 10) + 18; + const sideLength = Math.ceil(Math.random() * 100) + 70; + const stiffness = Math.random() * 0.03 + 0.005; + spawn.allowShields = false; //don't want shields on individual group mobs + const angle = 2 * Math.PI / nodes + for (let i = 0; i < nodes; ++i) { + spawn.focuser(x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), radius); + } + spawn.constrainAllMobCombos(nodes, stiffness); + spawn.allowShields = true; } } me.invulnerableTrap = function() { if (this.trapCycle < 1) return; this.trapCycle++; - // 32 is just an arbitrarily large number - const spawnCycles = Math.min(32, Math.max(8, 6 + Math.floor(simulation.difficulty / 3))); + // 24 is just an arbitrarily large number + const spawnCycles = Math.min(24, Math.max(6, 4 + Math.floor(simulation.difficulty / 3))); // I have no idea how to balance at all, please help me const spawnDelay = Math.floor(5 + 10 / (1 + Math.sqrt(simulation.difficulty) / 5)); - if (this.trapCycle >= 120) { - const cycle = this.trapCycle - 120; + if (this.trapCycle >= 90) { + const cycle = this.trapCycle - 90; if (!(cycle % spawnDelay)) { const radius = Math.min(500, 200 + simulation.difficulty * 3); mobGrenade(600, -13050, 30, radius); @@ -10220,7 +10226,6 @@ const level = { this.pit1.height = this.pit1.width = 0; this.pit2.height = this.pit2.width = 0; } - }, draw() { this.pit1.query(); @@ -10412,8 +10417,6 @@ const level = { break; } } - // UwU - // Will I get timed out for this if (!isInBounds) { m.damage(0.1 * simulation.difficultyMode); trapPlayer(level.enter.x, level.enter.y); @@ -10601,7 +10604,8 @@ const level = { powerUps.addResearchToLevel(); } if (templePlayer.room1.cycles % 600 === 0 && templePlayer.room1.cycles <= 2400) { - for (let i = 0; i < 3 + Math.pow(simulation.difficulty / 2, 0.7) + Math.floor(templePlayer.room1.cycles / 720); i++) { + const spawnAmt = Math.min(3 + Math.pow(simulation.difficulty / 1.7, 0.6), 10) + Math.floor(templePlayer.room1.cycles / 720); + for (let i = 0; i < spawnAmt; i++) { if (Math.random() < 0.5 + 0.07 * simulation.difficulty) { spawn.randomMob(800 + Math.random() * 3e3, -2400 - Math.random() * 600, Infinity); } diff --git a/js/mob.js b/js/mob.js index d182097..0197f71 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1060,28 +1060,17 @@ const mobs = { dmg *= tech.damageFromTech() //mobs specific damage changes if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500 - // if (this.shield) dmg *= 0.075 - // if (this.isBoss) dmg *= 0.25 - // if (this.damageReduction < 1) { //only used for bosses with this.armor() or shields - // this.damageReductionGoal += dmg * this.damageReductionScale //reduce damageReductionGoal - // dmg *= this.damageReduction - // } dmg *= this.damageReduction //energy and heal drain should be calculated after damage boosts if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp && Math.random() < tech.healthDrain * Math.min(this.health, dmg)) { powerUps.spawn(m.pos.x + 20 * (Math.random() - 0.5), m.pos.y + 20 * (Math.random() - 0.5), "heal"); - // powerUps.spawn(this.position.x + 20 * (Math.random() - 0.5), this.position.y + 20 * (Math.random() - 0.5), "heal"); - // m.addHealth(Math.min(this.health, dmg) * tech.healthDrain) - // if (m.health > m.maxHealth) m.health = m.maxHealth } dmg /= Math.sqrt(this.mass) this.health -= dmg //this.fill = this.color + this.health + ')'; this.onDamage(dmg); //custom damage effects - if ((this.health < 0.05 || isNaN(this.health)) && this.alive) { - this.death(); - } + if ((this.health < 0.05 || isNaN(this.health)) && this.alive) this.death(); } }, onDamage() { diff --git a/js/player.js b/js/player.js index 53cb94c..b43c7e0 100644 --- a/js/player.js +++ b/js/player.js @@ -543,18 +543,19 @@ const m = { for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) { b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade const who = bullet[bullet.length - 1] - if (tech.isVacuumBomb) { + + if (tech.isNeutronBomb) { + Matter.Body.setVelocity(who, { + x: who.velocity.x * 0.3, + y: who.velocity.y * 0.3 + }); + } else if (tech.isVacuumBomb) { Matter.Body.setVelocity(who, { x: who.velocity.x * 0.5, y: who.velocity.y * 0.5 }); } else if (tech.isRPG) { who.endCycle = simulation.cycle + 10 - } else if (tech.isNeutronBomb) { - Matter.Body.setVelocity(who, { - x: who.velocity.x * 0.3, - y: who.velocity.y * 0.3 - }); } else { Matter.Body.setVelocity(who, { x: who.velocity.x * 0.5, diff --git a/js/powerup.js b/js/powerup.js index 2381030..a2a7228 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -300,7 +300,7 @@ const powerUps = { }, endDraft(type, isCanceled = false) { //type should be a gun, tech, or field if (isCanceled) { - if (tech.isCancelTech && Math.random() < 0.9) { + if (tech.isCancelTech && Math.random() < 0.94) { // powerUps.research.use('tech') powerUps[type].effect(); return diff --git a/js/simulation.js b/js/simulation.js index ecf78bb..253b5d5 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -838,13 +838,13 @@ const simulation = { if (tech.isDronesTravel && m.alive) { //count drones - let count = 0 + let droneCount = 0 let sporeCount = 0 let wormCount = 0 let deliveryCount = 0 for (let i = 0; i < bullet.length; ++i) { if (bullet[i].isDrone) { - count++ + droneCount++ if (bullet[i].isImproved) deliveryCount++ } else if (bullet[i].isSpore) { sporeCount++ @@ -855,11 +855,11 @@ const simulation = { //respawn drones in animation frame let respawnDrones = () => { - if (count > 0) { + if (droneCount > 0) { requestAnimationFrame(respawnDrones); if (!simulation.paused && !simulation.isChoosing) { const where = { x: level.enter.x + 50, y: level.enter.y - 60 } - count-- + droneCount-- if (tech.isDroneRadioactive) { b.droneRadioactive({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5) }, 0) } else { @@ -1037,7 +1037,7 @@ const simulation = { if (!(m.cycle % 420)) { //once every 7 seconds if (tech.isZeno) { - m.health *= 0.93 //remove 7% + m.health *= 0.94 //remove 7% m.displayHealth(); } if (tech.cyclicImmunity && m.immuneCycle < m.cycle + tech.cyclicImmunity) m.immuneCycle = m.cycle + tech.cyclicImmunity; //player is immune to damage for 60 cycles diff --git a/js/tech.js b/js/tech.js index d4d73d0..5e64ae0 100644 --- a/js/tech.js +++ b/js/tech.js @@ -217,7 +217,7 @@ const tech = { } }, hasExplosiveDamageCheck() { - return tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.boomBotCount > 1 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) + return tech.haveGunCheck("missiles") || tech.isMissileField || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) }, damageFromTech() { let dmg = 1 //m.fieldDamage @@ -864,7 +864,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isExplosionStun + return tech.isStunField || tech.oneSuperBall || tech.isCloakStun || tech.isOrbitBotUpgrade || tech.isExplosionStun }, requires: "a stun effect", effect() { @@ -2539,7 +2539,7 @@ const tech = { }, { name: "Zeno's paradox", - description: "reduce harm by 85%, but every 5 seconds
remove 7% of your current health", + description: "reduce harm by 85%, but every 5 seconds
remove 6% of your current health", // description: "every 5 seconds remove 1/10 of your health
reduce harm by 90%", maxCount: 1, count: 0, @@ -2704,9 +2704,9 @@ const tech = { frequencyDefault: 1, isHealTech: true, allowed() { - return !tech.isEnergyHealth + return !tech.isNoHeals }, - requires: "not mass-energy equivalence", + requires: "not ergodicity", effect() { tech.healthDrain += 0.02; }, @@ -3296,9 +3296,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return level.onLevel > 1 && !tech.isEnergyHealth + return level.onLevel > 1 && !tech.isEnergyHealth && !tech.healthDrain }, - requires: "past level 1, not mass-energy", + requires: "past level 1, not mass-energy, enthalpy", effect() { tech.isNoHeals = true; level.difficultyDecrease(simulation.difficultyMode * 2) @@ -3338,7 +3338,7 @@ const tech = { { name: "options exchange", link: `options exchange`, - description: `clicking × for a field, tech, or gun has a 90%
chance to randomize choices and not cancel`, + description: `clicking × for a field, tech, or gun has a 94%
chance to randomize choices and not cancel`, maxCount: 1, count: 0, frequency: 1, @@ -3961,7 +3961,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 + return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1 }, requires: "nails, nail gun, rivets, shotgun", effect() { @@ -4073,7 +4073,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (tech.isNailShot || tech.isNeedles || tech.nailBotCount > 1 || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary + return (tech.isNailShot || tech.isNeedles || tech.isNailBotUpgrade || tech.haveGunCheck("nail gun") || tech.isRivets) && !tech.isIncendiary }, requires: "nail gun, needles, nails, rivets, not incendiary", effect() { @@ -4093,8 +4093,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - // return tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) + tech.isNeedles + tech.isNailShot) * 2 > 1 - return tech.isMineDrop || tech.nailBotCount || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot)) + return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !tech.isLaserMine) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot)) }, requires: "nail gun, nails, rivets, mine, not ceramic needles", effect() { @@ -4436,7 +4435,7 @@ const tech = { }, { name: "amplitude", - description: "wave packet amplitude is 33% higher
wave damage is increased by 50%", + description: "wave packet amplitude is 33% higher
wave damage is increased by 37%", isGunTech: true, maxCount: 3, count: 0, @@ -4448,7 +4447,7 @@ const tech = { requires: "matter wave", effect() { tech.waveFrequency *= 0.66 - tech.wavePacketDamage *= 1.5 + tech.wavePacketDamage *= 1.37 }, remove() { tech.waveFrequency = 0.2 @@ -4457,7 +4456,7 @@ const tech = { }, { name: "propagation", - description: "wave packet propagation speed is 20% slower
wave damage is increased by 50%", + description: "wave packet propagation speed is 25% slower
wave damage is increased by 37%", isGunTech: true, maxCount: 9, count: 0, @@ -4469,11 +4468,11 @@ const tech = { requires: "matter wave", effect() { tech.waveBeamSpeed *= 0.8; - tech.waveBeamDamage += 1.5 * 0.5 //this sets base matter wave damage, not used by arcs or circles + tech.waveBeamDamage += 1.5 * 0.37 //this sets base matter wave damage }, remove() { tech.waveBeamSpeed = 10; - tech.waveBeamDamage = 1.5 //this sets base matter wave damage, not used by arcs or circles + tech.waveBeamDamage = 1.5 //this sets base matter wave damage } }, { @@ -4662,9 +4661,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.explosiveRadius === 1 && !tech.isSmallExplosion && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.boomBotCount > 1 || tech.isTokamak) + return tech.implosion === -1 && tech.explosiveRadius === 1 && !tech.isSmallExplosion && !tech.isBlockExplode && !tech.fragments && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || tech.isMissileField || tech.isBoomBotUpgrade || tech.isTokamak) }, - requires: "an explosive damage source, not ammonium nitrate or nitroglycerin", + requires: "an explosive damage source, not ammonium nitrate, nitroglycerin, chain reaction, fragmentation, implosion", effect: () => { tech.isExplodeRadio = true; //iridium-192 }, @@ -4681,9 +4680,9 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075 + return !tech.isExplodeRadio && (tech.haveGunCheck("harpoon") || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isRivets || tech.blockDamage > 0.075) }, - requires: "grenades, missiles, rivets, harpoon, or mass driver", + requires: "grenades, missiles, rivets, harpoon, or mass driver, not iridium-192", effect() { tech.fragments++ }, @@ -4693,7 +4692,7 @@ const tech = { }, { name: "ammonium nitrate", - description: "increase explosive damage by 27%
increase explosive radius by 27%", + description: "increase explosive damage by 24%
increase explosive radius by 24%", isGunTech: true, maxCount: 9, count: 0, @@ -4704,7 +4703,7 @@ const tech = { }, requires: "an explosive damage source, not iridium-192", effect: () => { - tech.explosiveRadius += 0.27; + tech.explosiveRadius += 0.24; }, remove() { tech.explosiveRadius = 1; @@ -4719,9 +4718,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() + return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() && !tech.isExplosionHarm }, - requires: "an explosive damage source, not iridium-192", + requires: "an explosive damage source, not iridium-192, acetone peroxide", effect: () => { tech.isSmallExplosion = true; }, @@ -4739,9 +4738,9 @@ const tech = { frequencyDefault: 2, isBadRandomOption: true, allowed() { - return tech.hasExplosiveDamageCheck() + return tech.hasExplosiveDamageCheck() && !tech.isSmallExplosion }, - requires: "an explosive damage source", + requires: "an explosive damage source, not nitroglycerin", effect: () => { tech.isExplosionHarm = true; }, @@ -4833,7 +4832,7 @@ const tech = { }, { name: "MIRV", - description: "fire +1 missile and grenade per shot
decrease explosion radius up to 12%", + description: "fire +1 missile and grenade per shot
decrease explosion damage and radius 12%", isGunTech: true, maxCount: 9, count: 0, @@ -4892,6 +4891,25 @@ const tech = { b.setGrenadeMode() } }, + { + name: "implosion", + description: "explosions pull objects towards them
increase grenade radius and damage 25%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("grenades") && !tech.isExplodeRadio && !tech.isNeutronBomb + }, + requires: "grenades, not iridium-192, neutron bomb", + effect: () => { + tech.implosion = 1; + }, + remove() { + tech.implosion = -1; + } + }, { name: "chain reaction", description: "increase grenade radius and damage 33%
blocks caught in explosions also explode", @@ -4901,9 +4919,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.isVacuumBomb && !tech.isExplodeRadio + return tech.haveGunCheck("grenades") && !tech.isExplodeRadio && !tech.isNeutronBomb //tech.isVacuumBomb }, - requires: "grenades, vacuum bomb, not iridium-192", + requires: "grenades, not iridium-192, neutron bomb", effect() { tech.isBlockExplode = true; //chain reaction }, @@ -4911,6 +4929,44 @@ const tech = { tech.isBlockExplode = false; } }, + { + name: "flame test", + description: "when grenades detonate they release
a colorful cluster of small explosions", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("grenades") && !tech.isNeutronBomb + }, + requires: "grenades, not neutron bomb", + effect() { + tech.isClusterExplode = true; + }, + remove() { + tech.isClusterExplode = false; + } + }, + { + name: "pyrotechnics", + description: "when grenades detonate they release
a colorful circle of explosions", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("grenades") && !tech.isNeutronBomb && tech.isClusterExplode + }, + requires: "grenades, flame test, not neutron bomb", + effect() { + tech.isCircleExplode = true; + }, + remove() { + tech.isCircleExplode = false; + } + }, { name: "neutron bomb", description: "grenades are irradiated with Cf-252
does damage, harm, and drains energy", @@ -4920,9 +4976,9 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("grenades") && !tech.fragments && !tech.isVacuumBomb && !tech.isExplodeRadio + return tech.haveGunCheck("grenades") && !tech.fragments && !tech.isVacuumBomb && !tech.isExplodeRadio && !tech.isBlockExplode && !tech.isClusterExplode && tech.implosion === -1 }, - requires: "grenades, not fragmentation, vacuum bomb, iridium-192", + requires: "grenades, not fragmentation, vacuum bomb, iridium-192, pyrotechnics, implosion", effect() { tech.isNeutronBomb = true; b.setGrenadeMode() @@ -4972,9 +5028,9 @@ const tech = { }, { name: "nuclear transmutation", - description: "radiation does 70% more damage and harm
nail, drone, neutron bomb, iridium, string, deflect", + description: "radiation does 47% more damage and harm
nail, drone, neutron bomb, iridium, string, deflect", isGunTech: true, - maxCount: 1, + maxCount: 9, count: 0, frequency: 2, frequencyDefault: 2, @@ -4983,7 +5039,7 @@ const tech = { }, requires: "radiation damage source", effect() { - tech.radioactiveDamage = 1.7 + tech.radioactiveDamage += 1.47 }, remove() { tech.radioactiveDamage = 1 @@ -5213,7 +5269,7 @@ const tech = { }, { name: "annelids", - description: "increase worm size and damage
between 10% and 120%", + description: "increase worm size and damage
by an average of 37%", isGunTech: true, maxCount: 3, count: 0, @@ -5259,7 +5315,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.foamBotCount > 1 || tech.isFoamBall + return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || tech.haveGunCheck("spores") || tech.haveGunCheck("drones") || tech.haveGunCheck("missiles") || tech.haveGunCheck("foam") || tech.haveGunCheck("matter wave") || tech.isNeutronBomb || tech.isIceField || tech.isIceShot || tech.relayIce || tech.isNeedleIce || tech.blockingIce > 1 || tech.isSporeWorm || tech.isFoamBotUpgrade || tech.isFoamBall }, requires: "drones, spores, missiles, foam, matter wave, neutron bomb, ice IX", effect() { @@ -5530,7 +5586,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall) + return !tech.isBulletTeleport && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall) }, requires: "foam, not uncertainty", effect() { @@ -5549,7 +5605,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal) + return (!tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall)) || (tech.haveGunCheck("matter wave") && !tech.isLongitudinal) }, requires: "foam, matter wave, not electrostatic induction, not phonon", effect() { @@ -5568,7 +5624,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam") || tech.isFoamBall || tech.foamBotCount > 1 || tech.isFoamShot || tech.isSporeWorm + return tech.haveGunCheck("foam") || tech.isFoamBall || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isSporeWorm }, requires: "foam, worms", effect() { @@ -5587,7 +5643,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall + return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall }, requires: "foam", effect() { @@ -5608,7 +5664,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("foam") || tech.foamBotCount > 1 || tech.isFoamShot || tech.isFoamBall + return tech.haveGunCheck("foam") || tech.isFoamBotUpgrade || tech.isFoamShot || tech.isFoamBall }, requires: "foam", effect() { @@ -5814,7 +5870,7 @@ const tech = { }, { name: "alternator", - description: "harpoons drain no energy
railgun generates energy", //as they retract
crouch firing harpoon generates energy", + description: "harpoon, railgun, and grappling hook
drain 60% less energy", isGunTech: true, maxCount: 1, count: 0, @@ -5852,7 +5908,10 @@ const tech = { }, { name: "Bessemer process", - description: "increase the size of your harpoon
by 10% of the square root of harpoon ammo", + descriptionFunction() { + return `increase harpoon size and damage
by 1/10 √ harpoon ammo (${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}%)` + }, + // description: "increase the size of your harpoon
by 10% of √ of harpoon ammo", isGunTech: true, maxCount: 1, count: 0, @@ -5878,8 +5937,8 @@ const tech = { isGunTech: true, maxCount: 9, count: 0, - frequency: 1, - frequencyDefault: 1, + frequency: 2, + frequencyDefault: 2, allowed() { return tech.haveGunCheck("harpoon") && b.returnGunAmmo('harpoon') >= (tech.isRailGun ? 5 : 3) * (1 + this.count) }, @@ -5913,7 +5972,10 @@ const tech = { }, { name: "UHMWPE", - description: "increase the length of your harpoon's rope
by 1% per harpoon ammo", + descriptionFunction() { + return `increase the length of your harpoon's rope
by 1/100 of harpoon ammo (${(b.guns[9].ammo).toFixed(0)}%)` + }, + // description: "increase the length of your harpoon's rope
by 1% per harpoon ammo", isGunTech: true, maxCount: 1, count: 0, @@ -6021,7 +6083,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (tech.haveGunCheck("laser") || tech.laserBotCount > 1 || tech.isLaserMine) && tech.laserDamage === 0.17 + return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.17 }, requires: "laser, not free-electron", effect() { @@ -6044,7 +6106,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isPulseLaser && tech.isLaserDiode === 1 + return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade) && !tech.isPulseLaser && tech.isLaserDiode === 1 }, requires: "laser, not pulse, diodes", effect() { @@ -6069,7 +6131,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.laserBotCount > 1 + return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.isLaserBotUpgrade }, requires: "laser, not pulse", effect() { @@ -6088,7 +6150,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser + return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser }, requires: "laser, not diffuse beam, pulse, or slow light", effect() { @@ -6344,7 +6406,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" + return m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" }, requires: "standing wave, perfect diamagnetism", effect() { @@ -6363,7 +6425,7 @@ const tech = { frequency: 2, frequencyDefault: 2, allowed() { - return (m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism") && tech.blockDmg + return (m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && tech.blockDmg }, requires: "bremsstrahlung", effect() { @@ -6459,9 +6521,9 @@ const tech = { frequency: 3, frequencyDefault: 3, allowed() { - return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3) + return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "perfect diamagnetism" || m.fieldUpgrades[m.fieldMode].name === "negative mass") && (build.isExperimentSelection || powerUps.research.count > 3) && !tech.isEnergyHealth }, - requires: "perfect diamagnetism, negative mass, pilot wave", + requires: "perfect diamagnetism, negative mass, pilot wave, not mass energy", effect() { tech.isFieldHarmReduction = true for (let i = 0; i < 2; i++) { @@ -6710,7 +6772,7 @@ const tech = { frequency: 3, frequencyDefault: 3, allowed() { - return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport || tech.isDronesTravel) + return (build.isExperimentSelection || powerUps.research.count > 0) && m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport) }, requires: "molecular assembler, no other manufacturing, no drone tech", effect() { @@ -7732,7 +7794,7 @@ const tech = { // }, { name: "panpsychism", - description: "awaken all blocks
blocks have a chance to spawn random power ups", + description: "awaken all blocks
blocks have a chance to spawn power ups", maxCount: 1, count: 0, frequency: 0, @@ -9592,6 +9654,70 @@ const tech = { }, remove() {} }, + // { + // name: "rule 90", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isJunk: true, + // allowed() { + // return true + // }, + // requires: "", + // effect() {}, + // remove() {}, + // state: [ + // [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false] + // ], + // rule(state, a, b, c) { + // if (state[a] && state[b] && state[c]) return false; // TTT => F + // if (state[a] && state[b] && !state[c]) return true; // TTF => T + // if (state[a] && !state[b] && state[c]) return false; //TFT => F + // if (state[a] && !state[b] && !state[c]) return true; //TFF => T + // if (!state[a] && state[b] && state[c]) return true; //FTT => T + // if (!state[a] && state[b] && !state[c]) return false; //FTF => F + // if (!state[a] && !state[b] && state[c]) return true; //FFT => T + // if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + // }, + // id: 0, + // descriptionFunction() { + // const loop = () => { + // if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) + // let b = []; //produce next row + // b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around + // for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array + // b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1)); + // } + // b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around + // this.state.push(b) + // if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML + // if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); + // setTimeout(() => { loop() }, 400); + // } + // } + // setTimeout(() => { loop() }, 400); + // // if (this.id === 0) { + // // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed + // // } + // this.id++ + // return `${this.outputText()}` + // }, + // outputText() { + // let text = "" + // for (let j = 0; j < this.state.length; j++) { + // text += "

" + // for (let i = 0; i < this.state[j].length; i++) { + // if (this.state[j][i]) { + // text += "⬛" //"█" //"■" + // } else { + // text += "⬜" //"    " //"□" + // } + // } + // text += "

" + // } + // return text + // }, + // }, { name: "rule 30", maxCount: 1, @@ -9607,7 +9733,8 @@ const tech = { state: [ [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false] ], - rule30(state, a, b, c) { + rule(state, a, b, c) { + //30 if (state[a] && state[b] && state[c]) return false; // TTT => F if (state[a] && state[b] && !state[c]) return false; // TTF => F if (state[a] && !state[b] && state[c]) return false; //TFT => F @@ -9619,21 +9746,40 @@ const tech = { }, id: 0, descriptionFunction() { + + if (this.id === 0 && Math.random() < 0.5) { + // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed + this.name = "rule 90" + this.link = `${this.name}` + // console.log(this.name) + this.state[0] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false] + this.rule = function(state, a, b, c) { + if (state[a] && state[b] && state[c]) return false; // TTT => F + if (state[a] && state[b] && !state[c]) return true; // TTF => T + if (state[a] && !state[b] && state[c]) return false; //TFT => F + if (state[a] && !state[b] && !state[c]) return true; //TFF => T + if (!state[a] && state[b] && state[c]) return true; //FTT => T + if (!state[a] && state[b] && !state[c]) return false; //FTF => F + if (!state[a] && !state[b] && state[c]) return true; //FFT => T + if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + } + } + const loop = () => { if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) let b = []; //produce next row - b.push(this.rule30(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array - b.push(this.rule30(this.state[this.state.length - 1], i - 1, i, i + 1)); + b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1)); } - b.push(this.rule30(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around this.state.push(b) if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); - setTimeout(() => { loop() }, 500); + setTimeout(() => { loop() }, 400); } } - setTimeout(() => { loop() }, 500); + setTimeout(() => { loop() }, 400); this.id++ return `${this.outputText()}` }, @@ -10038,5 +10184,8 @@ const tech = { isFoamBall: null, isNoDraftPause: null, isFoamPressure: null, - foamDamage: null + foamDamage: null, + implosion: null, + isClusterExplode: null, + isCircleExplode: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 8e9b34a..07b16e9 100644 --- a/todo.txt +++ b/todo.txt @@ -1,22 +1,51 @@ ******************************************************** NEXT PATCH ************************************************** -bremsstrahlung does extra damage to shields +grenade tech: flame test - grenades release a cluster of smaller explosions +grenade tech: pyrotechnics - grenades release a circle of smaller explosions +grenade tech: implosion - explosions pull things in, not out, +25% to grenade explosion damage and radius +chain reaction no longer requires vacuum bomb +bosses and mobs have much less knock back from explosions + invulnerable mobs have no knock back + +alternator harpoon/grapple/railgun energy drain reduced by 100->60% +bots no longer unlock tech until you upgrade to a bot type +JUNK tech rule 30 is now sometimes rule 90 instead +disabled testing for why? mode + +wave beam + amplitude 50->37% damage + propagation 50->37% damage +worms + annelids 10-120% -> about 37% damage +radiation + nuclear transmutation stacks 9x + gives 70->47% damage per stack +explosions + ammonium nitrate 27->24% damage and radius -bug fixes ******************************************************** TODO ******************************************************** -tech: increase damage from all radioactive sources by 66% - apply to dots and to drones, neutron bomb, and radioactive explosions +buff early matter wave without phonon + +some grenade tech made all the bosses go away and not drop anything + check: fireworks, vacuum, stun, chain reaction, implosion + +more fireworks themed grenade tech + shotting star - fire a series of explosions higher and higher up, also increase radius with height + star burst - 5 explosions in star shape + delay - explosion in same place + pulse + 30s of lasers + +merge mines and grenades? +tech - neutron bombs deal 100% more damage, but finishes detonating much faster +tech - neutron bombs will explode into a small iridum explosion after it expires tech: damage mobs in your last 10 seconds of history field tech? time dilation? -standing wave is weak vs. exploding bullets - -add foam tech that makes foam stronger vs. shields - tech: eternalism - don't pause time during draft bugs? requirements change after draft is generated @@ -26,6 +55,7 @@ tech expansion: should also make other fields do things how to make the description work change description based on your current field? perfect diamagnetism moves forward when you hold down the shield + it's great, but maybe annoying? maybe only with crouch? time dilation drains 1/2 as much energy when paused grow plasma torch as you hold it down