diff --git a/js/bullet.js b/js/bullet.js index 2f4f2f6..25f36a7 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -280,10 +280,15 @@ const b = { }, fireCDscale: 1, setFireCD() { - b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage * m.fieldFireRate + b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage + if (m.fieldMode === 0) { + b.fireCDscale *= 0.8 ** (m.coupling) + } else if (m.fieldMode === 6) { + b.fireCDscale *= 0.75 * 0.8 ** (m.coupling) + } if (tech.isFastTime) b.fireCDscale *= 0.5 - if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.8, b.inventory.length) - if (tech.isFireMoveLock) b.fireCDscale *= 0.5 + if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.82, b.inventory.length) + if (tech.isFireMoveLock) b.fireCDscale *= 0.55 }, fireAttributes(dir, rotate = true) { if (rotate) { @@ -4876,7 +4881,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.00035 + m.fieldRegen //0.004; //normal plasma field is 0.00008 + m.fieldRegen = 0.00108 + m.energy -= 0.00135 //0.004; //normal plasma field is 0.00008 + m.fieldRegen = 0.00108 // if (m.energy < 0) { // m.fieldCDcycle = m.cycle + 120; // m.energy = 0; @@ -5866,7 +5871,7 @@ const b = { ctx.lineWidth = 2 * tech.wavePacketDamage ctx.beginPath(); const end = 700 * Math.sqrt(tech.isBulletsLastLonger) / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1060 - const damage = 2 * m.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage * (tech.isBulletTeleport ? 1.43 : 1) //damage is lower for large radius mobs, since they feel the waves longer + const damage = 1.8 * m.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage * (tech.isBulletTeleport ? 1.43 : 1) //damage is lower for large radius mobs, since they feel the waves longer for (let i = this.waves.length - 1; i > -1; i--) { //draw wave @@ -5959,7 +5964,7 @@ const b = { ctx.lineWidth = 2 * tech.wavePacketDamage ctx.beginPath(); const end = 1100 * tech.isBulletsLastLonger / Math.sqrt(tech.waveReflections * 0.5) //should equal about 1767 - const damage = 2 * m.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage * (tech.isBulletTeleport ? 1.43 : 1) //damage is lower for large radius mobs, since they feel the waves longer + const damage = 1.8 * m.dmgScale * tech.wavePacketDamage * tech.waveBeamDamage * (tech.isBulletTeleport ? 1.43 : 1) //damage is lower for large radius mobs, since they feel the waves longer for (let i = this.waves.length - 1; i > -1; i--) { const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius)) @@ -7024,7 +7029,6 @@ const b = { this.fire = () => { const drain = 0.01 * (tech.isCapacitor ? 10 : 1) / b.fireCDscale if (m.energy > drain) { - // m.energy -= m.fieldRegen if (this.charge < 50 * m.maxEnergy) { m.energy -= drain this.charge += drain * 100 @@ -7106,7 +7110,7 @@ const b = { // b.photon({ x: m.pos.x + 23 * Math.cos(m.angle), y: m.pos.y + 23 * Math.sin(m.angle) }, m.angle) // }, fireLaser() { - const drain = m.fieldRegen + tech.laserDrain / b.fireCDscale + const drain = 0.001 + tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -7124,7 +7128,7 @@ const b = { }, firePulse() {}, fireSplit() { - const drain = m.fieldRegen + tech.laserDrain / b.fireCDscale + const drain = 0.001 + tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -7149,7 +7153,7 @@ const b = { } }, fireWideBeam() { - const drain = m.fieldRegen + tech.laserDrain / b.fireCDscale + const drain = 0.001 + tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { @@ -7214,7 +7218,7 @@ const b = { } }, fireHistory() { - drain = m.fieldRegen + tech.laserDrain / b.fireCDscale + drain = 0.001 + tech.laserDrain / b.fireCDscale if (m.energy < drain) { m.fireCDcycle = m.cycle + 100; // cool down if out of energy } else { diff --git a/js/engine.js b/js/engine.js index 5767467..399ce79 100644 --- a/js/engine.js +++ b/js/engine.js @@ -42,7 +42,7 @@ function playerOnGroundCheck(event) { //falling damage if (tech.isFallingDamage && m.immuneCycle < m.cycle && momentum > 150) { m.damage(Math.min(Math.sqrt(momentum - 133) * 0.01, 0.25)); - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles } } else { m.yOffGoal = m.yOffWhen.stand; @@ -148,7 +148,7 @@ function collisionChecks(event) { if (tech.isPiezo) m.energy += 20.48; if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(); - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.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... let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); Matter.Body.setVelocity(player, { @@ -162,7 +162,7 @@ function collisionChecks(event) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy && mob[k].damageReduction > 0) { m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy - if (m.immuneCycle === m.cycle + tech.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage + if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage mob[k].death(); simulation.drawList.push({ //add dmg to draw queue x: pairs[i].activeContacts[0].vertex.x, @@ -224,7 +224,7 @@ function collisionChecks(event) { } } - let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1); + let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2.5 : 1) * (tech.isBlockRestitution ? 2.5 : 1) * ((m.fieldMode === 0 || m.fieldMode === 8) ? 1 + 0.4 * m.coupling : 1); if (mob[k].isShielded) dmg *= 0.7 mob[k].damage(dmg, true); diff --git a/js/index.js b/js/index.js index 3eae6ad..a77ed0b 100644 --- a/js/index.js +++ b/js/index.js @@ -226,6 +226,17 @@ for (let i = 0, len = tech.tech.length; i < len; i++) { } const build = { pauseGrid() { + + //used for junk estimation + let junkCount = 0 + let totalCount = 0 + for (let i = 0; i < tech.tech.length; i++) { + if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBanished) { + totalCount += tech.tech[i].frequency + if (tech.tech[i].isJunk) junkCount += tech.tech[i].frequency + } + } + // ${m.coupling> 0 ? '
'+m.couplingDescription(): ""} //left side let botText = "" if (tech.nailBotCount) botText += `
nail-bots: ${tech.nailBotCount}` @@ -248,13 +259,14 @@ const build = {
fire rate: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
duplication: ${(tech.duplicationChance()*100).toFixed(0)}%
coupling: ${(m.coupling).toFixed(2)} -${m.coupling> 0 ? '
'+m.couplingDescription(): ""} + ${botText}

health: (${(m.health*100).toFixed(0)} / ${(m.maxHealth*100).toFixed(0)}) -
energy: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) +
energy: (${(m.energy*100).toFixed(0)} / ${(m.maxEnergy*100).toFixed(0)}) +(${(m.fieldRegen*6000).toFixed(0)}/s)
gun: ${b.activeGun === null || b.activeGun === undefined ? "undefined":b.guns[b.activeGun].name}   ammo: ${b.activeGun === null || b.activeGun === undefined ? "0":b.guns[b.activeGun].ammo} -
tech: ${tech.totalCount}   research: ${powerUps.research.count} +
tech: ${tech.totalCount}   research: ${powerUps.research.count} +
JUNK: ${(junkCount / totalCount * 100).toFixed(1)}%

seed: ${Math.initialSeed}
level: ${level.levels[level.onLevel]} (${level.difficultyText()})   ${m.cycle} cycles @@ -972,7 +984,7 @@ window.addEventListener("keydown", function(event) { if (m.alive && localSettings.loreCount > 0) { if (simulation.difficultyMode > 4) { simulation.makeTextLog("testing mode disabled for this difficulty"); - // break + break } if (simulation.testing) { simulation.testing = false; @@ -1281,6 +1293,7 @@ if (localSettings.isAllowed && !localSettings.isEmpty) { } document.getElementById("fps-select").value = localSettings.fpsCapDefault + if (!localSettings.banList) localSettings.banList = "" if (localSettings.banList.length === 0 || localSettings.banList === "undefined") { localSettings.banList = "" localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage diff --git a/js/level.js b/js/level.js index c2f9a30..19db768 100644 --- a/js/level.js +++ b/js/level.js @@ -16,19 +16,19 @@ 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(5 * 4) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(1 * 4) //30 is near max on hard //60 is near max on why // simulation.isHorizontalFlipped = true // m.maxHealth = m.health = 100 // tech.isRerollDamage = true // powerUps.research.changeRerolls(100000) // m.immuneCycle = Infinity //you can't take damage // tech.tech[297].frequency = 100 - // m.setField("time dilation") //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 + m.setField("time dilation") //molecular assembler time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass + // 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 // b.guns[0].ammo = 1000000 - // tech.giveTech("sentry"); - // tech.giveTech("MACHO"); - // tech.giveTech("elephant's toothpaste") + // tech.giveTech("coupling"); + // tech.giveTech("time crystals"); + tech.giveTech("retrocausality") // for (let i = 0; i < 1; ++i) tech.giveTech("slow light") // for (let i = 0; i < 1; ++i) tech.giveTech("free-electron laser") // m.damage(0.1); @@ -37,7 +37,8 @@ const level = { // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research"); // spawn.starter(1900, -500, 200) - // spawn.snakeSpitBoss(1900, -400) + // spawn.beetleBoss(1900, -400) + // spawn.timeBoss(1900, -400) // for (let i = 0; i < 15; ++i) spawn.starter(1900 + 300 * Math.random(), -500 + 300 * Math.random()) // level.testing(); // for (let i = 0; i < 7; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); @@ -1134,10 +1135,10 @@ const level = { player.isInPortal = this.portalPair //teleport if (this.portalPair.angle % (Math.PI / 2)) { //if left, right up or down - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles Matter.Body.setPosition(player, this.portalPair.portal.position); } else { //if at some odd angle - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles Matter.Body.setPosition(player, this.portalPair.position); } //rotate velocity @@ -1325,7 +1326,7 @@ const level = { //collision with player if (this.height > 0 && Matter.Query.region([player], this).length && !(m.isCloak)) { if (m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; + m.immuneCycle = m.cycle + m.collisionImmuneCycles; m.damage(damage) simulation.drawList.push({ //add dmg to draw queue x: player.position.x, @@ -1357,7 +1358,7 @@ const level = { if (this.height > 0 && Matter.Query.region([player], this).length) { if (m.immuneCycle < m.cycle) { - const DRAIN = 0.0022 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen + const DRAIN = 0.0032 * (tech.isRadioactiveResistance ? 0.25 : 1) if (m.energy > DRAIN) { m.energy -= DRAIN // m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy @@ -10253,7 +10254,7 @@ const level = { me.onDeath = function() { //damage player if in range if (distance(player.position, this.position) < pulseRadius && m.immuneCycle < m.cycle) { - m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage m.damage(0.02 * simulation.dmgScale); } simulation.drawList.push({ //add dmg to draw queue @@ -10616,7 +10617,7 @@ const level = { // Trolled const hasCPT = tech.isRewindAvoidDeath; tech.isRewindAvoidDeath = false; - const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen; + const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + 0.001; if (m.energy > DRAIN && !tech.isEnergyHealth) { m.energy -= DRAIN; } @@ -10698,7 +10699,7 @@ const level = { if (this.isHeal) { m.energy += 0.005; } else { - m.energy = Math.max(m.energy - 0.007 - m.fieldRegen, 0); + m.energy = Math.max(m.energy - 0.006, 0); if (m.energy <= 0.01 && m.immuneCycle < m.cycle) m.damage(0.002); } }, @@ -11640,7 +11641,7 @@ const level = { // me.onDeath = function() { // //damage player if in range // if (distance(player.position, this.position) < pulseRadius && m.immuneCycle < m.cycle) { - // m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + // m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage // m.damage(0.02 * simulation.dmgScale); // } // simulation.drawList.push({ //add dmg to draw queue diff --git a/js/mob.js b/js/mob.js index aa51a78..ff0348b 100644 --- a/js/mob.js +++ b/js/mob.js @@ -235,7 +235,10 @@ const mobs = { // }) // } // }, - + mobSpawnWithHealth: 1, + setMobSpawnHealth() { + mobs.mobSpawnWithHealth = 0.87 ** (tech.mobSpawnWithHealth) //+ (m.fieldMode === 0 || m.fieldMode === 7) * m.coupling + }, //********************************************************************************************** //********************************************************************************************** spawn(xPos, yPos, sides, radius, color) { @@ -256,7 +259,7 @@ const mobs = { onHit: undefined, alive: true, index: i, - health: tech.mobSpawnWithHealth, + health: mobs.mobSpawnWithHealth, showHealthBar: true, accelMag: 0.001 * simulation.accelScale, cd: 0, //game cycle when cooldown will be over @@ -602,7 +605,7 @@ const mobs = { const hitPlayer = Matter.Query.ray([player], this.position, Vector.add(this.position, Vector.mult(perp, radius * 2.05)), minorRadius) if (hitPlayer.length && m.immuneCycle < m.cycle) { m.damage(dmg * simulation.dmgScale); - // m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage + // m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage } }, searchSpring() { diff --git a/js/player.js b/js/player.js index cd8ce46..6b3f1fa 100644 --- a/js/player.js +++ b/js/player.js @@ -56,12 +56,20 @@ const m = { light: 100, }, setFillColors() { - this.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` - this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%)` + m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` + m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%)` let grd = ctx.createLinearGradient(-30, 0, 30, 0); grd.addColorStop(0, m.fillColorDark); grd.addColorStop(1, m.fillColor); - this.bodyGradient = grd + m.bodyGradient = grd + }, + setFillColorsAlpha(alpha = 0.5) { + m.fillColor = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light}%,${alpha})` + m.fillColorDark = `hsla(${m.color.hue},${m.color.sat}%,${m.color.light - 25}%,${alpha})` + let grd = ctx.createLinearGradient(-30, 0, 30, 0); + grd.addColorStop(0, m.fillColorDark); + grd.addColorStop(1, m.fillColor); + m.bodyGradient = grd }, height: 42, yOffWhen: { @@ -498,7 +506,7 @@ const m = { }, baseHealth: 1, setMaxHealth() { - m.maxHealth = m.baseHealth + tech.extraMaxHealth + tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth + m.maxHealth = m.baseHealth + tech.extraMaxHealth + tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth + (m.fieldMode === 0 || m.fieldMode === 5) * 0.5 * m.coupling document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px` simulation.makeTextLog(`m.maxHealth = ${m.maxHealth.toFixed(2)}`) if (m.health > m.maxHealth) m.health = m.maxHealth; @@ -532,6 +540,7 @@ const m = { if (tech.isEntanglement && b.inventory[0] === b.activeGun) { for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15 } + if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.75 ** m.coupling return dmg }, rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy))) @@ -599,7 +608,7 @@ const m = { } } m.energy = Math.max(m.energy - steps / 150, 0.01) - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles let isDrawPlayer = true const shortPause = function() { @@ -647,6 +656,7 @@ const m = { } } }, + collisionImmuneCycles: 30, damage(dmg) { if (tech.isRewindAvoidDeath && m.energy > 0.6 && dmg > 0.01) { const steps = Math.floor(Math.min(299, 150 * m.energy)) @@ -845,7 +855,7 @@ const m = { ctx.rotate(m.angle); ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.strokeStyle = "#333"; @@ -873,7 +883,7 @@ const m = { ctx.rotate(m.angle); ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.strokeStyle = "#333"; @@ -902,7 +912,6 @@ const m = { // these values are set on reset by setHoldDefaults() fieldFx: 1, fieldJump: 1, - fieldFireRate: 1, blockingRecoil: 4, grabPowerUpRange2: 0, isFieldActive: false, @@ -935,7 +944,7 @@ const m = { fieldArc: 0, fieldThreshold: 0, calculateFieldThreshold() { - m.fieldThreshold = Math.cos(m.fieldArc * Math.PI) + m.fieldThreshold = Math.cos((m.fieldArc) * Math.PI) }, setHoldDefaults() { if (tech.isFreeWormHole && m.fieldUpgrades[m.fieldMode].name !== "wormhole") { @@ -947,7 +956,6 @@ const m = { if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); } if (m.energy < m.maxEnergy) m.energy = m.maxEnergy; - // m.fieldRegen = 0.001 m.fieldMeterColor = "#0cf" m.eyeFillColor = m.fieldMeterColor m.fieldShieldingScale = 1; @@ -956,7 +964,6 @@ const m = { m.lastHit = 0 m.isSneakAttack = false m.duplicateChance = 0 - powerUps.setDupChance(); m.grabPowerUpRange2 = 156000; m.blockingRecoil = 4; m.fieldRange = 155; @@ -965,10 +972,9 @@ const m = { m.isCloak = false; player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield m.airSpeedLimit = 125 - m.fieldFireRate = 1 - b.setFireCD(); m.fieldFx = 1 m.fieldJump = 1 + m.setFieldRegen(); m.setMovement(); m.drop(); m.holdingMassScale = 0.5; @@ -976,7 +982,7 @@ const m = { m.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) m.isBodiesAsleep = true; m.wakeCheck(); - m.setMaxEnergy(); + m.couplingChange() m.hole = { isOn: false, isReady: false, @@ -991,12 +997,12 @@ const m = { } }, setMaxEnergy() { - m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 0.6 * (m.fieldUpgrades[m.fieldMode].name === "standing wave") + m.maxEnergy = (m.fieldMode === 0 || m.fieldMode === 1) * 0.4 * m.coupling + (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 0.6 * (m.fieldUpgrades[m.fieldMode].name === "standing wave") // if (tech.isEnergyHealth) m.maxEnergy *= Math.sqrt(m.harmReduction()) simulation.makeTextLog(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`) }, fieldMeterColor: "#0cf", - drawFieldMeter(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) { + drawRegenEnergy(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) { if (m.energy < m.maxEnergy) { m.regenEnergy(); ctx.fillStyle = bgColor; @@ -1014,8 +1020,8 @@ const m = { ctx.fillRect(xOff, yOff, range * m.energy, 10); } }, - drawFieldMeterCloaking: function() { - if (m.energy < m.maxEnergy) { // replaces m.drawFieldMeter() with custom code + drawRegenEnergyCloaking: function() { + if (m.energy < m.maxEnergy) { // replaces m.drawRegenEnergy() with custom code m.regenEnergy(); const xOff = m.pos.x - m.radius * m.maxEnergy const yOff = m.pos.y - 50 @@ -1030,7 +1036,22 @@ const m = { ctx.stroke(); } }, - regenEnergy: function() { //used in drawFieldMeter // rewritten by some tech + setFieldRegen() { + if (m.fieldMode === 6) { + m.fieldRegen = 0.003 //18 energy per second + } else if (m.fieldMode === 4) { + m.fieldRegen = 0.002 //12 energy per second + } else { + m.fieldRegen = 0.001 //6 energy per second + } + if (m.fieldMode === 0 || m.fieldMode === 4) m.fieldRegen += 0.001 * m.coupling + if (tech.isTimeCrystals) { + m.fieldRegen *= 3 + } else if (tech.isGroundState) { + m.fieldRegen *= 0.5 + } + }, + regenEnergy: function() { //used in drawRegenEnergy // rewritten by some tech if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen; if (m.energy < 0) m.energy = 0 }, @@ -1428,7 +1449,6 @@ const m = { } }, lookForPickUp() { //find body to pickup - if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen; const grabbing = { targetIndex: null, targetRange: 150, @@ -1521,27 +1541,61 @@ const m = { couplingDescription() { switch (m.fieldMode) { case 0: //field emitter - return `gain the effects of all fields` + return `gain the effects of all other fields` case 1: //standing wave - return `+20 max energy per coupling` + return `+40 max energy per coupling` case 2: //perfect diamagnetism - return `+10° arc per coupling` + return `invulnerable +3 seconds post collision per coupling` case 3: //negative mass - return `+25% defense per coupling` + return `+20% defense per coupling` case 4: //assembler - return `generate 4 energy per second per coupling` + return `generate 6 energy per second per coupling` case 5: //plasma - return `+13% damage per coupling` + return `+50 max health per coupling` case 6: //time dilation return `+20% fire rate per coupling` //movement, jumping, and case 7: //cloaking - return `remove +10% mob durability per coupling` + return `+15% damage per coupling` case 8: //pilot wave - return `________ per coupling` + return `+40% block collision damage per coupling` case 9: //wormhole return `+5% duplication per coupling` } }, + couplingChange() { + m.setMaxEnergy(); + m.setMaxHealth(); + m.setFieldRegen() + mobs.setMobSpawnHealth(); + powerUps.setDupChance(); + b.setFireCD(); + m.collisionImmuneCycles = 30 + m.coupling * 180 + // switch (m.fieldMode) { + // case 0: //field emitter + // // m.fieldFireRate = 0.8 ** (m.coupling) + // // b.setFireCD(); + // break + // // case 1: //standing wave + // // break + // // case 2: //perfect diamagnetism + // // break + // // case 3: //negative mass + // // break + // // case 4: //assembler + // // break + // // case 5: //plasma + // // break + // case 6: //time dilation + // // m.fieldFireRate = 0.75 * 0.8 ** (m.coupling) + // break + // // case 7: //cloaking + // // break + // // case 8: //pilot wave + // // break + // // case 9: //wormhole + // // break + // } + }, setField(index) { if (isNaN(index)) { //find index by name let found = false @@ -1572,6 +1626,7 @@ const m = { m.holding(); m.throwBlock(); } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); if (m.energy > 0.05) { @@ -1583,7 +1638,7 @@ const m = { } else { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } - m.drawFieldMeter() + m.drawRegenEnergy() } } }, @@ -1667,6 +1722,7 @@ const m = { m.holding(); m.throwBlock(); } else if ((input.field) && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released @@ -1686,7 +1742,7 @@ const m = { } m.harmonicShield() } - m.drawFieldMeter() + m.drawRegenEnergy() } } }, @@ -1835,6 +1891,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); m.fieldPosition = { x: m.pos.x, y: m.pos.y } @@ -1883,8 +1940,8 @@ const m = { m.perfectPush(true); } } - // m.drawFieldMeter() - m.drawFieldMeter("rgba(0,0,0,0.2)") + // m.drawRegenEnergy() + m.drawRegenEnergy("rgba(0,0,0,0.2)") if (tech.isPerfectBrake) { //cap mob speed around player const range = 200 + 140 * wave + 150 * m.energy for (let i = 0; i < mob.length; i++) { @@ -1925,6 +1982,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { //push away + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); const DRAIN = 0.00035 @@ -2035,14 +2093,15 @@ const m = { // } // } // } - //draw zero-G range - ctx.beginPath(); - ctx.arc(m.pos.x, m.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI); - ctx.fillStyle = "#f5f5ff"; - ctx.globalCompositeOperation = "difference"; - ctx.fill(); - ctx.globalCompositeOperation = "source-over"; + if (!simulation.isTimeSkipping) { + ctx.beginPath(); + ctx.arc(m.pos.x, m.pos.y, this.fieldDrawRadius, 0, 2 * Math.PI); + ctx.fillStyle = "#f5f5ff"; + ctx.globalCompositeOperation = "difference"; + ctx.fill(); + ctx.globalCompositeOperation = "source-over"; + } } } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released m.pickUp(); @@ -2051,7 +2110,7 @@ const m = { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) this.fieldDrawRadius = 0 } - m.drawFieldMeter("rgba(0,0,0,0.2)") + m.drawRegenEnergy("rgba(0,0,0,0.2)") } } }, @@ -2136,6 +2195,7 @@ const m = { m.holding(); m.throwBlock(); } else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); if (m.energy > 0.05) { @@ -2147,8 +2207,7 @@ const m = { } else { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } - m.regenEnergy() - m.drawFieldMeter() + m.drawRegenEnergy() } } }, @@ -2177,7 +2236,7 @@ const m = { // } else { // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) // } - // m.drawFieldMeter("rgba(0, 0, 0, 0.2)") + // m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") // if (tech.isExtruder) { // if (input.field) { @@ -2434,6 +2493,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); @@ -2514,7 +2574,7 @@ const m = { m.plasmaBall.fire() } } - m.drawFieldMeter("rgba(0, 0, 0, 0.2)") + m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") m.plasmaBall.do() } } else if (tech.isExtruder) { @@ -2525,6 +2585,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); b.extruder(); @@ -2533,7 +2594,7 @@ const m = { } else { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } - m.drawFieldMeter("rgba(0, 0, 0, 0.2)") + m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") if (input.field) { b.wasExtruderOn = true } else { @@ -2565,6 +2626,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); b.plasma(); @@ -2573,7 +2635,7 @@ const m = { } else { m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } - m.drawFieldMeter("rgba(0, 0, 0, 0.2)") + m.drawRegenEnergy("rgba(0, 0, 0, 0.2)") } } }, @@ -2592,9 +2654,6 @@ const m = { // m.fieldMeterColor = "#ff0" m.fieldMeterColor = "#3fe" m.eyeFillColor = m.fieldMeterColor - - m.fieldFireRate = 0.75 - b.setFireCD(); m.fieldFx = 1.2 m.fieldJump = 1.09 m.setMovement(); @@ -2654,6 +2713,9 @@ const m = { m.throwBlock(); m.wakeCheck(); } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed + const drain = 0.002 + if (m.energy > drain) m.energy -= drain + m.grabPowerUp(); if (this.rewindCount === 0) m.lookForPickUp(); @@ -2716,13 +2778,11 @@ const m = { this.rewindCount = 0; m.wakeCheck(); } - if (m.energy < m.maxEnergy) m.regenEnergy(); //extra energy regen - m.drawFieldMeter() // this calls m.regenEnergy(); also + m.drawRegenEnergy() // this calls m.regenEnergy(); also } } else { m.fieldFire = true; m.isBodiesAsleep = false; - m.drain = 0.002 m.hold = function() { if (m.isHolding) { m.wakeCheck(); @@ -2730,17 +2790,16 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { + const drain = 0.0026 + if (m.energy > drain) m.energy -= drain m.grabPowerUp(); - m.lookForPickUp(); - if (m.energy > m.drain) { - m.energy -= m.drain; - if (m.energy < m.drain) { //out of energy - m.fieldCDcycle = m.cycle + 120; - m.energy = 0; - m.wakeCheck(); - } + m.lookForPickUp(); //this drains energy 0.001 + if (m.energy > drain) { timeStop(); } else { //holding, but field button is released + m.fieldCDcycle = m.cycle + 120; + m.energy = 0; + m.wakeCheck(); m.wakeCheck(); } } else if (tech.isTimeStop && player.speed < 1 && m.onGround && m.fireCDcycle < m.cycle && !input.fire) { @@ -2765,9 +2824,7 @@ const m = { m.wakeCheck(); m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) } - if (m.energy < m.maxEnergy) m.regenEnergy(); //extra energy regen - if (m.energy < m.maxEnergy) m.regenEnergy(); //extra energy regen - m.drawFieldMeter() + m.drawRegenEnergy() } } }, @@ -2813,6 +2870,7 @@ const m = { m.holding(); m.throwBlock(); } else if (input.field && m.fieldCDcycle < m.cycle) { //not hold and field button is pressed + if (m.energy > m.fieldRegen) m.energy -= m.fieldRegen m.grabPowerUp(); m.lookForPickUp(); } else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding target exists, and field button is not pressed @@ -2825,6 +2883,15 @@ const m = { if (m.fireCDcycle + 30 < m.cycle && !input.fire) { //automatically cloak if not firing if (!m.isCloak) { m.isCloak = true //enter cloak + + // m.color = { + // hue: 0, + // sat: 0, + // light: 100 + // } + // m.setFillColorsAlpha(0) + + m.enterCloakCycle = m.cycle if (tech.isCloakHealLastHit && m.lastHit > 0) { const heal = Math.min(0.75 * m.lastHit, m.energy) @@ -2914,7 +2981,7 @@ const m = { player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions } } - this.drawFieldMeterCloaking() + this.drawRegenEnergyCloaking() //show sneak attack status // if (m.cycle > m.lastKillCycle + 240) { // if (m.sneakAttackCharge > 0) { @@ -3258,7 +3325,7 @@ const m = { m.fieldOn = false m.fieldRadius = 0 } - m.drawFieldMeter("rgba(0,0,0,0.2)") + m.drawRegenEnergy("rgba(0,0,0,0.2)") } } }, @@ -3685,7 +3752,7 @@ const m = { // } else { // m.hole.isReady = true; // } - m.drawFieldMeter() + m.drawRegenEnergy() } }, @@ -3771,7 +3838,7 @@ const m = { // m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) // } // } - // m.drawFieldMeter() + // m.drawRegenEnergy() // }, }, ], @@ -3955,7 +4022,7 @@ const m = { //body ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.strokeStyle = "#333"; @@ -3998,7 +4065,7 @@ const m = { if (tech.isPiezo) m.energy += 20.48; if (tech.isStimulatedEmission) powerUps.ejectTech() if (mob[k].onHit) mob[k].onHit(); - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles + if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.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... let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); Matter.Body.setVelocity(player, { diff --git a/js/powerup.js b/js/powerup.js index 3e53405..0ad1750 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -825,15 +825,20 @@ const powerUps = { if (!tech.isSuperDeterminism) text += `
${tech.isCancelTech ? "?":"✕"}
` text += `

tech

` + //used for junk estimation + let junkCount = 0 + let totalCount = 0 + let options = []; //generate all options optionLengthNoDuplicates = 0 for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isBanished) { + totalCount += tech.tech[i].frequency + if (tech.tech[i].isJunk) junkCount += tech.tech[i].frequency if (tech.tech[i].frequency > 0) optionLengthNoDuplicates++ for (let j = 0, len = tech.tech[i].frequency; j < len; j++) options.push(i); } } - // console.log(optionLengthNoDuplicates, options.length) function removeOption(index) { for (let i = options.length; i > -1; i--) { @@ -1202,7 +1207,7 @@ const powerUps = { randomPowerUpCounter: 0, spawnBossPowerUp(x, y) { //boss spawns field and gun tech upgrades if (level.levels[level.onLevel] !== "final") { - if (m.fieldMode === 0) { + if (m.fieldMode === 0 && !m.coupling) { powerUps.spawn(x, y, "field") } else { powerUps.randomPowerUpCounter++; diff --git a/js/spawn.js b/js/spawn.js index d9c8bc9..a91f1e8 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -241,45 +241,47 @@ const spawn = { tech.isHarmMACHO = false; } me.do = function() { - const sine = Math.sin(simulation.cycle * 0.015) - this.radius = 370 * (1 + 0.1 * sine) - //chase player - const sub = Vector.sub(player.position, this.position) - const mag = Vector.magnitude(sub) - // follow physics - // Matter.Body.setVelocity(this, { x: 0, y: 0 }); - // const where = Vector.add(this.position, Vector.mult(Vector.normalise(sub), this.chaseSpeed)) - // if (mag > 10) Matter.Body.setPosition(this, { x: where.x, y: where.y }); + if (!simulation.isTimeSkipping) { + const sine = Math.sin(simulation.cycle * 0.015) + this.radius = 370 * (1 + 0.1 * sine) + //chase player + const sub = Vector.sub(player.position, this.position) + const mag = Vector.magnitude(sub) + // follow physics + // Matter.Body.setVelocity(this, { x: 0, y: 0 }); + // const where = Vector.add(this.position, Vector.mult(Vector.normalise(sub), this.chaseSpeed)) + // if (mag > 10) Matter.Body.setPosition(this, { x: where.x, y: where.y }); - //realistic physics - const force = Vector.mult(Vector.normalise(sub), 0.000000003) - this.force.x += force.x - this.force.y += force.y + //realistic physics + const force = Vector.mult(Vector.normalise(sub), 0.000000003) + this.force.x += force.x + this.force.y += force.y - if (mag < this.radius) { //buff to player when inside radius - tech.isHarmMACHO = true; + if (mag < this.radius) { //buff to player when inside radius + tech.isHarmMACHO = true; - //draw halo - ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` + //draw halo + ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` + ctx.beginPath(); + ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI); + ctx.lineWidth = 10; + ctx.stroke(); + // ctx.strokeStyle = "rgba(255,255,0,0.17)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` + // ctx.beginPath(); + // ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI); + // ctx.lineWidth = 30; + // ctx.stroke(); + } else { + tech.isHarmMACHO = false; + } + //draw outline ctx.beginPath(); - ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI); - ctx.lineWidth = 10; + ctx.arc(this.position.x, this.position.y, this.radius + 15, 0, 2 * Math.PI); + ctx.strokeStyle = "#000" + ctx.lineWidth = 1; ctx.stroke(); - // ctx.strokeStyle = "rgba(255,255,0,0.17)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` - // ctx.beginPath(); - // ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI); - // ctx.lineWidth = 30; - // ctx.stroke(); - } else { - tech.isHarmMACHO = false; } - //draw outline - ctx.beginPath(); - ctx.arc(this.position.x, this.position.y, this.radius + 15, 0, 2 * Math.PI); - ctx.strokeStyle = "#000" - ctx.lineWidth = 1; - ctx.stroke(); } }, WIMP(x = level.exit.x + tech.wimpCount * 200 * (Math.random() - 0.5), y = level.exit.y + tech.wimpCount * 200 * (Math.random() - 0.5)) { //immortal mob that follows player //if you have the tech it spawns at start of every level at the exit @@ -1296,7 +1298,7 @@ const spawn = { // Matter.Body.setDensity(me, 0.001); //normal is 0.001 me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map me.memory = Infinity; - me.seePlayerFreq = 20 + me.seePlayerFreq = 17 me.lockedOn = null; if (vertices === 9) { //on primary spawn @@ -1359,7 +1361,7 @@ const spawn = { y: 0 }) } - this.seePlayerByHistory(); + this.seePlayerByHistory(50); this.attraction(); this.checkStatus(); }; @@ -2724,7 +2726,7 @@ const spawn = { 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); me.accelMag = 0.0006 + 0.0007 * Math.sqrt(simulation.accelScale); - me.frictionAir = 0.05; + me.frictionAir = 0.04; // me.seePlayerFreq = 40 + Math.floor(13 * Math.random()) me.memory = 240; me.restitution = 1; @@ -2761,7 +2763,7 @@ const spawn = { const angle = this.angle + Math.PI / 2; c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; const threshold = 0.4; - const turn = 0.00003 * this.inertia + const turn = 0.000025 * this.inertia if (c > threshold) { this.torque += turn; } else if (c < -threshold) { @@ -2793,7 +2795,7 @@ const spawn = { Matter.Body.rotate(me, Math.random() * Math.PI * 2); me.accelMag = 0.00045 + 0.0005 * Math.sqrt(simulation.accelScale); me.frictionAir = 0.05; - me.seePlayerFreq = 20 + me.seePlayerFreq = 13 me.memory = 420; me.restitution = 1; me.frictionStatic = 0; @@ -2902,7 +2904,7 @@ const spawn = { } }; me.do = function() { - this.seePlayerByHistory() + this.seePlayerByHistory(50) this.checkStatus(); if (this.isInvulnerable) { this.invulnerableCount-- @@ -3329,7 +3331,7 @@ const spawn = { } me.do = function() { // this.armor(); - this.seePlayerByHistory() + this.seePlayerByHistory(40) if (this.nextBlinkCycle < simulation.cycle && this.seePlayer.yes) { //teleport towards the player this.nextBlinkCycle = simulation.cycle + this.delay; const dist = Vector.sub(this.seePlayer.position, this.position); @@ -4424,13 +4426,13 @@ const spawn = { } //time dilation if (!simulation.isTimeSkipping) { - // requestAnimationFrame(() => { - // simulation.timePlayerSkip(2) - // m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast - // }); //wrapping in animation frame prevents errors, probably + requestAnimationFrame(() => { + simulation.timePlayerSkip(2) + m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast + }); //wrapping in animation frame prevents errors, probably - simulation.timePlayerSkip(2) - m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast + // simulation.timePlayerSkip(2) + // m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast //draw invulnerable ctx.beginPath(); @@ -4516,7 +4518,7 @@ const spawn = { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; me.do = function() { - this.seePlayerByHistory(); + this.seePlayerByHistory(40); this.attraction(); this.checkStatus(); this.sword() //does various things depending on what stage of the sword swing @@ -5659,7 +5661,7 @@ const spawn = { // spawn.seeker(where.x, where.y); //give the bullet a rotational velocity as if they were attached to a vertex }; me.do = function() { - this.seePlayerByHistory(); + this.seePlayerByHistory(60); this.attraction(); this.checkStatus(); this.eventHorizon = 900 + 200 * Math.sin(simulation.cycle * 0.005) @@ -5673,12 +5675,14 @@ const spawn = { // // simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations // }); //wrapping in animation frame prevents errors, probably - // requestAnimationFrame(() => { + // // simulation.timePlayerSkip(1) // m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast // }); //wrapping in animation frame prevents errors, probably + requestAnimationFrame(() => { + simulation.timePlayerSkip(1) + }); //wrapping in animation frame prevents errors, probably - simulation.timePlayerSkip(1) m.walk_cycle += m.flipLegs * m.Vx //makes the legs look like they are moving fast ctx.beginPath(); @@ -5925,12 +5929,11 @@ const spawn = { }; }, snakeSpitBoss(x, y, radius = 50) { - const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) let angle = Math.PI - let mag = 300 + const tailRadius = 300 const color1 = "rgb(235,180,255)" - mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" + mobs.spawn(x + tailRadius * Math.cos(angle), y + tailRadius * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; me.accelMag = 0.0001 + 0.0004 * Math.sqrt(simulation.accelScale) @@ -5938,7 +5941,7 @@ const spawn = { 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 - me.startingDamageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) + me.startingDamageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0 me.isInvulnerable = true @@ -5956,7 +5959,7 @@ const spawn = { me.cycle = 0 me.do = function() { // this.armor(); - this.seePlayerByHistory() + this.seePlayerByHistory(40) this.checkStatus(); this.attraction(); this.cycle++ @@ -6017,24 +6020,19 @@ const spawn = { } }; //extra space to give head room - angle -= 0.1 - mag -= 10 + angle -= 0.07 let previousTailID = 0 - - const damping = 1 - const stiffness = 1 + const nodes = Math.min(10 + Math.ceil(0.6 * simulation.difficulty), 60) for (let i = 0; i < nodes; ++i) { - 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); - // mag -= 5 - // spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20); + angle -= 0.1 + spawn.snakeBody(x + tailRadius * Math.cos(angle), y + tailRadius * Math.sin(angle), i === 0 ? 25 : 20); if (i < 3) mob[mob.length - 1].snakeHeadID = me.id mob[mob.length - 1].previousTailID = previousTailID previousTailID = mob[mob.length - 1].id } + const damping = 1 + const stiffness = 1 this.constrain2AdjacentMobs(nodes, stiffness, false, damping); - for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors if (i % 2) { mob[i].fill = "#778" @@ -6064,21 +6062,21 @@ const spawn = { damping: damping }); Composite.add(engine.world, consBB[consBB.length - 1]); - // spawn.shield(me, x, y, 1); }, dragonFlyBoss(x, y, radius = 42) { //snake boss with a laser head let angle = Math.PI - let mag = 300 - mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, "#000"); //"rgb(55,170,170)" + const tailRadius = 300 + mobs.spawn(x + tailRadius * Math.cos(angle), y + tailRadius * Math.sin(angle), 8, radius, "#000"); //"rgb(55,170,170)" let me = mob[mob.length - 1]; me.isBoss = true; 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.startingDamageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0 me.isInvulnerable = true - me.accelMag = 0.0001 + 0.0004 * Math.sqrt(simulation.accelScale) + me.accelMag = 0.00008 + 0.00045 * Math.sqrt(simulation.accelScale) me.memory = 250; + me.seePlayerFreq = 13 me.flapRate = 0.4 me.flapArc = 0.2 //don't go past 1.57 for normal flaps me.wingLength = 150 @@ -6092,7 +6090,7 @@ const spawn = { } }; me.do = function() { - this.seePlayerByHistory() + this.seePlayerByHistory(40) this.checkStatus(); this.attraction(); @@ -6118,26 +6116,24 @@ const spawn = { this.wing(a - Math.PI / 2 + this.angleOff + this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) this.wing(a + Math.PI / 2 - this.angleOff - this.flapArc * Math.sin(simulation.cycle * this.flapRate), this.wingLength, this.ellipticity) }; - angle -= 0.1 - mag -= 10 + + angle -= 0.07 let previousTailID = 0 - const nodes = Math.min(8 + Math.ceil(0.5 * simulation.difficulty), 40) + const nodes = Math.min(10 + Math.ceil(0.6 * simulation.difficulty), 60) for (let i = 0; i < nodes; ++i) { - 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 < 3) mob[mob.length - 1].snakeHeadID = me.id - if (i === 0) me.snakeBody1 = mob[mob.length - 1] //track this segment, so the difference in position between this segment and the head can be used to angle the wings - mob[mob.length - 1].previousTailID = previousTailID - previousTailID = mob[mob.length - 1].id + angle -= 0.1 + spawn.snakeBody(x + tailRadius * Math.cos(angle), y + tailRadius * Math.sin(angle), i === 0 ? 25 : 20); + const who = mob[mob.length - 1] + who.fill = `hsl(${160+40*Math.random()}, 100%, ${5 + 25*Math.random()*Math.random()}%)` + if (i < 3) who.snakeHeadID = me.id + if (i === 0) me.snakeBody1 = who //track this segment, so the difference in position between this segment and the head can be used to angle the wings + who.previousTailID = previousTailID + previousTailID = who.id } const damping = 1 const stiffness = 1 this.constrain2AdjacentMobs(nodes, stiffness, false, damping); - for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors - mob[i].fill = `hsla(${160+40*Math.random()}, 100%, ${5 + 25*Math.random()*Math.random()}%, 0.9)` - } - //constraint with first 3 mobs in line + //constraint with first few mobs in tail consBB[consBB.length] = Constraint.create({ bodyA: mob[mob.length - nodes], bodyB: mob[mob.length - 1 - nodes], @@ -6159,13 +6155,12 @@ const spawn = { damping: damping }); Composite.add(engine.world, consBB[consBB.length - 1]); - // spawn.shield(me, x, y, 1); }, snakeBody(x, y, radius = 10) { 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.damageReduction = 0.015 + me.damageReduction = 0.021 Matter.Body.setDensity(me, 0.0001); //normal is 0.001 // me.accelMag = 0.0007 * simulation.accelScale; diff --git a/js/tech.js b/js/tech.js index efcef70..46cd82b 100644 --- a/js/tech.js +++ b/js/tech.js @@ -78,37 +78,20 @@ const tech = { // if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1) // } // }, - addJunkTechToPool(chance) { //chance is number between 0-1 - // { //count JUNK - // let count = 0 - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && tech.tech[i].isJunk && tech.tech[i].frequency > 0) count += tech.tech[i].frequency - // } - // console.log(count) - // } - // { //count not JUNK - // let count = 0 - // for (let i = 0, len = tech.tech.length; i < len; i++) { - // if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && tech.tech[i].frequency > 0) count++ - // } - // console.log(count) - // } - // count total non junk tech - id = "github" - - let count = 0 - for (let i = 0, len = tech.tech.length; i < len; i++) { - if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) count += tech.tech[i].frequency - } + addJunkTechToPool(percent) { //percent is number between 0-1 //make an array for possible junk tech to add let options = []; for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i); } - //add random array options to tech pool if (options.length) { - const num = chance * count //scale number added - for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++ + let countNonJunk = 0 // count total non junk tech + for (let i = 0, len = tech.tech.length; i < len; i++) { + if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) countNonJunk += tech.tech[i].frequency + } + const num = percent * countNonJunk //scale number added + console.log(num) + for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++ //add random array options to tech pool simulation.makeTextLog(`tech.tech.push(${num.toFixed(0)} JUNK)`) return num } else { @@ -162,7 +145,7 @@ const tech = { if (tech.isMetaAnalysis && tech.tech[index].isJunk) { simulation.makeTextLog(`//tech: meta-analysis replaced junk tech with random tech`); tech.giveTech('random') - for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 40 * Math.random(), m.pos.y + 40 * Math.random(), "research"); + for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 40 * Math.random(), m.pos.y + 40 * Math.random(), "research"); return } @@ -225,6 +208,7 @@ const tech = { }, damageFromTech() { let dmg = 1 //m.fieldDamage + if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 7)) dmg *= 1 + 0.15 * m.coupling if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime if (tech.isNoDraftPause) dmg *= 1.34 if (tech.isCloakingDamage) dmg *= 1.35 @@ -257,7 +241,7 @@ const tech = { return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { - return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.016 * (simulation.difficultyMode ** 2))) + return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + tech.isQuantumEraserDuplication * (1 - 0.016 * (simulation.difficultyMode ** 2)) + (m.fieldMode === 0 || m.fieldMode === 9) * 0.05 * m.coupling) }, isScaleMobsWithDuplication: false, maxDuplicationEvent() { @@ -306,41 +290,7 @@ const tech = { } } }, - tech: [ - // { - // name: "field coupling", - // descriptionFunction() { - // return `+1 field coupling (${m.fieldUpgrades[m.fieldMode].name})
${ m.couplingDescription()}` - // }, - // // isFieldTech: true, - // maxCount: 9, - // count: 0, - // frequency: 2, - // frequencyDefault: 2, - // allowed() { - // return (build.isExperimentSelection || powerUps.research.count > 1) - // }, - // requires: "", - // // researchUsed: 0, - // // couplingToResearch: 0.1, - // effect() { - // m.coupling++ - // // while (powerUps.research.count > 0) { - // // powerUps.research.changeRerolls(-1) - // // this.researchUsed++ - // // m.coupling += this.couplingToResearch - // // } - // }, - // remove() { - // m.coupling = 0 - // // if (this.count) { - // // m.coupling -= this.researchUsed * this.couplingToResearch - // // powerUps.research.changeRerolls(this.researchUsed) - // // this.researchUsed = 0 - // // } - // } - // }, - { + tech: [{ name: "ordnance", description: "double the frequency of finding guntech
spawn a gun", maxCount: 1, @@ -449,7 +399,7 @@ const tech = { }, { name: "active cooling", - description: "for each gun in your inventory
+20% fire rate", + description: "for each gun in your inventory
+18% fire rate", maxCount: 1, count: 0, frequency: 1, @@ -624,7 +574,7 @@ const tech = { return !tech.isEnergyNoAmmo }, requires: "not exciton", - effect: () => { + effect() { tech.isAmmoFromHealth = true; }, remove() { @@ -695,7 +645,7 @@ const tech = { frequencyDefault: 1, allowed() { return true }, requires: "", - effect: () => { + effect() { tech.restDamage += 0.36 }, remove() { @@ -704,7 +654,7 @@ const tech = { }, { name: "Higgs mechanism", - description: "+50% fire rate
while firing your position is fixed", + description: "+45% fire rate
while firing your position is fixed", maxCount: 1, count: 0, frequency: 1, @@ -713,7 +663,7 @@ const tech = { return !m.isShipMode && !tech.isAlwaysFire, !tech.isGrapple }, requires: "not ship mode, automatic, grappling hook", - effect: () => { + effect() { tech.isFireMoveLock = true; b.setFireCD(); b.setFireMethod(); @@ -876,7 +826,7 @@ const tech = { }, { name: "heuristics", - description: "+33% fire rate", + description: "+30% fire rate", maxCount: 9, count: 0, frequency: 1, @@ -884,7 +834,7 @@ const tech = { allowed() { return true }, requires: "", effect() { - tech.fireRate *= 0.67 + tech.fireRate *= 0.7 b.setFireCD(); }, remove() { @@ -941,7 +891,7 @@ const tech = { return !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath }, requires: "no other mob death tech", - effect: () => { + effect() { tech.isExplodeMob = true; }, remove() { @@ -959,7 +909,7 @@ const tech = { return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath }, requires: "no other mob death tech", - effect: () => { + effect() { tech.nailsDeathMob++ }, remove() { @@ -993,7 +943,7 @@ const tech = { }, { name: "reaction inhibitor", - description: "after mobs spawn
remove +13% of their durability", //health + description: "-13% maximum mob health", //health maxCount: 3, count: 0, frequency: 1, @@ -1002,16 +952,17 @@ const tech = { return true //tech.nailsDeathMob || tech.sporesOnDeath || tech.isExplodeMob || tech.botSpawner || tech.isMobBlockFling || tech.iceIXOnDeath }, requires: "", //"any mob death tech", - effect: () => { - tech.mobSpawnWithHealth *= 0.87 - + effect() { + tech.mobSpawnWithHealth++ + mobs.setMobSpawnHealth() //set all mobs at full health to 0.85 for (let i = 0; i < mob.length; i++) { - if (mob.health > tech.mobSpawnWithHealth) mob.health = tech.mobSpawnWithHealth + if (mob.health > mobs.mobSpawnWithHealth) mob.health = mobs.mobSpawnWithHealth } }, remove() { - tech.mobSpawnWithHealth = 1; + tech.mobSpawnWithHealth = 0 + mobs.setMobSpawnHealth() } }, { @@ -1620,7 +1571,7 @@ const tech = { return b.totalBots() > 1 || build.isExperimentSelection }, requires: "at least 2 bots", - effect: () => { + effect() { tech.isExtraBotOption = true for (let i = 0; i < 2; i++) b.randomBot() }, @@ -1645,7 +1596,7 @@ const tech = { return tech.isExtraBotOption }, requires: "robotics", - effect: () => { + effect() { for (let i = 0; i < 3; i++) b.randomBot() for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].isBotTech) tech.tech[i].frequency *= 3 @@ -1771,23 +1722,23 @@ const tech = { tech.isBlockPowerUps = false } }, - { - name: "Pauli exclusion", - description: `after mob collisions
become invulnerable for +3 seconds`, - maxCount: 9, - count: 0, - frequency: 1, - frequencyDefault: 1, - allowed() { return true }, - requires: "", - effect() { - tech.collisionImmuneCycles += 180; - if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage - }, - remove() { - tech.collisionImmuneCycles = 30; - } - }, + // { + // name: "Pauli exclusion", + // description: `after mob collisions
become invulnerable for +3 seconds`, + // maxCount: 9, + // count: 0, + // frequency: 1, + // frequencyDefault: 1, + // allowed() { return true }, + // requires: "", + // effect() { + // m.collisionImmuneCycles += 180; + // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage + // }, + // remove() { + // m.collisionImmuneCycles = 30; + // } + // }, { name: "spin–statistics theorem", description: `every 7 seconds
become invulnerable for +1.75 seconds`, @@ -1796,7 +1747,7 @@ const tech = { frequency: 1, frequencyDefault: 1, allowed() { - return true //tech.collisionImmuneCycles > 30 + return true //m.collisionImmuneCycles > 30 }, requires: "", effect() { @@ -2002,7 +1953,7 @@ const tech = { return tech.isRelay }, requires: "relay switch", - effect: () => { + effect() { tech.isRelayEnergy = true m.setMaxEnergy() }, @@ -2076,7 +2027,7 @@ const tech = { return !tech.isEnergyHealth }, requires: "not mass-energy", - effect: () => { + effect() { tech.isMACHO = true; //this harm reduction comes from the particle toggling tech.isHarmMACHO spawn.MACHO() }, @@ -2099,7 +2050,7 @@ const tech = { return tech.isMACHO }, requires: "MACHO", - effect: () => { + effect() { tech.isAxion = true }, remove() { @@ -2233,7 +2184,7 @@ const tech = { return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isMutualism //&& !tech.isAmmoFromHealth && !tech.isRewindGun }, requires: "not Zeno, ergodicity, piezoelectricity, CPT, antiscience, mutualism", - effect: () => { + effect() { m.health = 0 document.getElementById("health").style.display = "none" document.getElementById("health-bg").style.display = "none" @@ -2329,7 +2280,7 @@ const tech = { frequencyDefault: 1, allowed() { return true }, requires: "", - effect: () => { + effect() { tech.isEnergyDamage = true }, remove() { @@ -2348,14 +2299,14 @@ const tech = { return !tech.isTimeCrystals }, requires: "not time crystals", - effect: () => { - m.fieldRegen = 0.0005 + effect() { tech.isGroundState = true + m.setFieldRegen() m.setMaxEnergy() }, remove() { - m.fieldRegen = 0.001; tech.isGroundState = false + m.setFieldRegen() m.setMaxEnergy() } }, @@ -2475,7 +2426,7 @@ const tech = { effect() { tech.isCrouchRegen = true; //only used to check for requirements m.regenEnergy = function() { - if (m.immuneCycle < m.cycle && m.crouch) m.energy += 7 * m.fieldRegen; //m.fieldRegen = 0.001 + if (m.immuneCycle < m.cycle && m.crouch) m.energy += 7 * m.fieldRegen; if (m.energy < 0) m.energy = 0 } }, @@ -2549,7 +2500,7 @@ const tech = { effect() { tech.isDamageAfterKillNoRegen = true; m.regenEnergy = function() { - if (m.immuneCycle < m.cycle && (m.lastKillCycle + 300 < m.cycle)) m.energy += m.fieldRegen; //m.fieldRegen = 0.001 + if (m.immuneCycle < m.cycle && (m.lastKillCycle + 300 < m.cycle)) m.energy += m.fieldRegen; if (m.energy < 0) m.energy = 0 } }, @@ -3013,7 +2964,7 @@ const tech = { }, { name: "perturbation theory", - description: `if you have no ${powerUps.orb.research(1)} in your inventory
+66% fire rate`, + description: `if you have no ${powerUps.orb.research(1)} in your inventory
+60% fire rate`, maxCount: 1, count: 0, frequency: 1, @@ -3024,7 +2975,7 @@ const tech = { requires: "no research", effect() { tech.isRerollHaste = true; - tech.researchHaste = 0.33; + tech.researchHaste = 0.4; b.setFireCD(); }, remove() { @@ -3044,7 +2995,7 @@ const tech = { return powerUps.research.count === 0 && !tech.isSuperDeterminism && !tech.isRerollHaste && !tech.isResearchReality }, requires: "no research, not superdeterminism, Ψ(t) collapse, perturbation theory", - effect: () => { + effect() { tech.isAnsatz = true; }, remove() { @@ -3119,7 +3070,7 @@ const tech = { return !tech.isDeterminism && tech.duplicationChance() < 1 }, requires: "below 100% duplication chance not determinism", - effect: () => { + effect() { tech.isExtraGunField = true; }, remove() { @@ -3137,7 +3088,7 @@ const tech = { return !tech.isDeterminism }, requires: "not determinism", - effect: () => { + effect() { tech.extraChoices += 2; this.refundAmount += tech.addJunkTechToPool(0.04) }, @@ -3183,7 +3134,7 @@ const tech = { return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices }, requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary, integrated circuit", - effect: () => { + effect() { tech.isDeterminism = true; //if you change the number spawned also change it in Born rule for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech"); @@ -3205,7 +3156,7 @@ const tech = { return tech.isDeterminism && !tech.isAnsatz }, requires: "NOT EXPERIMENT MODE, determinism, not ansatz", - effect: () => { + effect() { tech.isSuperDeterminism = true; //if you change the number spawned also change it in Born rule for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech"); @@ -3314,7 +3265,7 @@ const tech = { }, { name: "meta-analysis", - description: `if you choose a JUNK tech you instead get a
random normal tech and ${powerUps.orb.research(1)}`, + description: `if you choose a JUNK tech you instead get a
random normal tech and ${powerUps.orb.research(2)}`, maxCount: 1, count: 0, frequency: 1, @@ -3496,7 +3447,7 @@ const tech = { return tech.duplicationChance() < 1.11 }, requires: "below 111% duplication chance", - effect: () => { + effect() { tech.isStimulatedEmission = true powerUps.setDupChance(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15); @@ -3517,7 +3468,7 @@ const tech = { return tech.duplicationChance() < 1.11 }, requires: "below 111% duplication chance", - effect: () => { + effect() { tech.isPowerUpsVanish = true powerUps.setDupChance(); //needed after adjusting duplication chance if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.12); @@ -3596,7 +3547,7 @@ const tech = { return (tech.totalCount > 6) }, requires: "NOT EXPERIMENT MODE, more than 6 tech", - effect: () => { + effect() { //remove active bullets //to get rid of bots for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]); bullet = []; @@ -3664,7 +3615,7 @@ const tech = { return (tech.totalCount > 3) && !tech.isSuperDeterminism }, requires: "NOT EXPERIMENT MODE, at least 4 tech, not superdeterminism", - effect: () => { + effect() { const have = [] //find which tech you have for (let i = 0; i < tech.tech.length; i++) { if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) have.push(i) @@ -3696,7 +3647,7 @@ const tech = { return (tech.totalCount > 3) && tech.duplicationChance() > 0 && !tech.isSuperDeterminism }, requires: "NOT EXPERIMENT MODE, some duplication, at least 4 tech, not superdeterminism", - effect: () => { + effect() { const removeTotal = tech.removeTech() for (let i = 0; i < removeTotal + 1; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech"); }, @@ -3716,7 +3667,7 @@ const tech = { return !tech.isSuperDeterminism && tech.duplicationChance() > 0 && powerUps.research.count > 1 }, requires: "NOT EXPERIMENT MODE, some duplication, not superdeterminism", - effect: () => { + effect() { powerUps.research.changeRerolls(-2) simulation.makeTextLog(`m.research -= 2`) powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); @@ -3735,7 +3686,7 @@ const tech = { return tech.totalCount > 9 }, requires: "at least 10 tech", - effect: () => { + effect() { for (let i = 0, len = tech.tech.length; i < len; i++) { if (tech.tech[i].count > 0) tech.tech[i].frequency *= 10 } @@ -4575,13 +4526,14 @@ const tech = { return tech.haveGunCheck("matter wave") && !tech.isPhaseVelocity && !tech.isBulletTeleport }, requires: "matter wave, not phase velocity, uncertainty principle", + ammoScale: 11, effect() { tech.isLongitudinal = true; for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (b.guns[i].name === "matter wave") { b.guns[i].chooseFireMethod() - b.guns[i].ammoPack = b.guns[i].defaultAmmoPack / 10 - b.guns[i].ammo = Math.ceil(b.guns[i].ammo / 10); + b.guns[i].ammoPack = b.guns[i].defaultAmmoPack / this.ammoScale + b.guns[i].ammo = Math.ceil(b.guns[i].ammo / this.ammoScale); simulation.updateGunHUD(); break } @@ -4594,7 +4546,7 @@ const tech = { tech.isLongitudinal = false; b.guns[i].chooseFireMethod() b.guns[i].ammoPack = b.guns[i].defaultAmmoPack - b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 10); + b.guns[i].ammo = Math.ceil(b.guns[i].ammo * this.ammoScale); simulation.updateGunHUD(); break } @@ -4771,7 +4723,7 @@ const tech = { return tech.explosiveRadius === 1 && !tech.isSmallExplosion && !tech.isBlockExplode && !tech.fragments && (tech.haveGunCheck("missiles") || tech.missileBotCount || tech.isIncendiary || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isPulseLaser || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.isBoomBotUpgrade || tech.isTokamak) }, requires: "an explosive damage source, not ammonium nitrate, nitroglycerin, chain reaction, fragmentation", - effect: () => { + effect() { tech.isExplodeRadio = true; //iridium-192 }, remove() { @@ -4809,7 +4761,7 @@ const tech = { return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() }, requires: "an explosive damage source, not iridium-192", - effect: () => { + effect() { tech.explosiveRadius += 0.24; }, remove() { @@ -4828,7 +4780,7 @@ const tech = { return !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() && !tech.isExplosionHarm }, requires: "an explosive damage source, not iridium-192, acetone peroxide", - effect: () => { + effect() { tech.isSmallExplosion = true; }, remove() { @@ -4848,7 +4800,7 @@ const tech = { return tech.hasExplosiveDamageCheck() && !tech.isSmallExplosion }, requires: "an explosive damage source, not nitroglycerin", - effect: () => { + effect() { tech.isExplosionHarm = true; }, remove() { @@ -4886,7 +4838,7 @@ const tech = { return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 3) && (tech.haveGunCheck("missiles") || (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)) }, requires: "an explosive damage source, not electric reactive armor", - effect: () => { + effect() { tech.isSmartRadius = true; for (let i = 0; i < 4; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) @@ -4910,7 +4862,7 @@ const tech = { return !tech.isSmartRadius && !tech.isExplodeRadio && tech.hasExplosiveDamageCheck() && !tech.isEnergyHealth }, requires: "an explosive damage source, not iridium-192, mass-energy", - effect: () => { + effect() { tech.isImmuneExplosion = true; }, remove() { @@ -6461,6 +6413,41 @@ const tech = { //************************************************** field //************************************************** tech //************************************************** + { + name: "coupling", + descriptionFunction() { + return `+1 field coupling (${m.fieldUpgrades[m.fieldMode].name})
${ m.couplingDescription()}` + }, + // isFieldTech: true, + maxCount: 9, + count: 0, + frequency: 1, + frequencyDefault: 1, + allowed() { + return (build.isExperimentSelection || powerUps.research.count > 1) + }, + requires: "", + // researchUsed: 0, + // couplingToResearch: 0.1, + effect() { + m.coupling++ + m.couplingChange() + // while (powerUps.research.count > 0) { + // powerUps.research.changeRerolls(-1) + // this.researchUsed++ + // m.coupling += this.couplingToResearch + // } + }, + remove() { + m.coupling -= this.count + m.couplingChange() + // if (this.count) { + // m.coupling -= this.researchUsed * this.couplingToResearch + // powerUps.research.changeRerolls(this.researchUsed) + // this.researchUsed = 0 + // } + } + }, { name: "zero point energy", description: `use ${powerUps.orb.research(2)}
+100 maximum energy`, @@ -6808,7 +6795,7 @@ const tech = { return powerUps.research.count > 1 && (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") }, requires: "NOT EXPERIMENT MODE, molecular assembler", - effect: () => { + effect() { for (let i = 0; i < 2; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) } @@ -6834,7 +6821,7 @@ const tech = { return powerUps.research.count > 2 && (m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") }, requires: "NOT EXPERIMENT MODE, molecular assembler", - effect: () => { + effect() { for (let i = 0; i < 3; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) } @@ -6988,7 +6975,7 @@ const tech = { return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" }, requires: "molecular assembler, pilot wave, standing wave", - effect: () => { + effect() { tech.isMassEnergy = true // used in m.grabPowerUp m.energy += 2 }, @@ -7278,13 +7265,13 @@ const tech = { return !tech.isGroundState && (m.fieldUpgrades[m.fieldMode].name === "time dilation" || m.fieldUpgrades[m.fieldMode].name === "pilot wave") }, requires: "time dilation or pilot wave, not ground state", - effect: () => { - m.fieldRegen = 0.004 + effect() { tech.isTimeCrystals = true + m.setFieldRegen() }, remove() { - m.fieldRegen = 0.001 tech.isTimeCrystals = false + m.setFieldRegen() } }, { @@ -7492,7 +7479,7 @@ const tech = { return m.fieldUpgrades[m.fieldMode].name === "wormhole" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" || m.fieldUpgrades[m.fieldMode].name === "time dilation" }, requires: "wormhole or pilot wave", - effect: () => { + effect() { tech.wimpCount++ spawn.WIMP() for (let j = 0, len = 5; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false) @@ -8646,7 +8633,7 @@ const tech = { return !tech.isFireMoveLock }, requires: "not Higgs mechanism", - effect: () => { + effect() { tech.isAlwaysFire = true; b.setFireMethod(); }, @@ -9346,7 +9333,7 @@ const tech = { ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.strokeStyle = "#333"; @@ -9389,7 +9376,7 @@ const tech = { ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.strokeStyle = "#333"; @@ -9458,7 +9445,7 @@ const tech = { ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.stroke(); ctx.moveTo(19, 0); @@ -9566,7 +9553,7 @@ const tech = { ctx.rotate(m.angle); ctx.beginPath(); ctx.arc(0, 0, 30, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient + ctx.fillStyle = m.bodyGradient ctx.fill(); ctx.strokeStyle = "#333"; ctx.lineWidth = 2; @@ -9586,7 +9573,7 @@ const tech = { ctx.stroke(); ctx.beginPath(); ctx.arc(18, 13, 10, 0, 2 * Math.PI); - ctx.fillStyle = this.bodyGradient; + ctx.fillStyle = m.bodyGradient; ctx.fill(); ctx.stroke(); ctx.beginPath(); @@ -10266,7 +10253,6 @@ const tech = { plasmaBotCount: null, missileBotCount: null, orbitBotCount: null, - collisionImmuneCycles: null, blockDmg: null, isBlockRadiation: null, isPiezo: null, diff --git a/todo.txt b/todo.txt index 76e01cd..4f02019 100644 --- a/todo.txt +++ b/todo.txt @@ -1,30 +1,52 @@ ******************************************************** NEXT PATCH ************************************************** -new setting: level ban list -bug fix: removed a command to preventDefault on space key, this might break something else -new boss added to level - Temple +tech: coupling - +1 coupling, coupling is a new stat that provides different buffs for each field + releasing this early for feedback about balance and bugs + +removed tech Pauli exclusion + now the perfect diamagnatism coupling effect + +snakeBoss tails are closer together +some bosses have a higher vision memory and response time + +phonon gets 10% less ammo and 10% less damage +meta-analysis gives 2 research per use +energy drain rework + in many situations drain no longer scales with regen + this might have some bad side effects, let me know + +bug fixes + made several tech effects not an arrow function + timeSkip graphical glitches might be improved -snake tails have a lower mass and whip around a bit -auto targeting no longer works for stealth mobs - snipers, sneakers, ghosters -snipers fire more often at high difficulty, but bullets move slower at all difficulties -hoppers have move gravity, so it feels like they are hopping a bit faster - *********************************************************** TODO ***************************************************** -tech: field coupling - +1 field coupling, coupling is a new stat that provides different buffs for each field - you can see your coupling in the pause menu -make field coupling a stat that shows in pause menu and is effected by other tech? + +coupling: + field emitter balance? + +coupling tech names: fine-structure constant, strongly coupled, Vibronic coupling tech: convert all research into "coupling" tech: +x% field coupling, your field changes randomly every y seconds tech: coupling starts at 200%, but decays when the field is in use, coupling recharges when the field is not in use some fields aren't used much (that's ok?) + Tech: Cancelling a tech/gun/field gives x coupling buffing your deflecting for 1 second after pressing the field button sounds cool 2 second cooldown on the effect to prevent spamming it buff: giving energy or doing damage makes sense maybe this could be a rework for bremstralung +rewindBoss: after hitting 1/5 damage theasholds the boss rewinds back in time to where it was a few seconds ago + track it's data like player history + +worms can target player, buff their damage + can't target player in first few seconds? + +draw player transparent or opaque when cloaking field is on + +plasma field tech - similar to regression, but for plasma ticks + greatly increase walking speed not mid air control? for time dilation field @@ -36,6 +58,8 @@ after taking damage explode while invulnerable quantum immortality: send you to a new tab after you die with a random load out basically everything is the same as it is now, but you switch tabs +Tech: Tech/guns/fields can no longer be duplicated. Duplication applies twice + tech: get sent to a new tab that closes in 3 minutes in the new tab you play reactor if you die in reactor you die in game, if you win you get 2-3 tech in the original game?