diff --git a/img/modified Newtonian dynamics.webp b/img/MOND.webp similarity index 100% rename from img/modified Newtonian dynamics.webp rename to img/MOND.webp diff --git a/img/hidden-variable theory.webp b/img/hidden-variable theory.webp new file mode 100644 index 00000000..1db74f5d Binary files /dev/null and b/img/hidden-variable theory.webp differ diff --git a/img/polariton.webp b/img/polariton.webp new file mode 100644 index 00000000..b512f02d Binary files /dev/null and b/img/polariton.webp differ diff --git a/js/bullet.js b/js/bullet.js index b5ed3c1c..5459cac5 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -1498,7 +1498,7 @@ const b = { if (this.pickUpTarget) { if (tech.isReel && this.blockDist > 150) { // console.log(0.0003 * Math.min(this.blockDist, 1000)) - m.energy += 0.00113 * Math.min(this.blockDist, 800) //max 0.352 energy + m.energy += 0.00113 * Math.min(this.blockDist, 800) * level.isReducedRegen //max 0.352 energy simulation.drawList.push({ //add dmg to draw queue x: m.pos.x, y: m.pos.y, @@ -2925,7 +2925,7 @@ const b = { if (!who.isInvulnerable) { if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) { setTimeout(() => { - if (!who.alive) m.energy += tech.iceEnergy * 0.8 + if (!who.alive) m.energy += tech.iceEnergy * 0.8 * level.isReducedRegen }, 10); } mobs.statusSlow(who, tech.iceIXFreezeTime) @@ -4683,7 +4683,7 @@ const b = { if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250 && m.immuneCycle < m.cycle) { //give energy Matter.Body.setAngularVelocity(this, this.spin) if (this.isUpgraded) { - m.energy += 0.12 + m.energy += 0.12 * level.isReducedRegen simulation.drawList.push({ //add dmg to draw queue x: this.position.x, y: this.position.y, @@ -4692,7 +4692,7 @@ const b = { time: simulation.drawTime }); } else { - m.energy += 0.04 + m.energy += 0.04 * level.isReducedRegen simulation.drawList.push({ //add dmg to draw queue x: this.position.x, y: this.position.y, @@ -4705,7 +4705,7 @@ const b = { } if (!m.isCloak) { //if cloaking field isn't active - const size = 33 + const size = 33 - 6 * isKeep q = Matter.Query.region(mob, { min: { x: this.position.x - size, @@ -4760,7 +4760,7 @@ const b = { minDmgSpeed: 2, // lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20, lastLookCycle: simulation.cycle + 60 * Math.random(), - delay: Math.floor((tech.isNailBotUpgrade ? 22 : 85)), + delay: Math.floor((tech.isNailBotUpgrade ? 22 : 85) + 10 * isKeep), acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, endCycle: Infinity, @@ -4895,7 +4895,7 @@ const b = { lookFrequency: 60 + Math.floor(17 * Math.random()) - 50 * tech.isFoamBotUpgrade, cd: 0, fireCount: 0, - fireLimit: 5 + 2 * tech.isFoamBotUpgrade, + fireLimit: 5 + 2 * tech.isFoamBotUpgrade - isKeep, delay: Math.floor((200 + (tech.isFoamBotUpgrade ? 0 : 200))),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move @@ -4968,7 +4968,7 @@ const b = { lookFrequency: 17 + Math.floor(7 * Math.random()) - 3 * tech.isSoundBotUpgrade, cd: 0, fireCount: 0, - fireLimit: 5, + fireLimit: 5 - isKeep, delay: Math.floor(140),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move @@ -5136,7 +5136,7 @@ const b = { lookFrequency: 20 + Math.floor(7 * Math.random()) - 13 * tech.isLaserBotUpgrade, range: (600 + 375 * tech.isLaserBotUpgrade) * (1 + 0.12 * Math.random()), drainThreshold: 0.15 + 0.5 * Math.random() + (tech.isEnergyHealth ? 0.3 : 0),// laser bot will not attack if the player is below this energy - drain: (0.57 - 0.43 * tech.isLaserBotUpgrade) * tech.laserDrain, + drain: (0.57 - 0.43 * tech.isLaserBotUpgrade + isKeep * 0.08) * tech.laserDrain, laserDamage: 0.75 + 0.75 * tech.isLaserBotUpgrade, endCycle: Infinity, classType: "bullet", @@ -5313,7 +5313,7 @@ const b = { restitution: 1, dmg: 0, minDmgSpeed: 0, - lookFrequency: 43 + Math.floor(7 * Math.random()) - 13 * tech.isBoomBotUpgrade, + lookFrequency: 43 + Math.floor(7 * Math.random()) - 15 * tech.isBoomBotUpgrade, acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), attackAcceleration: 0.012 + 0.005 * tech.isBoomBotUpgrade, range: 500 * (1 + 0.1 * Math.random()) + 250 * tech.isBoomBotUpgrade + !isKeep * 100, @@ -5443,11 +5443,7 @@ const b = { const DIST = Vector.magnitude(sub); const unit = Vector.normalise(sub) if (DIST < tech.isPlasmaRange * 450 && m.energy > this.drainThreshold) { - m.energy -= 0.0013 //0.004; //normal plasma field is 0.00008 + m.fieldRegen = 0.00108 - // if (m.energy < 0) { - // m.fieldCDcycle = m.cycle + 120; - // m.energy = 0; - // } + m.energy -= 0.001 //calculate laser collision let best; let range = tech.isPlasmaRange * (120 + 300 * Math.sqrt(Math.random())) @@ -5466,9 +5462,9 @@ const b = { // Matter.Body.applyForce(best.who, path[1], force) //push mobs away if (best.who.speed > 3) { - const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.005 * Math.min(5, best.who.mass)) + const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.004 * Math.min(5, best.who.mass)) Matter.Body.applyForce(best.who, path[1], force) - Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.4, y: best.who.velocity.y * 0.4 }); + Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.5, y: best.who.velocity.y * 0.5 }); } else { const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) Matter.Body.applyForce(best.who, path[1], force) @@ -5558,7 +5554,7 @@ const b = { } } }, - range: 190 + 170 * tech.isOrbitBotUpgrade + !isKeep * 60 * (0.5 - Math.random()), //range is set in bot upgrade too! + range: 160 + 170 * tech.isOrbitBotUpgrade + !isKeep * 100 * (0.5 - Math.random()), //range is set in bot upgrade too! orbitalSpeed: 0, phase: 2 * Math.PI * Math.random(), do() { @@ -7211,8 +7207,6 @@ const b = { const DRAIN = (tech.isRailEnergy ? 0 : 0.002) //exit railgun charging without firing if (m.energy < DRAIN) { - // m.energy += 0.025 + this.charge * 22 * this.drain - // m.energy -= this.drain m.fireCDcycle = m.cycle + 120; // cool down if out of energy this.endCycle = 0; this.charge = 0 @@ -7292,7 +7286,7 @@ const b = { const recoil = Vector.mult(Vector.normalise(Vector.sub(where, m.pos)), m.crouch ? 0.03 : 0.06) player.force.x -= recoil.x player.force.y -= recoil.y - const harpoonSize = tech.isLargeHarpoon ? 1 + 0.1 * Math.sqrt(this.ammo) : 1 + const harpoonSize = tech.isLargeHarpoon ? 1 + 0.07 * Math.sqrt(this.ammo) : 1 const thrust = 0.15 * (this.charge) if (tech.extraHarpoons) { let targetCount = 0 @@ -7452,10 +7446,7 @@ const b = { if (tech.extraHarpoons && !m.crouch) { //multiple harpoons const SPREAD = 0.2 let angle = m.angle - SPREAD * tech.extraHarpoons / 2; - const dir = { - x: Math.cos(angle), - y: Math.sin(angle) - }; //make a vector for the player's direction of length 1; used in dot product + const dir = { x: Math.cos(angle), y: Math.sin(angle) }; //make a vector for the player's direction of length 1; used in dot product const range = 450 * (tech.isFilament ? 1 + 0.012 * Math.min(110, this.ammo) : 1) let targetCount = 0 for (let i = 0, len = mob.length; i < len; ++i) { diff --git a/js/engine.js b/js/engine.js index 59427d0f..5a8f5442 100644 --- a/js/engine.js +++ b/js/engine.js @@ -120,7 +120,7 @@ function collisionChecks(event) { simulation.trails(90) simulation.inGameConsole(`simulation.amplitude = ${Math.random()}`); } - if (tech.isPiezo) m.energy += 20.48; + if (tech.isPiezo) m.energy += 20.48 * level.isReducedRegen; if (tech.isCouplingNoHit && m.coupling > 0) { m.couplingChange(-3) @@ -162,10 +162,12 @@ function collisionChecks(event) { const maxCount = 10 + 3 * tech.extraHarpoons //scale the number of hooks fired let count = maxCount - 1 const angle = Math.atan2(mob[k].position.y - player.position.y, mob[k].position.x - player.position.x); - b.harpoon(m.pos, mob[k], angle, 0.75, true, 7) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { + + const mass = 0.75 * (tech.isLargeHarpoon ? 1 + 0.05 * Math.sqrt(this.ammo) : 1) + b.harpoon(m.pos, mob[k], angle, mass, true, 7) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) { bullet[bullet.length - 1].drain = 0 for (; count > 0; count--) { - b.harpoon(m.pos, mob[k], angle + count * 2 * Math.PI / maxCount, 0.75, true, 7) + b.harpoon(m.pos, mob[k], angle + count * 2 * Math.PI / maxCount, mass, true, 7) bullet[bullet.length - 1].drain = 0 } } diff --git a/js/index.js b/js/index.js index e1f2b9a5..d36ff1b0 100644 --- a/js/index.js +++ b/js/index.js @@ -138,7 +138,8 @@ function beforeUnloadEventListener(event) { event.preventDefault(); if (tech.isExitPrompt) { tech.damage *= 1.25 - simulation.inGameConsole(`damage *= ${1.25}`) + // simulation.inGameConsole(`damage *= ${1.25}`) + simulation.inGameConsole(`tech.damage *= ${1.25} //beforeunload`); if (Math.random() < 0.25) { removeEventListener('beforeunload', beforeUnloadEventListener); } @@ -490,7 +491,7 @@ const build = { level ${(simulation.dmgScale).toPrecision(4)}x
health (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)}) ${powerUps.research.count} ${powerUps.orb.research()} -
energy (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000).toFixed(0)}/s) +
energy (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000 * level.isReducedRegen).toFixed(0)}/s) ${tech.totalCount} ${powerUps.orb.tech()}
fire rate ${(1 / b.fireCDscale).toFixed(2)}x mass ${player.mass.toFixed(1)} diff --git a/js/level.js b/js/level.js index 76420053..18ee2452 100644 --- a/js/level.js +++ b/js/level.js @@ -54,7 +54,7 @@ const level = { // for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 3; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 50, "boost", false); // spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing - // level.satellite(); + // level.heal(); level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** @@ -129,7 +129,9 @@ const level = { powerUps.directSpawn(flip * localSettings.entanglement.position.x, localSettings.entanglement.position.y, "entanglement", false); } level.newLevelOrPhase() - if (!simulation.isTraining) { + if (simulation.isTraining) { + simulation.difficultyMode = 2 + } else { simulation.inGameConsole(`level.onLevel = "${level.levels[level.onLevel]}"`); document.title = "n-gon: " + level.levelAnnounce(); } @@ -332,6 +334,15 @@ const level = { constraintDescription1: "", //used in pause menu and console constraintDescription2: "", constraint: [ + { + description: "0.5x energy regen", + effect() { + level.isReducedRegen = 0.5 + }, + remove() { + level.isReducedRegen = 1 + } + }, { description: "0.5x max health", effect() { @@ -351,7 +362,7 @@ const level = { } }, { - description: "periodically spawn WIMPs", + description: "after 30 seconds spawn WIMPs", effect() { simulation.ephemera.push({ name: "WIMPS", @@ -360,7 +371,7 @@ const level = { do() { this.time++ if (level.levels[level.onLevel] === this.levelName) { - if (!(this.time % 900)) spawn.WIMP(level.enter.x, level.enter.y) + if (this.time > 1800 && !(this.time % 360)) spawn.WIMP(level.enter.x, level.enter.y) } else { simulation.removeEphemera(this.name); } @@ -383,7 +394,7 @@ const level = { } }, { - description: "mobs heal for your lost health", + description: "mobs heal after you take damage", effect() { level.isMobHealPlayerDamage = true }, @@ -400,16 +411,16 @@ const level = { level.isMobDeathHeal = false } }, - { - description: "full damage taken after boss dies", - // description: "after boss dies damage taken = 1", - effect() { - level.noDefenseSetting = 1 //defense goes to zero once equal to 2 - }, - remove() { - level.noDefenseSetting = 0 - } - }, + // { + // description: "full damage taken after boss dies", + // // description: "after boss dies damage taken = 1", + // effect() { + // level.noDefenseSetting = 1 //defense goes to zero once equal to 2 + // }, + // remove() { + // level.noDefenseSetting = 0 + // } + // }, { description: "4x shielded mobs", effect() { @@ -420,9 +431,9 @@ const level = { } }, { - description: "50% JUNK chance", + description: "40% JUNK chance", effect() { - level.junkAdded = 0.5 + level.junkAdded = 0.4 }, remove() { level.junkAdded = 0 @@ -542,13 +553,14 @@ const level = { is2xAmmo: false, isReducedEnergy: false, isSlowBots: false, - noDefenseSetting: 0, + // noDefenseSetting: 0, isMobDeathHeal: false, isMobHealPlayerDamage: false, isNoDamage: false, noDamageCycle: 0, reducedHealthLost: 0, isReducedHealth: false, + isReducedRegen: 1, levelAnnounce() { const cheating = simulation.isCheating ? "(testing)" : "" if (level.levelsCleared === 0) { @@ -1239,7 +1251,7 @@ const level = { ctx.moveTo(x, y + height / 2); ctx.lineTo(x, maxHeight - height / 2); ctx.strokeStyle = `rgba(0,0,0,0.2)` - // ctx.lineWidth = "3" + ctx.lineWidth = "2" ctx.stroke(); //draw body @@ -35293,9 +35305,9 @@ const level = { spawn.mapRect(1375, -16, 50, 50); spawn.mapRect(1400, -8, 50, 25); spawn.mapRect(750, -24, 650, 100); - powerUps.directSpawn(875, -40, "heal", false, null, 15); - powerUps.directSpawn(1075, -50, "heal", false, null, 25); - powerUps.directSpawn(1275, -65, "heal", false, null, 35); + powerUps.directSpawn(875, -40, "heal", false, 15); + powerUps.directSpawn(1075, -50, "heal", false, 25); + powerUps.directSpawn(1275, -65, "heal", false, 35); const door = level.door(1612.5, -175, 25, 190, 185, 3) spawn.mapRect(1600, -1200, 500, 850); //exit roof diff --git a/js/mob.js b/js/mob.js index d4ecd86c..01a7f049 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1085,7 +1085,7 @@ const mobs = { if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 33% dmg at max range of 3000 dmg *= this.damageReduction //energy and heal drain should be calculated after damage boosts - if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon + if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon * level.isReducedRegen dmg /= Math.sqrt(this.mass) } @@ -1142,9 +1142,10 @@ const mobs = { if (this.isDropPowerUp) { if (level.isMobDeathHeal) { for (let i = 0; i < mob.length; i++) { - if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 1000000 && mob[i].alive) { //1000 + if (Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)) < 500000 && mob[i].alive) { //700 if (mob[i].health < 1) { - mob[i].health = 1 + mob[i].health += 0.33 + this.isBoss + if (mob[i].health > 1) mob[i].health = 1 simulation.drawList.push({ x: mob[i].position.x, y: mob[i].position.y, @@ -1304,9 +1305,6 @@ const mobs = { tech.cloakDuplication -= 0.01 powerUps.setPowerUpMode(); //needed after adjusting duplication chance } - if (level.noDefenseSetting && this.isBoss) { - level.noDefenseSetting = 2 - } } else if (tech.isShieldAmmo && this.shield && this.shieldCount === 1) { let type = tech.isEnergyNoAmmo ? "heal" : "ammo" if (Math.random() < 0.4) { diff --git a/js/player.js b/js/player.js index 90fe921e..9bd7a427 100644 --- a/js/player.js +++ b/js/player.js @@ -542,6 +542,8 @@ const m = { m.maxHealth *= 0.5 } document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px` + document.getElementById("defense-bar").style.width = Math.floor(300 * m.maxHealth * (1 - m.defense())) + "px"; + if (isMessage) simulation.inGameConsole(`m.maxHealth = ${m.maxHealth.toFixed(2)}`) if (m.health > m.maxHealth) m.health = m.maxHealth; m.displayHealth(); @@ -551,8 +553,8 @@ const m = { lastCalculatedDamage: 0, //used to decided if damage bar needs to be redrawn (in simulation.checks) lastCalculatedDefense: 0, //used to decided if defense bar needs to be redrawn (in simulation.checks) defense() { - if (level.noDefenseSetting === 2) return 1 //zero defense constraint let dmg = 1 + if (powerUps.boost.isDefense && powerUps.boost.endCycle > simulation.cycle) dmg *= 0.3 if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.3 if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075); if (tech.isZeno) dmg *= 0.15 @@ -794,7 +796,7 @@ const m = { color: "rgba(0,255,100,0.5)", time: 10 }); - mob[i].health += dmg * 10 + mob[i].health += dmg * 7 if (mob[i].health > 1) mob[i].health = 1 } } @@ -2509,11 +2511,11 @@ const m = { } }, regenEnergy() { //used in drawRegenEnergy // rewritten by some tech - if (m.immuneCycle < m.cycle && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen; + if (m.immuneCycle < m.cycle && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen * level.isReducedRegen; if (m.energy < 0) m.energy = 0 }, regenEnergyDefault() { - if (m.immuneCycle < m.cycle && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen; + if (m.immuneCycle < m.cycle && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen * level.isReducedRegen; if (m.energy < 0) m.energy = 0 }, lookingAt(who) { @@ -2696,7 +2698,7 @@ const m = { if (tech.isTokamak && m.throwCharge > 4) { //remove the block body and pulse in the direction you are facing //m.throwCharge > 5 seems to be when the field full colors in a block you are holding m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds - if (m.immuneCycle < m.cycle) m.energy += 0.25 * Math.sqrt(m.holdingTarget.mass) * Math.min(5, m.throwCharge) + if (m.immuneCycle < m.cycle) m.energy += 0.25 * Math.sqrt(m.holdingTarget.mass) * Math.min(5, m.throwCharge) * level.isReducedRegen m.throwCharge = 0; m.definePlayerMass() //return to normal player mass //remove block before pulse, so it doesn't get in the way @@ -3051,7 +3053,7 @@ const m = { m.pushMass(mob[i]); if (tech.deflectEnergy && !mob[i].isInvulnerable && !mob[i].isShielded) { - m.energy += tech.deflectEnergy + m.energy += tech.deflectEnergy * level.isReducedRegen } } } @@ -5049,7 +5051,7 @@ const m = { Matter.Composite.remove(engine.world, body[i]); body.splice(i, 1); m.fieldRange *= 0.8 - if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling + if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling * level.isReducedRegen if (tech.isWormholeWorms) { //pandimensional spermia b.worm(Vector.add(m.hole.pos2, Vector.rotate({ x: m.fieldRange * 0.4, y: 0 }, 2 * Math.PI * Math.random()))) Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -10)); @@ -5071,10 +5073,8 @@ const m = { Matter.Composite.remove(engine.world, body[i]); body.splice(i, 1); m.fieldRange *= 0.8 - // if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2 - // if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.5 - if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling - if (m.fieldMode === 0 || m.fieldMode === 9) m.energy += 0.02 * m.coupling + if ((m.fieldMode === 0 || m.fieldMode === 9) && m.immuneCycle < m.cycle) m.energy += 0.02 * m.coupling * level.isReducedRegen + if (m.fieldMode === 0 || m.fieldMode === 9) m.energy += 0.02 * m.coupling * level.isReducedRegen if (tech.isWormholeWorms) { //pandimensional spermia b.worm(Vector.add(m.hole.pos1, Vector.rotate({ x: m.fieldRange * 0.4, @@ -5825,7 +5825,7 @@ const m = { return } m.damage(dmg); - if (tech.isPiezo) m.energy += 20.48; + if (tech.isPiezo) m.energy += 20.48 * level.isReducedRegen; if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(); if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles diff --git a/js/powerup.js b/js/powerup.js index 3bc17185..4f3af638 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -503,6 +503,7 @@ const powerUps = { endCycle: 0, duration: null, //set by "tech: band gap" damage: null, //set by "tech: band gap" + isDefense: false, effect() { powerUps.animatePowerUpGrab('rgba(255, 0, 0, 0.5)') powerUps.boost.endCycle = simulation.cycle + Math.floor(Math.max(0, powerUps.boost.endCycle - simulation.cycle) * 0.6) + powerUps.boost.duration //duration+seconds plus 2/3 of current time left @@ -605,7 +606,7 @@ const powerUps = { } if (tech.isResearchDamage) { tech.damage *= 1.05 - simulation.inGameConsole(`1.05x damage`); + simulation.inGameConsole(`tech.damage *= ${1.05} //peer review`); tech.addJunkTechToPool(0.01) } powerUps.research.currentRerollCount++ @@ -1448,7 +1449,7 @@ const powerUps = { onPickUp(who) { powerUps.research.currentRerollCount = 0 if (tech.isTechDamage && who.name === "tech") m.damage(0.1) - if (tech.isMassEnergy) m.energy += 2; + if (tech.isMassEnergy) m.energy += 2 * level.isReducedRegen; if (tech.isMineDrop && bullet.length < 150 && Math.random() < 0.5) { if (tech.isLaserMine && input.down) { b.laserMine(who.position) diff --git a/js/simulation.js b/js/simulation.js index c991faba..86dc5e99 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -1012,7 +1012,7 @@ const simulation = { if (isNaN(player.position.x)) m.death(); if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) { - m.energy += m.maxEnergy * 0.05 + m.energy += m.maxEnergy * 0.05 * level.isReducedRegen simulation.drawList.push({ //add dmg to draw queue x: m.pos.x, y: m.pos.y - 45, @@ -1024,7 +1024,7 @@ const simulation = { if (tech.isHealthRecovery) { if (tech.isEnergyHealth) { if (m.immuneCycle < m.cycle) { - m.energy += m.maxEnergy * 0.005 + m.energy += m.maxEnergy * 0.005 * level.isReducedRegen simulation.drawList.push({ //add dmg to draw queue x: m.pos.x, y: m.pos.y, diff --git a/js/spawn.js b/js/spawn.js index 98f67757..b0f42072 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -144,7 +144,7 @@ const spawn = { } me.do = function () { if (!simulation.isTimeSkipping) { - const scale = (tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 1.6 : 1 + const scale = ((tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 1.6 : 1) * level.isReducedRegen const sine = Math.sin(simulation.cycle * 0.015) this.radius = 111 * tech.isDarkStar + 370 * (1 + 0.1 * sine) //chase player @@ -7726,7 +7726,7 @@ const spawn = { }; }, //chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance() - shield(target, x, y, chance = (level.isMobShields ? 3.25 : 1) * Math.min(0.02 + simulation.difficulty * 0.005, 0.2)) { + shield(target, x, y, chance = (level.isMobShields ? 4 : 1) * Math.min(0.02 + simulation.difficulty * 0.005, 0.2)) { 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]; diff --git a/js/tech.js b/js/tech.js index 1b2c5264..fc7ca793 100644 --- a/js/tech.js +++ b/js/tech.js @@ -149,6 +149,11 @@ const tech = { if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false //stops the bug where you can't gets stacks of tech you take with decoherence, I think + if (tech.isDamageFieldTech && tech.tech[index].isFieldTech) { + tech.damage *= 1.15 + // simulation.inGameConsole(`damage *= ${1.05}`) + simulation.inGameConsole(`tech.damage *= ${1.1} //hidden-variable theory`); + } tech.tech[index].effect(); //give specific tech tech.tech[index].count++ if (!tech.tech[index].isInstant) tech.totalCount++ //used in power up randomization @@ -717,7 +722,7 @@ const tech = { }, { name: "ordnance", - description: `spawn ${powerUps.orb.gun()} and get 2x frequency for ${powerUps.orb.gunTech()}
+6% JUNK chance`, + description: `spawn ${powerUps.orb.gun()} and get 2x frequency for ${powerUps.orb.gunTech()}
+6% JUNK choices`, maxCount: 1, count: 0, frequency: 1, @@ -1255,28 +1260,34 @@ const tech = { let totalRate = 1 for (let i = 0; i < this.totalRate.length; i++) totalRate *= this.totalRate[i] let currentRate = "" - if (this.count) currentRate = `
(${(totalRate).toFixed(2)}x)` - return `randomly gain between 1x and 1.5x fire rate` + currentRate + if (this.count) currentRate = `(${(totalRate).toFixed(2)}x)` + return `randomly gain between 1x and 2x fire rate
+5% JUNK choices` + currentRate }, maxCount: 9, count: 0, frequency: 1, frequencyDefault: 1, allowed() { - return true + return tech.junkChance < 1 }, requires: "", totalRate: [], //tracks the random damage upgrades so it can be removed and in descriptionFunction effect() { - const rate = (Math.floor((Math.random() * 0.5 + 1) * 100)) / 100 + const rate = (Math.floor((Math.random() + 1) * 100)) / 100 tech.fireRate /= rate this.totalRate.push(rate) b.setFireCD(); simulation.inGameConsole(`tech.fireRate *= ${rate} //heuristics`); + this.refundAmount += tech.addJunkTechToPool(0.05) }, + refundAmount: 0, remove() { if (this.count && m.alive) { for (let i = 0; i < this.totalRate.length; i++) tech.fireRate *= this.totalRate[i] + if (this.refundAmount > 0) { + tech.removeJunkTechFromPool(this.refundAmount) + this.refundAmount = 0 + } } this.totalRate.length = 0 b.setFireCD(); @@ -1460,7 +1471,9 @@ const tech = { { name: "band gap", descriptionFunction() { - return `${powerUps.orb.boost(1)} give 1.77x damage
but their duration is reduced by 1 second` + // return `${powerUps.orb.boost(1)} give ${(1 + powerUps.boost.damage).toFixed(2)}x ${(1 + powerUps.boost.damage + 0.77).toFixed(2)}x damage
but their duration is reduced by 1 second` + // const predict = this.count === 0 ? `${(1 + powerUps.boost.damage).toFixed(2)}x` : `` + return `${powerUps.orb.boost(1)} give an additional ${(1 + 0.75).toFixed(2)}x damage
but their duration is reduced by 1 second` }, maxCount: 9, count: 1, @@ -1472,13 +1485,33 @@ const tech = { requires: "exciton, quasiparticles", effect() { powerUps.boost.duration -= 60 - powerUps.boost.damage += 0.77 + powerUps.boost.damage += 0.75 }, remove() { powerUps.boost.duration = 600 powerUps.boost.damage = 1.25 } }, + { + name: "polariton", + descriptionFunction() { + return `${powerUps.orb.boost(1)} also give 0.3x damage taken
for ${(powerUps.boost.duration / 60).toFixed(0)} seconds` + }, + maxCount: 9, + count: 1, + frequency: 2, + frequencyDefault: 2, + allowed() { + return tech.isBoostPowerUps || tech.isBoostReplaceAmmo + }, + requires: "exciton, quasiparticles", + effect() { + powerUps.boost.isDefense = true + }, + remove() { + powerUps.boost.isDefense = false + } + }, { name: "collider", descriptionFunction() { @@ -2762,7 +2795,6 @@ const tech = { requires: "not mass-energy", effect() { tech.isPiezo = true; - // if (simulation.isTextLogOpen) m.energy += 20.48; }, remove() { tech.isPiezo = false; @@ -2854,7 +2886,7 @@ const tech = { }, { name: "overcharge", - description: "+88 maximum energy
+4% JUNK chance", + description: "+88 maximum energy
+4% JUNK choices", maxCount: 9, count: 0, frequency: 1, @@ -2880,7 +2912,7 @@ const tech = { }, { name: "Maxwells demon", - description: "energy above maximum decays 30x slower
+5% JUNK chance", + description: "energy above maximum decays 30x slower
+5% JUNK choices", maxCount: 1, count: 0, frequency: 2, @@ -2916,7 +2948,7 @@ const tech = { effect() { tech.isCrouchRegen = true; //only used to check for requirements m.regenEnergy = function () { - if (m.immuneCycle < m.cycle && m.crouch && m.fieldCDcycle < m.cycle) m.energy += 7 * m.fieldRegen; + if (m.immuneCycle < m.cycle && m.crouch && m.fieldCDcycle < m.cycle) m.energy += 7 * m.fieldRegen * level.isReducedRegen; if (m.energy < 0) m.energy = 0 } }, @@ -2957,7 +2989,7 @@ const tech = { effect() { tech.isDamageAfterKillNoRegen = true; m.regenEnergy = function () { - if (m.immuneCycle < m.cycle && (m.lastKillCycle + 300 < m.cycle) && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen; + if (m.immuneCycle < m.cycle && (m.lastKillCycle + 300 < m.cycle) && m.fieldCDcycle < m.cycle) m.energy += m.fieldRegen * level.isReducedRegen; if (m.energy < 0) m.energy = 0 } }, @@ -3250,7 +3282,7 @@ const tech = { { name: "adiabatic healing", descriptionFunction() { - return `2x healing from ${powerUps.orb.heal()}
+4% JUNK chance` + return `2x healing from ${powerUps.orb.heal()}
+4% JUNK choices` }, maxCount: 3, count: 0, @@ -3338,7 +3370,7 @@ const tech = { { name: "accretion disk", descriptionFunction() { - return `1.07x damage for each power up on this level
+5% JUNK chance (${(1 + 0.07 * powerUp.length).toFixed(2)}x)` + return `1.07x damage for each power up on this level
+5% JUNK choices (${(1 + 0.07 * powerUp.length).toFixed(2)}x)` }, maxCount: 1, count: 0, @@ -3584,7 +3616,7 @@ const tech = { }, { name: "peer review", - description: `after you research gain 1.05x damage
and +1% JUNK chance`, + description: `after you research gain 1.05x damage
and +1% JUNK choices`, maxCount: 1, count: 0, frequency: 1, @@ -3602,7 +3634,7 @@ const tech = { }, { name: "pseudoscience", - description: "research 2 times for free, but
add 1% JUNK chance each time", + description: "research 2 times for free, but
+1% JUNK choices each time", maxCount: 1, count: 0, frequency: 1, @@ -3620,7 +3652,7 @@ const tech = { }, { name: "renormalization", - description: `47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}
+5% JUNK chance`, + description: `47% chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}
+5% JUNK choices`, maxCount: 1, count: 0, frequency: 2, @@ -3817,7 +3849,7 @@ const tech = { { name: "path integral", link: `path integral`, - description: `your next ${powerUps.orb.tech()} has all possible choices
+4% JUNK chance`, + description: `your next ${powerUps.orb.tech()} has all possible choices
+4% JUNK choices`, maxCount: 1, count: 0, frequency: 1, @@ -3909,7 +3941,7 @@ const tech = { }, { name: "meta-analysis", - description: `if you choose a JUNK you instead get a
random nonJUNK ${powerUps.orb.tech()} and ${powerUps.orb.research(2)}`, + description: `if you choose JUNK
you get a random choice and ${powerUps.orb.research(2)} instead`, maxCount: 1, count: 0, frequency: 1, @@ -3927,7 +3959,7 @@ const tech = { }, { name: "dark patterns", - description: "1.3x damage
+15% JUNK chance", + description: "1.3x damage
+15% JUNK choices", maxCount: 9, count: 0, frequency: 1, @@ -4264,7 +4296,7 @@ const tech = { }, { name: "replication", - description: "+10% chance to duplicate spawned power ups
+15% JUNK chance", + description: "+10% chance to duplicate spawned power ups
+15% JUNK choices", maxCount: 9, count: 0, frequency: 1, @@ -4565,7 +4597,7 @@ const tech = { { name: "paradigm shift", descriptionFunction() { - return `when paused clicking your ${powerUps.orb.tech()} ejects them
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.3x cost each use)` + return `when paused clicking your ${powerUps.orb.tech()} ejects them
costs ${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} (1.3x cost each use)` }, maxCount: 1, count: 0, @@ -4657,7 +4689,7 @@ const tech = { for (let i = 0, len = pool.length * 0.5; i < len; i++) removeCount += tech.removeTech(pool[i]) this.damage = this.damagePerRemoved * removeCount tech.damage *= (1 + this.damage) - simulation.inGameConsole(`${(1 + this.damage).toFixed(2)}x damage //from Occam's razor`, 360) + simulation.inGameConsole(`tech.damage *= ${(1 + this.damage).toFixed(2)} //from Occam's razor`); }, remove() { if (this.count && m.alive) tech.damage /= (1 + this.damage) @@ -4990,7 +5022,7 @@ const tech = { { name: "irradiated nails", link: `irradiated nails`, - description: "nails, needles, and rivets are radioactive
1.9x radioactive damage over 3 seconds", + description: "nails, needles, and rivets are radioactive
2x radioactive damage over 3 seconds", isGunTech: true, maxCount: 1, count: 0, @@ -6189,7 +6221,7 @@ const tech = { }, { name: "booby trap", - description: "50% chance to drop a mine from power ups
+15% JUNK chance", + description: "50% chance to drop a mine from power ups
+15% JUNK choices", isGunTech: true, maxCount: 1, count: 0, @@ -7762,7 +7794,7 @@ const tech = { }, { name: "flux pinning", - description: "after deflecting a mob
it is stunned for up to 4 seconds", + description: `mobs deflected by your ${powerUps.orb.field()}
are stunned for 4 seconds`, isFieldTech: true, maxCount: 9, count: 0, @@ -7988,7 +8020,7 @@ const tech = { } }, { - name: "modified Newtonian dynamics", + name: "MOND", descriptionFunction() { return `your speed counts as +20 higher
(for Newton's 1st and 2nd laws)` }, @@ -8122,7 +8154,7 @@ const tech = { requires: "molecular assembler, pilot wave, standing wave", effect() { tech.isMassEnergy = true // used in m.grabPowerUp - m.energy += 2 + m.energy += 2 * level.isReducedRegen }, remove() { tech.isMassEnergy = false; @@ -8643,6 +8675,25 @@ const tech = { tech.isMobFullHealthCloak = false } }, + { + name: "hidden-variable theory", + description: `1.15x damage each time you choose ${powerUps.orb.fieldTech()}`, + isFieldTech: true, + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return m.fieldMode === 8 + }, + requires: "pilot wave", + effect() { + tech.isDamageFieldTech = true + }, + remove() { + tech.isDamageFieldTech = false + } + }, { name: "WIMPs", description: `at each level's exit, spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly chases you`, @@ -9450,7 +9501,7 @@ const tech = { requestAnimationFrame(() => { if ((simulation.cycle % 1440) > 720) { //kinda alternate between each option m.rewind(60) - m.energy += 0.4 //to make up for lost energy + m.energy += 0.4 * level.isReducedRegen//to make up for lost energy } else { simulation.timePlayerSkip(60) } @@ -10645,7 +10696,7 @@ const tech = { effect() { setInterval(() => { m.rewind(120) - m.energy += 0.4 + m.energy += 0.4 * level.isReducedRegen }, 10000); // for (let i = 0; i < 24; i++) { // setTimeout(() => { m.rewind(120) }, i * 5000); @@ -10668,7 +10719,7 @@ const tech = { effect() { setInterval(() => { m.rewind(30) - m.energy += 0.2 + m.energy += 0.2 * level.isReducedRegen }, 4000); }, remove() { } @@ -10742,7 +10793,7 @@ const tech = { }, { name: "expert system", - description: `spawn ${powerUps.orb.tech()}
+50% JUNK chance`, + description: `spawn ${powerUps.orb.tech()}
+50% JUNK choices`, maxCount: 9, count: 0, frequency: 0, @@ -12076,4 +12127,5 @@ const tech = { isEjectOld: null, isWiki: null, isStaticBlock: null, + isDamageFieldTech: null, } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 5f1086c0..e90b56d7 100644 --- a/todo.txt +++ b/todo.txt @@ -1,54 +1,33 @@ ******************************************************** NEXT PATCH ************************************************** -difficulty - difficulty level 6 adds flat damage and damage taken - bonus tech no longer spawns on level 2 and 3 on difficulty level 6 - at the end of subway you get 1 tech, but not on difficulty level 6 - difficulty level 3 and 5 add a random constraint that changes each level -constraints are effects that only last until the level ends - 50% JUNK chance - 4x shielded mob chance - power ups are sent to next level - +33% chance for mobs to respawn - -1 choice - 2x ammo costs - duplication is set to zero - 50% max energy - 50% max health - bots follow slow - full damage taken after boss dies - 0.1x damage after a power up - mob death heals mobs - mobs heal for your lost health - periodically spawn WIMPs - -exciton damage boost power up has a chance to spawn without the tech (~3%/mob) - damage boost has a unique gel/hair aura for each skin - damage boost timer no longer ticks with time dilation field -JUNK tech: stationary - thrown blocks can't move, but they still have momentum -added a classic n-gon link for the previous patch in settings - but images are disabled to save space -on levels where you can fall endlessly, power ups will also fall endlessly - they no longer teleport to the exit, sorry - -Newton's 1st and 2nd laws are field tech, and they give twice the effect -abelian group 4->3x damage while invulnerable -bot fabrication price increases after 5->4 bots -wikipedia 4->3 research per correct quiz -upgraded sound bots fire fewer waves but do more damage per wave - not much changed except improved performance, I think -incendiary ammunition drones explode when they run out of durability not on the first hit - this allows better synergy with other drone tech -grappling hook retract momentum no longer scales with distance - this should give you more control -pressing the 3rd button in factory will remove blocks resting on the second block - preventing an endless toggle - -bug fixes - fleas no longer die early after hitting a high health target only once - something with super ball density calculations for tech rebound - grabbing a big block can make grappling hook go flying - added 3 potential fixes, but the bug is too rare know if it's fixed +tech: hidden-variable theory - after choosing a fieldtech gain 1.15x damage + for pilot wave only +polariton - boosts also give 0.3x damage taken + +constraints + removed + full damage taken after boss dies + wording is too unclear + new + 0.5x energy regen from all sources + balanced + slow bots + bots have roughly 15% reduction in damage in addition to a slow follow speed + mob death heals mobs + has 1000->700 range and 1->0.33 healing + periodically spawn WIMPs + has a 30s delay and a 15->6s spawn rate + 50->40% JUNK chance + + +heuristics gives (1-1.5x)->(1-2x) fire rate and +5% JUNK +autonomous defense harpoon now scale from Bessemer process + but at half the rate since there are 6 harpoons +Bessemer process and rail gun scale at 0.1->0.07 + +bugs + crash with training level "heal" and power ups + set difficulty mode level 2 for training ******************************************************** BUGS ******************************************************** @@ -80,19 +59,36 @@ player can become crouched while not touching the ground if they exit the ground *********************************************************** TODO ***************************************************** +procedural animation + https://www.youtube.com/watch?v=qlfh_rv6khY + +maybe no constraints on final boss and reactor? + +constraints balance + 50% JUNK chance + 4x shielded mob chance + power ups are sent to next level + +33% chance for mobs to respawn + -1 choice + 2x ammo costs + maybe nerf... + 0 duplication + 50% max energy + 50% max health + bots follow slow + 0.1x damage after a power up + mob death heals mobs + mobs heal for your lost health + periodically spawn WIMPs + 0.5x energy regen + each difficulty setting adds a chance for a random effect make some effects only possible on certain levels, or with certain bosses? not implemented random constraint ideas________________________ - if player takes too long on a level - spawn mobs at the end of player's history - give a warning before they spawn - black holes, sneakers, bullets mob death spawns something - bullets + mob bullets bosses heals nearby mobs ammo power ups give 0.7x ammo - 2x energy costs - 0.5x energy regen from all sources 2x research costs mobs slowly regen health exit door takes 10x time to open, @@ -108,6 +104,12 @@ each difficulty setting adds a chance for a random effect explosions do 0.5x damage freeze effects last 0.25x time +tech: - lower damage taken over 10s to 0x but after taking damage increase damage taken to 1x + isn't this just CPT skin with less steps? + maybe skin + +tech: - freezing grenades/explosions + tech: - randomize constraints somehow in pause interface or power up selection menu? each time you research the current constraints also randomize?