diff --git a/.DS_Store b/.DS_Store index 9c8cac0..2273425 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 434cc8f..302e2bd 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -96,7 +96,7 @@ const b = { outOfAmmo() { //triggers after firing when you have NO ammo simulation.makeTextLog(`${b.guns[b.activeGun].name}.ammo: 0`); m.fireCDcycle = m.cycle + 30; //fire cooldown - if (tech.isAmmoFromHealth && m.maxHealth > 0.01) { + if (tech.isAmmoFromHealth && m.health > 0.01) { tech.extraMaxHealth -= 0.01 //decrease max health m.setMaxHealth(); for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + 50 * (Math.random() - 0.5), m.pos.y + 50 * (Math.random() - 0.5), "ammo"); @@ -312,7 +312,7 @@ const b = { explosion(where, radius, color = "rgba(255,25,0,0.6)") { // typically explode is used for some bullets with .onEnd radius *= tech.explosiveRadius let dist, sub, knock; - let dmg = radius * 0.013 * (tech.isExplosionStun ? 0.7 : 1); + let dmg = radius * 0.017 * (tech.isExplosionStun ? 0.7 : 1); //* 0.013 * (tech.isExplosionStun ? 0.7 : 1); if (tech.isExplosionHarm) radius *= 1.8 // 1/sqrt(2) radius -> area if (tech.isSmallExplosion) { color = "rgba(255,0,30,0.7)" @@ -333,7 +333,7 @@ const b = { //player damage if (Vector.magnitude(Vector.sub(where, player.position)) < radius) { - const DRAIN = (tech.isExplosionHarm ? 0.7 : 0.25) * (tech.isRadioactiveResistance ? 0.25 : 1) + const DRAIN = (tech.isExplosionHarm ? 1.2 : 0.45) * (tech.isRadioactiveResistance ? 0.25 : 1) // * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1) if (m.immuneCycle < m.cycle) m.energy -= DRAIN if (m.energy < 0) { @@ -381,11 +381,12 @@ const b = { dist = Vector.magnitude(sub); if (dist < radius) { + const harm = radius * (tech.isExplosionHarm ? 0.00055 : 0.00018) if (tech.isImmuneExplosion) { - const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0)) - m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0003 : 0.0001)); + const mitigate = Math.min(1, Math.max(1 - m.energy * 0.5, 0)) + m.damage(mitigate * harm); } else { - m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001)); + m.damage(harm); } knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013); player.force.x += knock.x; @@ -1713,7 +1714,8 @@ const b = { if (angle > -0.2 || angle < -1.5) { //don't stick to level ground Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setStatic(this, true) //don't set to static if not touching map - this.collisionFilter.mask = cat.map | cat.bullet + this.collisionFilter.category = 0 + this.collisionFilter.mask = 0 //cat.map | cat.bullet } else { Matter.Body.setVelocity(this, { x: 0, y: 0 }); Matter.Body.setAngularVelocity(this, 0) @@ -3219,7 +3221,7 @@ const b = { range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()), drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4, drain: (0.56 - 0.42 * tech.isLaserBotUpgrade) * tech.laserFieldDrain * tech.isLaserDiode, - laserDamage: 0.7 + 0.5 * tech.isLaserBotUpgrade, + laserDamage: 0.85 + 0.65 * tech.isLaserBotUpgrade, endCycle: Infinity, classType: "bullet", collisionFilter: { @@ -3312,7 +3314,7 @@ const b = { explode: 0, beforeDmg() { if (this.lockedOn) { - const explosionRadius = Math.min(170 + 220 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, m.pos)) - 30) + const explosionRadius = Math.min(136 + 180 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, m.pos)) - 30) if (explosionRadius > 60) { this.explode = explosionRadius // @@ -3399,12 +3401,10 @@ const b = { onEnd() {}, do() { const distanceToPlayer = Vector.magnitude(Vector.sub(this.position, m.pos)) - if (distanceToPlayer > 150) { //if far away move towards player - this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.acceleration) - } + if (distanceToPlayer > 150) this.force = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.mass * this.acceleration) //if far away move towards player Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.90), Vector.mult(player.velocity, 0.17))); //add player's velocity - //find closest - if (!(simulation.cycle % this.lookFrequency)) { + + if (!(simulation.cycle % this.lookFrequency)) { //find closest this.lockedOn = null; if (!m.isCloak) { let closeDist = tech.isPlasmaRange * 1000; @@ -3426,7 +3426,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.0003 + m.fieldRegen //0.004; //normal plasma field is 0.00008 + m.fieldRegen = 0.00108 + m.energy -= 0.00035 + m.fieldRegen //0.004; //normal plasma field is 0.00008 + m.fieldRegen = 0.00108 // if (m.energy < 0) { // m.fieldCDcycle = m.cycle + 120; // m.energy = 0; @@ -3501,7 +3501,7 @@ const b = { y: best.y }; if (best.who.alive) { - const dmg = 0.65 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* + const dmg = 0.6 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* best.who.damage(dmg); best.who.locatePlayer(); //push mobs away @@ -3593,26 +3593,16 @@ const b = { orbitalSpeed: 0, phase: 2 * Math.PI * Math.random(), do() { - - //check for damage if (!m.isCloak && !m.isBodiesAsleep) { //if time dilation isn't active - // q = Matter.Query.point(mob, this.position) - // q = Matter.Query.collides(this, mob) const size = 33 q = Matter.Query.region(mob, { - min: { - x: this.position.x - size, - y: this.position.y - size - }, - max: { - x: this.position.x + size, - y: this.position.y + size - } + min: { x: this.position.x - size, y: this.position.y - size }, + max: { x: this.position.x + size, y: this.position.y + size } }) for (let i = 0; i < q.length; i++) { if (!q[i].isShielded) { mobs.statusStun(q[i], 180) - const dmg = 0.5 * b.dmgScale * (this.isUpgraded ? 3.5 : 1) * (tech.isCrit ? 4 : 1) + const dmg = 0.4 * b.dmgScale * (this.isUpgraded ? 3.5 : 1) * (tech.isCrit ? 4 : 1) q[i].damage(dmg); if (q[i].alive) q[i].foundPlayer(); simulation.drawList.push({ //add dmg to draw queue @@ -4401,6 +4391,7 @@ const b = { if (tech.isPhaseVelocity) { waveSpeedMap = 3 waveSpeedBody = 1.9 + bullet[me].dmg *= 1.15 } if (tech.waveReflections) { bullet[me].reflectCycle = totalCycles / tech.waveReflections //tech.waveLengthRange diff --git a/js/index.js b/js/index.js index c2d3741..9941215 100644 --- a/js/index.js +++ b/js/index.js @@ -82,7 +82,6 @@ function getUrlVars() { return vars; } window.addEventListener('load', () => { - const set = getUrlVars() if (Object.keys(set).length !== 0) { build.populateGrid() //trying to solve a bug with this, but maybe it doesn't help @@ -290,6 +289,7 @@ const build = { window.scrollTo(0, 0); }, isExperimentSelection: false, + isExperimentRun: false, choosePowerUp(who, index, type, isAllowed = false) { if (type === "gun") { let isDeselect = false @@ -360,24 +360,32 @@ const build = { const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; //
- if (tech.tech[i].isFieldTech) { - techID.innerHTML = `
- -
-
-
-         ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` - //
- //
- // border: #fff solid 0px; - } else if (tech.tech[i].isGunTech) { - techID.innerHTML = `
- -
-
-
-         ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` - } else if (tech.tech[i].isJunk) { + // if (tech.tech[i].isFieldTech) { + // techID.classList.remove('experiment-grid-hide'); + + // techID.innerHTML = ` + //
+ // + //
+ //
+ //
+ //         ${tech.tech[i].name} ${isCount}
${tech.tech[i].description} + // ` + // //
+ // //
+ // // border: #fff solid 0px; + // } else if (tech.tech[i].isGunTech) { + // techID.classList.remove('experiment-grid-hide'); + // techID.innerHTML = ` + //
+ // + //
+ //
+ //
+ //         ${tech.tech[i].name} ${isCount}
${tech.tech[i].description} + // ` + // } else + if (tech.tech[i].isJunk) { // text += `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}
` techID.innerHTML = `
  ${tech.tech[i].name} ${isCount}
${tech.tech[i].description}` } else if (tech.tech[i].isExperimentalMode) { @@ -394,6 +402,8 @@ const build = { techID.classList.remove("experiment-grid-disabled"); techID.setAttribute("onClick", `javascript: build.choosePowerUp(this,${i},'tech')`); } + // } else if (tech.tech[i].isGunTech || tech.tech[i].isFieldTech) { + // techID.classList.add('experiment-grid-hide'); } else { //disabled color // techID.innerHTML = `
${tech.tech[i].name}
requires: ${tech.tech[i].requires}` // techID.innerHTML = `
${tech.tech[i].name}
requires: ${tech.tech[i].requires}` @@ -459,8 +469,15 @@ const build = { text += `
  ${tech.tech[i].name}
${tech.tech[i].description}
` } } else { - // text += `
${tech.tech[i].name}
requires: ${tech.tech[i].requires}
` text += `
${tech.tech[i].name}
${tech.tech[i].description}
` + // if (tech.tech[i].isGunTech || tech.tech[i].isFieldTech) { + // text += `
` //built but hidden + // } else { + // text += `
${tech.tech[i].name}
${tech.tech[i].description}
` + // } + // } else if (!tech.tech[i].isGunTech && !tech.tech[i].isFieldTech) { + // text += `
${tech.tech[i].name}
requires: ${tech.tech[i].requires}
` + } } } @@ -483,6 +500,7 @@ const build = { reset() { simulation.startGame(true); //starts game, but pauses it build.isExperimentSelection = true; + build.isExperimentRun = true; simulation.paused = true; m.setField(0) b.inventory = []; //removes guns and ammo diff --git a/js/level.js b/js/level.js index ec7504f..800be9a 100644 --- a/js/level.js +++ b/js/level.js @@ -62,7 +62,7 @@ const level = { spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns // spawn.pickList = ["focuser", "focuser"] level[level.levels[level.onLevel]](); //picks the current map from the the levels array - if (!simulation.isCheating) { + if (!simulation.isCheating && !build.isExperimentRun) { localSettings.runCount += level.levelsCleared //track the number of total runs locally localSettings.levelsClearedLastGame = level.levelsCleared localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage @@ -2273,12 +2273,12 @@ const level = { spawn.mapRect(4850, -275, 50, 175); // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // spawn.starter(1900, -500, 200) //big boy - spawn.necroBoss(1900, -500) + spawn.blockBoss(1900, -500) // for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40); // spawn.laserBombingBoss(1900, -500) // for (let i = 0; i < 5; i++) spawn.focuser(1900, -500) - // spawn.blockGroup(1900, -500) + // spawn.snakeSuckBoss(1900, -500) // spawn.grenadier(1900, -500) // spawn.sneaker(1900, -500) // spawn.shield(mob[mob.length - 1], 1900, -500, 1); @@ -2469,7 +2469,7 @@ const level = { powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 75, "heal", false); powerUps.spawnStartingPowerUps(2095 + 15 * (Math.random() - 0.5), -2070 - 125); if (localSettings.levelsClearedLastGame < 3) { - if (!simulation.isCheating && !m.isShipMode) { + if (!simulation.isCheating && !m.isShipMode && !build.isExperimentRun) { spawn.wireFoot(); spawn.wireFootLeft(); spawn.wireKnee(); @@ -2478,7 +2478,7 @@ const level = { // for (let i = 0; i < 3; i++) powerUps.spawn(2095, -1220 - 50 * i, "tech", false); //unavailable tech spawns // spawn.mapRect(2000, -1025, 200, 25); } - } else { + } else if (!build.isExperimentRun) { simulation.trails() //bonus power ups for clearing runs in the last game if (!simulation.isCheating && localSettings.levelsClearedLastGame > 1) { @@ -2489,13 +2489,103 @@ const level = { localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage } } + spawn.mapRect(2025, 0, 150, 50); //lid to floor hole } else { for (let i = 0; i < 60; i++) { setTimeout(() => { spawn.sneaker(2100, -1500 - 50 * i); }, 2000 + 500 * i); } } + const wires = new Path2D() //pre-draw the complex lighting path to save processing + wires.moveTo(-150, -275) + wires.lineTo(80, -275) + wires.lineTo(80, -1000) + wires.moveTo(-150, -265) + wires.lineTo(90, -265) + wires.lineTo(90, -1000) + wires.moveTo(-150, -255) + wires.lineTo(100, -255) + wires.lineTo(100, -1000) + wires.moveTo(-150, -245) + wires.lineTo(1145, -245) + wires.lineTo(1145, 0) + wires.moveTo(-150, -235) + wires.lineTo(1135, -235) + wires.lineTo(1135, 0) + wires.moveTo(-150, -225) + wires.lineTo(1125, -225) + wires.lineTo(1125, 0) + wires.moveTo(-150, -215) + wires.lineTo(460, -215) + wires.lineTo(460, 0) + wires.moveTo(-150, -205) + wires.lineTo(450, -205) + wires.lineTo(450, 0) + wires.moveTo(-150, -195) + wires.lineTo(440, -195) + wires.lineTo(440, 0) + + wires.moveTo(1155, 0) + wires.lineTo(1155, -450) + wires.lineTo(1000, -450) + wires.lineTo(1000, -1000) + wires.moveTo(1165, 0) + wires.lineTo(1165, -460) + wires.lineTo(1010, -460) + wires.lineTo(1010, -1000) + wires.moveTo(1175, 0) + wires.lineTo(1175, -470) + wires.lineTo(1020, -470) + wires.lineTo(1020, -1000) + wires.moveTo(1185, 0) + wires.lineTo(1185, -480) + wires.lineTo(1030, -480) + wires.lineTo(1030, -1000) + wires.moveTo(1195, 0) + wires.lineTo(1195, -490) + wires.lineTo(1040, -490) + wires.lineTo(1040, -1000) + + wires.moveTo(1625, -1000) + wires.lineTo(1625, 0) + wires.moveTo(1635, -1000) + wires.lineTo(1635, 0) + wires.moveTo(1645, -1000) + wires.lineTo(1645, 0) + wires.moveTo(1655, -1000) + wires.lineTo(1655, 0) + wires.moveTo(1665, -1000) + wires.lineTo(1665, 0) + + wires.moveTo(1675, -465) + wires.lineTo(2325, -465) + wires.lineTo(2325, 0) + wires.moveTo(1675, -455) + wires.lineTo(2315, -455) + wires.lineTo(2315, 0) + wires.moveTo(1675, -445) + wires.lineTo(2305, -445) + wires.lineTo(2305, 0) + wires.moveTo(1675, -435) + wires.lineTo(2295, -435) + wires.lineTo(2295, 0) + + wires.moveTo(2335, 0) + wires.lineTo(2335, -710) + wires.lineTo(2600, -710) + wires.moveTo(2345, 0) + wires.lineTo(2345, -700) + wires.lineTo(2600, -700) + wires.moveTo(2355, 0) + wires.lineTo(2355, -690) + wires.lineTo(2600, -690) level.custom = () => { + //push around power ups stuck in the tube wall + if (!(simulation.cycle % 30)) { + for (let i = 0, len = powerUp.length; i < len; i++) { + if (powerUp[i].position.y < -1000) powerUp[i].force.x += 0.01 * (Math.random() - 0.5) * powerUp[i].mass + } + } //draw binary number const binary = (localSettings.runCount >>> 0).toString(2) const height = 20 @@ -2521,93 +2611,10 @@ const level = { } ctx.stroke(); - //wires ctx.beginPath() - ctx.moveTo(-150, -275) - ctx.lineTo(80, -275) - ctx.lineTo(80, -1000) - ctx.moveTo(-150, -265) - ctx.lineTo(90, -265) - ctx.lineTo(90, -1000) - ctx.moveTo(-150, -255) - ctx.lineTo(100, -255) - ctx.lineTo(100, -1000) - ctx.moveTo(-150, -245) - ctx.lineTo(1145, -245) - ctx.lineTo(1145, 0) - ctx.moveTo(-150, -235) - ctx.lineTo(1135, -235) - ctx.lineTo(1135, 0) - ctx.moveTo(-150, -225) - ctx.lineTo(1125, -225) - ctx.lineTo(1125, 0) - ctx.moveTo(-150, -215) - ctx.lineTo(460, -215) - ctx.lineTo(460, 0) - ctx.moveTo(-150, -205) - ctx.lineTo(450, -205) - ctx.lineTo(450, 0) - ctx.moveTo(-150, -195) - ctx.lineTo(440, -195) - ctx.lineTo(440, 0) - - ctx.moveTo(1155, 0) - ctx.lineTo(1155, -450) - ctx.lineTo(1000, -450) - ctx.lineTo(1000, -1000) - ctx.moveTo(1165, 0) - ctx.lineTo(1165, -460) - ctx.lineTo(1010, -460) - ctx.lineTo(1010, -1000) - ctx.moveTo(1175, 0) - ctx.lineTo(1175, -470) - ctx.lineTo(1020, -470) - ctx.lineTo(1020, -1000) - ctx.moveTo(1185, 0) - ctx.lineTo(1185, -480) - ctx.lineTo(1030, -480) - ctx.lineTo(1030, -1000) - ctx.moveTo(1195, 0) - ctx.lineTo(1195, -490) - ctx.lineTo(1040, -490) - ctx.lineTo(1040, -1000) - - ctx.moveTo(1625, -1000) - ctx.lineTo(1625, 0) - ctx.moveTo(1635, -1000) - ctx.lineTo(1635, 0) - ctx.moveTo(1645, -1000) - ctx.lineTo(1645, 0) - ctx.moveTo(1655, -1000) - ctx.lineTo(1655, 0) - ctx.moveTo(1665, -1000) - ctx.lineTo(1665, 0) - - ctx.moveTo(1675, -465) - ctx.lineTo(2325, -465) - ctx.lineTo(2325, 0) - ctx.moveTo(1675, -455) - ctx.lineTo(2315, -455) - ctx.lineTo(2315, 0) - ctx.moveTo(1675, -445) - ctx.lineTo(2305, -445) - ctx.lineTo(2305, 0) - ctx.moveTo(1675, -435) - ctx.lineTo(2295, -435) - ctx.lineTo(2295, 0) - - ctx.moveTo(2335, 0) - ctx.lineTo(2335, -710) - ctx.lineTo(2600, -710) - ctx.moveTo(2345, 0) - ctx.lineTo(2345, -700) - ctx.lineTo(2600, -700) - ctx.moveTo(2355, 0) - ctx.lineTo(2355, -690) - ctx.lineTo(2600, -690) ctx.strokeStyle = "#ccc" ctx.lineWidth = 5; - ctx.stroke(); + ctx.stroke(wires); //squares that look like they keep the wires in place ctx.beginPath() @@ -2677,7 +2684,6 @@ const level = { spawn.mapRect(2150, 0, 1200, 1800); //split roof spawn.mapRect(2025, -3, 25, 15); //lip on power up chamber spawn.mapRect(2150, -3, 25, 15); //lip on power up chamber - spawn.mapRect(2025, 0, 150, 50); // spawn.mapRect(-250, -2800, 3600, 1800); //roof spawn.mapRect(-250, -2800, 2300, 1800); //split roof diff --git a/js/player.js b/js/player.js index 32a7ee0..fa6a7b2 100644 --- a/js/player.js +++ b/js/player.js @@ -2587,9 +2587,9 @@ const m = { }, { name: "wormhole", - description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
8% chance to duplicate spawned power ups", //
bullets may also traverse wormholes + description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups
7% chance to duplicate spawned power ups", //
bullets may also traverse wormholes effect: function() { - m.duplicateChance = 0.08 + m.duplicateChance = 0.07 powerUps.setDo(); //needed after adjusting duplication chance m.hold = function() { diff --git a/js/powerup.js b/js/powerup.js index bc9d96b..9c281c9 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -260,11 +260,11 @@ const powerUps = { tech.maxDuplicationEvent() } if (tech.isCancelRerolls) { - for (let i = 0; i < 9; i++) { + for (let i = 0, len = 5 + 5 * Math.random(); i < len; i++) { let spawnType = ((m.health < 0.25 && !tech.isEnergyHealth) || tech.isEnergyNoAmmo) ? "heal" : "ammo" - if (Math.random() < 0.33) { + if (Math.random() < 0.36) { spawnType = "heal" - } else if (Math.random() < 0.5 && !tech.isSuperDeterminism) { + } else if (Math.random() < 0.4 && !tech.isSuperDeterminism) { spawnType = "research" } powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), spawnType, false); diff --git a/js/simulation.js b/js/simulation.js index d95b481..bb4519a 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -644,6 +644,7 @@ const simulation = { simulation.difficultyMode = Number(document.getElementById("difficulty-select").value) build.isExperimentSelection = false; + build.isExperimentRun = false; simulation.clearNow = true; document.getElementById("text-log").style.opacity = 0; document.getElementById("fade-out").style.opacity = 0; diff --git a/js/spawn.js b/js/spawn.js index c1bfab5..372db82 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -1,7 +1,7 @@ //main object for spawning things in a level const spawn = { nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"], - randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "blockBoss", "blockBoss"]) { + randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "blockBoss"]) { // other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, @@ -726,14 +726,14 @@ const spawn = { } } }, - blockBoss(x, y, radius = 30) { + blockBoss(x, y, radius = 60) { const activeBeams = []; // used to draw beams when converting const beamTotalDuration = 60 mobs.spawn(x, y, 4, radius, "#999"); //#54291d const me = mob[mob.length - 1]; me.isBoss = true; - // Matter.Body.setDensity(me, 0.001); //normal density even though its a boss - me.damageReduction = 0.06; //extra reduction for a boss, because normal density + Matter.Body.setDensity(me, 0.002); //normal density even though its a boss + me.damageReduction = 0.05; //extra reduction for a boss, because normal density me.frictionAir = 0.01; me.accelMag = 0.0002; me.onDeath = function() { @@ -786,14 +786,19 @@ const spawn = { } //randomly spawn new mobs from nothing - if (!(simulation.cycle % 120)) { + if (!(simulation.cycle % 90)) { let count = 0 for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].isNecroMob) count++ } - if (count < 12 * Math.random() * Math.random()) { //limit number of spawns if there are already too many blockMobs + if (count < 20 * Math.random() * Math.random()) { //limit number of spawns if there are already too many blockMobs const unit = Vector.normalise(Vector.sub(player.position, this.position)) for (let i = 0, len = 3 * Math.random(); i < len; i++) { + this.damageReduction += 0.001; //0.05 is starting value + const scale = 0.99; //if 120 use 1.02 + Matter.Body.scale(this, scale, scale); + this.radius *= scale; + const where = Vector.add(Vector.mult(unit, radius + 200 * Math.random()), this.position) spawn.blockMob(where.x + 100 * (Math.random() - 0.5), where.y + 100 * (Math.random() - 0.5), null); this.torque += 0.000035 * this.inertia; //spin after spawning @@ -1836,7 +1841,7 @@ const spawn = { mobs.spawn(x, y, 0, radius, "transparent"); let me = mob[mob.length - 1]; Matter.Body.setDensity(me, 0.21); //extra dense //normal is 0.001 - me.laserRange = 300; + me.laserRange = 350; me.seeAtDistance2 = 2000000; me.isBoss = true; @@ -1849,7 +1854,7 @@ const spawn = { me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) }; - me.damageReduction = 0.25 // me.damageReductionGoal + me.damageReduction = 0.35 // me.damageReductionGoal me.awake = function() { // this.armor(); this.checkStatus(); @@ -1879,9 +1884,9 @@ const spawn = { if (this.distanceToPlayer() < this.laserRange) { if (m.immuneCycle < m.cycle) { if (m.energy > 0.002) { - m.energy -= 0.0035 + m.energy -= 0.004 } else { - m.damage(0.0003 * simulation.dmgScale) + m.damage(0.0004 * simulation.dmgScale) } } ctx.beginPath(); diff --git a/js/tech.js b/js/tech.js index 0d39a1e..4f7bcbd 100644 --- a/js/tech.js +++ b/js/tech.js @@ -193,7 +193,7 @@ return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { - return (tech.isPowerUpsVanish ? 0.15 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.cancelCount * 0.047 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) + return (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.17 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0) }, maxDuplicationEvent() { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { @@ -849,7 +849,6 @@ { name: "shock wave", description: "explosions stun mobs for 1-2 seconds
decrease explosive damage by 30%", - isGunTech: true, maxCount: 1, count: 0, frequency: 1, @@ -868,7 +867,7 @@ { name: "electric reactive armor", // description: "explosions do no harm
while your energy is above 98%", - description: "harm from explosions is passively reduced
by 6% for every 10 stored energy", + description: "harm from explosions is passively reduced
by 5% for every 10 stored energy", maxCount: 1, count: 0, frequency: 2, @@ -892,7 +891,7 @@ frequency: 1, frequencyDefault: 1, allowed() { - return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot + return ((m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isDroneTeleport || tech.isDroneRadioactive || tech.isSporeField || tech.isMissileField || tech.isIceField)) || (tech.haveGunCheck("drones") && !tech.isDroneRadioactive && !tech.isDroneTeleport) || tech.haveGunCheck("super balls") || tech.haveGunCheck("shotgun")) && !tech.isNailShot && !tech.isIceShot && !tech.isFoamShot && !tech.isWormShot && !tech.isNeedles }, requires: "super balls, basic or slug shotgun, drones, not irradiated drones or burst drones", effect() { @@ -1590,7 +1589,7 @@ frequency: 3, frequencyDefault: 3, allowed() { - return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name === "pilot wave" && !tech.isTokamak + return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak }, requires: "mass driver, not pilot wave not tokamak", effect() { @@ -1608,7 +1607,7 @@ frequency: 3, frequencyDefault: 3, allowed() { - return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name === "pilot wave" && !tech.isTokamak + return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isTokamak }, requires: "mass driver, not pilot wave not tokamak", effect() { @@ -1662,7 +1661,7 @@ frequency: 3, frequencyDefault: 3, allowed() { - return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name === "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isEnergyHealth + return tech.throwChargeRate > 1 && m.fieldUpgrades[m.fieldMode].name !== "pilot wave" && m.fieldUpgrades[m.fieldMode].name !== "wormhole" && !tech.isEnergyHealth }, requires: "mass driver, a field that can hold things, not mass-energy", effect() { @@ -2182,7 +2181,7 @@ frequency: 1, frequencyDefault: 1, allowed() { - return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isTechDamage && !tech.isMutualism + return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isTechDamage && !tech.isMutualism //&& !tech.isAmmoFromHealth }, requires: "not Zeno, ergodicity, piezoelectricity, CPT, rewind gun, antiscience, mutualism", effect: () => { @@ -2391,9 +2390,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isRailEnergyGain || tech.isWormholeEnergy || tech.iceEnergy > 0 || tech.isMassEnergy || tech.isTokamak + return m.energy > m.maxEnergy || build.isExperimentSelection }, - requires: "a source of overfilled energy", + requires: "energy above your max", effect() { tech.overfillDrain = 0.85 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87) tech.addJunkTechToPool(18) @@ -3057,7 +3056,7 @@ }, { name: "stimulated emission", - description: "20% chance to duplicate spawned power ups
but, after a collision eject 1 tech", + description: "17% chance to duplicate spawned power ups
but, after a collision eject 1 tech", maxCount: 1, count: 0, frequency: 1, @@ -3077,7 +3076,7 @@ }, { name: "metastability", - description: "15% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ", + description: "13% chance to duplicate spawned power ups
duplicates explode with a 3 second half-life ", maxCount: 1, count: 0, frequency: 1, @@ -3097,7 +3096,7 @@ }, { name: "futures exchange", - description: "clicking × to cancel a field, tech, or gun
adds 4.7% power up duplication chance", + description: "clicking × to cancel a field, tech, or gun
adds 4.5% power up duplication chance", maxCount: 1, count: 0, frequency: 1, @@ -3117,7 +3116,7 @@ }, { name: "commodities exchange", - description: `clicking × to cancel a field, tech, or gun
spawns 9 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`, + description: `clicking × to cancel a field, tech, or gun
spawns 5-10 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`, maxCount: 1, count: 0, frequency: 1, @@ -3632,9 +3631,9 @@ frequency: 2, frequencyDefault: 2, allowed() { - return (tech.isNeedles || tech.isNeedleShot) && !tech.isNailRadiation + return (tech.isNeedles || tech.isNeedleShot) }, - requires: "needle gun, needle-shot, not irradiated nails", + requires: "needle gun, needle-shot", effect() { tech.isNeedleShieldPierce = true }, @@ -3864,7 +3863,7 @@ }, { name: "shotgun spin-statistics", - description: "immune to harm while firing the shotgun
shotgun has gives 50% fewer shots", + description: "immune to harm while firing the shotgun
shotgun has 50% fewer shots", isGunTech: true, maxCount: 1, count: 0, @@ -4129,7 +4128,8 @@ }, { name: "phase velocity", - description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", + description: "wave beam propagates faster through solids
increase wave beam damage by 15%", + // description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks", isGunTech: true, maxCount: 1, count: 0, @@ -4709,7 +4709,8 @@ }, { name: "drone repair", - description: "broken drones repair if the drone gun is active
repairing has a 25% chance to use 1 drone", + description: "after a drone ends it redeploys
for a 25% chance to use 1 drone ammo", + // description: "broken drones repair if the drone gun is active
repairing has a 25% chance to use 1 drone", isGunTech: true, maxCount: 1, count: 0, @@ -6077,7 +6078,7 @@ }, { name: "virtual particles", - description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
16% chance to duplicate spawned power ups`, + description: `use ${powerUps.orb.research(4)}to exploit your wormhole for a
14% chance to duplicate spawned power ups`, isFieldTech: true, maxCount: 1, count: 0, @@ -6088,7 +6089,7 @@ }, requires: "wormhole,below 100% duplication chance", effect() { - tech.wormDuplicate = 0.16 + tech.wormDuplicate = 0.14 powerUps.setDo(); //needed after adjusting duplication chance for (let i = 0; i < 4; i++) { if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1) @@ -6809,6 +6810,27 @@ }, remove() {} }, + { + name: "score", + description: "Add a score to n-gon!", + maxCount: 1, + count: 0, + frequency: 0, + isNonRefundable: true, + isExperimentHide: true, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() { + setInterval(() => { + let score = Math.ceil(1000 * Math.random() * Math.random() * Math.random() * Math.random() * Math.random()) + simulation.makeTextLog(`simulation.score = ${score.toFixed(0)}`); + }, 1000); //every 10 seconds + }, + remove() {} + }, { name: "pop-ups", description: "sign up to learn endless easy ways to win n-gon
that Landgreen doesn't want you to know!!!1!!", diff --git a/style.css b/style.css index b099a4a..0ce7060 100644 --- a/style.css +++ b/style.css @@ -272,6 +272,22 @@ summary { font-size: 0.65em; } +/* .experiment-grid-module-field { + background-color: #eff; + opacity: 1; + transition: opacity 0.5s ease; +} + +.experiment-grid-module-gun { + background-color: #eef; + opacity: 1; + transition: opacity 0.5s ease; +} */ + +.experiment-grid-hide { + display: none; +} + .grid-title { padding-bottom: 6px; font-size: 1.4em; @@ -306,6 +322,10 @@ summary { background-color: hsl(253, 100%, 81%); } +/* .experiment-grid-show { + display: inline; +} */ + .experiment-grid-disabled { /* opacity: 0.5; */ background-color: var(--build-bg-color); diff --git a/todo.txt b/todo.txt index cf4b697..8a8ecf8 100644 --- a/todo.txt +++ b/todo.txt @@ -1,21 +1,42 @@ ******************************************************** NEXT PATCH ************************************************** -blockBoss: new boss based on work by TheShwarma - (3x chance to randomly see blockBoss until next patch) - it's over powered, I'll probably nerf it next patch, but I want to get some feedback first on how to nerf it - hint: if you kill the boss all the mobBlocks turn back into blocks +all explosions do 33% more damage to mobs + and 75% more damage to player + boom bot explosions are 16% smaller -very very small blocks are slightly limited in how fast they can be thrown - they were moving so fast they would miss their target sometimes +laser-bot does 15% more damage +missile bot fires 15% quicker +tech: phase velocity also adds 15% wave damage (because it disables phonon is was a bad choice) +many duplication tech add less duplication +Maxwell's demon now requires current energy above your max to unlock -tech: energy conservation gives 5% energy back (was 6%) -tech: arsenal requires at least 3 guns in your inventory -tech: active cooling requires at least 2 guns in your inventory - -several bug fixes +power ups in the intro tube get pushed around a bit, this might stop them from sliding on the walls +mines when they are stuck to walls no longer collide with blocks (to not block elevator) +more bug fixes ******************************************************** TODO ******************************************************** +JUNK tech: add a score to in game console every 10 seconds + +tech - explode after getting hit, but while you are immune to harm + +on mouse down wormhole shows a possible wormhole + on mouse up the wormhole becomes real +make the player get a buff after using wormhole + while energy lasts: drain energy and give damage buff +using wormhole makes you immune to harm and drains energy until you run out + disable incoming energy, by saving current energy and just setting energy in the next cycle to be lower then the saved value + +make a boss with a tail + but the tail is made of interesting mobs + stabbers maybe + suckers maybe + +set blockBoss frequency to 1x not 3x + +block groups should look for player, so the player doesn't step on them? + remove heath bar? + fix simulation.CDScale // it's always zero so it does nothing some mobs can't see player... 3 laser boss isn't rotating... @@ -33,11 +54,6 @@ tech missiles - move faster and more accurately, turn sharper experiment and understand vibe more obvious mostly in early game or first time players - -work on blockBoss from TheShwarma - make spawned blocks in the direction of the player - make it search the level for blocks, but also kinda avoid the player - falling particle rain what causes it? after taking damage @@ -68,11 +84,6 @@ make non moving bosses not move after getting hit buff rail gun -make the player get a buff after using wormhole - while energy lasts: drain energy and give damage buff -using wormhole makes you immune to harm and drains energy until you run out - disable incoming energy, by saving current energy and just setting energy in the next cycle to be lower then the saved value - block shattering get code from planetesimals https://codepen.io/lilgreenland/pen/jrMvaB?editors=0010