diff --git a/index.html b/index.html index 0017d3d..603e099 100644 --- a/index.html +++ b/index.html @@ -105,15 +105,12 @@ why... - include community maps: + include community maps: - remove power ups that require aiming: - - limit frames per second: no cap diff --git a/js/bullet.js b/js/bullet.js index f9ffb2f..0bcc948 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -674,14 +674,14 @@ const b = { drone(speed = 1) { const me = bullet.length; const THRUST = mod.isFastDrones ? 0.0025 : 0.0015 - const FRICTION = mod.isFastDrones ? 0.008 : 0.0005 + // const FRICTION = mod.isFastDrones ? 0.008 : 0.0005 const dir = mech.angle + 0.4 * (Math.random() - 0.5); const RADIUS = (4.5 + 3 * Math.random()) bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 8, RADIUS, { angle: dir, inertia: Infinity, friction: 0.05, - frictionAir: FRICTION, + frictionAir: 0, restitution: 1, dmg: 0.28, //damage done in addition to the damage from momentum lookFrequency: 80 + Math.floor(23 * Math.random()), @@ -741,33 +741,33 @@ const b = { let closeDist = Infinity; for (let i = 0, len = powerUp.length; i < len; ++i) { if ( - ((powerUp[i].name !== "field" && powerUp[i].name !== "heal") || (powerUp[i].name === "heal" && mech.health < 0.9 * mech.maxHealth)) && + (powerUp[i].name !== "heal" || mech.health < 0.9 * mech.maxHealth || mod.isDroneGrab) && Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 && Matter.Query.ray(body, this.position, powerUp[i].position).length === 0 ) { const TARGET_VECTOR = Vector.sub(this.position, powerUp[i].position) const DIST = Vector.magnitude(TARGET_VECTOR); if (DIST < closeDist) { - if (DIST < 100) { //eat the power up if close enough - powerUps.onPickUp(); - powerUp[i].effect(); - Matter.World.remove(engine.world, powerUp[i]); - powerUp.splice(i, 1); - if (mod.isDroneGrab) { - this.isImproved = true; - const SCALE = 2 - Matter.Body.scale(this, SCALE, SCALE); - this.lookFrequency = 30; - this.endCycle = game.cycle + Math.floor((1100 + 420 * Math.random()) * mod.isBulletsLastLonger) * 2 //set to double a normal lifespan - this.dmg *= 1.5; - this.frictionAir *= 0.9 - } - break; - } closeDist = DIST; this.lockedOn = powerUp[i] } } + if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 60000) { + powerUps.onPickUp(); + powerUp[i].effect(); + Matter.World.remove(engine.world, powerUp[i]); + powerUp.splice(i, 1); + if (mod.isDroneGrab) { + this.isImproved = true; + const SCALE = 2 + Matter.Body.scale(this, SCALE, SCALE); + this.lookFrequency = 30; + this.endCycle = Infinity + this.dmg *= 1.5; + this.frictionAir = 0 + } + break; + } } } } @@ -1011,13 +1011,13 @@ const b = { if (isKeep) mod.boomBotCount++; } }, - nailBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + nailBot(position = mech.pos) { const me = bullet.length; const dir = mech.angle; const RADIUS = (12 + 4 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, { - isUpgraded: isUpgraded, - isBot: true, + isUpgraded: mod.isNailBotUpgrade, + botType: "nail", angle: dir, friction: 0, frictionStatic: 0, @@ -1042,7 +1042,7 @@ const b = { onEnd() {}, do() { if (this.lastLookCycle < game.cycle) { - this.lastLookCycle = game.cycle + 65 - this.isUpgraded * 25 + this.lastLookCycle = game.cycle + 80 - this.isUpgraded * 40 let target for (let i = 0, len = mob.length; i < len; i++) { const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position)); @@ -1066,13 +1066,13 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, - foamBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + foamBot(position = mech.pos) { const me = bullet.length; const dir = mech.angle; const RADIUS = (10 + 5 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 6, RADIUS, { - isUpgraded: isUpgraded, - isBot: true, + isUpgraded: mod.isFoamBotUpgrade, + botType: "foam", angle: dir, friction: 0, frictionStatic: 0, @@ -1080,7 +1080,7 @@ const b = { restitution: 0.6 * (1 + 0.5 * Math.random()), dmg: 0, // 0.14 //damage done in addition to the damage from momentum minDmgSpeed: 2, - lookFrequency: 47 + Math.floor(17 * Math.random()), + lookFrequency: 60 + Math.floor(17 * Math.random()) - 10 * mod.isFoamBotUpgrade, cd: 0, delay: 100, acceleration: 0.005 * (1 + 0.5 * Math.random()), @@ -1107,7 +1107,7 @@ const b = { const radius = 6 + 7 * Math.random() const SPEED = 29 - radius * 0.5; //(mech.crouch ? 32 : 20) - radius * 0.7; const velocity = Vector.mult(Vector.normalise(Vector.sub(target, this.position)), SPEED) - b.foam(this.position, velocity, radius + 7 * this.isUpgraded) + b.foam(this.position, velocity, radius + 8 * this.isUpgraded) break; } } @@ -1122,13 +1122,13 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, - laserBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + laserBot(position = mech.pos) { const me = bullet.length; const dir = mech.angle; const RADIUS = (14 + 6 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 3, RADIUS, { - isUpgraded: isUpgraded, - isBot: true, + isUpgraded: mod.isLaserBotUpgrade, + botType: "laser", angle: dir, friction: 0, frictionStatic: 0, @@ -1136,9 +1136,9 @@ const b = { restitution: 0.5 * (1 + 0.5 * Math.random()), dmg: 0, // 0.14 //damage done in addition to the damage from momentum minDmgSpeed: 2, - lookFrequency: 27 + Math.floor(17 * Math.random()), + lookFrequency: 40 + Math.floor(7 * Math.random()), acceleration: 0.0015 * (1 + 0.3 * Math.random()), - range: 600 * (1 + 0.2 * Math.random()), + range: 600 * (1 + 0.2 * Math.random()) + 200 * mod.isLaserBotUpgrade, followRange: 150 + Math.floor(30 * Math.random()), offPlayer: { x: 0, @@ -1189,7 +1189,7 @@ const b = { } //hit target with laser if (this.lockedOn && this.lockedOn.alive && mech.energy > 0.15) { - mech.energy -= 0.0014 * mod.isLaserDiode - 0.0006 * this.isUpgraded + mech.energy -= 0.0014 * mod.isLaserDiode //make sure you can still see vertex const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position)); if (DIST - this.lockedOn.radius < this.range + 150 && @@ -1207,7 +1207,7 @@ const b = { bestVertexDistance = dist } } - const dmg = b.dmgScale * 0.05; + const dmg = b.dmgScale * (0.04 + 0.04 * this.isUpgraded); this.lockedOn.damage(dmg); this.lockedOn.locatePlayer(); @@ -1230,13 +1230,13 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, - boomBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + boomBot(position = mech.pos) { const me = bullet.length; const dir = mech.angle; const RADIUS = (7 + 2 * Math.random()) bullet[me] = Bodies.polygon(position.x, position.y, 4, RADIUS, { - isUpgraded: isUpgraded, - isBot: true, + isUpgraded: mod.isBoomBotUpgrade, + botType: "boom", angle: dir, friction: 0, frictionStatic: 0, @@ -1244,9 +1244,9 @@ const b = { restitution: 1, dmg: 0, minDmgSpeed: 0, - lookFrequency: 35 + Math.floor(7 * Math.random()), + lookFrequency: 43 + Math.floor(7 * Math.random()), acceleration: 0.005 * (1 + 0.5 * Math.random()), - range: 500 * (1 + 0.1 * Math.random()), + range: 500 * (1 + 0.1 * Math.random()) + 250 * mod.isBoomBotUpgrade, endCycle: Infinity, classType: "bullet", collisionFilter: { @@ -1257,7 +1257,7 @@ const b = { explode: 0, onDmg() { if (this.lockedOn) { - const explosionRadius = Math.min(170 + 70 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30) + const explosionRadius = Math.min(170 + 110 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30) if (explosionRadius > 60) { this.explode = explosionRadius // @@ -1308,13 +1308,12 @@ const b = { }) World.add(engine.world, bullet[me]); //add bullet to world }, - plasmaBot(position = mech.pos, isUpgraded = mod.isBotUpgrade) { + plasmaBot(position = mech.pos) { const me = bullet.length; const dir = mech.angle; const RADIUS = 21 bullet[me] = Bodies.polygon(position.x, position.y, 5, RADIUS, { - isUpgraded: isUpgraded, - isBot: true, + botType: "plasma", angle: dir, friction: 0, frictionStatic: 0, @@ -1543,7 +1542,6 @@ const b = { defaultAmmoPack: 75, recordedAmmo: 0, have: false, - isEasyToAim: false, nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count startingHoldCycle: 0, fire() { @@ -1581,7 +1579,6 @@ const b = { ammo: 0, ammoPack: 9, have: false, - isEasyToAim: true, fire() { let knock, spread if (mech.crouch) { @@ -1653,7 +1650,6 @@ const b = { ammoPack: 15, have: false, num: 5, - isEasyToAim: true, fire() { const SPEED = mech.crouch ? 43 : 32 mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 18) * b.fireCD); // cool down @@ -1709,7 +1705,6 @@ const b = { ammoPack: 42, defaultAmmoPack: 42, have: false, - isEasyToAim: false, count: 0, //used to track how many shots are in a volley before a big CD lastFireCycle: 0, //use to remember how longs its been since last fire, used to reset count fire() { @@ -1813,7 +1808,6 @@ const b = { ammo: 0, ammoPack: 110, have: false, - isEasyToAim: false, fire() { mech.fireCDcycle = mech.cycle + Math.floor(3 * b.fireCD); // cool down const dir = mech.angle @@ -1949,7 +1943,6 @@ const b = { ammo: 0, ammoPack: 5, have: false, - isEasyToAim: true, fireCycle: 0, ammoLoaded: 0, fire() { @@ -2007,7 +2000,6 @@ const b = { ammoPack: 6, defaultAmmoPack: 6, //use to revert ammoPack after mod changes drop rate have: false, - isEasyToAim: false, fire() { mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.fireCD); // cool down b.muzzleFlash(30); @@ -2051,7 +2043,6 @@ const b = { ammo: 0, ammoPack: 7, have: false, - isEasyToAim: false, fire() { const me = bullet.length; const dir = mech.angle; // + Math.random() * 0.05; @@ -2103,7 +2094,6 @@ const b = { ammo: 0, ammoPack: 3, have: false, - isEasyToAim: false, fire() { const me = bullet.length; const dir = mech.angle; @@ -2223,7 +2213,6 @@ const b = { ammo: 0, ammoPack: 7, have: false, - isEasyToAim: true, fire() { const me = bullet.length; const dir = mech.angle; @@ -2382,7 +2371,6 @@ const b = { ammo: 0, ammoPack: 3, have: false, - isEasyToAim: true, fire() { const pos = { x: mech.pos.x + 30 * Math.cos(mech.angle), @@ -2405,7 +2393,6 @@ const b = { ammo: 0, ammoPack: 5, have: false, - isEasyToAim: true, fire() { const me = bullet.length; const dir = mech.angle; @@ -2526,7 +2513,6 @@ const b = { ammo: 0, ammoPack: 15, have: false, - isEasyToAim: true, fire() { b.drone(mech.crouch ? 45 : 1) mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 13 : 5) * b.fireCD); // cool down @@ -2538,7 +2524,6 @@ const b = { ammo: 0, ammoPack: 73, have: false, - isEasyToAim: true, fire() { if (mech.crouch) { b.iceIX(10, 0.3) @@ -2556,7 +2541,6 @@ const b = { ammo: 0, ammoPack: 50, have: false, - isEasyToAim: false, fire() { mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 20 : 6) * b.fireCD); // cool down const radius = mech.crouch ? 10 + 7 * Math.random() : 4 + 6 * Math.random() //(4 + (mech.crouch ? 15 : 6) * Math.random()) @@ -2579,7 +2563,6 @@ const b = { ammo: 0, ammoPack: 4, have: false, - isEasyToAim: false, fire() { const me = bullet.length; bullet[me] = Bodies.rectangle(0, 0, 0.015, 0.0015, { @@ -2817,7 +2800,6 @@ const b = { ammo: 0, ammoPack: Infinity, have: false, - isEasyToAim: false, fire() { const reflectivity = 1 - 1 / (mod.laserReflections * 1.5) let damage = b.dmgScale * mod.laserDamage @@ -2976,7 +2958,6 @@ const b = { ammo: 0, ammoPack: Infinity, have: false, - isEasyToAim: false, fire() { //calculate laser collision let best, energy, explosionRange; @@ -3126,7 +3107,6 @@ const b = { // ammo: 0, // ammoPack: Infinity, // have: false, - // isEasyToAim: false, // fire() { // if (mech.energy < 0.002) { // mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy diff --git a/js/engine.js b/js/engine.js index 05711f4..f0e91a4 100644 --- a/js/engine.js +++ b/js/engine.js @@ -222,9 +222,9 @@ function collisionChecks(event) { if (obj.classType === "body" && obj.speed > 6) { const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)); if (v > 9) { - let dmg = b.dmgScale * v * obj.mass * 0.065 * mod.throwChargeRate; + let dmg = 0.06 * b.dmgScale * v * obj.mass * mod.throwChargeRate; if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5 - if (mob[k].isShielded) dmg *= 0.5 + if (mob[k].isShielded) dmg *= 0.4 mob[k].damage(dmg, true); if (mob[k].distanceToPlayer2() < 1000000) mob[k].foundPlayer(); game.drawList.push({ diff --git a/js/game.js b/js/game.js index 560d9f3..116bc30 100644 --- a/js/game.js +++ b/js/game.js @@ -118,7 +118,6 @@ const game = { cycle: 0, //total cycles, 60 per second fpsCap: null, //limits frames per second to 144/2=72, on most monitors the fps is capped at 60fps by the hardware fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob - isEasyToAimMode: true, //removes power ups that don't work well with a track pad isCommunityMaps: false, cyclePaused: 0, fallHeight: 3000, //below this y position the player dies @@ -476,7 +475,7 @@ const game = { const dx = game.mouse.x / window.innerWidth - 0.5 //x distance from mouse to window center scaled by window width const dy = game.mouse.y / window.innerHeight - 0.5 //y distance from mouse to window center scaled by window height const d = Math.max(dx * dx, dy * dy) - game.edgeZoomOutSmooth = (1 + 4 * d * d) * 0.05 + game.edgeZoomOutSmooth * 0.95 + game.edgeZoomOutSmooth = (1 + 4 * d * d) * 0.04 + game.edgeZoomOutSmooth * 0.96 ctx.save(); @@ -754,7 +753,7 @@ const game = { }); // move bots for (let i = 0; i < bullet.length; i++) { - if (bullet[i].isBot) { + if (bullet[i].botType) { Matter.Body.setPosition(bullet[i], player.position); Matter.Body.setVelocity(bullet[i], { x: 0, @@ -1050,6 +1049,7 @@ const game = { document.execCommand('copy'); } catch (err) { // Unable to copy + console.log(err) } finally { // Remove the textarea document.body.removeChild(textAreaEle); @@ -1083,6 +1083,7 @@ const game = { out += game.constructMapString[i]; outHTML += "" + game.constructMapString[i] + "" } + console.log(out) game.copyToClipBoard(out) document.getElementById("construct").innerHTML = outHTML }, diff --git a/js/index.js b/js/index.js index ac29206..45c9a27 100644 --- a/js/index.js +++ b/js/index.js @@ -357,9 +357,6 @@ if (localSettings) { // game.isBodyDamage = localSettings.isBodyDamage // document.getElementById("body-damage").checked = localSettings.isBodyDamage - game.isEasyToAimMode = localSettings.isEasyToAimMode - document.getElementById("track-pad-mode").checked = localSettings.isEasyToAimMode - game.isCommunityMaps = localSettings.isCommunityMaps document.getElementById("community-maps").checked = localSettings.isCommunityMaps @@ -374,17 +371,12 @@ if (localSettings) { document.getElementById("fps-select").value = localSettings.fpsCapDefault } else { localSettings = { - // isBodyDamage: true, - isEasyToAimMode: false, isCommunityMaps: false, difficultyMode: '1', fpsCapDefault: 'max', }; localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage - // document.getElementById("body-damage").checked = localSettings.isBodyDamage - document.getElementById("track-pad-mode").checked = localSettings.isEasyToAimMode - game.isEasyToAimMode = localSettings.isEasyToAimMode - document.getElementById("community-maps").checked = localSettings.isEasyToAimMode + document.getElementById("community-maps").checked = localSettings.isCommunityMaps game.isCommunityMaps = localSettings.isCommunityMaps document.getElementById("difficulty-select").value = localSettings.difficultyMode document.getElementById("fps-select").value = localSettings.fpsCapDefault @@ -510,18 +502,6 @@ document.getElementById("fps-select").addEventListener("input", () => { localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage }); -// document.getElementById("body-damage").addEventListener("input", () => { -// game.isBodyDamage = document.getElementById("body-damage").checked -// localSettings.isBodyDamage = game.isBodyDamage -// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage -// }); - -document.getElementById("track-pad-mode").addEventListener("input", () => { - game.isEasyToAimMode = document.getElementById("track-pad-mode").checked - localSettings.isEasyToAimMode = game.isEasyToAimMode - localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage -}); - document.getElementById("community-maps").addEventListener("input", () => { game.isCommunityMaps = document.getElementById("community-maps").checked localSettings.isCommunityMaps = game.isCommunityMaps diff --git a/js/level.js b/js/level.js index 948fc0b..8d39759 100644 --- a/js/level.js +++ b/js/level.js @@ -62,6 +62,121 @@ const level = { //****************************************************************************************************************** //****************************************************************************************************************** //****************************************************************************************************************** + testing() { + level.custom = () => { + level.playerExitCheck(); + }; + level.customTopLayer = () => {}; + + level.setPosToSpawn(0, -750); //normal spawn + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.exit.x = 6500; + level.exit.y = -230; + + // level.difficultyIncrease(14); //hard mode level 7 + spawn.setSpawnList(); + spawn.setSpawnList(); + level.defaultZoom = 1500 + game.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#ddd"; + // game.draw.mapFill = "#444" + // game.draw.bodyFill = "rgba(140,140,140,0.85)" + // game.draw.bodyStroke = "#222" + + level.fill.push({ + x: 6400, + y: -550, + width: 300, + height: 350, + color: "rgba(0,255,255,0.1)" + }); + + // level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel"); + + spawn.mapRect(-950, 0, 8200, 800); //ground + spawn.mapRect(-950, -1200, 800, 1400); //left wall + spawn.mapRect(-950, -1800, 8200, 800); //roof + spawn.mapRect(-250, -700, 1000, 900); // shelf + spawn.mapRect(-250, -1200, 1000, 250); // shelf roof + powerUps.spawnStartingPowerUps(600, -800); + powerUps.spawn(550, -800, "reroll", false); + + function blockDoor(x, y, blockSize = 58) { + spawn.mapRect(x, y - 290, 40, 60); // door lip + spawn.mapRect(x, y, 40, 50); // door lip + for (let i = 0; i < 4; ++i) { + spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize); + } + } + blockDoor(710, -710); + spawn.mapRect(2500, -1200, 200, 750); //right wall + blockDoor(2585, -210) + spawn.mapRect(2500, -200, 200, 300); //right wall + spawn.mapRect(4500, -1200, 200, 650); //right wall + blockDoor(4585, -310) + spawn.mapRect(4500, -300, 200, 400); //right wall + spawn.mapRect(6400, -1200, 400, 750); //right wall + spawn.mapRect(6400, -200, 400, 300); //right wall + spawn.mapRect(6700, -1800, 800, 2600); //right wall + spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump + spawn.boost(1500, 0, 900); + + // spawn.bomberBoss(2900, -500) + // spawn.launcherBoss(1200, -500) + // spawn.laserTargetingBoss(1600, -400) + // spawn.spawner(1600, -500) + // spawn.sniper(1700, -120, 50) + // spawn.sniper(1400, -120) + // spawn.sniper(1800, -120) + // spawn.sniper(2200, -120) + // spawn.cellBossCulture(1600, -500) + // spawn.starter(1600, -500, 60) + spawn.powerUpBoss(1600, -500) + // spawn.shield(mob[mob.length - 1], 1200, -500, 1); + + // spawn.nodeBoss(1200, -500, "launcher") + // spawn.spiderBoss(1200, -500) + // spawn.timeSkipBoss(2900, -500) + // spawn.randomMob(1600, -500) + }, + template() { + level.custom = () => { + level.playerExitCheck(); + }; + level.customTopLayer = () => {}; + level.setPosToSpawn(0, -50); //normal spawn + spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); + level.exit.x = 1500; + level.exit.y = -1875; + level.defaultZoom = 1800 + game.zoomTransition(level.defaultZoom) + document.body.style.backgroundColor = "#dcdcde"; + // powerUps.spawnStartingPowerUps(1475, -1175); + // spawn.debris(750, -2200, 3700, 16); //16 debris per level + // level.fill.push({ //foreground + // x: 2500, + // y: -1100, + // width: 450, + // height: 250, + // color: "rgba(0,0,0,0.1)" + // }); + // level.fillBG.push({ //background + // x: 1300, + // y: -1800, + // width: 750, + // height: 1800, + // color: "#d4d4d7" + // }); + + spawn.mapRect(-100, 0, 1000, 100); + // spawn.bodyRect(1540, -1110, 300, 25, 0.9); + // spawn.boost(4150, 0, 1300); + // spawn.randomSmallMob(1300, -70); + // spawn.randomMob(2650, -975, 0.8); + // spawn.randomBoss(1700, -900, 0.4); + // if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300); + powerUps.addRerollToLevel() //needs to run after mobs are spawned + }, testChamber() { level.setPosToSpawn(0, -50); //lower start level.exit.y = level.enter.y - 550; @@ -419,121 +534,6 @@ const level = { if (game.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss"]); powerUps.addRerollToLevel() //needs to run after mobs are spawned }, - template() { - level.custom = () => { - level.playerExitCheck(); - }; - level.customTopLayer = () => {}; - level.setPosToSpawn(0, -50); //normal spawn - spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - level.exit.x = 1500; - level.exit.y = -1875; - level.defaultZoom = 1800 - game.zoomTransition(level.defaultZoom) - document.body.style.backgroundColor = "#dcdcde"; - // powerUps.spawnStartingPowerUps(1475, -1175); - // spawn.debris(750, -2200, 3700, 16); //16 debris per level - // level.fill.push({ //foreground - // x: 2500, - // y: -1100, - // width: 450, - // height: 250, - // color: "rgba(0,0,0,0.1)" - // }); - // level.fillBG.push({ //background - // x: 1300, - // y: -1800, - // width: 750, - // height: 1800, - // color: "#d4d4d7" - // }); - - spawn.mapRect(-100, 0, 1000, 100); - // spawn.bodyRect(1540, -1110, 300, 25, 0.9); - // spawn.boost(4150, 0, 1300); - // spawn.randomSmallMob(1300, -70); - // spawn.randomMob(2650, -975, 0.8); - // spawn.randomBoss(1700, -900, 0.4); - // if (game.difficulty > 3) spawn.randomLevelBoss(2200, -1300); - powerUps.addRerollToLevel() //needs to run after mobs are spawned - }, - testing() { - level.custom = () => { - level.playerExitCheck(); - }; - level.customTopLayer = () => {}; - - level.setPosToSpawn(0, -750); //normal spawn - spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); - level.exit.x = 6500; - level.exit.y = -230; - - // level.difficultyIncrease(14); //hard mode level 7 - spawn.setSpawnList(); - spawn.setSpawnList(); - level.defaultZoom = 1500 - game.zoomTransition(level.defaultZoom) - document.body.style.backgroundColor = "#ddd"; - // game.draw.mapFill = "#444" - // game.draw.bodyFill = "rgba(140,140,140,0.85)" - // game.draw.bodyStroke = "#222" - - level.fill.push({ - x: 6400, - y: -550, - width: 300, - height: 350, - color: "rgba(0,255,255,0.1)" - }); - - // level.addZone(level.exit.x, level.exit.y, 100, 30, "nextLevel"); - - spawn.mapRect(-950, 0, 8200, 800); //ground - spawn.mapRect(-950, -1200, 800, 1400); //left wall - spawn.mapRect(-950, -1800, 8200, 800); //roof - spawn.mapRect(-250, -700, 1000, 900); // shelf - spawn.mapRect(-250, -1200, 1000, 250); // shelf roof - powerUps.spawnStartingPowerUps(600, -800); - powerUps.spawn(550, -800, "reroll", false); - - function blockDoor(x, y, blockSize = 58) { - spawn.mapRect(x, y - 290, 40, 60); // door lip - spawn.mapRect(x, y, 40, 50); // door lip - for (let i = 0; i < 4; ++i) { - spawn.bodyRect(x + 5, y - 260 + i * blockSize, 30, blockSize); - } - } - blockDoor(710, -710); - spawn.mapRect(2500, -1200, 200, 750); //right wall - blockDoor(2585, -210) - spawn.mapRect(2500, -200, 200, 300); //right wall - spawn.mapRect(4500, -1200, 200, 650); //right wall - blockDoor(4585, -310) - spawn.mapRect(4500, -300, 200, 400); //right wall - spawn.mapRect(6400, -1200, 400, 750); //right wall - spawn.mapRect(6400, -200, 400, 300); //right wall - spawn.mapRect(6700, -1800, 800, 2600); //right wall - spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump - spawn.boost(1500, 0, 900); - - // spawn.bomberBoss(2900, -500) - // spawn.launcherBoss(1200, -500) - // spawn.laserTargetingBoss(1600, -400) - // spawn.spawner(1600, -500) - // spawn.sniper(1700, -120, 50) - // spawn.sniper(1400, -120) - // spawn.sniper(1800, -120) - // spawn.sniper(2200, -120) - // spawn.cellBossCulture(1600, -500) - // spawn.starter(1600, -500, 60) - // spawn.striker(1600, -500) - // spawn.shield(mob[mob.length - 1], 1200, -500, 1); - - // spawn.nodeBoss(1200, -500, "launcher") - spawn.spiderBoss(1200, -500) - // spawn.timeSkipBoss(2900, -500) - // spawn.randomMob(1600, -500) - }, bosses() { level.custom = () => { level.playerExitCheck(); @@ -1325,7 +1325,7 @@ const level = { spawn.randomBoss(4000, -350, 0.6); spawn.randomBoss(2750, -550, 0.1); if (game.difficulty > 2) { - if (Math.random() < 0.09) { // tether ball + if (Math.random() < 0.1) { // tether ball spawn.tetherBoss(4250, 0) cons[cons.length] = Constraint.create({ pointA: { @@ -1336,7 +1336,7 @@ const level = { stiffness: 0.00007 }); if (game.difficulty > 4) spawn.nodeBoss(4250, 0, "spawns", 8, 20, 105); //chance to spawn a ring of exploding mobs around this boss - } else if (Math.random() < 0.08) { + } else if (Math.random() < 0.15) { spawn.randomLevelBoss(4250, -250); } else { //floor below right tall tower @@ -2023,7 +2023,7 @@ const level = { spawn.randomBoss(4150, -1000, 0.6); if (game.difficulty > 2) { - if (Math.random() < 0.75) { + if (Math.random() < 0.65) { // tether ball level.fillBG.push({ x: 2495, @@ -2043,8 +2043,8 @@ const level = { }); //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); + } else { + spawn.randomLevelBoss(2200, -650) } } powerUps.addRerollToLevel() //needs to run after mobs are spawned @@ -3072,10 +3072,10 @@ const level = { draw = function () { ctx.beginPath(); //portal - sensor = this.vertices; - ctx.moveTo(sensor[0].x, sensor[0].y); - for (let i = 1; i < sensor.length; ++i) { - ctx.lineTo(sensor[i].x, sensor[i].y); + let v = this.vertices; + ctx.moveTo(v[0].x, v[0].y); + for (let i = 1; i < v.length; ++i) { + ctx.lineTo(v[i].x, v[i].y); } ctx.fillStyle = this.color ctx.fill(); @@ -3104,7 +3104,7 @@ const level = { Matter.Body.setVelocity(player, v); // move bots to follow player for (let i = 0; i < bullet.length; i++) { - if (bullet[i].isBot) { + if (bullet[i].botType) { Matter.Body.setPosition(bullet[i], this.portalPair.portal.position); Matter.Body.setVelocity(bullet[i], { x: 0, @@ -3113,8 +3113,6 @@ const level = { } } } - - if (body.length) { for (let i = 0, len = body.length; i < len; i++) { if (body[i] !== mech.holdingTarget) { @@ -3210,7 +3208,7 @@ const level = { color: game.draw.mapFill, draw: draw, query: query, - lastPortalCycle: 0 + lastPortalCycle: 0, }); Matter.Body.setStatic(mapB, true); //make static World.add(engine.world, mapB); //add to world diff --git a/js/mob.js b/js/mob.js index a0b4360..510da75 100644 --- a/js/mob.js +++ b/js/mob.js @@ -47,7 +47,7 @@ const mobs = { applySlow(who) //look for mobs near the target if (mod.isAoESlow) { - const range = (220 + 150 * Math.random()) ** 2 + const range = (320 + 150 * Math.random()) ** 2 for (let i = 0, len = mob.length; i < len; i++) { if (Vector.magnitudeSquared(Vector.sub(who.position, mob[i].position)) < range) applySlow(mob[i]) } @@ -705,10 +705,13 @@ const mobs = { //accelerate towards the player if (this.seePlayer.recall) { // && dx * dx + dy * dy < 2000000) { - const forceMag = this.accelMag * this.mass; - const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); - this.force.x += forceMag * Math.cos(angle); - this.force.y += forceMag * Math.sin(angle); + // const forceMag = this.accelMag * this.mass; + // const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x); + // this.force.x += forceMag * Math.cos(angle); + // this.force.y += forceMag * Math.sin(angle); + const force = Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position, this.position)), this.accelMag * this.mass) + this.force.x += force.x; + this.force.y += force.y; } }, repulsionRange: 500000, @@ -1076,7 +1079,7 @@ const mobs = { //replace dead mob with a regular body replace(i) { //if there are too many bodies don't turn into blocks to help performance - if (this.leaveBody && body.length < 60 && this.mass < 100) { + if (this.leaveBody && body.length < 60 && this.mass < 200) { const len = body.length; const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v); @@ -1091,7 +1094,7 @@ const mobs = { World.add(engine.world, body[len]); //add to world //large mobs shrink so they don't block paths - if (body[len].mass > 10) { + if (body[len].mass > 9) { const shrink = function (that, massLimit) { if (that.mass > massLimit) { const scale = 0.95; @@ -1099,7 +1102,7 @@ const mobs = { setTimeout(shrink, 20, that, massLimit); } }; - shrink(body[len], 9 + 5 * Math.random()) + shrink(body[len], 7 + 4 * Math.random()) } } Matter.World.remove(engine.world, this); diff --git a/js/mods.js b/js/mods.js index e1d722a..e094746 100644 --- a/js/mods.js +++ b/js/mods.js @@ -79,7 +79,7 @@ const mod = { if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 5.5; if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.006 if (mod.isRerollDamage) dmg *= 1 + 0.05 * powerUps.reroll.rerolls - if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.25 + if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.22 return dmg * mod.slowFire }, totalBots() { @@ -87,7 +87,7 @@ const mod = { }, mods: [{ name: "integrated armament", - description: "increase damage by 25%your inventory can only hold 1 gun", + description: "increase damage by 22%your inventory can only hold 1 gun", maxCount: 1, count: 0, allowed() { @@ -389,6 +389,23 @@ const mod = { mod.nailsDeathMob = 0; } }, + { + name: "bot fabrication", + description: "anytime you collect 4 rerollsuse them to build a random bot", + maxCount: 1, + count: 0, + allowed() { + return powerUps.reroll.rerolls > 3 || build.isCustomSelection + }, + requires: "at least 4 rerolls", + effect() { + mod.isRerollBots = true; + powerUps.reroll.changeRerolls(0) + }, + remove() { + mod.isRerollBots = false; + } + }, { name: "nail-bot", description: "a bot fires nails at targets in line of sight", @@ -406,6 +423,28 @@ const mod = { mod.nailBotCount = 0; } }, + { + name: "nail-bot upgrade", + description: "100% increased nail-bot fire rateapplies to all current and future nail-bots", + maxCount: 1, + count: 0, + allowed() { + return mod.nailBotCount > 1 + }, + requires: "2 or more nail bots", + effect() { + mod.isNailBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'nail') bullet[i].isUpgraded = true + } + }, + remove() { + mod.isNailBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'nail') bullet[i].isUpgraded = false + } + } + }, { name: "foam-bot", description: "a bot fires foam at targets in line of sight", @@ -423,6 +462,28 @@ const mod = { mod.foamBotCount = 0; } }, + { + name: "foam-bot upgrade", + description: "100% increased foam-bot foam sizeapplies to all current and future foam-bots", + maxCount: 1, + count: 0, + allowed() { + return mod.foamBotCount > 1 + }, + requires: "2 or more foam bots", + effect() { + mod.isFoamBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'foam') bullet[i].isUpgraded = true + } + }, + remove() { + mod.isFoamBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'foam') bullet[i].isUpgraded = false + } + } + }, { name: "boom-bot", description: "a bot defends the space around youignites an explosion after hitting a mob", @@ -440,6 +501,28 @@ const mod = { mod.boomBotCount = 0; } }, + { + name: "boom-bot upgrade", + description: "100% increased boom-bot explosion sizeapplies to all current and future boom-bots", + maxCount: 1, + count: 0, + allowed() { + return mod.boomBotCount > 1 + }, + requires: "2 or more boom bots", + effect() { + mod.isBoomBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'boom') bullet[i].isUpgraded = true + } + }, + remove() { + mod.isBoomBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'boom') bullet[i].isUpgraded = false + } + } + }, { name: "laser-bot", description: "a bot defends the space around youuses a short range laser that drains energy", @@ -458,20 +541,25 @@ const mod = { } }, { - name: "bot fabrication", - description: "anytime you collect 4 rerollsuse them to build a random bot", + name: "laser-bot upgrade", + description: "100% increased laser-bot damageapplies to all current and future laser-bots", maxCount: 1, count: 0, allowed() { - return powerUps.reroll.rerolls > 3 || build.isCustomSelection + return mod.laserBotCount > 1 }, - requires: "at least 4 rerolls", + requires: "2 or more laser bots", effect() { - mod.isRerollBots = true; - powerUps.reroll.changeRerolls(0) + mod.isLaserBotUpgrade = true + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'laser') bullet[i].isUpgraded = true + } }, remove() { - mod.isRerollBots = false; + mod.isLaserBotUpgrade = false + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].botType = 'laser') bullet[i].isUpgraded = false + } } }, { @@ -506,28 +594,6 @@ const mod = { mod.isBotArmor = false } }, - { - name: "bot upgrades", - description: "40% improved: nail fire rate, boom explosion,foam size, laser drain, and plasma drain", - maxCount: 1, - count: 0, - allowed() { - return mod.totalBots() > 1 - }, - requires: "2 or more bots", - effect() { - mod.isBotUpgrade = true - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].isBot) bullet[i].isUpgraded = true - } - }, - remove() { - mod.isBotUpgrade = false - for (let i = 0; i < bullet.length; i++) { - if (bullet[i].isBot) bullet[i].isUpgraded = false - } - } - }, { name: "bot replication", description: "duplicate your permanent botsremove all of your guns", @@ -1724,7 +1790,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.nailBotCount + mod.grenadeFragments + mod.nailsDeathMob > 1 || mod.haveGunCheck("mine") || mod.isRailNails || mod.isNailShot + return mod.nailBotCount + mod.grenadeFragments + mod.nailsDeathMob / 2 + mod.haveGunCheck("mine") + mod.isRailNails + mod.isNailShot > 1 }, requires: "nails", effect() { @@ -1817,7 +1883,7 @@ const mod = { }, { name: "harvester", - description: "when a drone picks up a power up improve its size, duration, and vision rate", + description: "after a drone picks up a power up,it's bigger, faster, and infinitely durable", maxCount: 1, count: 0, allowed() { @@ -2483,7 +2549,10 @@ const mod = { isMineDrop: null, isRerollBots: null, isRailTimeSlow: null, - isBotUpgrade: null, + isNailBotUpgrade: null, + isFoamBotUpgrade: null, + isLaserBotUpgrade: null, + isBoomBotUpgrade: null, isDroneGrab: null, isOneGun: null } \ No newline at end of file diff --git a/js/player.js b/js/player.js index e5d9260..f6a91ed 100644 --- a/js/player.js +++ b/js/player.js @@ -1175,7 +1175,6 @@ const mech = { fieldUpgrades: [{ name: "field emitter", description: "use energy to shield yourself from harmpick up and throw objects", - isEasyToAim: false, effect: () => { game.replaceTextLog = true; //allow text over write mech.hold = function () { @@ -1202,7 +1201,6 @@ const mech = { { name: "standing wave harmonics", description: "three oscillating shields are permanently activereduce harm by 33%", - isEasyToAim: true, effect: () => { mech.fieldHarmReduction = 0.67; mech.fieldBlockCD = 0; @@ -1245,7 +1243,6 @@ const mech = { name: "perfect diamagnetism", // description: "gain energy when blockingno recoil when blocking", description: "blocking does not drain energyblocking has no cool down and less recoil", - isEasyToAim: false, effect: () => { mech.fieldShieldingScale = 0; // mech.fieldMeterColor = "#0af" @@ -1302,7 +1299,6 @@ const mech = { { name: "nano-scale manufacturing", description: "excess energy used to build dronesenergy regeneration is doubled", - isEasyToAim: true, effect: () => { // mech.fieldRegen *= 2; mech.hold = function () { @@ -1326,7 +1322,7 @@ const mech = { 1, mod.babyMissiles) } else if (mod.isIceField) { // mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones - mech.energy -= 0.061; + mech.energy -= 0.045; b.iceIX(1) } else { // mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones @@ -1360,7 +1356,6 @@ const mech = { name: "negative mass field", description: "use energy to nullify gravityreduce harm by 50%", fieldDrawRadius: 0, - isEasyToAim: true, effect: () => { mech.fieldFire = true; mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping @@ -1478,7 +1473,6 @@ const mech = { { name: "plasma torch", description: "use energy to emit short range plasmaplasma damages and pushes mobs", - isEasyToAim: false, effect() { mech.fieldMeterColor = "#f0f" mech.hold = function () { @@ -1634,7 +1628,6 @@ const mech = { { name: "time dilation field", description: "use energy to stop timeyou can move and fire while time is stopped", - isEasyToAim: true, effect: () => { // mech.fieldMeterColor = "#000" mech.fieldFire = true; @@ -1727,7 +1720,6 @@ const mech = { { name: "phase decoherence field", description: "use energy to become intangiblefiring and touching shields increases drain", - isEasyToAim: true, effect: () => { mech.fieldFire = true; mech.fieldMeterColor = "#fff"; @@ -1876,7 +1868,6 @@ const mech = { { name: "pilot wave", description: "use energy to push blocks with your mousefield radius decreases out of line of sight", - isEasyToAim: false, effect: () => { game.replaceTextLog = true; //allow text over write game.isBodyDamage = false; diff --git a/js/powerup.js b/js/powerup.js index c8c6680..f85c107 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -171,7 +171,7 @@ const powerUps = { function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { let options = []; for (let i = 1; i < who.length; i++) { - if (i !== mech.fieldMode && (!game.isEasyToAimMode || mech.fieldUpgrades[i].isEasyToAim) && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); + if (i !== mech.fieldMode && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) options.push(i); } //remove repeats from last selection const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2 @@ -310,7 +310,7 @@ const powerUps = { function pick(who, skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { let options = []; for (let i = 0; i < who.length; i++) { - if (!who[i].have && (!game.isEasyToAimMode || b.guns[i].isEasyToAim) && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { + if (!who[i].have && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4) { options.push(i); } } diff --git a/js/spawn.js b/js/spawn.js index 419fbf9..b978659 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -81,7 +81,7 @@ const spawn = { } } }, - randomLevelBoss(x, y, options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"]) { + randomLevelBoss(x, y, options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss"]) { // other bosses: suckerBoss, laserBoss, tetherBoss, snakeBoss //all need a particular level to work so they are not included spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, @@ -227,6 +227,50 @@ const spawn = { } } }, + powerUpBoss(x, y, vertices = 9, radius = 150) { + mobs.spawn(x, y, vertices, radius, "transparent"); + let me = mob[mob.length - 1]; + me.isBoss = true; + me.frictionAir = 0.05 + me.seeAtDistance2 = 600000; + me.accelMag = 0.0005 * game.accelScale; + if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search + Matter.Body.setDensity(me, 0.001); //normal is 0.001 + me.collisionFilter.mask = cat.bullet | cat.player + // me.memory = 480; + // me.seePlayerFreq = 40 + Math.floor(10 * Math.random()) + + me.lockedOn = null; + if (vertices === 9) { + powerUps.spawnBossPowerUp(me.position.x, me.position.y) + powerUp[powerUp.length - 1].collisionFilter.mask = 0 + me.powerUpInventory = [powerUp[powerUp.length - 1]]; + } + + me.onDeath = function () { + if (vertices > 3) spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1) + for (let i = 0; i < powerUp.length; i++) { + powerUp[i].collisionFilter.mask = cat.map | cat.powerUp + } + }; + me.do = function () { + this.stroke = `hsl(0,0%,${80+25*Math.sin(game.cycle*0.01)}%)` + + //steal all power ups + for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) { + powerUp[i].collisionFilter.mask = 0 + Matter.Body.setPosition(powerUp[i], this.vertices[i]) + Matter.Body.setVelocity(powerUp[i], { + x: 0, + y: 0 + }) + } + + this.seePlayerByLookingAt(); + this.attraction(); + this.checkStatus(); + }; + }, // healer(x, y, radius = 20) { // mobs.spawn(x, y, 3, radius, "rgba(50,255,200,0.4)"); // let me = mob[mob.length - 1]; diff --git a/todo.txt b/todo.txt index cfb458f..a3ca2e5 100644 --- a/todo.txt +++ b/todo.txt @@ -1,15 +1,32 @@ -the game zooms out a bit when the mouse is near the edge of the browser window - (is it annoying or helpful?) - maybe I should add in a smoothing variable for the edge zoom +removed eay to aim setting + the addition of gun selection make this setting less important + +mod: bot upgrades - forked into 4 different mods for each bot + effect is increased to 100% improvement (up from 40%) + +drones are more likely to pick up power ups +mod harvester: now also gives the drone immortality + +new level boss: after it dies it returns with one less vertex + also it steals all your power ups (what!) ************** TODO - n-gon ************** -drop level boss rate mods a bit earlier - or increase damage scaling +ghosters are always visible +ghoster mobs eat power ups and drop them on death + draw ghoster if it has a power up + or just always draw ghoster? + if no power ups on map go for player -fix tension on stronghold - -zoom out a bit when mouse is near edge of screen +give mobs more animal-like behaviors + like rain world + give mobs something to do when they don't see player + explore map + mobs some times aren't aggressive + when low on life or after taking a large hit + mobs can fight each other + this might be hard to code + isolated mobs try to group up map: laboratory rooms with switches that change physics @@ -54,6 +71,8 @@ lore - a robot (the player) gains self awareness new gun - deploy a turret that last for 20 seconds fire nails at nearby targets once a second. use mine code and bot code +mod - mines become a turret that fires nails + it could float to the mouse location on fire minigun: high caliber - rework slow down the bullets even more and increase the size? @@ -65,10 +84,6 @@ portals: extend to bodies (mobs?) use buttons to turn on and off? -level boss: boss that dies and comes back to life but with one less side until it hits 3 sides - change color too (hsl) - boss shrinks and moves faster after each death - level boss: fires a line intersection in a random direction every few seconds. the last two intersections have a destructive laser between them. @@ -83,10 +98,6 @@ map: prison map: airport -button: blocks that are on the button at an angle will slowly slide off the button - maybe just avoid long blocks near the button? - maybe actively hold the button in place? - mod - do 50% more damage in close, but 50% less at a distance code it like mod.isFarAwayDmg have these mods disable each other @@ -130,8 +141,6 @@ redblobgames.com/articles/visibility https://github.com/Silverwolf90/2d-visibility/tree/master/src could apply to explosions, neutron bomb, player LOS -bug - sticking bullets don't always gain the correct speed from mobs after they die - possible names for mods Hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other. @@ -145,47 +154,19 @@ boss levels - small levels just a boss, and maybe a few mobs boss level for timeSkipBoss because of game instability for boss on normal levels this might not fix issues -bullets cost 5 life instead of ammo, but return 5 life when they hit a mob - replace life with energy or ammo? - an effect when canceling a power up ammo? heals? 50% chance for a mod, 25% heal, 25% ammo -liquid nitrogen cooling - Mobs freeze on contact with the player - -uranium reactor core - Mobs get irradiated on contact with the player - add player Scent Trails for mob navigation https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding -mod - scale squirrel cage rotor with current energy - is variable speed going to be hard to deal with? - mod - you can no longer see your current health -mod - increase laser bot range, and reduce energy drain - -mod - mines become a turret that fires nails - it could float to the mouse location on fire - -mod - blocks stun mobs - settings - custom keys binding css transition for pause menu -gun/field: portals - use the code from mines to get them to stick to walls - or lasers - alternate red and blue portals - -weekly random challenge where everyone playing each week gets the same random setup. - The randomness would be determined by the date so it would sync everyone. - power ups still drop, but the drops are determined by a preset list that changes each week. - gun: Spirit Bomb (singularity) use charge up like rail gun electricity graphics like plasma torch @@ -194,41 +175,11 @@ gun: Spirit Bomb (singularity) uses energy hold above the player's head -add a key that player picks up and needs to set on the exit door to open it - make power ups keep moving to player if the pickup field is turned off before they get picked up not sure how to do this without adding a constant check animate new level spawn by having the map aspects randomly fly into place -give mobs more animal-like behaviors - like rain world - give mobs something to do when they don't see player - explore map - eat power ups - drop power up (if killed after eating one) - mobs some times aren't aggressive - when low on life or after taking a large hit - mobs can fight each other - this might be hard to code - isolated mobs try to group up. - -game mechanics - mechanics that support the physics engine - add rope/constraint - get ideas from game: limbo / inside - environmental hazards - laser - lava - button / switch - door - fizzler - moving platform - map zones - water - low friction ground - bouncy ground - n-gon outreach ideas blips - errant signal on youtube reddit - r/IndieGaming