From d346afb2d002e6fc2469cd0b2a04efcd91bc51e0 Mon Sep 17 00:00:00 2001 From: landgreen Date: Wed, 7 Jul 2021 19:26:47 -0700 Subject: [PATCH] pressure wave tech: pressure wave - wave beam fires lower frequency, higher damage, wide arcs that propagate through solids tech: gamma-ray laser - increase laser damage by 150% and energy drain by 200% works for all lasers except pulse tech: specular reflection - now just gives +2 laser reflections (was +1, and damage/energy increase) you, pilot wave, and drones can't pick up ammo if you have Infinite ammo on your current gun wormhole still eats everything Bayesian statistics gives 4.2% damage per research (was 3.9%) bot fabrication needs 3 research to make a random bot (was 4) --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 144 +++++++++++++++++++++++++++++++++++++++++--------- js/level.js | 8 +-- js/lore.js | 13 ++--- js/player.js | 23 +++++--- js/powerup.js | 5 +- js/tech.js | 137 +++++++++++++++++++++++++++++++++-------------- todo.txt | 23 +++++++- 8 files changed, 264 insertions(+), 89 deletions(-) diff --git a/.DS_Store b/.DS_Store index 03292074950cc9fe63d01c35ba5f15f30a9e3297..b8d7b759a6aef0183146ca3fe54e847c90907eba 100644 GIT binary patch delta 22 dcmZoMXffEJ#muyL`(zzvUnWU~&DG4EA^=jK2D$(M delta 22 dcmZoMXffEJ#mrP!I$4L=mr3Hm=4$3n5dcxR2ND1P diff --git a/js/bullet.js b/js/bullet.js index ebc6b79..384ede8 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -527,11 +527,13 @@ const b = { let dist = 2200 for (let i = 0, len = mob.length; i < len; i++) { const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position)) - if (explosionRadius < newDist && + if ( + explosionRadius < newDist && newDist < dist && !mob[i].isBadTarget && Matter.Query.ray(map, path[0], mob[i].position).length === 0 && - Matter.Query.ray(body, path[0], mob[i].position).length === 0) { + Matter.Query.ray(body, path[0], mob[i].position).length === 0 + ) { dist = newDist best.who = mob[i] path[path.length - 1] = mob[i].position @@ -959,7 +961,7 @@ const b = { y: 0 } that.do = that.radiationMode; - // if (Matter.Query.collides(that, map).length || Matter.Query.collides(that, body).length || Matter.Query.collides(that, mob).length) { + // if (collides(that, map).length || Matter.Query.collides(that, body).length || Matter.Query.collides(that, mob).length) { } const mobCollisions = Matter.Query.collides(this, mob) @@ -1439,7 +1441,6 @@ const b = { v1: null, v2: null }; - const color = "#f00"; const path = [{ x: where.x, y: where.y @@ -1511,7 +1512,7 @@ const b = { x: path[path.length - 1].x, y: path[path.length - 1].y, radius: Math.sqrt(damage) * 100, - color: "rgba(255,0,0,0.5)", + color: tech.laserColorAlpha, time: simulation.drawTime }); if (tech.isLaserPush) { //push mobs away @@ -1569,7 +1570,7 @@ const b = { ctx.lineTo(path[i].x, path[i].y); } } else { - ctx.strokeStyle = color; + ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 2 ctx.lineDashOffset = 300 * Math.random() ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); @@ -1642,7 +1643,7 @@ const b = { if (this.angularSpeed < 0.02) this.torque += this.inertia * this.torqueMagnitude //spin //fire lasers - ctx.strokeStyle = "#f00"; + ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 1.5 // ctx.globalAlpha = 1; ctx.beginPath(); @@ -2114,9 +2115,10 @@ const b = { //grab, but don't lock onto nearby power up for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && + Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isDeterminism) && - Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { //draw pickup for a single cycle ctx.beginPath(); @@ -2145,8 +2147,9 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && - (powerUp[i].name !== "field" || !tech.isDeterminism) + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "field" || !tech.isDeterminism) && + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { //draw pickup for a single cycle @@ -2328,9 +2331,10 @@ const b = { //grab, but don't lock onto nearby power up for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && + Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "field" || !tech.isDeterminism) && - Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { //draw pickup for a single cycle ctx.beginPath(); @@ -2360,8 +2364,9 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && - (powerUp[i].name !== "field" || !tech.isDeterminism) + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) && + (powerUp[i].name !== "field" || !tech.isDeterminism) && + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab) ) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) { //draw pickup for a single cycle @@ -3045,7 +3050,7 @@ const b = { lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade, range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()), drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4, - drain: 0.56 - 0.42 * tech.isLaserBotUpgrade, + drain: (0.56 - 0.42 * tech.isLaserBotUpgrade) * tech.laserFieldDrain * tech.isLaserDiode, laserDamage: 0.6 + 0.43 * tech.isLaserBotUpgrade, endCycle: Infinity, classType: "bullet", @@ -3095,7 +3100,7 @@ const b = { } //hit target with laser if (this.lockedOn && this.lockedOn.alive && m.energy > this.drainThreshold) { - m.energy -= tech.laserFieldDrain * tech.isLaserDiode * this.drain + m.energy -= this.drain b.laser(this.vertices[0], this.lockedOn.position, b.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), @@ -3960,22 +3965,107 @@ const b = { } }, fire() {} - }, { + }, + { name: "wave beam", description: "emit a wave packet of oscillating particles
that propagates through solids", ammo: 0, - ammoPack: 100, + ammoPack: 120, + defaultAmmoPack: 120, have: false, wavePacketCycle: 0, delay: 40, - do() { + propagationRate: 20, + waves: [], //used in longitudinal mode + chooseFireMethod() { //set in simulation.startGame + if (tech.isLongitudinal) { + this.fire = this.fireLongitudinal + this.do = this.doLongitudinal + } else { + this.fire = this.fireTransverse + this.do = this.doTransverse + } + }, + do() {}, + doLongitudinal() { + ctx.strokeStyle = "rgba(0,0,0,0.2)" //"000"; + ctx.lineWidth = 2 + ctx.beginPath(); + for (let i = this.waves.length - 1; i > -1; i--) { + const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius)) + const v2 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit2, this.waves[i].radius)) + // collisions + //using small angle linear approximation of circle arc, this will not work if the arc gets large // https://stackoverflow.com/questions/13652518/efficiently-find-points-inside-a-circle-sector + let hits = Matter.Query.ray(mob, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) + for (let j = 0; j < hits.length; j++) { + const who = hits[j].body + //make them shake around + who.force.x += 0.01 * (Math.random() - 0.5) * who.mass + who.force.y += 0.01 * (Math.random() - 0.5) * who.mass + Matter.Body.setVelocity(who, { //friction + x: who.velocity.x * 0.95, + y: who.velocity.y * 0.95 + }); + + let vertices = who.vertices; + const vibe = 50 + who.radius * 0.15 + ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + for (let j = 1; j < vertices.length; j++) { + ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); + } + ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + const damage = 1.65 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer + who.locatePlayer(); + who.damage(damage); + } + + hits = Matter.Query.ray(body, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) + for (let j = 0; j < hits.length; j++) { + const who = hits[j].body + //make them shake around + who.force.x += 0.01 * (Math.random() - 0.5) * who.mass + who.force.y += (0.01 * (Math.random() - 0.5) - simulation.g * 0.25) * who.mass //remove force of gravity + + let vertices = who.vertices; + const vibe = 25 + ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + for (let j = 1; j < vertices.length; j++) { + ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5)); + } + ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5)); + } + ctx.stroke(); //draw vibes + + // ctx.beginPath(); //draw wave + ctx.moveTo(v1.x, v1.y) + ctx.arc(this.waves[i].position.x, this.waves[i].position.y, this.waves[i].radius, this.waves[i].angle, this.waves[i].angle + this.waves[i].arc); + if (!m.isBodiesAsleep) this.waves[i].radius += tech.waveBeamSpeed * 2 //expand / move + if (this.waves[i].radius > 1800 * tech.isBulletsLastLonger) this.waves.splice(i, 1) //end + } + ctx.stroke(); + }, + fireLongitudinal() { + m.fireCDcycle = m.cycle + Math.floor(8 * b.fireCDscale); // cool down + const halfArc = Math.PI / 8 * (m.crouch ? 0.7 : 0.5) + this.waves.push({ + position: { + x: m.pos.x + 25 * Math.cos(m.angle), + y: m.pos.y + 25 * Math.sin(m.angle), + }, + angle: m.angle - halfArc, //used in drawing ctx.arc + unit1: { x: Math.cos(m.angle - halfArc), y: Math.sin(m.angle - halfArc) }, //used for collision + unit2: { x: Math.cos(m.angle + halfArc), y: Math.sin(m.angle + halfArc) }, //used for collision + arc: halfArc * 2, + radius: 25 + }) + }, + doTransverse() { if (this.wavePacketCycle && !input.fire) { this.wavePacketCycle = 0; m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down } }, - damage: 1, - fire() { + fireTransverse() { totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) const me = bullet.length; bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, { @@ -4074,8 +4164,10 @@ const b = { m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down this.wavePacketCycle = 0; } - } - }, { + }, + + }, + { name: "missiles", description: "launch homing missiles that explode
crouch to rapidly launch smaller missiles", ammo: 0, @@ -4979,7 +5071,7 @@ const b = { x: m.pos.x + 15 * Math.cos(m.angle), y: m.pos.y + 15 * Math.sin(m.angle) } - ctx.strokeStyle = "#f00"; + ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 8 ctx.globalAlpha = 0.5; ctx.beginPath(); @@ -5046,7 +5138,7 @@ const b = { y: history.position.y + 3000 * Math.sin(history.angle) - off }, dmg, 0, true, 0.2); } - ctx.strokeStyle = "#f00"; + ctx.strokeStyle = tech.laserColor; ctx.lineWidth = 1 ctx.stroke(); } diff --git a/js/level.js b/js/level.js index e262f6f..a696d5f 100644 --- a/js/level.js +++ b/js/level.js @@ -15,8 +15,8 @@ const level = { // level.difficultyIncrease(30) // simulation.isHorizontalFlipped = true // m.setField("wormhole") - // b.giveGuns("foam") - // tech.giveTech("quenching") + // b.giveGuns("wave beam") + // tech.giveTech("pressure wave") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") // tech.giveTech("supertemporal") // for (let i = 0; i < 3; i++) tech.giveTech("packet length") @@ -2244,10 +2244,10 @@ const level = { spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump - // spawn.starter(1900, -500, 200) //big boy + spawn.starter(1900, -500, 200) //big boy // spawn.pulseShooter(1900, -500) // spawn.pulsarBoss(1900, -500) - spawn.grenadierBoss(1900, -500) + // spawn.grenadierBoss(1900, -500) // spawn.shieldingBoss(1900, -500) // spawn.historyBoss(1200, -500) diff --git a/js/lore.js b/js/lore.js index 7c59b58..ea3aea1 100644 --- a/js/lore.js +++ b/js/lore.js @@ -351,14 +351,11 @@ const lore = { // [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust. // /* - // The player has different aspects that aren't directly communicating - // like each part is a separate local minimum solution, and the project is the superposition of both goals. - // part of it wants to undo what has happened, that part is making the null level spawn so it can communicate - // just do its job: research tech - // part of it wants to escape/fight - // part wants to explore self awareness and make connections with the scientists - // maybe... player must make a choice? - // keep fighting + // The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game. + // this means the player can use console commands to change the way the game works + // the scientists tell the player about interesting console commands + // player must make a choice? + // keep fighting and supporting the AI's goals // exit the simulation // enter real world // close tab? diff --git a/js/player.js b/js/player.js index 2aa419f..9a84530 100644 --- a/js/player.js +++ b/js/player.js @@ -1232,7 +1232,7 @@ const m = { for (let i = 0, len = powerUp.length; i < len; ++i) { const dxP = m.pos.x - powerUp[i].position.x; const dyP = m.pos.y - powerUp[i].position.y; - const dist2 = dxP * dxP + dyP * dyP; + const dist2 = dxP * dxP + dyP * dyP + 10; // float towards player if looking at and in range or if very close to player if ( dist2 < m.grabPowerUpRange2 && @@ -1249,7 +1249,8 @@ const m = { if ( //use power up if it is close enough dist2 < 5000 && !simulation.isChoosing && - !(m.health === m.maxHealth && powerUp[i].name === "heal" && !tech.isOverHeal) + (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) && + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) ) { powerUps.onPickUp(powerUp[i]); Matter.Body.setVelocity(player, { //player knock back, after grabbing power up @@ -2367,17 +2368,25 @@ const m = { for (let i = 0, len = powerUp.length; i < len; ++i) { const dxP = m.fieldPosition.x - powerUp[i].position.x; const dyP = m.fieldPosition.y - powerUp[i].position.y; - const dist2 = dxP * dxP + dyP * dyP; + const dist2 = dxP * dxP + dyP * dyP + 200; // float towards field if looking at and in range or if very close to player - if (dist2 < m.fieldRadius * m.fieldRadius && (m.lookingAt(powerUp[i]) || dist2 < 16000) && !(m.health === m.maxHealth && powerUp[i].name === "heal")) { - powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; - powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity + if ( + dist2 < m.fieldRadius * m.fieldRadius && + (m.lookingAt(powerUp[i]) || dist2 < 16000) + ) { + powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass; + powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity //extra friction Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.11, y: powerUp[i].velocity.y * 0.11 }); - if (dist2 < 5000 && !simulation.isChoosing) { //use power up if it is close enough + if ( + dist2 < 5000 && + !simulation.isChoosing && + (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) && + (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity) + ) { //use power up if it is close enough powerUps.onPickUp(powerUp[i]); powerUp[i].effect(); Matter.World.remove(engine.world, powerUp[i]); diff --git a/js/powerup.js b/js/powerup.js index 56c71a9..0945ac2 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -234,11 +234,10 @@ const powerUps = { } } if (tech.isRerollBots) { - const limit = 4 - for (; powerUps.research.count > limit - 1; powerUps.research.count -= limit) { + for (const cost = 3; powerUps.research.count > cost - 1; powerUps.research.count -= cost) { b.randomBot() if (tech.renormalization) { - for (let i = 0; i < limit; i++) { + for (let i = 0; i < cost; i++) { if (Math.random() < 0.4) { m.fieldCDcycle = m.cycle + 30; powerUps.spawn(m.pos.x, m.pos.y, "research"); diff --git a/js/tech.js b/js/tech.js index 3c42b6f..39cfd03 100644 --- a/js/tech.js +++ b/js/tech.js @@ -168,7 +168,7 @@ if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.isEnergyDamage) dmg *= 1 + m.energy / 9; if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038 - if (tech.isRerollDamage) dmg *= 1 + 0.039 * powerUps.research.count + if (tech.isRerollDamage) dmg *= 1 + 0.042 * powerUps.research.count if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.22 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 1.9 if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.43, player.speed * 0.015) @@ -1341,15 +1341,15 @@ }, { name: "bot fabrication", - description: "anytime you collect 4 research
use them to build a random bot", + description: "anytime you collect 3 research
use them to build a random bot", maxCount: 1, count: 0, frequency: 2, isBotTech: true, allowed() { - return powerUps.research.count > 3 || build.isExperimentSelection + return powerUps.research.count > 2 || build.isExperimentSelection }, - requires: "at least 4 research", + requires: "at least 3 research", effect() { tech.isRerollBots = true; powerUps.research.changeRerolls(0) @@ -2783,7 +2783,7 @@ }, { name: "Bayesian statistics", - description: "increase damage by 3.9%
for each research in your inventory", + description: "increase damage by 4.2%
for each research in your inventory", maxCount: 1, count: 0, frequency: 2, @@ -2801,7 +2801,7 @@ }, { name: "pseudoscience", - description: "resetting power up choices costs no research
but adds 0-4 JUNK to the potential tech pool", + description: "rerolling choices no longer costs research
instead it adds 0-4 JUNK to the tech pool", maxCount: 1, count: 0, frequency: 1, @@ -3695,24 +3695,21 @@ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "shotgun") { b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.5); - break; - } - } - simulation.updateGunHUD(); - - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "shotgun") { b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.5 break; } } + simulation.updateGunHUD(); }, remove() { - tech.isShotgunImmune = false; - for (i = 0, len = b.guns.length; i < len; i++) { //find which gun - if (b.guns[i].name === "shotgun") { - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; - break; + if (tech.isShotgunImmune) { + tech.isShotgunImmune = false; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "shotgun") { + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 2); + break; + } } } } @@ -3875,7 +3872,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("wave beam") + return tech.haveGunCheck("wave beam") && !tech.isLongitudinal }, requires: "wave beam", effect() { @@ -3885,6 +3882,25 @@ tech.waveReflections = 1 } }, + { + name: "phase velocity", + description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.haveGunCheck("wave beam") && !tech.isLongitudinal + }, + requires: "wave beam", + effect() { + tech.isPhaseVelocity = true; + }, + remove() { + tech.isPhaseVelocity = false; + } + }, { name: "packet length", description: "wave packet length and duration
is increased by 50%", // description: "holding fire allows the wave beam to emits a second packet
at zero ammo cost", @@ -3894,7 +3910,7 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("wave beam") + return tech.haveGunCheck("wave beam") && !tech.isLongitudinal }, requires: "wave beam", effect() { @@ -3952,22 +3968,42 @@ } }, { - name: "phase velocity", - description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", + name: "pressure wave", //longitudinal //gravitational wave? + description: "wave beam emits low frequency, high damage
expanding arcs that propagate through solids", isGunTech: true, maxCount: 1, count: 0, - frequency: 2, - frequencyDefault: 2, + frequency: 4, + frequencyDefault: 4, allowed() { - return tech.haveGunCheck("wave beam") + return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity && tech.waveLengthRange === 130 && tech.waveReflections === 1 }, - requires: "wave beam", + requires: "wave beam, not phase velocity, packet length, bound state", effect() { - tech.isPhaseVelocity = true; + tech.isLongitudinal = true; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "wave beam") { + b.guns[i].chooseFireMethod() + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.1 + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.1); + simulation.updateGunHUD(); + break + } + } }, remove() { - tech.isPhaseVelocity = false; + for (i = 0, len = b.guns.length; i < len; i++) { //find which gun + if (b.guns[i].name === "wave beam") { + b.guns[i].chooseFireMethod() + if (tech.isLongitudinal) { + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 10); + simulation.updateGunHUD(); + } + break + } + } + tech.isLongitudinal = false; } }, { @@ -4620,6 +4656,31 @@ tech.isLaserDiode = 1; } }, + { + name: "gamma-ray laser", + description: "increase all laser damage by 150%
increase all laser energy drain by 200%", + isGunTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser + }, + requires: "laser, not pulse", + effect() { + tech.laserFieldDrain = 0.006 //base is 0.002 + tech.laserDamage = 0.375; //base is 0.15 + tech.laserColor = "#83f" + tech.laserColorAlpha = "rgba(136, 51, 255,0.5)" + }, + remove() { + tech.laserFieldDrain = 0.002; + tech.laserDamage = 0.15; //used in check on pulse: tech.laserDamage === 0.15 + tech.laserColor = "#f00" + tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)" + } + }, { name: "relativistic momentum", description: "all lasers push mobs away
affects laser-gun, laser-bot, and laser-mines", @@ -4639,12 +4700,11 @@ tech.isLaserPush = false; } }, - { name: "specular reflection", - description: "increase damage and energy drain by 50%
and +1 reflection for all lasers (gun, bot, mine)", + description: "+2 reflection for all lasers
affects laser-gun, laser-bot, and laser-mines", isGunTech: true, - maxCount: 9, + maxCount: 3, count: 0, frequency: 2, frequencyDefault: 2, @@ -4653,14 +4713,10 @@ }, requires: "laser, not wide beam, diffuse beam, pulse, or slow light", effect() { - tech.laserReflections++; - tech.laserDamage += 0.075; //base is 0.12 - tech.laserFieldDrain += 0.001 //base is 0.002 + tech.laserReflections += 2; }, remove() { tech.laserReflections = 2; - tech.laserDamage = 0.15; - tech.laserFieldDrain = 0.002; } }, { @@ -4786,9 +4842,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser + return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.15 }, - requires: "laser, not specular reflection, not diffuse", + requires: "laser, not specular reflection, diffuse, solid-state", effect() { tech.isPulseLaser = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun @@ -7302,5 +7358,8 @@ isFoamTeleport: null, isResearchBoss: null, isJunkResearch: null, - junkResearchNumber: null + junkResearchNumber: null, + laserColor: null, + laserColorAlpha: null, + isLongitudinal: null } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 5493a5c..f565cec 100644 --- a/todo.txt +++ b/todo.txt @@ -1,8 +1,27 @@ ******************************************************** NEXT PATCH ******************************************************** +tech: pressure wave - wave beam fires lower frequency, higher damage, wide arcs that propagate through solids + +tech: gamma-ray laser - increase laser damage by 150% and energy drain by 200% + works for all lasers except pulse + +tech: specular reflection - now just gives +2 laser reflections (was +1, and damage/energy increase) + +you, pilot wave, and drones can't pick up ammo if you have Infinite ammo on your current gun + wormhole still eats everything + +Bayesian statistics gives 4.2% damage per research (was 3.9%) +bot fabrication needs 3 research to make a random bot (was 4) + ******************************************************** TODO ******************************************************** +wave arcs + do something similar to laser + find intersection of the small angle approximation of the arc and all mobs + tech: this.arc: Math.PI/8 // increase or decrease arc + wipe arcs on next level + try crosshair invert colors tech wave gun - no bullets just draw circle arcs that do damage to mobs near the circle arc @@ -252,8 +271,8 @@ map: observatory ******************************************************** MOBS ******************************************************** -mob bullets that explode (use the pulsar effect) -mobs that explode before they die (use the pulsar effect) +mob that spawns eggs after they die + eggs don't attack but grow back into a mob after about 10s mob mechanics use the force at a location effect, like the plasma field