From b6604643dba6e52ceec00ce07b99b36977057cee Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 9 Feb 2020 16:13:17 -0800 Subject: [PATCH] added several new mods --- js/bullets.js | 269 +++++++++++++++++++++++++++++++------------------ js/engine.js | 4 +- js/game.js | 1 - js/index.js | 27 +++-- js/level.js | 112 ++++++++++---------- js/player.js | 8 +- js/powerups.js | 18 ++-- 7 files changed, 254 insertions(+), 185 deletions(-) diff --git a/js/bullets.js b/js/bullets.js index 20d01f3..1ca0023 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -33,9 +33,13 @@ const b = { modCollisionImmuneCycles: null, modBlockDmg: null, isModPiezo: null, - isModFastDrones: null, + isModDroneCollide: null, + isModFastSpores: null, isModStomp: null, modSuperBallNumber: null, + modLaserReflections: null, + isModNoAmmo: null, + isModAmmoFromHealth: null, setModDefaults() { b.modCount = 0; b.modFireRate = 1; @@ -47,7 +51,8 @@ const b = { b.modHealthDrain = 0; b.modNoAmmo = 0; b.isModBulletsLastLonger = 1; - b.isModFastDrones = false; + b.isModDroneCollide = true; + b.isModFastSpores = false b.isModImmortal = false; b.modSpores = 0; b.modAcidDmg = 0; @@ -70,18 +75,24 @@ const b = { b.isModStomp = false; b.modCollisionImmuneCycles = 30; b.modSuperBallNumber = 4; + b.modLaserReflections = 2; + b.isModNoAmmo = false; + b.isModAmmoFromHealth = false; mech.Fx = 0.015; mech.jumpForce = 0.38; mech.maxHealth = 1; mech.fieldEnergyMax = 1; + 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; + } for (let i = 0; i < b.mods.length; i++) { b.mods[i].count = 0 } }, modOnHealthChange() { - if (b.isModAcidDmg && mech.health > 0.9) { + if (b.isModAcidDmg && mech.health > 0.8) { game.playerDmgColor = "rgba(0,80,80,0.9)" - b.modAcidDmg = 1.4 + b.modAcidDmg = 1.1 } else { game.playerDmgColor = "rgba(0,0,0,0.7)" b.modAcidDmg = 0 @@ -101,11 +112,11 @@ const b = { }, { name: "fluoroantimonic acid", - description: "each bullet does extra chemical damage
only active when you are above 90% health", + description: "each bullet does extra chemical damage
only active when you are above 80% health", maxCount: 1, count: 0, allowed() { - return true + return mech.health > 0.8 }, effect() { b.isModAcidDmg = true; @@ -138,11 +149,11 @@ const b = { }, { name: "quasistatic equilibrium", - description: "do extra damage at low health
up to 50% increase when near death", + description: "do extra damage at low health
up to 50% increase when near death", maxCount: 1, count: 0, allowed() { - return true + return mech.health < 0.75 }, effect() { b.isModLowHealthDmg = true; //used in mob.damage() @@ -150,7 +161,7 @@ const b = { }, { name: "high explosives", - description: "explosions do +20% more damage
explosive area is +44% larger", + description: "explosions do +20% more damage
explosive area is +44% larger", maxCount: 3, count: 0, allowed() { @@ -174,7 +185,7 @@ const b = { }, { name: "auto-loading heuristics", - description: "your delay after firing is +14% shorter", + description: "your delay after firing is +14% shorter", maxCount: 9, count: 0, allowed() { @@ -186,7 +197,7 @@ const b = { }, { name: "desublimated ammunition", - description: "use 50% less ammo when crouching", + description: "use 50% less ammo when crouching", maxCount: 1, count: 0, allowed() { @@ -198,11 +209,11 @@ const b = { }, { name: "Lorentzian topology", - description: "your bullets last +33% longer", + description: "your bullets last +33% longer", maxCount: 3, count: 0, allowed() { - return true + return b.haveGunCheck("spores") || b.haveGunCheck("drones") || b.haveGunCheck("super balls") || b.haveGunCheck("foam") }, effect() { b.isModBulletsLastLonger += 0.33 @@ -219,7 +230,7 @@ const b = { effect() { b.modSpores += 0.11; for (let i = 0; i < 10; i++) { - b.spore(player) //spawn drone + b.spore(player) } } }, @@ -270,7 +281,7 @@ const b = { maxCount: 9, count: 0, allowed() { - return true + return mech.fieldUpgrades[mech.fieldMode].name !== "time dilation field" && mech.fieldUpgrades[mech.fieldMode].name !== "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 @@ -278,7 +289,7 @@ const b = { }, { name: "entanglement", - description: "when your first gun is equipped
reduce harm by 10% for each gun you have", + description: "only when your first gun is equipped
reduce harm by 10% for each gun you have", maxCount: 1, count: 0, allowed() { @@ -303,7 +314,7 @@ const b = { } }, { - name: "Calvatia", + name: "basidio-stomp", description: "hard landings disrupt spores from the ground", maxCount: 1, count: 0, @@ -316,7 +327,7 @@ const b = { }, { name: "Pauli exclusion", - description: `unable to collide with enemies for +2 seconds
activates after being harmed from a collision`, + description: `unable to collide with enemies for +2 seconds
activates after being harmed from a collision`, maxCount: 9, count: 0, allowed() { @@ -329,7 +340,7 @@ const b = { }, { name: "annihilation", - description: "after touching enemies, they are annihilated", + description: "after touching enemies, they are annihilated", maxCount: 1, count: 0, allowed() { @@ -409,7 +420,7 @@ const b = { maxCount: 9, count: 0, allowed() { - return true + return mech.health < 0.7 }, effect() { b.modRecursiveHealing += 1 @@ -417,7 +428,7 @@ const b = { }, { name: "mass-energy equivalence", - description: "power ups fill your energy and heal for +5%", + description: "power ups fill your energy and heal for +5%
applies to guns, ammo, fields, mods, and heals", maxCount: 1, count: 0, allowed() { @@ -452,6 +463,36 @@ const b = { b.isModBayesian = 0.20; } }, + { + name: "catabolism", + description: "when you fire while out of ammo
convert 5% health into an ammo power up", + maxCount: 1, + count: 0, + allowed() { + return true + }, + effect: () => { + b.isModAmmoFromHealth = true; + } + }, + { + name: "leveraged investment", + description: "remove all future ammo power ups
spawn 6 mods and 3 healing power ups", + maxCount: 1, + count: 0, + allowed() { + return true + }, + effect: () => { + b.isModNoAmmo = true; + for (let i = 0; i < 6; i++) { // spawn new mods + powerUps.spawn(mech.pos.x, mech.pos.y, "mod"); + } + for (let i = 0; i < 3; i++) { // spawn new mods + powerUps.spawn(mech.pos.x, mech.pos.y, "heal"); + } + } + }, { name: "+1 cardinality", description: "one extra choice when selecting power ups", @@ -481,20 +522,32 @@ const b = { } }, { - name: "brushless motors", - description: "your drones accelerate 33% faster", + name: "redundant systems", + description: "drone collisions no longer reduce their lifespan", maxCount: 1, count: 0, allowed() { - return b.haveGunCheck("drones") + return b.haveGunCheck("drones") || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" }, effect() { - b.isModFastDrones = true + b.isModDroneCollide = true } }, { - name: "super duper balls", - description: "your super balls fire +1 extra ball", + name: "tinsellated flagella", + description: "your spores accelerate 33% faster", + maxCount: 1, + count: 0, + allowed() { + return b.haveGunCheck("spores") || b.modSpores > 0 || b.isModStomp + }, + effect() { + b.isModFastSpores = true + } + }, + { + name: "super duper", + description: "you fire +1 additional super ball", maxCount: 9, count: 0, allowed() { @@ -504,7 +557,32 @@ const b = { b.modSuperBallNumber++ } }, - + { + name: "specular reflection", + description: "your laser gains +1 reflection", + maxCount: 9, + count: 0, + allowed() { + return b.haveGunCheck("laser") + }, + effect() { + b.modLaserReflections++; + } + }, + { + name: "optimized shell packing", + description: "flak ammo drops contain 2x more shells", + maxCount: 3, + count: 0, + allowed() { + return b.haveGunCheck("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); + } + } + }, ], giveMod(index = 'random') { if (index === 'random') { @@ -556,7 +634,12 @@ const b = { game.updateGunHUD(); } } else { - mech.fireCDcycle = mech.cycle + 30; //cooldown + + if (b.isModAmmoFromHealth && mech.health > 0.05) { + mech.damage(0.05); + powerUps.spawn(mech.pos.x, mech.pos.y, "ammo"); + } + mech.fireCDcycle = mech.cycle + 30; //fire cooldown // game.makeTextLog("
NO AMMO
E / Q", 200); game.replaceTextLog = true; game.makeTextLog("
NO AMMO

Q, E, and mouse wheel change weapons

", 200); @@ -922,6 +1005,7 @@ const b = { angle: Math.random() * 2 * Math.PI, friction: 0, frictionAir: 0.025, + thrust: b.isModFastSpores ? 0.0008 : 0.0004, dmg: 2.2, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { @@ -956,9 +1040,8 @@ const b = { } } //accelerate towards mobs - const THRUST = 0.0004 if (this.lockedOn && this.lockedOn.alive) { - this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST) + this.force = Vector.mult(Vector.normalise(Vector.sub(this.position, this.lockedOn.position)), -this.mass * this.thrust) // this.force.x -= THRUST * this.lockedOn.x // this.force.y -= THRUST * this.lockedOn.y } else { @@ -976,7 +1059,7 @@ const b = { }, drone(speed = 1) { const me = bullet.length; - const THRUST = b.isModFastDrones ? 0.002 : 0.0015 + const THRUST = 0.0015 const dir = mech.angle + 0.2 * (Math.random() - 0.5); const RADIUS = (4.5 + 3 * Math.random()) * b.modBulletSize bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 8, RADIUS, { @@ -998,7 +1081,7 @@ const b = { isFollowMouse: true, onDmg() { this.lockedOn = null - if (this.endCycle > game.cycle + 180) { + if (this.endCycle > game.cycle + 180 && b.isModDroneCollide) { this.endCycle -= 60 if (game.cycle + 180 > this.endCycle) this.endCycle = game.cycle + 180 } @@ -1110,7 +1193,7 @@ const b = { }, onEnd() {}, do() { - if (!(game.cycle % this.lookFrequency)) { + if (!(game.cycle % this.lookFrequency) && !mech.isStealth) { let target for (let i = 0, len = mob.length; i < len; i++) { const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); @@ -1190,7 +1273,7 @@ const b = { }); //find targets - if (!(game.cycle % this.lookFrequency)) { + if (!(game.cycle % this.lookFrequency) && !mech.isStealth) { this.lockedOn = null; let closeDist = this.range; for (let i = 0, len = mob.length; i < len; ++i) { @@ -1328,9 +1411,9 @@ const b = { b.muzzleFlash(35); // mobs.alert(650); const side = 13 * b.modBulletSize - for (let i = 0; i < 11; i++) { + for (let i = 0; i < 12; i++) { const me = bullet.length; - const dir = mech.angle + (Math.random() - 0.5) * (mech.crouch ? 0.35 : 1.1) + const dir = mech.angle + (Math.random() - 0.5) * (mech.crouch ? 0.40 : 1.2) bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle) + 15 * (Math.random() - 0.5), mech.pos.y + 35 * Math.sin(mech.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir)); World.add(engine.world, bullet[me]); //add bullet to world const SPEED = 50 + Math.random() * 10 @@ -1479,7 +1562,7 @@ const b = { } }, { - name: "missiles", //5 + name: "missiles", description: "fire missiles that accelerate towards enemies
explodes when near target", ammo: 0, ammoPack: 4, @@ -1577,10 +1660,11 @@ const b = { } } }, { - name: "flak", //6 + name: "flak", description: "fire a cluster of short range projectiles
explodes on contact or after half a second", ammo: 0, ammoPack: 6, + defaultAmmoPack: 6, //use to revert ammoPack after mod changes drop rate have: false, isStarterGun: true, fire() { @@ -1820,7 +1904,7 @@ const b = { }, { name: "drones", //11 - description: "deploy drones that crash into enemies
collisions reduce drone cycles by 1 second", + description: "deploy drones that crash into enemies
collisions reduce their lifespan by 1 second", ammo: 0, ammoPack: (game.difficultyMode > 3) ? 8 : 10, have: false, @@ -1849,7 +1933,7 @@ const b = { frictionAir: 0.003, friction: 0.2, restitution: 0.2, - dmg: 0, //damage done in addition to the damage from momentum + dmg: 0.1, //damage done in addition to the damage from momentum classType: "bullet", collisionFilter: { category: cat.bullet, @@ -1954,8 +2038,6 @@ const b = { bullet[me].endCycle = Infinity bullet[me].charge = 0; bullet[me].do = function () { - const FIELD_DRAIN = 0.002 //laser drains energy as well as bullets - if ((!game.mouseDown && this.charge > 0.6)) { //fire on mouse release //normal bullet behavior occurs after firing, overwrite this function this.do = function () { @@ -2014,7 +2096,7 @@ const b = { this.charge = this.charge * chargeRate + (1 - chargeRate) // this.charge converges to 1 mech.fieldMeter -= (this.charge - lastCharge) * 0.28 //energy drain is proportional to charge gained, but doesn't stop normal mech.fieldRegen - //draw laser targeting + //draw targeting let best; let range = 3000 const dir = mech.angle @@ -2087,7 +2169,7 @@ const b = { }; } - //draw laser beam + //draw beam ctx.beginPath(); ctx.moveTo(path[0].x, path[0].y); ctx.lineTo(path[1].x, path[1].y); @@ -2136,12 +2218,20 @@ const b = { isStarterGun: true, fire() { const FIELD_DRAIN = 0.0018 //laser drains energy as well as bullets - const damage = 0.05 + const reflectivity = 1 - 1 / (b.modLaserReflections * 1.5) + let damage = b.dmgScale * 0.05 if (mech.fieldMeter < FIELD_DRAIN) { mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy } else { mech.fieldMeter -= mech.fieldRegen + FIELD_DRAIN - let best; + let best = { + x: null, + y: null, + dist2: Infinity, + who: null, + v1: null, + v2: null + }; const color = "#f00"; const range = 3000; const path = [{ @@ -2207,92 +2297,71 @@ const b = { vertexCollision(path[path.length - 2], path[path.length - 1], map); vertexCollision(path[path.length - 2], path[path.length - 1], body); }; - const laserHitMob = function (dmg) { + const laserHitMob = function () { if (best.who.alive) { - dmg *= b.dmgScale * damage; - best.who.damage(dmg); + best.who.damage(damage); best.who.locatePlayer(); - //draw mob damage circle - ctx.fillStyle = color; + ctx.fillStyle = color; //draw mob damage circle ctx.beginPath(); - ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI); + ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(damage) * 100, 0, 2 * Math.PI); ctx.fill(); } }; - - const reflection = function () { - // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector + const reflection = function () { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2))); const d = Vector.sub(path[path.length - 1], path[path.length - 2]); const nn = Vector.mult(n, 2 * Vector.dot(d, n)); const r = Vector.normalise(Vector.sub(d, nn)); path[path.length] = Vector.add(Vector.mult(r, range), path[path.length - 1]); }; - //beam before reflection + checkForCollisions(); - if (best.dist2 != Infinity) { + let lastBestOdd + let lastBestEven = best.who //used in hack below + if (best.dist2 !== Infinity) { //if hitting something path[path.length - 1] = { x: best.x, y: best.y }; - laserHitMob(1); + laserHitMob(); + for (let i = 0; i < b.modLaserReflections; i++) { + reflection(); + checkForCollisions(); + if (best.dist2 !== Infinity) { //if hitting something + lastReflection = best - //1st reflection beam - reflection(); - //ugly bug fix: this stops the reflection on a bug where the beam gets trapped inside a body - let who = best.who; - checkForCollisions(); - if (best.dist2 != Infinity) { - //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; - laserHitMob(0.8); - - //2nd reflection beam - //ugly bug fix: this stops the reflection on a bug where the beam gets trapped inside a body - if (who !== best.who) { - reflection(); - checkForCollisions(); - if (best.dist2 != Infinity) { - //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; - laserHitMob(0.63); - - - reflection(); - checkForCollisions(); - if (best.dist2 != Infinity) { - //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; - laserHitMob(0.5); - } + path[path.length - 1] = { + x: best.x, + y: best.y + }; + damage *= reflectivity + laserHitMob(); + //I'm not clear on how this works, but it gets ride of a bug where the laser reflects inside a block, often vertically. + //I think it checks to see if the laser is reflecting off a different part of the same block, if it is "inside" a block + if (i % 2) { + if (lastBestOdd === best.who) break + } else { + lastBestOdd = best.who + if (lastBestEven === best.who) break } + } else { + break } } } + ctx.fillStyle = color; ctx.strokeStyle = color; ctx.lineWidth = 2; ctx.lineDashOffset = 300 * Math.random() - // ctx.setLineDash([200 * Math.random(), 250 * Math.random()]); - ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); for (let i = 1, len = path.length; i < len; ++i) { ctx.beginPath(); ctx.moveTo(path[i - 1].x, path[i - 1].y); ctx.lineTo(path[i].x, path[i].y); ctx.stroke(); - ctx.globalAlpha *= 0.65; //reflections are less intense - // ctx.globalAlpha -= 0.1; //reflections are less intense + ctx.globalAlpha *= reflectivity; //reflections are less intense } ctx.setLineDash([0, 0]); ctx.globalAlpha = 1; diff --git a/js/engine.js b/js/engine.js index 1b6f010..a3a433b 100644 --- a/js/engine.js +++ b/js/engine.js @@ -100,7 +100,9 @@ function collisionChecks(event) { } function collidePlayer(obj, speedThreshold = 12, massThreshold = 2) { - if (obj.classType === "body" && obj.speed > speedThreshold && obj.mass > massThreshold) { //dmg from hitting a body + //player dmg from hitting a body + if (obj.classType === "body" && obj.speed > speedThreshold && obj.mass > massThreshold && + (obj.velocity.y > 0 || player.velocity.y > 0)) { const v = Vector.magnitude(Vector.sub(player.velocity, obj.velocity)); if (v > speedThreshold && mech.collisionImmune < mech.cycle) { mech.collisionImmune = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles diff --git a/js/game.js b/js/game.js index 5096869..467cabc 100644 --- a/js/game.js +++ b/js/game.js @@ -557,7 +557,6 @@ const game = { game.reset(); game.firstRun = false; - //setup FPS cap game.fpsInterval = 1000 / game.fpsCap; game.then = Date.now(); diff --git a/js/index.js b/js/index.js index 27720b9..a4bb59c 100644 --- a/js/index.js +++ b/js/index.js @@ -2,9 +2,18 @@ /* TODO: ******************************************* ***************************************************** -add difficulty slider to custom? +speed up movement + higher gravity, larger jump force + faster horizontal acceleration + only increase top speed a bit -phase decoherence energy drain is proportional to player speed +mod: if you fire when out of ammo you gain 1 ammo pack at the cost of + 10% max health + 20% of your current health + +mob: targeting laser, then a high speed, no gravity bullet + +add difficulty slider to custom? add recursive mod counts to pause screen @@ -14,8 +23,6 @@ key required to open the exit to some levels css transition for pause menu -mod: remove all ammo drops from the game, but double player damage - mod: like Born rule, but for guns field that pushes everything back, and can destroy smaller blocks @@ -23,6 +30,7 @@ field that pushes everything back, and can destroy smaller blocks mod: make player invisible when... use the flag from phase field + when health is low? field: a larger radius that attracted enemies still deflected them near the robot @@ -60,10 +68,6 @@ mod: do something at the end of each level take no damage don't shoot -mod: if you fire when out of ammo you gain 1 ammo pack at the cost of - 10% max health - 20% of your current health - gun: Spirit Bomb (singularity) use charge up like rail gun electricity graphics like plasma torch @@ -243,7 +247,7 @@ const build = { text += `
  ${b.guns[i].name}
${b.guns[i].description}
` } for (let i = 0, len = b.mods.length; i < len; i++) { - if (b.mods[i].name === "Born rule" || b.mods[i].name === "+1 cardinality") { + if (b.mods[i].name === "Born rule" || b.mods[i].name === "+1 cardinality" || b.mods[i].name === "leveraged investment") { text += `
  ${b.mods[i].name}
${b.mods[i].description}
` } else { text += `
  ${b.mods[i].name}
${b.mods[i].description}
` @@ -318,8 +322,8 @@ const build = { document.getElementById("starting-level").innerHTML = `starting difficulty: ${difficulty}` }, startBuildRun() { + spawn.setSpawnList(); //gives random mobs, not starter mobs spawn.setSpawnList(); - spawn.setSpawnList(); //gives random mobs, not starter game.startGame(); let difficulty = build.list.length * game.difficultyMode - 1 if (game.difficultyMode === 0) { @@ -330,6 +334,9 @@ const build = { level.difficultyIncrease(difficulty) level.isBuildRun = true; + build.givePowerUps(); + }, + givePowerUps() { for (let i = 0; i < build.list.length; i++) { if (build.list[i].type === "field") { mech.setField(build.list[i].index) diff --git a/js/level.js b/js/level.js index 2696a64..ef9684b 100644 --- a/js/level.js +++ b/js/level.js @@ -13,17 +13,13 @@ const level = { levelsCleared: 0, start() { if (level.levelsCleared === 0) { - // level.difficultyIncrease(15) - b.giveGuns("super balls") + // level.difficultyIncrease(5) + // b.giveGuns("laser") // mech.setField("phase decoherence field") - // b.giveMod("squirrel-cage rotor"); - b.giveMod("super duper balls"); - b.giveMod("super duper balls"); - b.giveMod("super duper balls"); + // b.giveMod("optimized shell packing"); - - // level.intro(); //starting level - level.testingMap(); + level.intro(); //starting level + // level.testingMap(); // level.bosses(); // level.satellite(); // level.skyscrapers(); @@ -38,6 +34,7 @@ const level = { level[level.levels[level.onLevel]](); //picks the current map from the the levels array level.levelAnnounce(); } + // if (level.isBuildRun) build.givePowerUps(); game.noCameraScroll(); game.setZoom(); level.addToWorld(); //add bodies to game engine @@ -54,26 +51,39 @@ const level = { // if (level.isBuildRun) num++ for (let i = 0; i < num; i++) { game.difficulty++ - game.dmgScale += 0.13; //damage done by mobs increases each level - b.dmgScale *= 0.93; //damage done by player decreases each level + game.dmgScale += 0.17; //damage done by mobs increases each level + b.dmgScale *= 0.91; //damage done by player decreases each level game.accelScale *= 1.02 //mob acceleration increases each level game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level game.CDScale *= 0.97 //mob CD time decreases each level } - game.healScale = 1 / (1 + game.difficulty * 0.065) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; + game.healScale = 1 / (1 + game.difficulty * 0.09) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; }, difficultyDecrease(num = 1) { //used in easy mode for game.reset() for (let i = 0; i < num; i++) { game.difficulty-- - game.dmgScale -= 0.13; //damage done by mobs increases each level + game.dmgScale -= 0.17; //damage done by mobs increases each level if (game.dmgScale < 0.1) game.dmgScale = 0.1; - b.dmgScale /= 0.93; //damage done by player decreases each level + b.dmgScale /= 0.91; //damage done by player decreases each level game.accelScale /= 1.02 //mob acceleration increases each level game.lookFreqScale /= 0.98 //mob cycles between looks decreases each level game.CDScale /= 0.97 //mob CD time decreases each level } if (game.difficulty < 1) game.difficulty = 1; - game.healScale = 1 / (1 + game.difficulty * 0.065) + game.healScale = 1 / (1 + game.difficulty * 0.09) + }, + levelAnnounce() { + let mode = document.getElementById("difficulty-select").value + if (mode === "0") { + mode = "(easy)" + } else if (mode === "1") { + mode = "(normal)" + } else if (mode === "2") { + mode = "(hard)" + } else if (mode === "4") { + mode = "(why)" + } + document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " " + mode; }, //****************************************************************************************************************** //****************************************************************************************************************** @@ -1559,25 +1569,32 @@ const level = { spawn.randomBoss(1800, -800, -0.2); spawn.randomBoss(4150, -1000, 0.6); - if (game.difficulty > 2) { // tether ball - level.fillBG.push({ - x: 2495, - y: -500, - width: 10, - height: 525, - color: "#ccc" - }); - spawn.tetherBoss(2850, -80) - cons[cons.length] = Constraint.create({ - pointA: { - x: 2500, - y: -500 - }, - bodyB: mob[mob.length - 1], - stiffness: 0.00012 - }); - //chance to spawn a ring of exploding mobs around this boss - if (game.difficulty > 4) spawn.nodeBoss(2850, -80, "spawns", 8, 20, 105); + if (game.difficulty > 2) { + if (Math.random() < 0.7) { + // tether ball + level.fillBG.push({ + x: 2495, + y: -500, + width: 10, + height: 525, + color: "#ccc" + }); + spawn.tetherBoss(2850, -80) + cons[cons.length] = Constraint.create({ + pointA: { + x: 2500, + y: -500 + }, + bodyB: mob[mob.length - 1], + stiffness: 0.00012 + }); + //chance to spawn a ring of exploding mobs around this boss + if (game.difficulty > 4) spawn.nodeBoss(2850, -80, "spawns", 8, 20, 105); + } else if (game.difficulty > 3) { + spawn.shooterBoss(2200, -650); + + } + } }, //***************************************************************************************************************** @@ -1763,32 +1780,7 @@ const level = { target.death(); } }, - levelAnnounce() { - let mode = document.getElementById("difficulty-select").value - if (mode === "0") { - mode = "(easy)" - } else if (mode === "1") { - mode = "(normal)" - } else if (mode === "2") { - mode = "(hard)" - } else if (mode === "6") { - mode = "(why)" - } - document.title = "n-gon: L" + (level.levelsCleared) + " " + level.levels[level.onLevel] + " " + mode; - // game.makeTextLog(`
level ${game.difficulty}
${level.levels[level.onLevel]}
`, 300); - // if (game.difficulty === 0) text = ""; - // text = "Level " + (game.difficulty + 1) + ": " + spawn.pickList[0] + "s + " + spawn.pickList[1] + "s"; - - // text = text + " with population: "; - // for (let i = 0, len = spawn.pickList.length; i < len; ++i) { - // if (spawn.pickList[i] != spawn.pickList[i - 1]) { - // text += spawn.pickList[i] + ", "; - // } - // } - // this.speech(text); - // game.makeTextLog(text, 360); - }, - addToWorld(mapName) { + addToWorld() { //needs to be run to put bodies into the world for (let i = 0; i < body.length; i++) { //body[i].collisionFilter.group = 0; diff --git a/js/player.js b/js/player.js index ebef536..7e159df 100644 --- a/js/player.js +++ b/js/player.js @@ -477,9 +477,9 @@ const mech = { //chance to build a drone on damage from mod if (b.isModDroneOnDamage) { - const len = (dmg - 0.06 + 0.07 * Math.random()) / 0.05 + const len = (dmg - 0.06 * Math.random()) * 40 for (let i = 0; i < len; i++) { - if (Math.random() < 0.6) b.drone() //spawn drone + if (Math.random() < 0.75) b.drone() //spawn drone } } @@ -1512,7 +1512,7 @@ const mech = { }, { name: "phase decoherence field", - description: "use energy to to become intangible
can't see or be seen outside field", + description: "become intangible and invisible
drains energy as you move", effect: () => { // mech.grabRange = 230 mech.hold = function () { @@ -1523,7 +1523,7 @@ const mech = { mech.holding(); mech.throwBlock(); } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { - const DRAIN = 0.0015 + const DRAIN = 0.0002 + 0.00027 * player.speed if (mech.fieldMeter > DRAIN) { mech.fieldMeter -= DRAIN; diff --git a/js/powerups.js b/js/powerups.js index 6962fd7..34b0cd7 100644 --- a/js/powerups.js +++ b/js/powerups.js @@ -79,7 +79,7 @@ const powerUps = { if (!game.lastLogTime) game.makeTextLog("+energy", 300); } else { let ammo = Math.ceil((target.ammoPack * (1 + 0.1 * Math.random()))); - if (level.isBuildRun) ammo = Math.floor(ammo * 1.1) //extra ammo on build run because no ammo from getting a new gun + // if (level.isBuildRun) ammo = Math.floor(ammo * 1.1) //extra ammo on build run because no ammo from getting a new gun target.ammo += ammo; game.updateGunHUD(); game.makeTextLog("
  +" + ammo + " ammo for " + target.name + "", 300); @@ -227,17 +227,17 @@ const powerUps = { if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "heal"); return; } - if (Math.random() < 0.15 && b.inventory.length > 0) { + if (Math.random() < 0.15 && b.inventory.length > 0 && !b.isModNoAmmo) { powerUps.spawn(x, y, "ammo"); if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "ammo"); return; } - if (Math.random() < 0.0025 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 3 + if (Math.random() < 0.002 * (3 - b.inventory.length)) { //a new gun has a low chance for each not acquired gun up to 3 powerUps.spawn(x, y, "gun"); if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun"); return; } - if (Math.random() < 0.003 * (12 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 7 + if (Math.random() < 0.0027 * (14 - b.modCount)) { //a new mod has a low chance for each not acquired mod up to 15 powerUps.spawn(x, y, "mod"); if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod"); return; @@ -252,13 +252,13 @@ const powerUps = { if (mech.fieldMode === 0) { powerUps.spawn(x, y, "field") if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field") - } else if (Math.random() < 0.75) { + } else if (Math.random() < 0.80) { powerUps.spawn(x, y, "mod") if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "mod") - } else if (Math.random() < 0.2) { + } else if (Math.random() < 0.35) { powerUps.spawn(x, y, "gun") if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "gun") - } else if (Math.random() < 0.6) { + } else if (Math.random() < 0.65) { powerUps.spawn(x, y, "field"); if (Math.random() < b.isModBayesian) powerUps.spawn(x, y, "field"); } else if (mech.health < 0.7) { @@ -270,7 +270,7 @@ const powerUps = { powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal"); } - } else { + } else if (!b.isModNoAmmo) { powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo"); powerUps.spawn(x, y, "ammo"); @@ -286,7 +286,7 @@ const powerUps = { if (Math.random() < 0.5) { powerUps.spawn(x, y, "heal", false); } else { - powerUps.spawn(x, y, "ammo", false); + if (!b.isModNoAmmo) powerUps.spawn(x, y, "ammo", false); } }, spawnStartingPowerUps(x, y) { //used for map specific power ups, mostly to give player a starting gun