From 00191431249f93c1142cf0675c5dd70d3db6ebc4 Mon Sep 17 00:00:00 2001 From: landgreen Date: Mon, 10 May 2021 06:20:19 -0700 Subject: [PATCH] metastability tech: metastability - 20% dup chance, but duplicated powers up eventually explode nerfed tech: electric reactive armor 6% (was 7%) explosion damage reduction for every 10 energy you currently have --- .DS_Store | Bin 6148 -> 6148 bytes js/bullet.js | 62 +++++++++++++------------- js/engine.js | 2 +- js/index.js | 2 +- js/level.js | 5 ++- js/mob.js | 10 ++--- js/player.js | 6 +-- js/powerup.js | 110 ++++++++++++++++++++++++++++++++++++++++++++-- js/simulation.js | 111 +++++++++++++++++++++++------------------------ js/spawn.js | 4 +- js/tech.js | 58 ++++++++++++++++--------- todo.txt | 11 ++++- 12 files changed, 253 insertions(+), 128 deletions(-) diff --git a/.DS_Store b/.DS_Store index caebfc06e58d2ba702c1cfe6ee675940a146cc31..ecf6676799449a170c3dac52116940368f799dab 100644 GIT binary patch delta 22 dcmZoMXffEJ#mux`Zn6%uFOw+4=4$3n5dcc21_=NF delta 22 dcmZoMXffEJ#mqEIY_blsFO$fF&DG4EA^=WN2Fm~d diff --git a/js/bullet.js b/js/bullet.js index 6117f35..c92b548 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -319,11 +319,8 @@ const b = { time: simulation.drawTime * 2 }); - //player damage and knock back - sub = Vector.sub(where, player.position); - dist = Vector.magnitude(sub); - - if (dist < radius) { + //player damage + if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { const drain = (tech.isExplosionHarm ? 0.5 : 0.25) * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) m.energy -= drain if (m.energy < 0) { @@ -389,6 +386,7 @@ const b = { //body knock backs for (let i = 0, len = body.length; i < len; ++i) { + if (body[i].isNotHoldable) continue sub = Vector.sub(where, body[i].position); dist = Vector.magnitude(sub); if (dist < radius) { @@ -560,11 +558,11 @@ const b = { for (let i = 0, len = Math.floor(mag * 0.0005 * charge); i < len; i++) { const dist = Math.random() simulation.drawList.push({ - x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5), - y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5), - radius: 1 + 4 * Math.random(), + x: path[0].x + sub.x * dist + 10 * (Math.random() - 0.5), + y: path[0].y + sub.y * dist + 10 * (Math.random() - 0.5), + radius: 1.5 + 5 * Math.random(), color: "rgba(255,0,0,0.5)", - time: Math.floor(2 + 33 * Math.random() * Math.random()) + time: Math.floor(9 + 25 * Math.random() * Math.random()) }); } }, @@ -3625,7 +3623,6 @@ const b = { damage: 1, fire() { totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) - // for (let i = 0; i < 2; i++) { 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, { angle: m.angle, @@ -3634,7 +3631,7 @@ const b = { inertia: Infinity, frictionAir: 0, slow: 0, - amplitude: (m.crouch ? 5 : 10) * Math.sin(this.wavePacketCycle * tech.wavePacketFrequency) * ((this.wavePacketCycle % 2) ? -1 : 1), + amplitude: (m.crouch ? 5 : 10) * ((this.wavePacketCycle % 2) ? -1 : 1) * Math.sin((this.wavePacketCycle + 1) * tech.wavePacketFrequency), // minDmgSpeed: 0, dmg: b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage, //also control damage when you divide by mob.mass classType: "bullet", @@ -3716,8 +3713,7 @@ const b = { y: tech.waveBeamSpeed * Math.sin(m.angle) }); const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) - // } - //fire some of bullets then delay for a while + //fire a packet of bullets then delay for a while this.wavePacketCycle++ if (this.wavePacketCycle > tech.wavePacketLength) { m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCD); // cool down @@ -4487,28 +4483,30 @@ const b = { } } if (tech.historyLaser) { + const len = 1 + tech.historyLaser + const spacing = Math.ceil(30 - 2 * tech.historyLaser) this.do = () => { - const len = 1 + 2 * tech.historyLaser - const spacing = Math.ceil(40 - 9 * tech.historyLaser) if (this.charge > 0) { //draw charge level - ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`; + const mag = 4.1 * Math.sqrt(this.charge) ctx.beginPath(); - const mag = 4.5 * Math.sqrt(this.charge) for (let i = 0; i < len; i++) { const history = m.history[(m.cycle - i * spacing) % 600] const off = history.yOff - 24.2859 ctx.moveTo(history.position.x, history.position.y - off); - ctx.ellipse(history.position.x, history.position.y - off, mag, mag * 0.5, history.angle, 0, 2 * Math.PI) + ctx.ellipse(history.position.x, history.position.y - off, mag, mag * 0.65, history.angle, 0, 2 * Math.PI) } + ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`; ctx.fill(); //fire if (!input.fire) { - m.fireCDcycle = m.cycle + 10; // cool down - for (let i = 1; i < len; i++) { - const history = m.history[(m.cycle - i * spacing) % 600] - const off = history.yOff - 24.2859 - b.pulse(1.4 * this.charge, history.angle, { x: history.position.x, y: history.position.y - off }) + if (this.charge > 5) { + m.fireCDcycle = m.cycle + 40; // cool down + for (let i = 0; i < len; i++) { + const history = m.history[(m.cycle - i * spacing) % 600] + const off = history.yOff - 24.2859 + b.pulse(1.65 * this.charge, history.angle, { x: history.position.x, y: history.position.y - off }) + } } this.charge = 0; } @@ -4518,19 +4516,21 @@ const b = { this.do = () => { if (this.charge > 0) { //draw charge level - ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`; ctx.beginPath(); ctx.arc(m.pos.x, m.pos.y, 4.2 * Math.sqrt(this.charge), 0, 2 * Math.PI); + ctx.fillStyle = `rgba(255,0,0,${0.09 * Math.sqrt(this.charge)})`; ctx.fill(); //fire if (!input.fire) { - m.fireCDcycle = m.cycle + 10; // cool down - if (tech.beamSplitter) { - const divergence = m.crouch ? 0.2 : 0.5 - const angle = m.angle - tech.beamSplitter * divergence / 2 - for (let i = 0; i < 1 + tech.beamSplitter; i++) b.pulse(this.charge, angle + i * divergence) - } else { - b.pulse(1.75 * this.charge, m.angle) + if (this.charge > 5) { + m.fireCDcycle = m.cycle + 35; // cool down + if (tech.beamSplitter) { + const divergence = m.crouch ? 0.2 : 0.5 + const angle = m.angle - tech.beamSplitter * divergence / 2 + for (let i = 0; i < 1 + tech.beamSplitter; i++) b.pulse(this.charge, angle + i * divergence) + } else { + b.pulse(1.8 * this.charge, m.angle) + } } this.charge = 0; } diff --git a/js/engine.js b/js/engine.js index bea675a..1353642 100644 --- a/js/engine.js +++ b/js/engine.js @@ -130,7 +130,7 @@ function collisionChecks(event) { simulation.makeTextLog(`simulation.amplitude = ${Math.random()}`); } if (tech.isPiezo) m.energy += 20.48; - if (tech.isBayesian) powerUps.ejectTech() + if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(k); m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles //extra kick between player and mob //this section would be better with forces but they don't work... diff --git a/js/index.js b/js/index.js index beaf253..002e31a 100644 --- a/js/index.js +++ b/js/index.js @@ -117,7 +117,7 @@ window.addEventListener('load', () => { //********************************************************************** //set up canvas //********************************************************************** -var canvas = document.getElementById("canvas"); +const canvas = document.getElementById("canvas"); //using "const" causes problems in safari when an ID shares the same name. const ctx = canvas.getContext("2d"); document.body.style.backgroundColor = "#fff"; diff --git a/js/level.js b/js/level.js index b9ad736..99d5d94 100644 --- a/js/level.js +++ b/js/level.js @@ -16,15 +16,16 @@ const level = { // simulation.zoomScale = 1000; // simulation.setZoom(); // m.setField("metamaterial cloaking") - // b.giveGuns("wave beam") + b.giveGuns("wave beam") // b.giveGuns("laser") // tech.isExplodeRadio = true // tech.giveTech("pulse") // for (let i = 0; i < 1; i++) tech.giveTech("crystallizer") // for (let i = 0; i < 3; i++) tech.giveTech("packet length") - // for (let i = 0; i < 3; i++) tech.giveTech("bound state") // for (let i = 0; i < 3; i++) tech.giveTech("propagation") + // for (let i = 0; i < 3; i++) tech.giveTech("bound state") // for (let i = 0; i < 9; i++) tech.giveTech("slow light") + tech.giveTech("metastability") level.intro(); //starting level // level.testing(); //not in rotation diff --git a/js/mob.js b/js/mob.js index d596e86..e375750 100644 --- a/js/mob.js +++ b/js/mob.js @@ -155,10 +155,10 @@ const mobs = { } }, statusDoT(who, tickDamage, cycles = 180) { - if (!who.isShielded && !m.isBodiesAsleep && who.alive) { + if (!who.isShielded && who.alive) { who.status.push({ effect() { - if ((simulation.cycle - this.startCycle) % 30 === 0) { + if ((simulation.cycle - this.startCycle) % 30 === 0 && !m.isBodiesAsleep) { let dmg = b.dmgScale * this.dmg who.damage(dmg); simulation.drawList.push({ //add dmg to draw queue @@ -169,10 +169,6 @@ const mobs = { time: simulation.drawTime }); } - // if (true) { - // //check for nearby mobs - - // } }, endEffect() {}, dmg: tickDamage, @@ -1090,7 +1086,7 @@ const mobs = { bullet[bullet.length - 1].endCycle = simulation.cycle + 660 //10 seconds and 1 extra second for fun this.leaveBody = false; // no body since it turned into the bot } - } else if (tech.isShieldAmmo && this.shield && !this.isBonusShield) { + } else if (tech.isShieldAmmo && this.shield && !this.isExtraShield) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { type = "heal" diff --git a/js/player.js b/js/player.js index f117160..758f841 100644 --- a/js/player.js +++ b/js/player.js @@ -976,7 +976,7 @@ const m = { m.fieldHarmReduction = 1; m.fieldDamage = 1 m.duplicateChance = 0 - if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal + powerUps.setDo(); m.grabPowerUpRange2 = 156000; m.fieldRange = 155; m.fieldFire = false; @@ -2370,7 +2370,7 @@ const m = { description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
7% chance to duplicate spawned power ups", //
bullets may also traverse wormholes effect: function() { m.duplicateChance = 0.07 - simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw + powerUps.setDo(); //needed after adjusting duplication chance m.hold = function() { // m.hole = { //this is reset with each new field, but I'm leaving it here for reference @@ -2922,7 +2922,7 @@ const m = { } m.damage(dmg); if (tech.isPiezo) m.energy += 20.48; - if (tech.isBayesian) powerUps.ejectTech() + if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(k); if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles //extra kick between player and mob //this section would be better with forces but they don't work... diff --git a/js/powerup.js b/js/powerup.js index c82dd6b..8fca203 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -3,6 +3,107 @@ let powerUp = []; const powerUps = { totalPowerUps: 0, //used for tech that count power ups at the end of a level lastTechIndex: null, + do() {}, + setDo() { + if (tech.duplicationChance() > 0) { + if (tech.isPowerUpsVanish) { + powerUps.do = powerUps.doDuplicatesVanish + } else { + powerUps.do = powerUps.doDuplicates + } + tech.maxDuplicationEvent() //check to see if hitting 100% duplication + } else { + powerUps.do = powerUps.doDefault + } + }, + doDefault() { //draw power ups + ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; + for (let i = 0, len = powerUp.length; i < len; ++i) { + ctx.beginPath(); + ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + ctx.fillStyle = powerUp[i].color; + ctx.fill(); + } + ctx.globalAlpha = 1; + }, + doDuplicates() { //draw power ups but give duplicates some electricity + ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; + for (let i = 0, len = powerUp.length; i < len; ++i) { + ctx.beginPath(); + ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + ctx.fillStyle = powerUp[i].color; + ctx.fill(); + } + ctx.globalAlpha = 1; + for (let i = 0, len = powerUp.length; i < len; ++i) { + if (powerUp[i].isDuplicated && Math.random() < 0.1) { + //draw electricity + const mag = 5 + powerUp[i].size / 5 + let unit = Vector.rotate({ + x: mag, + y: mag + }, 2 * Math.PI * Math.random()) + let path = { + x: powerUp[i].position.x + unit.x, + y: powerUp[i].position.y + unit.y + } + ctx.beginPath(); + ctx.moveTo(path.x, path.y); + for (let i = 0; i < 6; i++) { + unit = Vector.rotate(unit, 3 * (Math.random() - 0.5)) + path = Vector.add(path, unit) + ctx.lineTo(path.x, path.y); + } + ctx.lineWidth = 0.5 + 2 * Math.random(); + ctx.strokeStyle = "#000" + ctx.stroke(); + } + } + }, + doDuplicatesVanish() { //draw power ups but give duplicates some electricity + //remove power ups after 3 seconds + for (let i = 0, len = powerUp.length; i < len; ++i) { + if (powerUp[i].isDuplicated && Math.random() < 0.004) { // (1-0.004)^150 = chance to be removed after 3 seconds + b.explosion(powerUp[i].position, (10 + 3 * Math.random()) * powerUp[i].size); + Matter.World.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + break + } + } + + ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.25) + 0.6 + for (let i = 0, len = powerUp.length; i < len; ++i) { + ctx.beginPath(); + ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + ctx.fillStyle = powerUp[i].color; + ctx.fill(); + } + ctx.globalAlpha = 1; + for (let i = 0, len = powerUp.length; i < len; ++i) { + if (powerUp[i].isDuplicated && Math.random() < 0.3) { + //draw electricity + const mag = 5 + powerUp[i].size / 5 + let unit = Vector.rotate({ + x: mag, + y: mag + }, 2 * Math.PI * Math.random()) + let path = { + x: powerUp[i].position.x + unit.x, + y: powerUp[i].position.y + unit.y + } + ctx.beginPath(); + ctx.moveTo(path.x, path.y); + for (let i = 0; i < 6; i++) { + unit = Vector.rotate(unit, 3 * (Math.random() - 0.5)) + path = Vector.add(path, unit) + ctx.lineTo(path.x, path.y); + } + ctx.lineWidth = 0.5 + 2 * Math.random(); + ctx.strokeStyle = "#000" + ctx.stroke(); + } + } + }, choose(type, index) { if (type === "gun") { b.giveGuns(index) @@ -175,7 +276,7 @@ const powerUps = { powerUps.directSpawn(x, y, "heal", false, null, size) if (Math.random() < tech.duplicationChance()) { powerUps.directSpawn(x, y, "heal", false, null, size) - powerUp[powerUp.length - 1].isBonus = true + powerUp[powerUp.length - 1].isDuplicated = true } } }, @@ -640,7 +741,7 @@ const powerUps = { for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); - powerUp[powerUp.length - 1].isBonus = true + powerUp[powerUp.length - 1].isDuplicated = true } // remove a random tech from the list of tech you have tech.tech[choose].remove(); @@ -655,7 +756,7 @@ const powerUps = { for (let i = 0; i < tech.tech[choose].count; i++) { powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); - powerUp[powerUp.length - 1].isBonus = true + powerUp[powerUp.length - 1].isDuplicated = true } // remove a random tech from the list of tech you have tech.tech[choose].remove(); @@ -720,7 +821,8 @@ const powerUps = { powerUps.directSpawn(x, y, target, moving, mode, size) if (Math.random() < tech.duplicationChance()) { powerUps.directSpawn(x, y, target, moving, mode, size) - powerUp[powerUp.length - 1].isBonus = true + powerUp[powerUp.length - 1].isDuplicated = true + // if (tech.isPowerUpsVanish) powerUp[powerUp.length - 1].endCycle = simulation.cycle + 300 } } }, diff --git a/js/simulation.js b/js/simulation.js index 5e28d98..0a267b8 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -20,7 +20,7 @@ const simulation = { ctx.save(); simulation.camera(); level.custom(); - simulation.draw.powerUp(); + powerUps.do(); mobs.draw(); simulation.draw.cons(); simulation.draw.body(); @@ -900,61 +900,60 @@ const simulation = { ctx.fillText(`(${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})`, simulation.mouse.x, simulation.mouse.y - 20); }, draw: { - powerUp() { //is set by Bayesian tech - // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; - // for (let i = 0, len = powerUp.length; i < len; ++i) { - // ctx.beginPath(); - // ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); - // ctx.fillStyle = powerUp[i].color; - // ctx.fill(); - // } - // ctx.globalAlpha = 1; - }, - powerUpNormal() { //back up in case power up draw gets changed - ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; - for (let i = 0, len = powerUp.length; i < len; ++i) { - ctx.beginPath(); - ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); - ctx.fillStyle = powerUp[i].color; - ctx.fill(); - } - ctx.globalAlpha = 1; - }, - powerUpBonus() { //draws crackle effect for bonus power ups - ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; - for (let i = 0, len = powerUp.length; i < len; ++i) { - ctx.beginPath(); - ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); - ctx.fillStyle = powerUp[i].color; - ctx.fill(); - } - ctx.globalAlpha = 1; - for (let i = 0, len = powerUp.length; i < len; ++i) { - if (powerUp[i].isBonus && Math.random() < 0.1) { - //draw electricity - const mag = 5 + powerUp[i].size / 5 - let unit = Vector.rotate({ - x: mag, - y: mag - }, 2 * Math.PI * Math.random()) - let path = { - x: powerUp[i].position.x + unit.x, - y: powerUp[i].position.y + unit.y - } - ctx.beginPath(); - ctx.moveTo(path.x, path.y); - for (let i = 0; i < 6; i++) { - unit = Vector.rotate(unit, 3 * (Math.random() - 0.5)) - path = Vector.add(path, unit) - ctx.lineTo(path.x, path.y); - } - ctx.lineWidth = 0.5 + 2 * Math.random(); - ctx.strokeStyle = "#000" - ctx.stroke(); - } - } - // ctx.globalAlpha = 1; - }, + // powerUp() { //is set by Bayesian tech + // // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; + // // for (let i = 0, len = powerUp.length; i < len; ++i) { + // // ctx.beginPath(); + // // ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + // // ctx.fillStyle = powerUp[i].color; + // // ctx.fill(); + // // } + // // ctx.globalAlpha = 1; + // }, + // powerUpNormal() { //back up in case power up draw gets changed + // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; + // for (let i = 0, len = powerUp.length; i < len; ++i) { + // ctx.beginPath(); + // ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + // ctx.fillStyle = powerUp[i].color; + // ctx.fill(); + // } + // ctx.globalAlpha = 1; + // }, + // powerUpBonus() { //draws crackle effect for bonus power ups + // ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6; + // for (let i = 0, len = powerUp.length; i < len; ++i) { + // ctx.beginPath(); + // ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI); + // ctx.fillStyle = powerUp[i].color; + // ctx.fill(); + // } + // ctx.globalAlpha = 1; + // for (let i = 0, len = powerUp.length; i < len; ++i) { + // if (powerUp[i].isDuplicated && Math.random() < 0.1) { + // //draw electricity + // const mag = 5 + powerUp[i].size / 5 + // let unit = Vector.rotate({ + // x: mag, + // y: mag + // }, 2 * Math.PI * Math.random()) + // let path = { + // x: powerUp[i].position.x + unit.x, + // y: powerUp[i].position.y + unit.y + // } + // ctx.beginPath(); + // ctx.moveTo(path.x, path.y); + // for (let i = 0; i < 6; i++) { + // unit = Vector.rotate(unit, 3 * (Math.random() - 0.5)) + // path = Vector.add(path, unit) + // ctx.lineTo(path.x, path.y); + // } + // ctx.lineWidth = 0.5 + 2 * Math.random(); + // ctx.strokeStyle = "#000" + // ctx.stroke(); + // } + // } + // }, // map: function() { // ctx.beginPath(); diff --git a/js/spawn.js b/js/spawn.js index bc15deb..0d0073e 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -3025,14 +3025,14 @@ const spawn = { this.attraction(); }; }, - shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2), isBonusShield = false) { + shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2), isExtraShield = false) { if (this.allowShields && Math.random() < chance) { mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)"); let me = mob[mob.length - 1]; me.stroke = "rgb(220,220,255)"; Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion me.shield = true; - me.isBonusShield = isBonusShield //this prevents spamming with tech.isShieldAmmo + me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo me.collisionFilter.category = cat.mobShield me.collisionFilter.mask = cat.bullet; consBB[consBB.length] = Constraint.create({ diff --git a/js/tech.js b/js/tech.js index befd668..286a438 100644 --- a/js/tech.js +++ b/js/tech.js @@ -170,7 +170,7 @@ return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { - return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance + return (tech.isPowerUpsVanish ? 0.2 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.043 + tech.duplicateChance + m.duplicateChance }, maxDuplicationEvent() { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { @@ -821,7 +821,7 @@ { name: "electric reactive armor", // description: "explosions do no harm
while your energy is above 98%", - description: "harm from explosions is passively reduced
by 7% for every 10 stored energy", + description: "harm from explosions is passively reduced
by 6% for every 10 stored energy", maxCount: 1, count: 0, frequency: 2, @@ -1790,7 +1790,7 @@ count: 0, frequency: 2, allowed() { - return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 + return tech.isIceCrystals || tech.isSporeFreeze || tech.isIceField || tech.relayIce || tech.blockingIce > 1 || tech.iceIXOnDeath }, requires: "a localized freeze effect", effect() { @@ -1807,7 +1807,7 @@ count: 0, frequency: 2, allowed() { - return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 + return tech.isStunField || tech.isExplosionStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath }, requires: "a freezing or stunning effect", effect() { @@ -2762,13 +2762,12 @@ requires: "below 100% duplication chance", effect() { tech.duplicateChance += 0.075 - tech.maxDuplicationEvent() - simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw + powerUps.setDo(); //needed after adjusting duplication chance tech.addJunkTechToPool(12) }, remove() { tech.duplicateChance = 0 - if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal + powerUps.setDo(); //needed after adjusting duplication chance if (this.count > 1) tech.removeJunkTechFromPool(12) } }, @@ -2780,17 +2779,36 @@ frequency: 1, frequencyDefault: 1, allowed() { - return tech.duplicationChance() < 1 && level.levelsCleared < 6 + return tech.duplicationChance() < 1 }, requires: "below 100% duplication chance", effect: () => { - tech.isBayesian = true - simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw - tech.maxDuplicationEvent() + tech.isStimulatedEmission = true + powerUps.setDo(); //needed after adjusting duplication chance }, remove() { - tech.isBayesian = false - if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal + tech.isStimulatedEmission = false + powerUps.setDo(); //needed after adjusting duplication chance + } + }, + { + name: "metastability", + description: "20% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return tech.duplicationChance() < 1 + }, + requires: "below 100% duplication chance", + effect: () => { + tech.isPowerUpsVanish = true + powerUps.setDo(); //needed after adjusting duplication chance + }, + remove() { + tech.isPowerUpsVanish = false + powerUps.setDo(); //needed after adjusting duplication chance } }, { @@ -2801,18 +2819,18 @@ frequency: 1, frequencyDefault: 1, allowed() { - return tech.duplicationChance() < 1 && !tech.isDeterminism && level.levelsCleared < 4 + return tech.duplicationChance() < 1 && !tech.isDeterminism }, requires: "below 100% duplication chance, below level 5, not determinism", effect() { // tech.cancelCount = 0 tech.isCancelDuplication = true - simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw + powerUps.setDo(); //needed after adjusting duplication chance }, remove() { // tech.cancelCount = 0 tech.isCancelDuplication = false - if (tech.duplicationChance() === 0) simulation.draw.powerUp = simulation.draw.powerUpNormal + powerUps.setDo(); //needed after adjusting duplication chance } }, { @@ -2953,7 +2971,7 @@ simulation.makeTextLog(`m.research -= 2
${powerUps.research.count}`) const chanceStore = tech.duplicateChance - tech.duplicateChance = (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.045 + m.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance + tech.duplicateChance = (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.045 + m.duplicateChance + tech.duplicateChance * 2 //increase duplication chance to simulate doubling all 3 sources of duplication chance powerUps.spawn(m.pos.x, m.pos.y, "tech"); tech.duplicateChance = chanceStore }, @@ -3703,7 +3721,7 @@ }, remove() { tech.wavePacketFrequency = 0.088 //0.0968 //0.1012 //0.11 //0.088 //shorten wave packet - tech.wavePacketLength = 36 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets + tech.wavePacketLength = 34 //32.7 //31.3 //28.8 //36 //how many wave packets are released // double this to emit 2 packets tech.waveLengthRange = 130; } }, @@ -4818,7 +4836,7 @@ count: 0, frequency: 2, allowed() { - return tech.isIceField || tech.relayIce || tech.blockingIce + return tech.isIceField || tech.relayIce || tech.blockingIce || tech.iceIXOnDeath }, requires: "ice IX", effect() { @@ -6528,7 +6546,7 @@ isGunCycle: null, isFastFoam: null, isSporeGrowth: null, - isBayesian: null, + isStimulatedEmission: null, nailGun: null, nailInstantFireRate: null, isCapacitor: null, diff --git a/todo.txt b/todo.txt index ab4fbd9..26c1ceb 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,7 @@ ******************************************************** NEXT PATCH ******************************************************** - +tech: metastability - 20% dup chance, but duplicated powers up eventually explode +nerfed tech: electric reactive armor 6% (was 7%) explosion damage reduction for every 10 energy you currently have ******************************************************** BUGS ******************************************************** @@ -38,6 +39,14 @@ is there a way to check if the player is stuck inside the map or block ******************************************************** TODO ******************************************************** +make wave packets a tech + use the tech that makes the wave packets longer? + default wave can be two oscillating waves + +make beating the final boss without undefined feel like winning, not like dieing + +try making more things const to change the color to purple in simulation loop + power ups disappear after 3-5 seconds only apply to drops from killing mobs +duplication 20%