diff --git a/js/bullets.js b/js/bullets.js index c32e171..b65e5a2 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -15,6 +15,7 @@ const b = { isModImmortal: null, modSpores: null, isModImmuneExplosion: null, + isModExplodeMob: null, isModDroneOnDamage: null, modAcidDmg: null, isModAcidDmg: null, @@ -61,8 +62,9 @@ const b = { count: 0, maxCount: 9, allowed() { - return true + return b.haveGunCheck("minigun") || b.haveGunCheck("shotgun") || b.haveGunCheck("super balls") || b.haveGunCheck("foam") }, + requires: "minigun, shotgun, super balls, foam", effect() { b.modBulletSize += 0.13 }, @@ -76,8 +78,9 @@ const b = { maxCount: 1, count: 0, allowed() { - return mech.health > 0.8 || level.isBuildRun + return mech.health > 0.8 || build.isCustomSelection }, + requires: "health above 80%", effect() { b.isModAcidDmg = true; b.modOnHealthChange(); @@ -88,21 +91,6 @@ const b = { game.playerDmgColor = "rgba(0,0,0,0.7)" } }, - { - name: "fracture analysis", - description: "5x physical damage to unaware enemies
unaware enemies don't have a health bar", - maxCount: 1, - count: 0, - allowed() { - return true - }, - effect() { - b.isModCrit = true; - }, - remove() { - b.isModCrit = false; - } - }, { name: "kinetic bombardment", description: "do up to 33% more damage at a distance
increase maxes out at about 40 steps away", @@ -111,6 +99,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModFarAwayDmg = true; //used in mob.damage() }, @@ -118,14 +107,31 @@ const b = { b.isModFarAwayDmg = false; } }, + { + name: "fracture analysis", + description: "5x physical damage to unaware enemies
unaware enemies don't have a health bar", + maxCount: 1, + count: 0, + allowed() { + return b.isModFarAwayDmg + }, + requires: "kinetic bombardment", + effect() { + b.isModCrit = true; + }, + remove() { + b.isModCrit = false; + } + }, { name: "quasistatic equilibrium", description: "do extra damage at low health
up to 50% increase when near death", maxCount: 1, count: 0, allowed() { - return mech.health < 0.75 || level.isBuildRun + return mech.health < 0.8 || build.isCustomSelection }, + requires: "health below 80%", effect() { b.isModLowHealthDmg = true; //used in mob.damage() }, @@ -133,6 +139,38 @@ const b = { b.isModLowHealthDmg = false; } }, + { + name: "reaction inhibitor", + description: "mobs die if their life goes below 12%", + maxCount: 1, + count: 0, + allowed() { + return b.isModLowHealthDmg + }, + requires: "quasistatic equilibrium", + effect: () => { + b.modMobDieAtHealth = 0.15 + }, + remove() { + b.modMobDieAtHealth = 0.05; + } + }, + { + name: "thermal runaway", + description: "mobs explode when they die", + maxCount: 1, + count: 0, + allowed() { + return b.modMobDieAtHealth > 0.05 + }, + requires: "reaction inhibitor", + effect: () => { + b.isModExplodeMob = true; + }, + remove() { + b.isModExplodeMob = false; + } + }, { name: "high explosives", description: "explosions do +20% more damage
explosive area is +44% larger", @@ -141,6 +179,7 @@ const b = { allowed() { return b.haveGunCheck("missiles") || b.haveGunCheck("flak") || b.haveGunCheck("grenades") || b.haveGunCheck("vacuum bomb") || b.haveGunCheck("pulse"); }, + requires: "an explosive gun", effect: () => { b.modExplosionRadius += 0.2; }, @@ -154,16 +193,17 @@ const b = { maxCount: 1, count: 0, allowed() { - return (b.modExplosionRadius > 1) + return b.modExplosionRadius > 1 }, + requires: "high explosives", effect: () => { b.isModImmuneExplosion = true; }, remove() { b.isModImmuneExplosion = false; - } }, + { name: "auto-loading heuristics", description: "your delay after firing is +14% shorter", @@ -172,6 +212,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modFireRate *= 0.86 }, @@ -187,6 +228,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modNoAmmo = 1 }, @@ -202,6 +244,7 @@ const b = { allowed() { return mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || b.haveGunCheck("spores") || b.haveGunCheck("drones") || b.haveGunCheck("super balls") || b.haveGunCheck("foam") }, + requires: "drones, spores, super balls, or foam", effect() { b.isModBulletsLastLonger += 0.33 }, @@ -209,21 +252,7 @@ const b = { b.isModBulletsLastLonger = 1; } }, - { - name: "reaction inhibitor", - description: "mobs die if their life goes below 12%", - maxCount: 1, - count: 0, - allowed() { - return true - }, - effect: () => { - b.modMobDieAtHealth = 0.15 - }, - remove() { - b.modMobDieAtHealth = 0.05; - } - }, + { name: "zoospore vector", description: "enemies discharge spores on death
+11% chance", @@ -232,6 +261,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modSpores += 0.11; for (let i = 0; i < 10; i++) { @@ -250,6 +280,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modLaserBotCount++; b.laserBot(); @@ -266,6 +297,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modNailBotCount++; b.nailBot(); @@ -282,6 +314,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModDroneOnDamage = true; for (let i = 0; i < 4; i++) { @@ -300,6 +333,7 @@ const b = { allowed() { return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field" }, + requires: "not time dilation field
requires not phase decoherence field", effect() { b.modBlockDmg += 0.7 //if you change this value also update the for loop in the electricity graphics in mech.pushMass }, @@ -315,6 +349,7 @@ const b = { allowed() { return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "phase decoherence field" }, + requires: "not time dilation field
requires not phase decoherence field", effect() { mech.fieldRange = 175 * 1.4 }, @@ -330,6 +365,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModEntanglement = true }, @@ -345,6 +381,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModEnergyRecovery = true; }, @@ -360,6 +397,7 @@ const b = { allowed() { return b.isModEnergyRecovery }, + requires: "waste energy recovery", effect() { b.isModHealthRecovery = true; }, @@ -375,6 +413,7 @@ const b = { allowed() { return b.isModEnergyRecovery }, + requires: "waste energy recovery", effect() { b.isModEnergyLoss = true; }, @@ -390,6 +429,7 @@ const b = { allowed() { return true }, + requires: "", effect() { // good with melee builds, content skipping builds b.modSquirrelFx += 0.2; mech.Fx = 0.016 * b.modSquirrelFx; @@ -409,6 +449,7 @@ const b = { allowed() { return b.modSquirrelFx > 1 }, + requires: "squirrel-cage rotor", effect() { b.isModStomp = true }, @@ -424,6 +465,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modCollisionImmuneCycles += 120; mech.collisionImmune = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles @@ -438,8 +480,9 @@ const b = { maxCount: 1, count: 0, allowed() { - return b.modCollisionImmuneCycles > 120 || b.isModPiezo + return b.modCollisionImmuneCycles > 120 }, + requires: "Pauli exclusion", effect() { b.isModAnnihilation = true }, @@ -455,6 +498,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModPiezo = true; mech.fieldMeter = mech.fieldEnergyMax; @@ -471,6 +515,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modEnergySiphon += 0.15; mech.fieldMeter = mech.fieldEnergyMax @@ -487,6 +532,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.modHealthDrain += 0.015; }, @@ -502,6 +548,7 @@ const b = { allowed() { return true }, + requires: "", effect() { mech.fieldEnergyMax += 0.5 mech.fieldMeter += 0.5 @@ -512,12 +559,13 @@ const b = { }, { name: "supersaturation", - description: "heal +50% beyond your max health", + description: "increase your maximum health by +50%", maxCount: 9, count: 0, allowed() { return true }, + requires: "", effect() { mech.maxHealth += 0.50 mech.addHealth(0.50) @@ -532,8 +580,9 @@ const b = { maxCount: 9, count: 0, allowed() { - return mech.health < 0.7 || level.isBuildRun + return mech.health < 0.7 || build.isCustomSelection }, + requires: "health below 70%", effect() { b.modRecursiveHealing += 1 }, @@ -543,12 +592,13 @@ const b = { }, { name: "mass-energy equivalence", - description: "power ups overcharge your energy
temporarily gain 150% of maximum", + description: "power ups overfill your energy
temporarily gain 50% above your max", maxCount: 1, count: 0, allowed() { return true }, + requires: "", effect: () => { b.isModMassEnergy = true // used in mech.grabPowerUp mech.fieldMeter = mech.fieldEnergyMax * 2 @@ -565,6 +615,7 @@ const b = { allowed() { return true }, + requires: "", effect() { b.isModImmortal = true; }, @@ -580,6 +631,7 @@ const b = { allowed() { return true }, + requires: "", effect: () => { b.isModBayesian = 0.20; }, @@ -589,12 +641,13 @@ const b = { }, { name: "catabolism", - description: "when you fire while out of ammo
convert 3% of current health into ammo", + description: "convert 3% of current health into ammo
when you fire while out of ammo", maxCount: 1, count: 0, allowed() { return true }, + requires: "", effect: () => { b.isModAmmoFromHealth = 0.03; }, @@ -610,6 +663,7 @@ const b = { allowed() { return true }, + requires: "", effect: () => { b.isModNoAmmo = true; for (let i = 0; i < 6; i++) { //if you change the six also change it in Born rule @@ -633,6 +687,7 @@ const b = { allowed() { return true }, + requires: "", effect: () => { b.isModFourOptions = true; }, @@ -646,8 +701,9 @@ const b = { maxCount: 1, count: 0, allowed() { - return (b.modCount > 6) && !level.isBuildRun + return (b.modCount > 6) && !build.isCustomSelection }, + requires: "more than 6 mods", effect: () => { let count = b.modCount if (b.isModNoAmmo) count - 6 //remove the 6 bonus mods when getting rid of leveraged investment @@ -669,6 +725,7 @@ const b = { allowed() { return b.haveGunCheck("drones") || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" }, + requires: "drones", effect() { b.isModDroneCollide = true }, @@ -684,6 +741,7 @@ const b = { allowed() { return b.haveGunCheck("spores") || b.modSpores > 0 || b.isModStomp }, + requires: "spores", effect() { b.isModFastSpores = true }, @@ -699,6 +757,7 @@ const b = { allowed() { return b.haveGunCheck("super balls") }, + requires: "super balls", effect() { b.modSuperBallNumber++ }, @@ -714,6 +773,7 @@ const b = { allowed() { return b.haveGunCheck("laser") }, + requires: "laser", effect() { b.modLaserReflections++; b.modLaserDamage += 0.015; //base is 0.05 @@ -733,6 +793,7 @@ const b = { allowed() { return b.haveGunCheck("flak") }, + requires: "flak", effect() { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is flak if (b.guns[i].name === "flak") b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * (2 + this.count); @@ -752,6 +813,7 @@ const b = { // allowed() { // return b.haveGunCheck("mines") // }, + // requires: "", // effect() { // } @@ -986,11 +1048,17 @@ const b = { dist = Vector.magnitude(sub); if (dist < radius) { - if (!b.isModImmuneExplosion && mech.fieldMeter > 0.1) { - mech.damage(radius * 0.0002); + if (b.isModImmuneExplosion) { + const drain = Math.max(radius * 0.0006, 0.2) + if (mech.fieldMeter > drain) { + mech.fieldMeter -= drain + } else { + mech.damage(radius * 0.0001); //do half damage if have the mod, but out of mana + } } else { - mech.fieldMeter -= Math.max(radius * 0.0006, 0.1) + mech.damage(radius * 0.0002); //normal player damage from explosions } + knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass / 30); player.force.x += knock.x; player.force.y += knock.y; diff --git a/js/index.js b/js/index.js index 6087db7..de388f4 100644 --- a/js/index.js +++ b/js/index.js @@ -61,6 +61,7 @@ const build = { document.getElementById("pause-grid-left").style.display = "none" document.getElementById("pause-grid-right").style.display = "none" }, + isCustomSelection: false, choosePowerUp(who, index, type) { if (type === "gun") { let isDeselect = false @@ -91,23 +92,30 @@ const build = { if (b.mods[index].count < b.mods[index].maxCount) { if (!who.classList.contains("build-grid-selected")) who.classList.add("build-grid-selected"); b.giveMod(index) - if (b.mods[index].count > 1) who.innerHTML = `
  ${b.mods[index].name} (${b.mods[index].count}x)
${b.mods[index].description}` + // if (b.mods[index].count > 1) who.innerHTML = `
  ${b.mods[index].name} (${b.mods[index].count}x)
${b.mods[index].description}` } else { b.removeMod(index); - who.innerHTML = `
  ${b.mods[index].name}
${b.mods[index].description}` + // who.innerHTML = `
  ${b.mods[index].name}
${b.mods[index].description}` who.classList.remove("build-grid-selected"); } } - //disable not allowed mods + //update mod text //disable not allowed mods for (let i = 0, len = b.mods.length; i < len; i++) { const modID = document.getElementById("mod-" + i) if (b.mods[i].allowed()) { + if (b.mods[i].count > 1) { + modID.innerHTML = `
  ${b.mods[i].name} (${b.mods[i].count}x)
${b.mods[i].description}` + } else { + modID.innerHTML = `
  ${b.mods[i].name}
${b.mods[i].description}` + } + if (modID.classList.contains("build-grid-disabled")) { modID.classList.remove("build-grid-disabled"); modID.setAttribute("onClick", `javascript: build.choosePowerUp(this,${i},'mod')`); } } else { + modID.innerHTML = `
  ${b.mods[i].name}
requires: ${b.mods[i].requires}` if (!modID.classList.contains("build-grid-disabled")) { modID.classList.add("build-grid-disabled"); modID.onclick = null @@ -122,7 +130,6 @@ const build = { } }, populateGrid() { - level.isBuildRun = true; let text = `
@@ -154,7 +161,7 @@ const build = { } for (let i = 0, len = b.mods.length; i < len; i++) { if (!b.mods[i].allowed()) { // || b.mods[i].name === "+1 cardinality") { //|| b.mods[i].name === "leveraged investment" - text += `
  ${b.mods[i].name}
${b.mods[i].description}
` + text += `
  ${b.mods[i].name}
requires: ${b.mods[i].requires}
` } else if (b.mods[i].count > 1) { text += `
  ${b.mods[i].name} (${b.mods[i].count}x)
${b.mods[i].description}
` } else { @@ -183,13 +190,14 @@ const build = { game.makeGunHUD(); b.setupAllMods(); - + build.isCustomSelection = true; build.populateGrid(); document.getElementById("field-0").classList.add("build-grid-selected"); document.getElementById("build-grid").style.display = "grid" }, startBuildRun() { + build.isCustomSelection = false; spawn.setSpawnList(); //gives random mobs, not starter mobs spawn.setSpawnList(); if (b.inventory.length > 0) { diff --git a/js/level.js b/js/level.js index 0bdf927..1ad28e3 100644 --- a/js/level.js +++ b/js/level.js @@ -18,7 +18,7 @@ const level = { // mech.setField("negative mass field") // for (let i = 0; i < 9; i++) { // b.giveMod("waste energy recovery"); - // b.giveMod("scrap recycling"); + // b.giveMod("thermal runaway"); // b.giveMod("acute stress response"); // } diff --git a/js/mobs.js b/js/mobs.js index 3b9c11d..236a7e7 100644 --- a/js/mobs.js +++ b/js/mobs.js @@ -973,6 +973,7 @@ const mobs = { b.spore(this) //spawn drone } } + if (b.isModExplodeMob) b.explosion(this.position, Math.min(500, Math.sqrt(this.mass + 2) * 80)) } }, diff --git a/js/player.js b/js/player.js index deb0c1c..4fe0400 100644 --- a/js/player.js +++ b/js/player.js @@ -411,7 +411,6 @@ const mech = { } game.replaceTextLog = true; game.makeTextLog("your quantum probability has stabilized", 1000); - document.title = "n-gon: L" + (game.difficulty) + " " + level.levels[level.onLevel]; }, 8000); } else if (mech.alive) { //normal death code here diff --git a/style.css b/style.css index ee7fcda..3d61928 100644 --- a/style.css +++ b/style.css @@ -215,15 +215,16 @@ summary { } .build-grid-selected { - background-color: #919ba8; + background-color: #76808d; } .build-grid-selected:hover { - background-color: #919ba8; + background-color: #76808d; } .build-grid-disabled { - opacity: 0.15; + opacity: 0.5; + color: #ccc; } #info { @@ -444,6 +445,10 @@ em { background: #96e; } +.grey { + background: #ccc; +} + .gun { background: #149; } diff --git a/todo.txt b/todo.txt index 732769e..8a467c2 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,10 @@ ************** TODO - n-gon ************** +level - decrease all lips from 15 to 10 (under the new gravity players get stuck) + consider making jumping cost energy (like stamina) should walking cost energy too? -add in requirements to custom mode - grey out mods that don't meet requirements - make custom undo method for mods - this makes toggleing mods on and off easier in custom - -mod - acute stress response - permanently increase damage by 30% - for 5 seconds after a mob dies - drain energy down to zero - - mod - nano-scale field makes spores instead of drones mod - mines - fire something instead of needles on activation