From e14a56f362d7884b9833a7b48bd0901ddf4eec88 Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 31 May 2020 09:11:53 -0700 Subject: [PATCH] flechettes pierce above level 20 boss power ups only drop on even levels removed mod ablative mines (was buggy, and too similar to ablative drones) flechettes get stuck in walls flechettes do no damage to mobs on hit flechettes do more damage over time, and have more ammo mod - flechettes pierce mobs mod - mutualism: each spore does 2x damage but they borrow 1% life from player --- js/bullet.js | 147 ++++++++++++++++++++++++++++++++++++++++---------- js/engine.js | 1 + js/game.js | 15 ++++++ js/level.js | 18 ++++--- js/mods.js | 82 +++++++++++++++++++--------- js/player.js | 35 ++++++------ js/powerup.js | 24 +++++---- js/spawn.js | 11 ++-- todo.txt | 29 +++++----- 9 files changed, 249 insertions(+), 113 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index 4de5348..4fa4ded 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -475,7 +475,7 @@ const b = { friction: 0, frictionAir: 0.025, thrust: mod.isFastSpores ? 0.001 : 0.0004, - dmg: 2.8, //damage done in addition to the damage from momentum + dmg: mod.isMutualism ? 5.6 : 2.8, //2x bonus damage from mod.isMutualism lookFrequency: 97 + Math.floor(117 * Math.random()), classType: "bullet", collisionFilter: { @@ -491,7 +491,18 @@ const b = { onDmg() { this.endCycle = 0; //bullet ends cycle after doing damage }, - onEnd() {}, + onEnd() { + if (mod.isMutualism && this.isMutualismActive) { + if (mod.isEnergyHealth) { + mech.energy += 0.01; + } else { + mech.health += 0.01 + if (mech.health > mech.maxHealth) mech.health = mech.maxHealth; + mod.onHealthChange(); + mech.displayHealth(); + } + } + }, do() { if (!(game.cycle % this.lookFrequency)) { //find mob targets this.closestTarget = null; @@ -535,6 +546,20 @@ const b = { y: SPEED * Math.sin(ANGLE) }); World.add(engine.world, bullet[bIndex]); //add bullet to world + + if (mod.isMutualism) { + if (mod.isEnergyHealth) { + if (mech.energy > 0.02) { + mech.energy -= 0.01; //energy takes an extra 25% damage for balancing purposes + bullet[bIndex].isMutualismActive = true + } + } else if (mech.health > 0.02) { + mech.health -= 0.01 + mod.onHealthChange(); + mech.displayHealth(); + bullet[bIndex].isMutualismActive = true + } + } }, iceIX(speed = 0, spread = 2 * Math.PI) { const me = bullet.length; @@ -1306,42 +1331,72 @@ const b = { name: "flechettes", description: "fire a volley of uranium-235 needles
does damage over 3 seconds", ammo: 0, - ammoPack: 23, - defaultAmmoPack: 23, + ammoPack: 30, + defaultAmmoPack: 30, have: false, isStarterGun: true, 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() { - const CD = (mech.crouch) ? 50 : 30 - if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD - this.lastFireCycle = mech.cycle - if (this.count > ((mech.crouch) ? 6 : 1)) { - this.count = 0 - mech.fireCDcycle = mech.cycle + Math.floor(CD * mod.fireRate); // cool down - } else { - this.count++ - mech.fireCDcycle = mech.cycle + Math.floor(3 * mod.fireRate); // cool down - } - function makeFlechette(angle = mech.angle) { const me = bullet.length; bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle), 45, 1.4, b.fireAttributes(angle)); - // Matter.Body.setDensity(bullet[me], 0.0001); //0.001 is normal + bullet[me].collisionFilter.mask = cat.body; //cat.mobShield | //cat.map | cat.body | + Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal bullet[me].endCycle = game.cycle + 180; bullet[me].dmg = 0; - bullet[me].onDmg = function (who) { - if (mod.isDotFlechette) { - mobs.statusDoT(who, 0.33, 360) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) - } else { - mobs.statusDoT(who, 0.33, 180) // (2.3) / 6 ticks (3 seconds) + bullet[me].immuneList = [] + bullet[me].do = function () { + const whom = Matter.Query.collides(this, mob) + if (whom.length && this.speed > 20) { //if touching a mob + who = whom[0].bodyA + if (who) { + + function hit(that) { + who.foundPlayer(); + if (mod.isDotFlechette) { + mobs.statusDoT(who, 0.5, 360) + } else { + mobs.statusDoT(who, 0.5, 180) + } + game.drawList.push({ //add dmg to draw queue + x: that.position.x, + y: that.position.y, + radius: 40, + color: "rgba(0,80,80,0.3)", + time: game.drawTime + }); + } + + if (mod.pierce) { + let immune = false + for (let i = 0; i < this.immuneList.length; i++) { + if (this.immuneList[i] === who.id) immune = true + } + if (!immune) { + this.immuneList.push(who.id) + hit(this) + } + } else { + this.endCycle = 0; + hit(this) + } + } + } else if (Matter.Query.collides(this, map).length) { //stick in walls + this.collisionFilter.mask = 0; + Matter.Body.setAngularVelocity(this, 0) + Matter.Body.setVelocity(this, { + x: 0, + y: 0 + }); + this.do = function () {} + } else if (this.speed < 30) { + this.force.y += this.mass * 0.0007; //no gravity until it slows down to improve aiming } }; - bullet[me].do = function () { - if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming - }; + const SPEED = 50 Matter.Body.setVelocity(bullet[me], { x: mech.Vx / 2 + SPEED * Math.cos(angle), @@ -1351,9 +1406,46 @@ const b = { } makeFlechette() if (mod.isFlechetteMultiShot) { - makeFlechette(mech.angle + 0.01 + 0.01 * Math.random()) - makeFlechette(mech.angle - 0.01 - 0.01 * Math.random()) + makeFlechette(mech.angle + 0.02 + 0.005 * Math.random()) + makeFlechette(mech.angle - 0.02 - 0.005 * Math.random()) } + + const CD = (mech.crouch) ? 60 : 30 + if (this.lastFireCycle + CD < mech.cycle) this.count = 0 //reset count if it cycles past the CD + this.lastFireCycle = mech.cycle + if (this.count > ((mech.crouch) ? 7 : 1)) { + this.count = 0 + mech.fireCDcycle = mech.cycle + Math.floor(CD * mod.fireRate); // cool down + + const who = bullet[bullet.length - 1] + Matter.Body.setDensity(who, 0.00001); + // who.onDmg = function (who) { + // if (mod.isDotFlechette) { + // mobs.statusDoT(who, 0.33, 360) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) + // mobs.statusSlow(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) + // } else { + // mobs.statusDoT(who, 0.33, 180) // (2.3) / 6 ticks (3 seconds) + // mobs.statusSlow(who, 60) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) + // } + // this.endCycle = 0; + // }; + + // who.onEnd = function () { + // b.explosion(this.position, 220); //makes bullet do explosive damage at end + // } + // who.do = function () { + // if (this.speed < 10) this.force.y += this.mass * 0.0003; //no gravity until it slows don to improve aiming + // if (Matter.Query.collides(this, map).length || Matter.Query.collides(this, body).length) { + // this.endCycle = 0; //explode if touching map or blocks + // } + // } + + } else { + this.count++ + mech.fireCDcycle = mech.cycle + Math.floor(3 * mod.fireRate); // cool down + } + + } }, { @@ -1956,7 +2048,7 @@ const b = { }, { name: "spores", - description: "fire a sporangium that discharges spores", + description: "fire a sporangium that discharges spores
spores seek out nearby mobs", ammo: 0, ammoPack: 5, have: false, @@ -2069,7 +2161,6 @@ const b = { b.spore(this) } } - } }, { diff --git a/js/engine.js b/js/engine.js index 2f344cd..dfc4a65 100644 --- a/js/engine.js +++ b/js/engine.js @@ -208,6 +208,7 @@ function collisionChecks(event) { if (mod.isCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5 mob[k].foundPlayer(); mob[k].damage(dmg); + // console.log(dmg) obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn game.drawList.push({ //add dmg to draw queue x: pairs[i].activeContacts[0].vertex.x, diff --git a/js/game.js b/js/game.js index 9394731..c4eb2e7 100644 --- a/js/game.js +++ b/js/game.js @@ -644,6 +644,21 @@ const game = { } } + if (mod.isMutualism) { + for (let i = 0; i < bullet.length; i++) { + if (bullet[i].isMutualismActive) { + if (mod.isEnergyHealth) { + mech.energy += 0.01; + } else { + mech.health += 0.01 + if (mech.health > mech.maxHealth) mech.health = mech.maxHealth; + mod.onHealthChange(); + mech.displayHealth(); + } + } + } + } + //if player is holding something this remembers it before it gets deleted let holdTarget; if (mech.holdingTarget) { diff --git a/js/level.js b/js/level.js index dff58af..1e15812 100644 --- a/js/level.js +++ b/js/level.js @@ -17,9 +17,9 @@ const level = { // game.enableConstructMode() //used to build maps in testing mode // level.difficultyIncrease(9) // mech.setField("time dilation field") - // mod.giveMod("brushless motor"); + // mod.giveMod("mutualism"); // b.giveGuns("drones") - // b.giveGuns("mine") + // b.giveGuns("spores") // mech.setField("pilot wave") // mech.setField("phase decoherence field") @@ -60,10 +60,10 @@ const level = { // if (level.isBuildRun) num++ for (let i = 0; i < num; i++) { game.difficulty++ - game.dmgScale += 0.205; //damage done by mobs increases each level + game.dmgScale += 0.21; //damage done by mobs increases each level b.dmgScale *= 0.91; //damage done by player decreases each level - game.accelScale *= 1.024 //mob acceleration increases each level - game.lookFreqScale *= 0.976 //mob cycles between looks decreases each level + game.accelScale *= 1.027 //mob acceleration increases each level + game.lookFreqScale *= 0.974 //mob cycles between looks decreases each level game.CDScale *= 0.964 //mob CD time decreases each level } game.healScale = 1 / (1 + game.difficulty * 0.09) //a higher denominator makes for lower heals // mech.health += heal * game.healScale; @@ -71,11 +71,11 @@ const level = { difficultyDecrease(num = 1) { //used in easy mode for game.reset() for (let i = 0; i < num; i++) { game.difficulty-- - game.dmgScale -= 0.205; //damage done by mobs increases each level + game.dmgScale -= 0.21; //damage done by mobs increases each level if (game.dmgScale < 0.1) game.dmgScale = 0.1; b.dmgScale /= 0.91; //damage done by player decreases each level - game.accelScale /= 1.024 //mob acceleration increases each level - game.lookFreqScale /= 0.976 //mob cycles between looks decreases each level + game.accelScale /= 1.027 //mob acceleration increases each level + game.lookFreqScale /= 0.974 //mob cycles between looks decreases each level game.CDScale /= 0.964 //mob CD time decreases each level } if (game.difficulty < 1) game.difficulty = 0; @@ -187,6 +187,8 @@ const level = { // spawn.laserTargetingBoss(1600, -400) // spawn.spawner(1600, -500) spawn.sniper(1700, -120) + // spawn.sniper(1600, -120) + // spawn.sniper(1800, -120) // spawn.cellBossCulture(1600, -500) // spawn.shooter(1600, -500) // spawn.striker(1600, -500) diff --git a/js/mods.js b/js/mods.js index 74ea71e..ddc0279 100644 --- a/js/mods.js +++ b/js/mods.js @@ -374,29 +374,29 @@ const mod = { }, remove() {} }, - { - name: "ablative mines", - description: "rebuild your broken parts as a mine
chance to occur after being harmed", - maxCount: 1, - count: 0, - allowed() { - return true - }, - requires: "", - effect() { - mod.isMineOnDamage = true; - b.mine({ - x: mech.pos.x, - y: mech.pos.y - 80 - }, { - x: 0, - y: 0 - }) - }, - remove() { - mod.isMineOnDamage = false; - } - }, + // { + // name: "ablative mines", + // description: "rebuild your broken parts as a mine
chance to occur after being harmed", + // maxCount: 1, + // count: 0, + // allowed() { + // return true + // }, + // requires: "", + // effect() { + // mod.isMineOnDamage = true; + // b.mine({ + // x: mech.pos.x, + // y: mech.pos.y - 80 + // }, { + // x: 0, + // y: 0 + // }) + // }, + // remove() { + // mod.isMineOnDamage = false; + // } + // }, { name: "ablative drones", description: "rebuild your broken parts as drones
chance to occur after being harmed", @@ -767,7 +767,7 @@ const mod = { }, { name: "catabolism", - description: "gain ammo when you fire while out of ammo
drains 3% of current remaining health", + description: "gain ammo when you fire while out of ammo
drains 3% of current remaining health", maxCount: 1, count: 0, allowed() { @@ -1143,6 +1143,22 @@ const mod = { mod.isDotFlechette = false; } }, + { + name: "piercing needles", + description: "needles penetrate mobs
potentially hitting multiple targets", + maxCount: 1, + count: 0, + allowed() { + return mod.haveGunCheck("flechettes") + }, + requires: "flechettes", + effect() { + mod.pierce = true; + }, + remove() { + mod.pierce = false; + } + }, { name: "wave packet", description: "wave beam emits two oscillating particles
wave particles do 40% less damage", @@ -1421,6 +1437,22 @@ const mod = { mod.isSporeFollow = false } }, + { + name: "mutualism", + description: "spores do 2x damage
spores borrow 1% health until they die", + maxCount: 1, + count: 0, + allowed() { + return mod.haveGunCheck("spores") || mod.sporesOnDeath > 0 || mod.isSporeField + }, + requires: "spores", + effect() { + mod.isMutualism = true + }, + remove() { + mod.isMutualism = false + } + }, { name: "brushless motor", description: "drones accelerate 50% faster", @@ -1785,7 +1817,7 @@ const mod = { isImmuneExplosion: null, isExplodeMob: null, isDroneOnDamage: null, - isMineOnDamage: null, + // isMineOnDamage: null, acidDmg: null, isAcidDmg: null, isAnnihilation: null, diff --git a/js/player.js b/js/player.js index 89b3ffb..b3b41da 100644 --- a/js/player.js +++ b/js/player.js @@ -478,15 +478,15 @@ const mech = { if (Math.random() < 0.5) b.drone() //spawn drone } } - if (mod.isMineOnDamage && dmg > 0.004 + 0.05 * Math.random()) { - b.mine({ - x: mech.pos.x, - y: mech.pos.y - 80 - }, { - x: 0, - y: 0 - }) - } + // if (mod.isMineOnDamage && dmg > 0.004 + 0.05 * Math.random()) { + // b.mine({ + // x: mech.pos.x, + // y: mech.pos.y - 80 + // }, { + // x: 0, + // y: 0 + // }) + // } dmg *= mech.harmReduction() if (mod.isEnergyHealth) { @@ -543,15 +543,14 @@ const mech = { return; } } + mod.onHealthChange(); + mech.displayHealth(); + document.getElementById("dmg").style.transition = "opacity 0s"; + document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4); } if (dmg > 0.2 * mech.holdingMassScale) mech.drop(); //drop block if holding - mod.onHealthChange(); - mech.displayHealth(); - document.getElementById("dmg").style.transition = "opacity 0s"; - document.getElementById("dmg").style.opacity = 0.1 + Math.min(0.6, dmg * 4); - const normalFPS = function () { if (mech.defaultFPSCycle < mech.cycle) { //back to default values game.fpsCap = game.fpsCapDefault @@ -698,10 +697,10 @@ const mech = { fieldMode: 0, //basic field mode before upgrades maxEnergy: 1, //can be increased by a mod holdingTarget: null, - fieldShieldingScale: 1, timeSkipLastCycle: 0, // these values are set on reset by setHoldDefaults() fieldRange: 155, + fieldShieldingScale: 1, energy: 0, fieldRegen: 0, fieldMode: 0, @@ -1220,9 +1219,10 @@ const mech = { }, { name: "standing wave harmonics", - description: "three oscillating shields are permanently active
energy regenerates while field is active", + description: "three oscillating shields are permanently active
reduce harm by 33%", isEasyToAim: true, effect: () => { + mech.fieldHarmReduction = 0.67; mech.fieldBlockCD = 0; mech.hold = function () { if (mech.isHolding) { @@ -1510,11 +1510,10 @@ const mech = { }, { name: "plasma torch", - description: "use energy to emit damaging plasma
reduce harm by 20%", + description: "use energy to emit short range plasma
plasma damages and pushes mobs", isEasyToAim: false, effect: () => { mech.fieldMeterColor = "#f0f" - mech.fieldHarmReduction = 0.80; mech.hold = function () { if (mech.isHolding) { diff --git a/js/powerup.js b/js/powerup.js index 2295d71..11f46aa 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -389,20 +389,22 @@ const powerUps = { } }, spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades - 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 && level.levelsCleared % 2 == 0) spawnPowerUps() //why? has an extra power up on even numbered levels - } else { - if (mech.health < 0.65 && !mod.isEnergyHealth) { - powerUps.spawn(x, y, "heal"); - powerUps.spawn(x, y, "heal"); - if (Math.random() < mod.bayesian) { + if (level.levelsCleared < 20 || level.levelsCleared % 2 == 0) { //drop only on even levels above level 20 + 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 && level.levelsCleared % 2 == 0) spawnPowerUps() //why? has an extra power up on even numbered levels + } 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"); } } diff --git a/js/spawn.js b/js/spawn.js index f01158f..4d107be 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -83,8 +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 - // "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", - const options = ["laserTargetingBoss"] // , "timeSkipBoss" + const options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss"] // , "timeSkipBoss" spawn[options[Math.floor(Math.random() * options.length)]](x, y) }, //mob templates ********************************************************************************************* @@ -893,17 +892,17 @@ const spawn = { }; } }, - laserTargetingBoss(x, y, radius = 70) { + laserTargetingBoss(x, y, radius = 65) { 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.accelMag = 0.0005 * game.accelScale; me.seePlayerFreq = Math.floor(25 * game.lookFreqScale); me.memory = 600; me.restitution = 1; - me.frictionAir = 0.06; + me.frictionAir = 0.05; me.frictionStatic = 0; me.friction = 0; @@ -913,7 +912,7 @@ const spawn = { x: 0, y: 0 } - Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger + Matter.Body.setDensity(me, 0.025); //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 diff --git a/todo.txt b/todo.txt index 2e7d2cb..f70def1 100644 --- a/todo.txt +++ b/todo.txt @@ -1,19 +1,21 @@ -harmonic field now has no cooldown after blocking -negative mass field accelerates slower, but with a higher top speed -negative mass field harm reduction is now 60% and always on -mod degenerate matter increases the damage reduction from 60% to 80% - -falling damage and damage from blocks have been removed -(I'm trying it out, let me know if you want it back) +above level 20 boss power ups only drop on even levels +removed mod ablative mines (was buggy, and too similar to ablative drones) +flechettes get stuck in walls +flechettes do no damage to mobs on hit +flechettes do more damage over time, and have more ammo +mod - flechettes pierce mobs +mod - mutualism: each spore does 2x damage but they borrow 1% life from player ************** TODO - n-gon ************** +shrink font on small screens (so you can see 5 options on power ups) + +graphic idea: bezier curve that moves smoothly from mob to mob + loops around player + add air control check box set mech.airSpeedLimit to 0? to disable -on damage mines mod needs a nerf - spawns 2 mines every time... (from on dmg effects) - give rail gun projectile a trail only draw above speed 5 track previous positions? @@ -32,13 +34,6 @@ movement fluidity wall grab? maybe remove falling damage and block damage? -rays can have width, how to use this? - Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth]) - wide lasers? - -new type of mob vision that uses ray query with thickness - maybe use for bosses - bug - mines spawn extra mines when fired at thin map wall while jumping what about a neutron bomb mod, that causes the bomb to activate right after you fire and slowly move forward with no gravity