From 3e8f07ab04ebbf902e1584afaccbc09d6581b50c Mon Sep 17 00:00:00 2001 From: landgreen Date: Tue, 26 Jul 2022 08:26:05 -0700 Subject: [PATCH] patch field tech: patch - after cloaking recover 75% of last health lost using that much energy taking damage now forces decloaking field tech: dynamic equilibrium - increase damage by 5% the value of your last health loss foam has less velocity after a mob it's stuck to dies snakeBoss becomes vulnerable if you remove any of the first 3 body segments body segments have more health bug fix: quantum eraser now removes mobs in a more random order it used to have a too low chance to remove bosses --- js/bullet.js | 19 +++++-- js/index.js | 4 -- js/level.js | 18 +++--- js/player.js | 61 ++++++++++++-------- js/simulation.js | 1 - js/spawn.js | 114 ++++++++++++++++++++++++++++++------- js/tech.js | 145 +++++++++++++++++++++++++++-------------------- style.css | 2 + todo.txt | 85 +++++++++++++++------------ 9 files changed, 288 insertions(+), 161 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 8417c98..ae94732 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1450,7 +1450,7 @@ const b = { } if (tech.isFoamBall) { const radius = 5 + 8 * Math.random() - const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } for (let i = 0, len = 2 * this.mass; i < len; i++) { b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) } @@ -1732,7 +1732,7 @@ const b = { if (tech.isFoamBall) { const radius = 5 + 8 * Math.random() - const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } for (let i = 0, len = 2 * this.mass; i < len; i++) { b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) } @@ -3707,6 +3707,10 @@ const b = { } } this.targetVertex = bestVertex + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); } }, onEnd() {}, @@ -3778,6 +3782,10 @@ const b = { } else if (this.target !== null) { //look for a new target this.collisionFilter.category = cat.bullet; this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield + Matter.Body.setVelocity(this, { + x: this.target.velocity.x, + y: this.target.velocity.y + }); if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) { let targets = [] for (let i = 0, len = mob.length; i < len; i++) { @@ -5645,7 +5653,8 @@ const b = { } if (tech.isFoamBall) { const radius = 5 + 8 * Math.random() - const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + // const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } for (let i = 0, len = 6 * this.mass; i < len; i++) { b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) } @@ -5693,7 +5702,7 @@ const b = { } if (tech.isFoamBall) { const radius = 5 + 8 * Math.random() - const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } for (let i = 0, len = 6 * this.mass; i < len; i++) { b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) } @@ -5745,7 +5754,7 @@ const b = { } if (tech.isFoamBall) { const radius = 5 + 8 * Math.random() - const velocity = { x: Math.max(2, 10 - radius * 0.25), y: 0 } + const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } for (let i = 0, len = 6 * this.mass; i < len; i++) { b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) } diff --git a/js/index.js b/js/index.js index 6045d04..651329c 100644 --- a/js/index.js +++ b/js/index.js @@ -224,10 +224,6 @@ window.onresize = () => { for (let i = 0, len = tech.tech.length; i < len; i++) { if (!tech.tech[i].link) tech.tech[i].link = `${tech.tech[i].name}` } - - -//
effective defense: ${(1-simulation.dmgScale*m.harmReduction()).toPrecision(3)} -//
effective damage: ${(tech.damageFromTech() * m.dmgScale).toPrecision(3)} const build = { pauseGrid() { //left side diff --git a/js/level.js b/js/level.js index 4a48aa7..432ff4b 100644 --- a/js/level.js +++ b/js/level.js @@ -16,7 +16,7 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // simulation.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(8 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(4 * 4) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.maxHealth = m.health = 100 // powerUps.research.changeRerolls(100000) @@ -24,19 +24,19 @@ const level = { // powerUps.research.changeRerolls(100) // tech.tech[297].frequency = 100 // b.guns[0].ammo = 10000 - // m.setField("metamaterial cloaking") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole - // b.giveGuns("laser") //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 - // tech.giveTech("robotics") - // tech.giveTech("CPT symmetry"); - // tech.giveTech("lens"); - // tech.giveTech("robotics") + // m.setField("metamaterial cloaking") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass + // b.giveGuns("nail gun") //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 + // tech.giveTech("dynamic equilibrium") + // tech.giveTech("quantum eraser"); + // tech.giveTech("patch"); + // tech.giveTech("polyurethane foam") // for (let i = 0; i < 100; ++i) tech.giveTech("nail-bot") // for (let i = 0; i < 1; ++i) tech.giveTech("electric generator") // for (let i = 0; i < 9; i++) tech.giveTech("compound lens") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research"); - // spawn.starter(1900, -500) - // spawn.laserTargetingBoss(1900, -500) + // spawn.starter(1900, -500, 100) + // spawn.snakeBoss(1900, -500) // for (let i = 0; i < 10; ++i) spawn.grower(1900, -500) // level.testing(); //not in rotation, used for testing // for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); diff --git a/js/player.js b/js/player.js index 262fe1a..d404f1b 100644 --- a/js/player.js +++ b/js/player.js @@ -363,11 +363,8 @@ const m = { m.health = m.health * (1 + 0.5 * (Math.random() - 0.5)) if (m.health > 1) m.health = 1; m.displayHealth(); - //randomize field m.setField(Math.ceil(Math.random() * (m.fieldUpgrades.length - 1))) - - //removes guns and ammo b.inventory = []; b.activeGun = null; @@ -726,7 +723,11 @@ const m = { document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4); } - if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding + if (dmg > 0.03) { + m.lastHit = dmg; + if (dmg > 0.06 / m.holdingMassScale) m.drop(); //drop block if holding // m.holdingMassScale = 0.5 for most fields + if (m.isCloak) m.fireCDcycle = m.cycle //forced exit cloak + } const normalFPS = function() { if (m.defaultFPSCycle < m.cycle) { //back to default values simulation.fpsCap = simulation.fpsCapDefault @@ -908,6 +909,7 @@ const m = { fieldShieldingScale: 1, // fieldDamage: 1, isSneakAttack: false, + lastHit: 0, //stores value of last damage player took above a threshold, in m.damage sneakAttackCycle: 0, enterCloakCycle: 0, duplicateChance: 0, @@ -950,6 +952,7 @@ const m = { m.fieldShieldingScale = 1; m.fieldBlockCD = 10; m.fieldHarmReduction = 1; + m.lastHit = 0 m.isSneakAttack = false m.duplicateChance = 0 powerUps.setDupChance(); @@ -1015,7 +1018,7 @@ const m = { m.regenEnergy(); const xOff = m.pos.x - m.radius * m.maxEnergy const yOff = m.pos.y - 50 - ctx.fillStyle = "rgba(0, 0, 0, 0.3)" // + ctx.fillStyle = "rgba(0, 0, 0, 0.2)" // ctx.fillRect(xOff, yOff, 60 * m.maxEnergy, 10); ctx.fillStyle = "#fff" //m.cycle > m.lastKillCycle + 300 ? "#000" : "#fff" //"#fff"; ctx.fillRect(xOff, yOff, 60 * m.energy, 10); @@ -2750,39 +2753,27 @@ const m = { m.fieldFire = true; m.fieldMeterColor = "#333"; m.eyeFillColor = m.fieldMeterColor - // m.eyeFillColor = '#333' m.fieldPhase = 0; m.isCloak = false - // m.fieldDamage = 2.46 // 1 + 146/100 m.fieldDrawRadius = 0 m.isSneakAttack = true; - // m.sneakAttackCharge = 0; m.sneakAttackCycle = 0; m.enterCloakCycle = 0; - const drawRadius = 800 m.drawCloak = function() { m.fieldPhase += 0.007 const wiggle = 0.15 * Math.sin(m.fieldPhase * 0.5) ctx.beginPath(); ctx.ellipse(m.pos.x, m.pos.y, m.fieldDrawRadius * (1 - wiggle), m.fieldDrawRadius * (1 + wiggle), m.fieldPhase, 0, 2 * Math.PI); - // if (m.fireCDcycle > m.cycle && (input.field)) {} ctx.fillStyle = "#fff" ctx.lineWidth = 2; ctx.strokeStyle = "#000" ctx.stroke() - // ctx.fillStyle = "#fff" //`rgba(0,0,0,${0.5+0.5*m.energy})`; ctx.globalCompositeOperation = "destination-in"; ctx.fill(); ctx.globalCompositeOperation = "source-over"; ctx.clip(); } m.hold = function() { - // if (m.isCloak) { - // if (m.sneakAttackCharge < 120) m.sneakAttackCharge += 0.5 - // } else { - // if (m.sneakAttackCharge > 0) m.sneakAttackCharge-- - // } - if (m.isHolding) { m.drawHold(m.holdingTarget); m.holding(); @@ -2801,7 +2792,31 @@ const m = { if (!m.isCloak) { m.isCloak = true //enter cloak m.enterCloakCycle = m.cycle - // console.log(m.enterCloakCycle) + if (tech.isCloakHealLastHit && m.lastHit > 0) { + const heal = Math.min(0.75 * m.lastHit, m.energy) + m.energy -= heal + simulation.drawList.push({ //add dmg to draw queue + x: m.pos.x, + y: m.pos.y, + radius: Math.sqrt(heal) * 200, + color: "rgba(0,255,200,0.6)", + time: 16 + }); + m.addHealth(heal); //heal from last hit + // if (tech.isEnergyHealth) { + // simulation.drawList.push({ //add dmg to draw queue + // x: m.pos.x, + // y: m.pos.y, + // radius: Math.sqrt(heal) * 200, + // color: "#0ad", //simulation.mobDmgColor + // time: 16 + // }); + // m.energy += heal + // } else { + // } + m.lastHit = 0 + // simulation.makeTextLog(`m.health += ${(heal).toFixed(3)}`) //
${m.health.toFixed(3)} + } if (tech.isIntangible) { for (let i = 0; i < bullet.length; i++) { if (bullet[i].botType && bullet[i].botType !== "orbit") bullet[i].collisionFilter.mask = cat.map | cat.bullet | cat.mobBullet | cat.mobShield @@ -2841,12 +2856,12 @@ const m = { } } if (m.isCloak) { - this.fieldRange = this.fieldRange * 0.9 + 0.1 * drawRadius - m.fieldDrawRadius = this.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); + m.fieldRange = m.fieldRange * 0.9 + 80 + m.fieldDrawRadius = m.fieldRange * 0.88 //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); m.drawCloak() - } else if (this.fieldRange < 4000) { - this.fieldRange += 50 - m.fieldDrawRadius = this.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); + } else if (m.fieldRange < 4000) { + m.fieldRange += 50 + m.fieldDrawRadius = m.fieldRange //* Math.min(1, 0.3 + 0.5 * Math.min(1, energy * energy)); m.drawCloak() } if (tech.isIntangible) { diff --git a/js/simulation.js b/js/simulation.js index d2fc0af..7f483bf 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -980,7 +980,6 @@ const simulation = { } if (tech.isQuantumEraser) { - // tech.quantumEraserCount = 0 for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].isDropPowerUp && mob[i].alive) tech.quantumEraserCount++ } diff --git a/js/spawn.js b/js/spawn.js index bd19022..6c63036 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -48,7 +48,13 @@ const spawn = { }, quantumEraserCheck() { //remove mobs from tech: quantum eraser if (tech.isQuantumEraser && tech.quantumEraserCount > 0) { - for (let i = 0, len = mob.length; i < len; i++) { + + //start at a random location in array + const randomMiddle = Math.floor(mob.length * Math.random()) + let i = randomMiddle + for (let j = 0; j < mob.length; j++) { + i++ + if (i > mob.length - 1) i = 0 if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss if (mob[i].isFinalBoss) { tech.quantumEraserCount = 0; @@ -86,6 +92,47 @@ const spawn = { if (tech.quantumEraserCount < 1) break } } + + + + // for (let i = 0, len = mob.length; i < len; i++) { + // if (mob[i].isDropPowerUp && mob[i].alive) { //&& !mob[i].isBoss + // if (mob[i].isFinalBoss) { + // tech.quantumEraserCount = 0; + // return + // } else { + // tech.isQuantumEraserDuplication = true + // mob[i].death() + // tech.isQuantumEraserDuplication = false + // } + // //graphics + // const color = 'rgba(255,255,255, 0.8)' + // simulation.drawList.push({ + // x: mob[i].position.x, + // y: mob[i].position.y, + // radius: mob[i].radius * 2, + // color: color, //"rgba(0,0,0,0.6)", + // time: 60 + // }); + // simulation.drawList.push({ + // x: mob[i].position.x, + // y: mob[i].position.y, + // radius: mob[i].radius * 1, + // color: color, //"rgba(0,0,0,0.85)", + // time: 90 + // }); + // simulation.drawList.push({ + // x: mob[i].position.x, + // y: mob[i].position.y, + // radius: mob[i].radius * 0.5, + // color: color, //"rgb(0,0,0)", + // time: 120 + // }); + // tech.quantumEraserCount-- + // simulation.makeTextLog(`tech.quantumEraserCount = ${tech.quantumEraserCount}`) + // if (tech.quantumEraserCount < 1) break + // } + // } } }, randomMob(x, y, chance = 1) { @@ -2786,6 +2833,7 @@ const spawn = { mobs.spawn(x, y, 3, radius, "rgb(0,235,255)"); let me = mob[mob.length - 1]; me.isBoss = true; + me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front Matter.Body.rotate(me, Math.random() * Math.PI * 2); @@ -2808,11 +2856,29 @@ const spawn = { me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; - me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.targetingCount = 0; me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty) me.do = function() { - // this.armor(); + + // //wings + // const wing = (simulation.cycle % 9) > 4 ? this.vertices[0] : this.vertices[2] //Vector.add(this.position, { x: 100, y: 0 }) + // const radius = 200 + // //draw + // ctx.beginPath(); + // ctx.arc(wing.x, wing.y, radius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay + // ctx.fillStyle = "rgba(0,235,255,0.3)"; + // ctx.fill(); + // //check damage + // const hitPlayer = Matter.Query.ray([player], this.position, wing, radius) + // if (hitPlayer.length && m.immuneCycle < m.cycle) { + // m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + // m.damage(0.02 * simulation.dmgScale); + // } + + + + + this.seePlayerByLookingAt(); this.checkStatus(); this.attraction(); @@ -5566,7 +5632,7 @@ const spawn = { mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; - me.accelMag = 0.0003 + 0.0002 * Math.sqrt(simulation.accelScale) + me.accelMag = 0.0004 + 0.0002 * Math.sqrt(simulation.accelScale) me.memory = 250; me.laserRange = 500; Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger @@ -5576,13 +5642,12 @@ const spawn = { me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) - for (let i = 0; i < mob.length; i++) { //wake up tail mobs - if (mob[i].isSnakeTail && mob[i].alive) { - mob[i].isSnakeTail = false; - mob[i].do = mob[i].doActive - // mob[i].removeConsBB(); + me.onDeath = function() { + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + for (let i = 0, len = mob.length; i < len; i++) { + if (this.id === mob[i].snakeHeadID && mob[i].alive) mob[i].death() } - } + }; }; me.canFire = false; me.closestVertex1 = 0; @@ -5660,7 +5725,7 @@ const spawn = { spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), i === 0 ? 25 : 20); // mag -= 5 // spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20); - if (i === 0) mob[mob.length - 1].snakeHeadID = me.id + if (i < 3) mob[mob.length - 1].snakeHeadID = me.id mob[mob.length - 1].previousTailID = previousTailID previousTailID = mob[mob.length - 1].id } @@ -5703,9 +5768,9 @@ const spawn = { mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; - me.accelMag = 0.00045 + 0.0002 * Math.sqrt(simulation.accelScale) + me.accelMag = 0.0009 + 0.0002 * Math.sqrt(simulation.accelScale) me.memory = 250; - me.laserRange = 500; + me.laserRange = 400; Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger me.startingDamageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0 @@ -5713,6 +5778,9 @@ const spawn = { me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) + for (let i = 0, len = mob.length; i < len; i++) { + if (this.id === mob[i].snakeHeadID && mob[i].alive) mob[i].death() + } }; me.do = function() { this.seePlayerByHistory() @@ -5738,7 +5806,7 @@ const spawn = { angle -= 0.15 + i * 0.008 mag -= (i < 2) ? -15 : 5 spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), i === 0 ? 25 : 20); - if (i === 0) mob[mob.length - 1].snakeHeadID = me.id + if (i < 3) mob[mob.length - 1].snakeHeadID = me.id mob[mob.length - 1].previousTailID = previousTailID previousTailID = mob[mob.length - 1].id } @@ -5775,11 +5843,13 @@ const spawn = { mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); let me = mob[mob.length - 1]; me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body - me.accelMag = 0.0007 * simulation.accelScale; + me.damageReduction = 0.2 + Matter.Body.setDensity(me, 0.005); //normal is 0.001 + + // me.accelMag = 0.0007 * simulation.accelScale; me.leaveBody = Math.random() < 0.33 ? true : false; me.showHealthBar = false; me.isDropPowerUp = false; - Matter.Body.setDensity(me, 0.005); //normal is 0.001 me.frictionAir = 0.015; me.isSnakeTail = true; me.stroke = "transparent" @@ -5792,16 +5862,16 @@ const spawn = { mob[i].damageReduction = mob[i].startingDamageReduction } } - }, 150); + }, 500); }; me.do = function() { this.checkStatus(); }; - me.doActive = function() { - this.checkStatus(); - this.alwaysSeePlayer(); - this.attraction(); - }; + // me.doActive = function() { + // this.checkStatus(); + // this.alwaysSeePlayer(); + // this.attraction(); + // }; }, tetherBoss(x, y, constraint, radius = 90) { // constrained mob boss for the towers level diff --git a/js/tech.js b/js/tech.js index 14832fc..7e6583f 100644 --- a/js/tech.js +++ b/js/tech.js @@ -239,7 +239,6 @@ const tech = { if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDamageForGuns) dmg *= 1 + 0.13 * b.inventory.length if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5 - if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (tech.isAcidDmg && m.health > 1) dmg *= 1.35; if (tech.isRerollDamage) dmg *= 1 + 0.038 * powerUps.research.count @@ -251,10 +250,10 @@ const tech = { if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2 if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165) if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.6 - // if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg if (m.isSneakAttack && m.sneakAttackCycle + Math.min(120, 0.5 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= tech.sneakAttackDmg - // if (m.isSneakAttack && m.sneakAttackCharge > 0) dmg *= tech.sneakAttackDmg if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 - m.harmReduction() + if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; + if (tech.isLastHitDamage && m.lastHit) dmg *= 1 + 5 * m.lastHit // if (!simulation.paused) m.lastHit = 0 return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { @@ -2115,24 +2114,6 @@ const tech = { tech.isHarmArmor = false; } }, - // { - // name: "radiative equilibrium", - // description: "for 10 seconds after receiving defense
increase damage by 200%", - // maxCount: 1, - // count: 0, - // frequency: 1, - // frequencyDefault: 1, - // allowed() { - // return true - // }, - // requires: "", - // effect() { - // tech.isHarmDamage = true; - // }, - // remove() { - // tech.isHarmDamage = false; - // } - // }, { name: "CPT symmetry", // description: "charge, parity, and time invert to undo defense
rewind (1.5—5) seconds for (66—220) energy", @@ -2272,42 +2253,42 @@ const tech = { } } }, - { - name: "weak interaction", - description: "for each unused power up at the end of a level
+10 maximum energy", // (up to 51 health per level)", - maxCount: 1, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { - return !tech.isDroneGrab - }, - requires: "not delivery drone", - effect() { - tech.isExtraMaxEnergy = true; //tracked by tech.extraMaxHealth - }, - remove() { - tech.isExtraMaxEnergy = false; - } - }, - { - name: "electroweak interaction", - description: "unused power ups at the end of a level
are still activated (selections are random)", - maxCount: 1, - count: 0, - frequency: 2, - frequencyDefault: 2, - allowed() { - return tech.isExtraMaxEnergy - }, - requires: "weak interaction", - effect() { - tech.isEndLevelPowerUp = true; - }, - remove() { - tech.isEndLevelPowerUp = false; - } - }, + // { + // name: "weak interaction", + // description: "for each unused power up at the end of a level
+10 maximum energy", // (up to 51 health per level)", + // maxCount: 1, + // count: 0, + // frequency: 1, + // frequencyDefault: 1, + // allowed() { + // return !tech.isDroneGrab + // }, + // requires: "not delivery drone", + // effect() { + // tech.isExtraMaxEnergy = true; //tracked by tech.extraMaxHealth + // }, + // remove() { + // tech.isExtraMaxEnergy = false; + // } + // }, + // { + // name: "electroweak interaction", + // description: "unused power ups at the end of a level
are still activated (selections are random)", + // maxCount: 1, + // count: 0, + // frequency: 2, + // frequencyDefault: 2, + // allowed() { + // return tech.isExtraMaxEnergy + // }, + // requires: "weak interaction", + // effect() { + // tech.isEndLevelPowerUp = true; + // }, + // remove() { + // tech.isEndLevelPowerUp = false; + // } + // }, { name: "electronegativity", description: "+1% damage per 8 stored energy", @@ -4107,7 +4088,7 @@ const tech = { { name: "spin-statistics", link: `spin-statistics`, - description: "invulnerable while firing the shotgun
shotgun has 50% fewer shots", + description: "after firing the shotgun you are invulnerable
shotgun has 50% fewer shots", isGunTech: true, maxCount: 1, count: 0, @@ -6665,8 +6646,8 @@ const tech = { isFieldTech: true, maxCount: 1, count: 0, - frequency: 1, - frequencyDefault: 1, + frequency: 2, + frequencyDefault: 2, allowed() { return m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" }, @@ -6678,6 +6659,26 @@ const tech = { tech.isHarmDamage = false; } }, + { + name: "dynamic equilibrium", + descriptionFunction() { return `increase damage by 5%
of your last ${tech.isEnergyHealth ? "energy" : "health"} loss` }, + // description: `increase damage by 500%
of your last health loss`, + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return (m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "negative mass" || m.fieldUpgrades[m.fieldMode].name === "standing wave") && !tech.isCloakHealLastHit + }, + requires: "negative mass, pilot wave, not patch", + effect() { + tech.isLastHitDamage = true; + }, + remove() { + tech.isLastHitDamage = false; + } + }, { name: "neutronium", description: `move and jump 25% slower
if your field is active +90% defense`, @@ -7347,6 +7348,26 @@ const tech = { } } }, + { + name: "patch", + link: `patch`, + description: "after cloaking recover 75% of your
last health loss using that much energy", + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 2, + frequencyDefault: 2, + allowed() { + return m.fieldUpgrades[m.fieldMode].name === "metamaterial cloaking" && !tech.isLastHitDamage && !tech.isEnergyHealth + }, + requires: "metamaterial cloaking, not dynamic equilibrium, mass-energy", + effect() { + tech.isCloakHealLastHit = true; + }, + remove() { + tech.isCloakHealLastHit = false; + } + }, { name: "dazzler", link: `dazzler`, @@ -10528,5 +10549,7 @@ const tech = { isLaserLens: null, laserCrit: null, isSporeColony: null, - isExtraBotOption: null + isExtraBotOption: null, + isLastHitDamage: null, + isCloakHealLastHit: null } \ No newline at end of file diff --git a/style.css b/style.css index 0eae605..18a785a 100644 --- a/style.css +++ b/style.css @@ -532,6 +532,8 @@ summary { transition: opacity 0.25s; pointer-events: none; user-select: none; + /* white-space: pre; + font-family: 'Menlo', 'Monaco', monospace; */ } /* color for in game console output */ diff --git a/todo.txt b/todo.txt index e82a0ca..536ca39 100644 --- a/todo.txt +++ b/todo.txt @@ -1,43 +1,62 @@ ******************************************************** NEXT PATCH ************************************************** -tech: electric generator - deflecting mobs generates energy for molecular assembler -tech: homeostasis - for each health below 100 +0.8% defense -tech: compound lens - +77% laser lens damage, +10° lens arc +field tech: patch - after cloaking recover 75% of last health lost using that much energy + taking damage now forces decloaking +field tech: dynamic equilibrium - increase damage by 5% the value of your last health loss -tech: robotics - 2 random bots, power up choices include a bot tech option -tech: open-source - 3 random bots, 4x bot tech frequency - renamed from previous robotics tech -slightly buffed all bot upgrades +foam has less velocity after a mob it's stuck to dies +snakeBoss becomes vulnerable if you remove any of the first 3 body segments + body segments have more health -+9% iceIX damage -catabolism uses energy instead of health if you have mass-energy -optical amplifier laser tech options include laser-bot -rule 90 and rule 30 looks better on more browsers, I hope +bug fix: quantum eraser now removes mobs in a more random order + it used to have a too low chance to remove bosses *********************************************************** TODO ***************************************************** +labs room: + low gravity zone + a button that toggles it on/off + +boss mechanics + bullets hit player and stay attached for 4-5 seconds, slowing player + hopperBullets? + black hole sucker effect on tail + flickering wings + draw pair of circles at 2 different locations, like beetle wings flapping + draw as ellipse + damage player if caught in wings + +tech: ricochet after nails do damage, the nail fires at a different nearby mobs + can reuse some targeted nail code + don't target 'who' you just damaged + +tech: You can place an extra perfect diamagnatism field on the map + +standing wave no longer pushes mobs away, but it can do damage to mobs caught in area effect +negative mass field does damage to mobs inside field + combine with standing wave effect? pilot wave? + store value of last hit health lost - names: patch - - tech: after cloaking regen 1/2 of the last hit - spawning a heal power up is annoying because you'd be cloaked, so direct healing? - time limit for effect? - while still under ambush damage? - tech: killing the mob that caused the last hit spawns a heal power up equal to 1/2 of last hit - time limit for effect? 3-4 seconds? - - tech: doing damage can recover up to 1/2 of the last hit - spawn a heal equal to 1/2 of last hit - time limit for effect? 3-4 seconds? - - tech increase damage by how much health was lost in last hit - +damage = 3x health lost? - if you went from 100 -> 60 health = +40%*3 = 120% damage - negative mass field tech? - too similar to radiative equilibrium - pick between them? + time limit for effect? + need to also store who hit player +add small SVG pics to in-game console + when? + one for each field? + use stuff on physics notes: +simulation.makeTextLog(` + + + + + + + + + + +`); path-finding build a path-finding map on level load @@ -49,12 +68,6 @@ path-finding drones? bots that can go far from player and return -tech ______ effect that last until you get hit - field or bots can check your health every cycle and see if it lower - if it's high update the health check value - effect: - +damage until getting hit for cloaking field - make plasma ball power up and block pick up still work when you have no no energy make a unique CD var for plasma ball?