diff --git a/js/bullet.js b/js/bullet.js index 7650726..e80fc71 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -2251,23 +2251,8 @@ 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, - dist2: Infinity, - who: null, - v1: 1, - v2: 1 - }; - const path = [{ - x: where.x, - y: where.y - }, - { - x: whereEnd.x, - y: whereEnd.y - } - ]; + let best = { x: 1, y: 1, dist2: Infinity, who: null, v1: 1, v2: 1 }; + const path = [{ x: where.x, y: where.y }, { 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; @@ -2310,14 +2295,7 @@ const b = { }; const checkForCollisions = function() { - best = { - x: 1, - y: 1, - dist2: Infinity, - who: null, - v1: 1, - v2: 1 - }; + 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); @@ -2328,7 +2306,7 @@ const b = { if (best.who.damageReduction) { if ( //iridescence tech.laserCrit && !best.who.shield && - Vector.dot(Vector.normalise(Vector.sub(best.who.position, path[path.length - 1])), Vector.normalise(Vector.sub(path[path.length - 1], path[path.length - 2]))) > 0.997 - 0.6 / best.who.radius + Vector.dot(Vector.normalise(Vector.sub(best.who.position, path[path.length - 1])), Vector.normalise(Vector.sub(path[path.length - 1], path[path.length - 2]))) > 0.999 - 0.5 / best.who.radius ) { damage *= 1 + tech.laserCrit simulation.drawList.push({ //add dmg to draw queue @@ -2374,10 +2352,7 @@ 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 < reflections; i++) { reflection(); @@ -2385,10 +2360,7 @@ const b = { 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. @@ -2409,6 +2381,31 @@ const b = { ctx.moveTo(path[i - 1].x, path[i - 1].y); ctx.lineTo(path[i].x, path[i].y); } + } else if (tech.isLaserLens && b.guns[11].lensDamage !== 1) { + ctx.strokeStyle = tech.laserColor; + ctx.lineWidth = 2 + ctx.lineDashOffset = 900 * Math.random() + ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + for (let i = 1, len = path.length; i < len; ++i) { + ctx.beginPath(); + ctx.moveTo(path[i - 1].x, path[i - 1].y); + ctx.lineTo(path[i].x, path[i].y); + ctx.stroke(); + ctx.globalAlpha *= reflectivity; //reflections are less intense + } + ctx.setLineDash([]); + // ctx.globalAlpha = 1; + + //glow + ctx.lineWidth = 9 + 2 * b.guns[11].lensDamageOn + ctx.globalAlpha = 0.13 + ctx.beginPath(); + for (let i = 1, len = path.length; i < len; ++i) { + ctx.moveTo(path[i - 1].x, path[i - 1].y); + ctx.lineTo(path[i].x, path[i].y); + } + ctx.stroke(); + ctx.globalAlpha = 1; } else { ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 2 @@ -3356,20 +3353,8 @@ const b = { deathCycles: 110 + RADIUS * 5, isImproved: false, radioRadius: 0, - maxRadioRadius: 300 + Math.floor(100 * Math.random()), - beforeDmg() { - // const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) //move away from target after hitting - // Matter.Body.setVelocity(this, { - // x: unit.x, - // y: unit.y - // }); - // this.lockedOn = null - - // if (this.endCycle > simulation.cycle + this.deathCycles) { - // this.endCycle -= 60 - // if (simulation.cycle + this.deathCycles > this.endCycle) this.endCycle = simulation.cycle + this.deathCycles - // } - }, + maxRadioRadius: 270 + Math.floor(90 * Math.random()), + beforeDmg() {}, onEnd() { if (tech.isDroneRespawn && b.inventory.length) { const who = b.guns[b.activeGun] @@ -3387,12 +3372,12 @@ const b = { this.radioRadius = this.radioRadius * 0.993 + 0.007 * this.maxRadioRadius //smooth radius towards max //aoe damage to player if (Vector.magnitude(Vector.sub(player.position, this.position)) < this.radioRadius) { - const DRAIN = tech.isRadioactiveResistance ? 0.002 * 0.25 : 0.002 + const DRAIN = tech.isRadioactiveResistance ? 0.001 : 0.004 if (m.energy > DRAIN) { if (m.immuneCycle < m.cycle) m.energy -= DRAIN } else { m.energy = 0; - if (simulation.dmgScale) m.damage((tech.isRadioactiveResistance ? 0.00015 * 0.25 : 0.00015) * tech.radioactiveDamage) //0.00015 + if (simulation.dmgScale) m.damage((tech.isRadioactiveResistance ? 0.00005 : 0.0002) * tech.radioactiveDamage) //0.00015 } } //aoe damage to mobs @@ -3928,7 +3913,8 @@ const b = { } }, crit(mob, bullet) { - if (!mob.shield && Vector.dot(Vector.normalise(Vector.sub(mob.position, bullet.position)), Vector.normalise(bullet.velocity)) > 0.99 - 4 / mob.radius) { + if (!mob.shield && Vector.dot(Vector.normalise(Vector.sub(mob.position, bullet.position)), Vector.normalise(bullet.velocity)) > 0.999 - 1 / mob.radius) { + if (mob.isFinalBoss && !(Vector.dot(Vector.normalise(Vector.sub(mob.position, bullet.position)), Vector.normalise(bullet.velocity)) > 0.999999)) return let cycle = () => { //makes this run after damage if (mob.health < 0.5 && mob.damageReduction > 0 && mob.alive) { // mob.death(); @@ -4693,45 +4679,155 @@ const b = { //hit target with laser if (this.lockedOn && this.lockedOn.alive && m.energy > this.drainThreshold) { m.energy -= this.drain - b.laser(this.vertices[0], this.lockedOn.position, m.dmgScale * this.laserDamage * tech.laserDamage, tech.laserReflections, false, 0.4) //tech.laserDamage = 0.16 - // laser(where = { - // x: m.pos.x + 20 * Math.cos(m.angle), - // y: m.pos.y + 20 * Math.sin(m.angle) - // }, whereEnd = { - // x: where.x + 3000 * Math.cos(m.angle), - // y: where.y + 3000 * Math.sin(m.angle) - // }, dmg = tech.laserDamage, reflections = tech.laserReflections, isThickBeam = false, push = 1) { + this.laser(); + // b.laser(this.vertices[0], this.lockedOn.position, m.dmgScale * this.laserDamage * tech.laserDamage, tech.laserReflections, false, 0.4) //tech.laserDamage = 0.16 } + }, + laser() { + const push = 0.4 + const reflectivity = 1 - 1 / (tech.laserReflections * 3) + let damage = m.dmgScale * this.laserDamage * tech.laserDamage + let best = { x: 1, y: 1, dist2: Infinity, who: null, v1: 1, v2: 1 }; + const path = [{ x: this.vertices[0].x, y: this.vertices[0].y }, { x: this.lockedOn.position.x, y: this.lockedOn.position.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); + }; + const laserHitMob = function() { + if (best.who.alive) { + best.who.locatePlayer(); + if (best.who.damageReduction) { + if ( //iridescence + tech.laserCrit && !best.who.shield && + Vector.dot(Vector.normalise(Vector.sub(best.who.position, path[path.length - 1])), Vector.normalise(Vector.sub(path[path.length - 1], path[path.length - 2]))) > 0.999 - 0.5 / best.who.radius + ) { + damage *= 1 + tech.laserCrit + simulation.drawList.push({ //add dmg to draw queue + x: path[path.length - 1].x, + y: path[path.length - 1].y, + radius: Math.sqrt(2500 * damage * best.who.damageReduction) + 5, + color: `hsla(${60 + 283*Math.random()},100%,70%,0.5)`, // random hue, but not red + time: 16 + }); + } else { + simulation.drawList.push({ //add dmg to draw queue + x: path[path.length - 1].x, + y: path[path.length - 1].y, + radius: Math.sqrt(2000 * damage * best.who.damageReduction) + 2, + color: tech.laserColorAlpha, + time: simulation.drawTime + }); + } + best.who.damage(damage); + } + 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 }); + 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 }); + 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) + } + }; + const reflection = function() { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector + const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2))); + const d = Vector.sub(path[path.length - 1], path[path.length - 2]); + const nn = Vector.mult(n, 2 * Vector.dot(d, n)); + const r = Vector.normalise(Vector.sub(d, nn)); + path[path.length] = Vector.add(Vector.mult(r, 3000), path[path.length - 1]); + }; + + checkForCollisions(); + 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 }; + 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 }; + 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. + //I think it checks to see if the laser is reflecting off a different part of the same block, if it is "inside" a block + if (i % 2) { + if (lastBestOdd === best.who) break + } else { + lastBestOdd = best.who + if (lastBestEven === best.who) break + } + } else { + break + } + } + } + ctx.strokeStyle = tech.laserColor; + ctx.lineWidth = 2 + ctx.lineDashOffset = 900 * Math.random() + ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + for (let i = 1, len = path.length; i < len; ++i) { + ctx.beginPath(); + ctx.moveTo(path[i - 1].x, path[i - 1].y); + ctx.lineTo(path[i].x, path[i].y); + ctx.stroke(); + ctx.globalAlpha *= reflectivity; //reflections are less intense + } + ctx.setLineDash([]); + ctx.globalAlpha = 1; } }) Composite.add(engine.world, bullet[me]); //add bullet to world - - //laser mobs that fire with the player - // if (true) { - // bullet[me].do = function() { - // if (!(simulation.cycle % this.lookFrequency)) { - // if (Math.random() < 0.15) { - // const range = 170 + 3 * b.totalBots() - // this.offPlayer = { - // x: range * (Math.random() - 0.5), - // y: range * (Math.random() - 0.5) - 20, - // } - // } - // } - // const playerPos = Vector.add(Vector.add(this.offPlayer, m.pos), Vector.mult(player.velocity, 20)) //also include an offset unique to this bot to keep many bots spread out - // const farAway = Math.max(0, (Vector.magnitude(Vector.sub(this.position, playerPos))) / this.playerRange) //linear bounding well - // const mag = Math.min(farAway, 4) * this.mass * this.acceleration - // this.force = Vector.mult(Vector.normalise(Vector.sub(playerPos, this.position)), mag) - // //manual friction to not lose rotational velocity - // Matter.Body.setVelocity(this, { x: this.velocity.x * 0.95, y: this.velocity.y * 0.95 }); - // //hit target with laser - // if (input.fire && m.energy > this.drain) { - // m.energy -= this.drain - // const unit = Vector.sub(simulation.mouseInGame, this.vertices[0]) - // b.laser(this.vertices[0], Vector.mult(unit, 1000), m.dmgScale * this.laserDamage * tech.laserDamage, tech.laserReflections, false, 0.4) //tech.laserDamage = 0.16 - // } - // } - // } }, boomBot(position = { x: player.position.x + 50 * (Math.random() - 0.5), y: player.position.y + 50 * (Math.random() - 0.5) }, isConsole = true) { if (isConsole) simulation.makeTextLog(`b.boomBot()`); @@ -7255,6 +7351,11 @@ const b = { } } ctx.stroke(); + if (tech.isLaserLens && b.guns[11].lensDamage !== 1) { + ctx.lineWidth = 20 + 3 * b.guns[11].lensDamageOn + ctx.globalAlpha = 0.3 + ctx.stroke(); + } ctx.globalAlpha = 1; } }, @@ -7265,8 +7366,8 @@ const b = { } else { m.fireCDcycle = m.cycle m.energy -= drain - const dmg = 0.37 * tech.laserDamage / b.fireCDscale * this.lensDamage // 3.5 * 0.55 = 200% more damage - const spacing = Math.ceil(5 - 0.4 * tech.historyLaser) + const dmg = 0.5 * tech.laserDamage / b.fireCDscale * this.lensDamage // 3.5 * 0.55 = 200% more damage + const spacing = Math.ceil(10 - 0.4 * tech.historyLaser) ctx.beginPath(); b.laser({ x: m.pos.x + 20 * Math.cos(m.angle), @@ -7275,7 +7376,7 @@ const b = { x: m.pos.x + 3000 * Math.cos(m.angle), y: m.pos.y + 3000 * Math.sin(m.angle) }, dmg, 0, true, 0.2); - for (let i = 1, len = 5 + tech.historyLaser * 5; i < len; i++) { + for (let i = 1, len = 3 + tech.historyLaser * 3; i < len; i++) { const history = m.history[(m.cycle - i * spacing) % 600] const off = history.yOff - 24.2859 b.laser({ @@ -7289,6 +7390,13 @@ const b = { ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 1 ctx.stroke(); + if (tech.isLaserLens && b.guns[11].lensDamage !== 1) { + ctx.strokeStyle = tech.laserColor; + ctx.lineWidth = 10 + 2 * b.guns[11].lensDamageOn + ctx.globalAlpha = 0.2 + ctx.stroke(); //glow + ctx.globalAlpha = 1; + } } }, }, diff --git a/js/level.js b/js/level.js index 6c262f8..c5afaec 100644 --- a/js/level.js +++ b/js/level.js @@ -28,19 +28,20 @@ const level = { // m.setField("standing wave") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass pilot wave // simulation.molecularMode = 2 // m.damage(0.1); - // b.giveGuns("nail gun") //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[0].ammo = 10000 - // for (let i = 0; i < 1; ++i) tech.giveTech("needle gun") - // tech.giveTech("pressure vessel") - // tech.giveTech("quintessence") - // for (let i = 0; i < 1; ++i) tech.giveTech("freezer burn") - // for (let i = 0; i < 1; i++) tech.giveTech("reaction inhibitor") + // tech.giveTech("lens") + // for (let i = 0; i < 9; ++i) tech.giveTech("compound lens") + // tech.giveTech("dye laser") + // for (let i = 0; i < 1; ++i) tech.giveTech("iridescence") + // for (let i = 0; i < 1; i++) tech.giveTech("slow light") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); - // level.final(); + // level.testing(); + // spawn.starter(1900, -500, 200) // spawn.starter(1900, -500) // spawn.timeBoss(2538, -950) // for (let i = 0; i < 33; ++i) spawn.sniper(1000 + 5000 * Math.random(), -500 + 300 * Math.random()) @@ -1088,7 +1089,7 @@ const level = { if (!m.isBodiesAsleep) { if (this.isClosing) { if (this.position.y < y) { //try to close - if ( + if ( //if clear of stuff Matter.Query.collides(this, [player]).length === 0 && Matter.Query.collides(this, body).length < 2 && Matter.Query.collides(this, mob).length === 0 @@ -1100,6 +1101,25 @@ const level = { Matter.Body.setPosition(this, position) } } + // else { + // const blocks = Matter.Query.collides(this, body) + // console.log(blocks.length) + // for (let i = 0; i < blocks.length; i++) { + // // console.log(blocks[i]) + // if (blocks[i].bodyA) { + // if (touching[i].bodyB !== m.holdingTarget) { + // for (let j = 0, len = body.length; j < len; j++) { + // if (body[j] === touching[i].bodyB) { + // body.splice(j, 1); + // len-- + // Matter.Composite.remove(engine.world, touching[i].bodyB); + // break; + // } + // } + // } + // } + // } + // } } else { if (this.position.y > y - distance) { //try to open const position = { @@ -2955,6 +2975,12 @@ const level = { if (!doorOut.isClosed() || !doorIn.isClosed()) { doorIn.isClosing = true doorOut.isClosing = true + //block caught in a door + if (Matter.Query.collides(doorOut, body).length > 1 || Matter.Query.collides(doorIn, body).length > 1) { + button.isUp = true + doorIn.isClosing = false + doorOut.isClosing = false + } } else { isSpawnedBoss = true isDoorsLocked = true @@ -3039,6 +3065,12 @@ const level = { if (!doorOut.isClosed() || !doorIn.isClosed()) { doorIn.isClosing = true doorOut.isClosing = true + //block caught in a door + if (Matter.Query.collides(doorOut, body).length > 1 || Matter.Query.collides(doorIn, body).length > 1) { + button.isUp = true + doorIn.isClosing = false + doorOut.isClosing = false + } } else { isSpawnedBoss = true isDoorsLocked = true diff --git a/js/player.js b/js/player.js index 4c8e58c..9154cec 100644 --- a/js/player.js +++ b/js/player.js @@ -602,13 +602,10 @@ const m = { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) })); - Matter.Body.setVelocity(bullet[i], { - x: 0, - y: 0 - }); + Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 }); } } - m.energy = Math.max(m.energy - steps / 150, 0.01) + m.energy = Math.max(m.energy - steps / 200, 0.01) if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles let isDrawPlayer = true @@ -1049,7 +1046,7 @@ const m = { } else { m.fieldRegen = 0.001 //6 energy per second } - if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.001 * m.coupling + if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.008333 * m.coupling if (tech.isTimeCrystals) { m.fieldRegen *= 3 } else if (tech.isGroundState) { @@ -1572,7 +1569,7 @@ const m = { case 3: //negative mass return `+${((1-0.73 ** couple)*100).toFixed(1)}% defense` case 4: //assembler - return `generate ${(6*couple).toFixed(0)} energy per second` + return `generate ${(5*couple).toFixed(0)} energy per second` case 5: //plasma return `+${(15*couple).toFixed(0)}% damage` case 6: //time dilation diff --git a/js/powerup.js b/js/powerup.js index 0a1b836..f6e0434 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -331,7 +331,7 @@ const powerUps = { // } // requestAnimationFrame(cycle); - document.getElementById("choose-grid").style.opacity = "0.9" + document.getElementById("choose-grid").style.opacity = "0.92" } else { simulation.paused = true; document.getElementById("choose-grid").style.opacity = "1" @@ -343,8 +343,8 @@ const powerUps = { ctx.fillStyle = `rgba(221,221,221,0.6)`; ctx.fillRect(0, 0, canvas.width, canvas.height); }); - document.getElementById("pause-grid-right").style.opacity = "0.3" - document.getElementById("pause-grid-left").style.opacity = "0.3" + document.getElementById("pause-grid-right").style.opacity = "0.7" + document.getElementById("pause-grid-left").style.opacity = "0.7" } build.pauseGrid() }, diff --git a/js/simulation.js b/js/simulation.js index b261fd9..9e3bf28 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -954,7 +954,7 @@ const simulation = { let respawnDrones = () => { if (droneCount > 0) { requestAnimationFrame(respawnDrones); - if (!simulation.paused && !simulation.isChoosing) { + if (!simulation.paused && !simulation.isChoosing && m.alive) { const where = { x: level.enter.x + 50, y: level.enter.y - 60 } droneCount-- if (tech.isDroneRadioactive) { diff --git a/js/spawn.js b/js/spawn.js index 3e1558d..097af74 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -367,7 +367,7 @@ const spawn = { me.cycle = 1; Matter.Body.setDensity(me, 0.2); //extra dense //normal is 0.001 //makes effective life much larger - me.damageReduction = 0.12 + me.damageReduction = 0.14 me.startingDamageReduction = me.damageReduction me.nextHealthThreshold = 0.999 me.invulnerableCount = 0 diff --git a/js/tech.js b/js/tech.js index e01119f..3043f31 100644 --- a/js/tech.js +++ b/js/tech.js @@ -288,7 +288,7 @@ const tech = { }, tech: [{ name: "ordnance", - description: "double the frequency of finding guntech
spawn a gun", + description: "double the frequency of finding guntech
spawn a gun and +5% JUNK to tech pool", maxCount: 1, count: 0, frequency: 1, @@ -299,12 +299,18 @@ const tech = { requires: "", effect() { powerUps.spawn(m.pos.x, m.pos.y, "gun"); - // this.count-- for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].isGunTech) tech.tech[i].frequency *= 2 } + this.refundAmount += tech.addJunkTechToPool(0.05) }, - remove() {} + refundAmount: 0, + remove() { + if (this.count > 0 && this.refundAmount > 0) { + tech.removeJunkTechFromPool(this.refundAmount) + this.refundAmount = 0 + } + } }, { name: "ad hoc", @@ -4956,8 +4962,8 @@ const tech = { isRemoveGun: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, isBot: true, isBotTech: true, allowed() { @@ -4984,8 +4990,8 @@ const tech = { isGunTech: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { return !tech.isImmuneExplosion && tech.explosiveRadius === 1 && !tech.isSmallExplosion && !tech.isBlockExplode && !tech.fragments && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.isBoomBotUpgrade || tech.isTokamak) }, @@ -6305,8 +6311,8 @@ const tech = { isGunTech: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { return ((tech.haveGunCheck("wave") && tech.infiniteWaveAmmo !== 1) || tech.haveGunCheck("laser") || (tech.haveGunCheck("harpoon") && !tech.isRailGun)) && !tech.isEnergyNoAmmo }, @@ -6479,8 +6485,8 @@ const tech = { isGunTech: true, maxCount: 3, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.isLaserBotUpgrade) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser }, @@ -6498,8 +6504,8 @@ const tech = { isGunTech: true, maxCount: 9, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 1, + frequencyDefault: 1, allowed() { return tech.haveGunCheck("laser") && !tech.isWideLaser && !tech.isPulseAim && !tech.historyLaser }, @@ -6522,8 +6528,8 @@ const tech = { isGunTech: true, maxCount: 1, count: 0, - frequency: 3, - frequencyDefault: 3, + frequency: 2, + frequencyDefault: 2, allowed() { return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser && !tech.historyLaser }, @@ -6592,7 +6598,7 @@ const tech = { }, { name: "infrared diode", - description: "+50% laser energy efficiency
infrared light is outside visual perception", + description: "+60% laser energy efficiency
infrared light is outside visual perception", isGunTech: true, maxCount: 1, count: 0, @@ -6603,7 +6609,7 @@ const tech = { }, requires: "laser, not free-electron, pulse", effect() { - tech.laserDrain *= 0.5; //100%-50% + tech.laserDrain *= 0.4; //100%-50% tech.laserColor = "transparent" //"rgb(255,0,20,0.02)" // tech.laserColorAlpha = "rgba(255,0,20,0.05)" }, @@ -6615,7 +6621,7 @@ const tech = { }, { name: "dye laser", - description: "+20% laser energy efficiency
+20% laser damage", + description: "+25% laser energy efficiency
+25% laser damage", isGunTech: true, maxCount: 1, count: 0, @@ -6626,8 +6632,8 @@ const tech = { }, requires: "laser, not pulse, infrared diode", effect() { - tech.laserDrain *= 0.8 - tech.laserDamage *= 1 + 0.2 + tech.laserDrain *= 0.75 + tech.laserDamage *= 1.25 tech.laserColor = "rgb(0, 11, 255)" tech.laserColorAlpha = "rgba(0, 11, 255,0.5)" }, @@ -6640,7 +6646,7 @@ const tech = { }, { name: "free-electron laser", - description: "–250% laser energy efficiency
+190% laser damage", + description: "–250% laser energy efficiency
+200% laser damage", isGunTech: true, maxCount: 1, count: 0, @@ -6652,7 +6658,7 @@ const tech = { requires: "laser, not pulse, infrared diode", effect() { tech.laserDrain *= 1 + 2.5 //250% more drain - tech.laserDamage *= 1 + 1.9 //190% more damage + tech.laserDamage *= 1 + 2 //190% more damage tech.laserColor = "#83f" tech.laserColorAlpha = "rgba(136, 51, 255,0.5)" }, @@ -8172,6 +8178,18 @@ const tech = { return `${this.text}` }, }, + { + name: "placebo", + description: "+777% damage
+777% defense
", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed: () => true, + requires: "", + effect() {}, + remove() {} + }, { name: "return", description: "return to the introduction level
reduce combat difficulty by 2 levels", diff --git a/todo.txt b/todo.txt index 12bf373..7133930 100644 --- a/todo.txt +++ b/todo.txt @@ -1,15 +1,28 @@ ******************************************************** NEXT PATCH ************************************************** -finalBoss has a new phase: "boulders" - each phase has been rebalanced - boss health is a bit higher - mob mines are white now +finalBoss has a bit less health -pilot wave gets +1 choice for gun,field,tech +laser lens has a glow effect +slow light has 11->7 unique beams + slow light has 38% more damage per beam +infrared diode 50->60% energy efficiency +dye laser 20->25% energy efficiency + 20->25% laser damage +free-electron laser 190->200% laser damage +crit angle is smaller for iridescence and stress concentration on large mobs +ordnance has +5% JUNK +CPT uses 25% less energy and leaves you with about 10-20 energy + +JUNK tech: placebo - +777% damage +777% defense + +bug fixes + -bug fixes: *********************************************************** TODO ***************************************************** + +laserMines need a copy of laser-bot method + this is a very rare bug, so not a priority finalBoss add synergies between modes: @@ -1047,8 +1060,7 @@ possible names for tech prion quine - self replicating protein Unitarity - https://en.wikipedia.org/wiki/Unitarity_(physics) - all probabilities add up to 1, calculations work the same forward and backwards in time this is violated by expansion of the universe - - + https://en.wikipedia.org/wiki/Cosmic_censorship_hypothesis - black holes can't leak