From ff78c731fce1edf9cd485ce6873d7305cead9c70 Mon Sep 17 00:00:00 2001 From: landgreen Date: Mon, 25 May 2020 13:22:15 -0700 Subject: [PATCH] difficulty spawns lasertargetingboss, nailshot --- js/bullet.js | 58 ++++++++++------ js/level.js | 8 +-- js/mob.js | 2 +- js/mods.js | 21 +++++- js/powerup.js | 70 +++++++++++-------- js/spawn.js | 188 ++++++++++++++++++++++++++++++++++++++++++++------ todo.txt | 18 ++++- 7 files changed, 287 insertions(+), 78 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 3e807d8..188b99d 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -398,7 +398,7 @@ const b = { const that = this setTimeout(function () { if (Matter.Query.collides(that, map).length === 0 || Matter.Query.point(map, that.position).length > 0) { - console.log(that) + // console.log(that) that.endCycle = 0 // if not touching map explode that.isArmed = false b.mine(that.position, that.velocity, that.angle) @@ -1203,27 +1203,43 @@ const b = { player.force.y -= knock * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps if (mod.isShotgunImmune) mech.immuneCycle = mech.cycle + 60; //player is immune to collision damage for 30 cycles b.muzzleFlash(35); - const side = 19 * mod.bulletSize - for (let i = 0; i < 15; i++) { - const me = bullet.length; - const dir = mech.angle + (Math.random() - 0.5) * spread - 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 - Matter.Body.setVelocity(bullet[me], { - x: SPEED * Math.cos(dir), - y: SPEED * Math.sin(dir) - }); - bullet[me].endCycle = game.cycle + 40 - bullet[me].minDmgSpeed = 20 - // bullet[me].dmg = 0.1 - bullet[me].frictionAir = 0.034; - bullet[me].do = function () { - if (!mech.isBodiesAsleep) { - const scale = 1 - 0.035 / mod.isBulletsLastLonger - Matter.Body.scale(this, scale, scale); + if (mod.isNailShot) { + for (let i = 0; i < 15; i++) { + const dir = mech.angle + (Math.random() - 0.5) * spread * 0.2 + const pos = { + x: mech.pos.x + 35 * Math.cos(mech.angle) + 15 * (Math.random() - 0.5), + y: mech.pos.y + 35 * Math.sin(mech.angle) + 15 * (Math.random() - 0.5) } - }; + speed = 35 + 15 * Math.random() + const velocity = { + x: speed * Math.cos(dir), + y: speed * Math.sin(dir) + } + b.nail(pos, velocity, 0.6) + } + } else { + const side = 19 * mod.bulletSize + for (let i = 0; i < 15; i++) { + const me = bullet.length; + const dir = mech.angle + (Math.random() - 0.5) * spread + 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 + Matter.Body.setVelocity(bullet[me], { + x: SPEED * Math.cos(dir), + y: SPEED * Math.sin(dir) + }); + bullet[me].endCycle = game.cycle + 40 + bullet[me].minDmgSpeed = 20 + // bullet[me].dmg = 0.1 + bullet[me].frictionAir = 0.034; + bullet[me].do = function () { + if (!mech.isBodiesAsleep) { + const scale = 1 - 0.035 / mod.isBulletsLastLonger + Matter.Body.scale(this, scale, scale); + } + }; + } } } }, diff --git a/js/level.js b/js/level.js index 4df99eb..d770020 100644 --- a/js/level.js +++ b/js/level.js @@ -23,8 +23,8 @@ const level = { // mech.setField("pilot wave") // mech.setField("phase decoherence field") - // level.intro(); //starting level - level.testing(); + level.intro(); //starting level + // level.testing(); // level.stronghold() // level.bosses(); // level.satellite(); @@ -184,9 +184,9 @@ const level = { // spawn.bomberBoss(2900, -500) // spawn.launcherBoss(1200, -500) - // spawn.sniper(1600, -400) + spawn.laserTargetingBoss(1600, -400) // spawn.sneaker(1600, -500) - spawn.sniper(1700, -120) + // spawn.sniper(1700, -120) // spawn.cellBossCulture(1600, -500) // spawn.shooter(1600, -500) // spawn.striker(1600, -500) diff --git a/js/mob.js b/js/mob.js index f85b586..978ac4e 100644 --- a/js/mob.js +++ b/js/mob.js @@ -467,7 +467,7 @@ const mobs = { //draw damage ctx.fillStyle = "#f00"; ctx.beginPath(); - ctx.arc(best.x, best.y, dmg * 2000, 0, 2 * Math.PI); + ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI); ctx.fill(); } } diff --git a/js/mods.js b/js/mods.js index 8d38775..8111fbb 100644 --- a/js/mods.js +++ b/js/mods.js @@ -947,7 +947,7 @@ const mod = { { name: "microstates", description: "+7% damage for every 10 active bullets", - maxCount: 3, + maxCount: 1, count: 0, allowed() { return mod.isBulletsLastLonger > 1 @@ -1046,6 +1046,22 @@ const mod = { mod.isShotgunImmune = false; } }, + { + name: "nailshot", + description: "the shotgun fires nails
effective at a distance", + maxCount: 1, + count: 0, + allowed() { + return mod.haveGunCheck("shotgun") + }, + requires: "shotgun", + effect() { + mod.isNailShot = true; + }, + remove() { + mod.isNailShot = false; + } + }, { name: "super duper", description: "fire +2 additional super balls", @@ -1362,7 +1378,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.nailBotCount > 1 || mod.haveGunCheck("mine") || mod.grenadeFragments > 5 || mod.isRailNails || mod.nailsDeathMob > 2 + return mod.nailBotCount + mod.grenadeFragments + mod.nailsDeathMob > 1 || mod.haveGunCheck("mine") || mod.isRailNails || mod.isNailShot }, requires: "nails", effect() { @@ -1838,4 +1854,5 @@ const mod = { manyWorlds: null, isDamageFromBulletCount: null, isLaserDiode: null, + isNailShot: null } \ No newline at end of file diff --git a/js/powerup.js b/js/powerup.js index 0ba6da9..ef11596 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -389,37 +389,53 @@ const powerUps = { } }, spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades - if (mech.fieldMode === 0) { - powerUps.spawn(x, y, "field") - if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "field") - } else if (Math.random() < 0.9) { - powerUps.spawn(x, y, "mod") - if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "mod") - } else if (Math.random() < 0.5) { - powerUps.spawn(x, y, "gun") - if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "gun") - // } else if (Math.random() < 0.5) { - // powerUps.spawn(x, y, "field"); - // if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "field"); - } else if (mech.health < 0.65 && !mod.isEnergyHealth) { - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - if (Math.random() < mod.bayesian) { - powerUps.spawn(x, y, "heal"); + if (game.difficultyMode > 1 || Math.random() < 0.66) { //easy and normal have only a 66% chance for a power up + spawnPowerUps() + if (game.difficultyMode > 2 && Math.random() < 0.33) spawnPowerUps() //why? has a 33% chance for an extra power up + } else { + if (mech.health < 0.65 && !mod.isEnergyHealth) { powerUps.spawn(x, y, "heal"); powerUps.spawn(x, y, "heal"); + if (Math.random() < mod.bayesian) { + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + } + } else if (!mod.bayesian) { + powerUps.spawn(x, y, "ammo"); + powerUps.spawn(x, y, "ammo"); } - } else if (!mod.bayesian) { - powerUps.spawn(x, y, "ammo"); - powerUps.spawn(x, y, "ammo"); - powerUps.spawn(x, y, "ammo"); - powerUps.spawn(x, y, "ammo"); - powerUps.spawn(x, y, "ammo"); } + + function spawnPowerUps() { + if (mech.fieldMode === 0) { + powerUps.spawn(x, y, "field") + if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "field") + } else if (Math.random() < 0.9) { + powerUps.spawn(x, y, "mod") + if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "mod") + } else if (Math.random() < 0.5) { + powerUps.spawn(x, y, "gun") + if (Math.random() < mod.bayesian) powerUps.spawn(x, y, "gun") + } else if (mech.health < 0.65 && !mod.isEnergyHealth) { + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + if (Math.random() < mod.bayesian) { + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + powerUps.spawn(x, y, "heal"); + } + } else if (!mod.bayesian) { + powerUps.spawn(x, y, "ammo"); + powerUps.spawn(x, y, "ammo"); + powerUps.spawn(x, y, "ammo"); + powerUps.spawn(x, y, "ammo"); + } + } + + }, chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris if (Math.random() < 0.05) { diff --git a/js/spawn.js b/js/spawn.js index 5552d2c..84b85f6 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -2,24 +2,24 @@ const spawn = { pickList: ["starter", "starter"], fullPickList: [ - // "hopper", "hopper", "hopper", "hopper", - // "shooter", "shooter", "shooter", - // "chaser", "chaser", - // "striker", "striker", - // "laser", "laser", - // "exploder", "exploder", - // "stabber", "stabber", - // "launcher", "launcher", + "hopper", "hopper", "hopper", "hopper", + "shooter", "shooter", "shooter", + "chaser", "chaser", + "striker", "striker", + "laser", "laser", + "exploder", "exploder", + "stabber", "stabber", + "launcher", "launcher", "sniper", - // "spinner", - // "grower", - // "springer", - // "beamer", - // "focuser", - // "sucker", - // "spawner", - // "ghoster", - // "sneaker", + "spinner", + "grower", + "springer", + "beamer", + "focuser", + "sucker", + "spawner", + "ghoster", + "sneaker", ], allowedBossList: ["chaser", "spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper"], setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level @@ -83,7 +83,7 @@ const spawn = { }, randomLevelBoss(x, y) { // other bosses: suckerBoss, laserBoss, tetherBoss, snakeBoss //all need a particular level to work so they are not included - const options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss"] // , "timeSkipBoss" + const options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"] // , "timeSkipBoss" spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, //mob templates ********************************************************************************************* @@ -892,6 +892,148 @@ const spawn = { }; } }, + laserTargetingBoss(x, y, radius = 70) { + const color = "#05f" + mobs.spawn(x, y, 3, radius, color); + let me = mob[mob.length - 1]; + me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front + Matter.Body.rotate(me, Math.random() * Math.PI * 2); + me.accelMag = 0.0006 * game.accelScale; + me.seePlayerFreq = Math.floor(25 * game.lookFreqScale); + me.memory = 600; + me.restitution = 1; + me.frictionAir = 0.06; + me.frictionStatic = 0; + me.friction = 0; + + me.lookTorque = 0.000005 * (Math.random() > 0.5 ? -1 : 1); + + me.fireDir = { + x: 0, + y: 0 + } + Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger + spawn.shield(me, x, y, 1); + me.onHit = function () { + //run this function on hitting player + // this.explode(); + }; + // spawn.shield(me, x, y, 1); //not working, not sure why + me.onDeath = function () { + powerUps.spawnBossPowerUp(this.position.x, this.position.y) + }; + me.do = function () { + this.seePlayerByLookingAt(); + this.checkStatus(); + this.attraction(); + + if (this.seePlayer.recall) { + //set direction to turn to fire + if (!(game.cycle % this.seePlayerFreq)) { + this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); + // this.fireDir.y -= Math.abs(this.seePlayer.position.x - this.position.x) / 1600; //gives the bullet an arc + } + + //rotate towards fireAngle + const angle = this.angle + Math.PI / 2; + c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; + const threshold = 0.04; + if (c > threshold) { + this.torque += 0.000004 * this.inertia; + } else if (c < -threshold) { + this.torque -= 0.000004 * this.inertia; + } + // if (Math.abs(c) < 0.3) { + // const mag = 0.05 + // this.force.x += mag * Math.cos(this.angle) + // this.force.y += mag * Math.sin(this.angle) + // } + + const vertexCollision = function (v1, v1End, domain) { + for (let i = 0; i < domain.length; ++i) { + let vertices = domain[i].vertices; + const len = vertices.length - 1; + for (let j = 0; j < len; j++) { + results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) { + best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[j], + v2: vertices[j + 1] + }; + } + } + } + results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]); + if (results.onLine1 && results.onLine2) { + const dx = v1.x - results.x; + const dy = v1.y - results.y; + const dist2 = dx * dx + dy * dy; + if (dist2 < best.dist2) { + best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[0], + v2: vertices[len] + }; + } + } + } + }; + + const seeRange = 8000; + best = { + x: null, + y: null, + dist2: Infinity, + who: null, + v1: null, + v2: null + }; + const look = { + x: this.position.x + seeRange * Math.cos(this.angle), + y: this.position.y + seeRange * Math.sin(this.angle) + }; + vertexCollision(this.position, look, map); + vertexCollision(this.position, look, body); + if (!mech.isStealth) vertexCollision(this.position, look, [player]); + // hitting player + if (best.who === player) { + if (mech.immuneCycle < mech.cycle) { + const dmg = 0.0005 * game.dmgScale; + mech.damage(dmg); + //draw damage + ctx.fillStyle = color; + ctx.beginPath(); + ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI); + ctx.fill(); + } + } + //draw beam + if (best.dist2 === Infinity) { + best = look; + } + ctx.beginPath(); + ctx.moveTo(this.vertices[1].x, this.vertices[1].y); + ctx.lineTo(best.x, best.y); + ctx.strokeStyle = color; + ctx.lineWidth = 3; + ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]); + ctx.stroke(); + ctx.setLineDash([0, 0]); + + } + }; + }, laser(x, y, radius = 30) { mobs.spawn(x, y, 3, radius, "#f00"); let me = mob[mob.length - 1]; @@ -1364,6 +1506,8 @@ const spawn = { me.noseLength = 0; me.fireAngle = 0; me.accelMag = 0.0005 * game.accelScale; + me.frictionStatic = 0; + me.friction = 0; me.frictionAir = 0.05; me.lookTorque = 0.0000025 * (Math.random() > 0.5 ? -1 : 1); me.fireDir = { @@ -1439,6 +1583,7 @@ const spawn = { this.timeLimit(); }; }, + sniper(x, y, radius = 35 + Math.ceil(Math.random() * 30)) { mobs.spawn(x, y, 3, radius, "transparent"); //"rgb(25,0,50)") let me = mob[mob.length - 1]; @@ -1448,7 +1593,8 @@ const spawn = { me.stroke = "transparent"; //used for drawSneaker me.alpha = 1; //used in drawSneaker me.showHealthBar = false; - + me.frictionStatic = 0; + me.friction = 0; me.canTouchPlayer = false; //used in drawSneaker me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player @@ -1572,8 +1718,8 @@ const spawn = { me.do = function () { // this.gravity(); this.timeLimit(); - if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0) { - // this.timeLeft = 0 + + if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) { this.dropPowerUp = false; this.death(); //death with no power up } diff --git a/todo.txt b/todo.txt index 5154eba..33fcfc3 100644 --- a/todo.txt +++ b/todo.txt @@ -1,10 +1,24 @@ -new mod: doubles current bots +mod: doubles current bots +mod: shotgun fires nails +difficulty mode why? now has 33% chance for a second boss power up +difficulty mode normal and easy now have a 33% lower chance for a boss power up +mob: sniper +mob boss: Laser Targeting (might need balancing) + ************** TODO - n-gon ************** +maybe increase chance of boss power ups on why difficulty + hard as well? + +mod - shotgun: fire nails instead of bullets + gain range? + shielded mobs don't knock back the same as unshielded mobs -buff harmonic field to cover legs +buff harmonic field + cover legs? + no flicker after blocking? movement fluidity let legs jump on mobs, but player will still take damage