diff --git a/js/bullet.js b/js/bullet.js index a726528..f9a0c93 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -108,7 +108,7 @@ const b = { mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield }, minDmgSpeed: 10, - onDmg() {}, //this.endCycle = 0 //triggers despawn + beforeDmg() {}, //this.endCycle = 0 //triggers despawn onEnd() {} }; } else { @@ -125,7 +125,7 @@ const b = { mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield }, minDmgSpeed: 10, - onDmg() {}, //this.endCycle = 0 //triggers despawn + beforeDmg() {}, //this.endCycle = 0 //triggers despawn onEnd() {} }; } @@ -276,13 +276,13 @@ const b = { } } }, - missile(where, dir, speed, size = 1, spawn = 0) { + missile(where, angle, speed, size = 1, spawn = 0) { const me = bullet.length; - bullet[me] = Bodies.rectangle(where.x, where.y, 30 * size, 4 * size, b.fireAttributes(dir)); + bullet[me] = Bodies.rectangle(where.x, where.y, 30 * size, 4 * size, b.fireAttributes(angle)); const thrust = 0.00417 * bullet[me].mass; Matter.Body.setVelocity(bullet[me], { - x: mech.Vx / 2 + speed * Math.cos(dir), - y: mech.Vy / 2 + speed * Math.sin(dir) + x: mech.Vx / 2 + speed * Math.cos(angle), + y: mech.Vy / 2 + speed * Math.sin(angle) }); World.add(engine.world, bullet[me]); //add bullet to world bullet[me].frictionAir = 0.023 @@ -300,7 +300,7 @@ const b = { } } } - bullet[me].onDmg = function () { + bullet[me].beforeDmg = function () { this.tryToLockOn(); this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion }; @@ -557,7 +557,7 @@ const b = { endCycle: Infinity, lookFrequency: 0, range: 700, - onDmg() {}, + beforeDmg() {}, do() { this.force.y += this.mass * 0.002; //extra gravity let collide = Matter.Query.collides(this, map) //check if collides with map @@ -686,7 +686,7 @@ const b = { x: 100 * (Math.random() - 0.5), y: 100 * (Math.random() - 0.5) }, - onDmg(who) { + beforeDmg(who) { this.endCycle = 0; //bullet ends cycle after doing damage if (this.isFreeze) mobs.statusSlow(who, 60) }, @@ -800,7 +800,7 @@ const b = { minDmgSpeed: 0, lockedOn: null, isFollowMouse: true, - onDmg(who) { + beforeDmg(who) { mobs.statusSlow(who, 60) this.endCycle = game.cycle if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300) @@ -877,7 +877,7 @@ const b = { isFollowMouse: true, deathCycles: 110 + RADIUS * 5, isImproved: false, - onDmg(who) { + beforeDmg(who) { //move away from target after hitting const unit = Vector.mult(Vector.normalise(Vector.sub(this.position, who.position)), -20) Matter.Body.setVelocity(this, { @@ -1002,7 +1002,7 @@ const b = { target: null, targetVertex: null, targetRelativePosition: null, - onDmg(who) { + beforeDmg(who) { if (!this.target && who.alive) { this.target = who; if (who.radius < 20) { @@ -1154,15 +1154,14 @@ const b = { }, nail(pos, velocity, dmg = 0) { const me = bullet.length; - // bullet[me] = Bodies.rectangle(pos.x, pos.y, 25, 2, b.fireAttributes(Math.atan2(velocity.y, velocity.x))); bullet[me] = Bodies.rectangle(pos.x, pos.y, 25 * mod.biggerNails, 2 * mod.biggerNails, b.fireAttributes(Math.atan2(velocity.y, velocity.x))); - Matter.Body.setVelocity(bullet[me], velocity); World.add(engine.world, bullet[me]); //add bullet to world bullet[me].endCycle = game.cycle + 60 + 18 * Math.random(); bullet[me].dmg = dmg - bullet[me].onDmg = function (who) { + bullet[me].beforeDmg = function (who) { if (mod.isNailPoison) mobs.statusDoT(who, dmg * 0.22, 120) // one tick every 30 cycles + if (mod.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.99) this.dmg *= 5 //crit if hit near center }; bullet[me].do = function () {}; }, @@ -1227,7 +1226,7 @@ const b = { mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield }, lockedOn: null, - onDmg() { + beforeDmg() { this.lockedOn = null }, onEnd() {}, @@ -1283,7 +1282,7 @@ const b = { mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield }, lockedOn: null, - onDmg() { + beforeDmg() { this.lockedOn = null }, onEnd() {}, @@ -1342,7 +1341,7 @@ const b = { mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield }, lockedOn: null, - onDmg() { + beforeDmg() { this.lockedOn = null }, onEnd() {}, @@ -1452,7 +1451,7 @@ const b = { }, lockedOn: null, explode: 0, - onDmg() { + beforeDmg() { if (this.lockedOn) { const explosionRadius = Math.min(170 + 140 * this.isUpgraded, Vector.magnitude(Vector.sub(this.position, mech.pos)) - 30) if (explosionRadius > 60) { @@ -1528,7 +1527,7 @@ const b = { mask: cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield }, lockedOn: null, - onDmg() { + beforeDmg() { this.lockedOn = null }, onEnd() {}, @@ -1706,7 +1705,7 @@ const b = { category: cat.bullet, mask: 0 //cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield }, - onDmg() {}, + beforeDmg() {}, onEnd() {}, range: 190 + 50 * mod.isOrbitBotUpgrade, //range is set in bot upgrade too! //150 + (80 + 100 * mod.isOrbitBotUpgrade) * Math.random(), // + 5 * mod.orbitBotCount, orbitalSpeed: 0, @@ -1850,7 +1849,7 @@ const b = { y: mech.Vy / 2 + speed * Math.sin(angle) }, dmg) //position, velocity, damage if (mod.isIceCrystals) { - bullet[bullet.length - 1].onDmg = function (who) { + bullet[bullet.length - 1].beforeDmg = function (who) { mobs.statusSlow(who, 30) if (mod.isNailPoison) mobs.statusDoT(who, dmg * 0.22, 120) // one tick every 30 cycles }; @@ -1957,7 +1956,7 @@ const b = { bullet[me].do = function () { this.force.y += this.mass * 0.001; }; - bullet[me].onDmg = function (who) { + bullet[me].beforeDmg = function (who) { mobs.statusStun(who, 180) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) }; } else { @@ -2031,6 +2030,11 @@ const b = { } } else { this.endCycle = 0; + if (mod.isFlechetteExplode && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.98) { + // mobs.statusStun(who, 120) + this.explodeRad = 250 + 30 * Math.random(); + b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end + } who.foundPlayer(); if (mod.isFastDot) { mobs.statusDoT(who, 3.78, 30) @@ -2120,7 +2124,7 @@ const b = { category: 0, mask: 0, //cat.mob | cat.mobBullet | cat.mobShield }, - onDmg() {}, + beforeDmg() {}, onEnd() {}, do() { if (!mech.isBodiesAsleep) { @@ -2309,7 +2313,7 @@ const b = { bullet[me].onEnd = function () { b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end } - bullet[me].onDmg = function () { + bullet[me].beforeDmg = function () { this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion }; bullet[me].do = function () { @@ -2335,7 +2339,7 @@ const b = { if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments) } bullet[me].minDmgSpeed = 1; - bullet[me].onDmg = function () { + bullet[me].beforeDmg = function () { this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion }; @@ -2401,7 +2405,7 @@ const b = { if (dist < this.explodeRad) mech.energy = 0 //remove player energy } } - bullet[me].onDmg = function () { + bullet[me].beforeDmg = function () { // this.endCycle = 0; //bullet ends cycle after doing damage //this triggers explosion }; bullet[me].radius = 22; //used from drawing timer @@ -2510,7 +2514,7 @@ const b = { bullet[me].maxDamageRadius = (435 + 150 * Math.random()) * (mod.isNeutronImmune ? 1.2 : 1) bullet[me].stuckTo = null; bullet[me].stuckToRelativePosition = null; - bullet[me].onDmg = function () {}; + bullet[me].beforeDmg = function () {}; bullet[me].stuck = function () {}; bullet[me].do = function () { function onCollide(that) { @@ -2682,7 +2686,7 @@ const b = { bullet[me].minDmgSpeed = 0; bullet[me].totalSpores = 8 + 2 * mod.isFastSpores + 2 * mod.isSporeFreeze bullet[me].stuck = function () {}; - bullet[me].onDmg = function () {}; + bullet[me].beforeDmg = function () {}; bullet[me].do = function () { function onCollide(that) { that.collisionFilter.mask = 0; //non collide with everything @@ -2850,7 +2854,7 @@ const b = { name: "rail gun", description: "use energy to launch a high-speed dense rod
hold left mouse to charge, release to fire", ammo: 0, - ammoPack: 3, + ammoPack: 3.5, have: false, fire() { if (mod.isCapacitor) { @@ -2871,7 +2875,7 @@ const b = { }, minDmgSpeed: 5, endCycle: game.cycle + 140, - onDmg(who) { + beforeDmg(who) { if (who.shield) { for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks @@ -2880,10 +2884,10 @@ const b = { } } Matter.Body.setVelocity(this, { - x: -0.1 * this.velocity.x, - y: -0.1 * this.velocity.y + x: -0.5 * this.velocity.x, + y: -0.5 * this.velocity.y }); - Matter.Body.setDensity(this, 0.001); + // Matter.Body.setDensity(this, 0.001); } if (mod.isRailNails && this.speed > 10) { b.targetedNail(this.position, (Math.min(40, this.speed) - 10) * 0.6) // 0.6 as many nails as the normal rail gun @@ -2980,7 +2984,7 @@ const b = { mask: cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield }, minDmgSpeed: 5, - onDmg(who) { + beforeDmg(who) { if (who.shield) { for (let i = 0, len = mob.length; i < len; i++) { if (mob[i].id === who.shieldTargetID) { //apply some knock back to shield mob before shield breaks @@ -3472,7 +3476,7 @@ const b = { // }, // minDmgSpeed: 5, // range: 0, - // onDmg() { + // beforeDmg() { // this.endCycle = 0; // }, //this.endCycle = 0 //triggers despawn // onEnd() {}, diff --git a/js/engine.js b/js/engine.js index ab467b4..5092847 100644 --- a/js/engine.js +++ b/js/engine.js @@ -173,11 +173,11 @@ function collisionChecks(event) { } //mob + bullet collisions if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { + obj.beforeDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here let dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity))) if (mod.isCrit && mob[k].isStunned) dmg *= 4 mob[k].foundPlayer(); mob[k].damage(dmg); - obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn //forces don't seem to work here game.drawList.push({ //add dmg to draw queue x: pairs[i].activeContacts[0].vertex.x, y: pairs[i].activeContacts[0].vertex.y, diff --git a/js/level.js b/js/level.js index 3a2f756..217884b 100644 --- a/js/level.js +++ b/js/level.js @@ -15,12 +15,12 @@ const level = { // game.zoomScale = 1000; // game.setZoom(); // mech.isCloak = true; - mech.setField("wormhole") - // b.giveGuns("nail gun") + // mech.setField("wormhole") + // b.giveGuns("flechettes") // for (let i = 0; i < 10; i++) { // mod.giveMod("laser-bot"); // } - mod.giveMod("cosmic string") + // mod.giveMod("supercritical fission") level.intro(); //starting level @@ -149,10 +149,10 @@ const level = { // spawn.sniper(1700, -120, 50) // spawn.bomberBoss(1400, -500) // spawn.sniper(1800, -120) - // spawn.sniper(2200, -120) // spawn.cellBossCulture(1600, -500) - spawn.powerUpBoss(1600, -500) - // spawn.shield(mob[mob.length - 1], 1200, -500, 1); + // spawn.powerUpBoss(1600, -500) + spawn.sniper(1200, -500) + spawn.shield(mob[mob.length - 1], 1200, -500, 1); // spawn.nodeBoss(1200, -500, "launcher") // spawn.snakeBoss(1200, -500) @@ -3841,7 +3841,7 @@ const level = { difficultyIncrease(num = 1) { for (let i = 0; i < num; i++) { game.difficulty++ - game.dmgScale += 0.37; //damage done by mobs increases each level + game.dmgScale += 0.38; //damage done by mobs increases each level b.dmgScale *= 0.93; //damage done by player decreases each level if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level @@ -3852,7 +3852,7 @@ const level = { difficultyDecrease(num = 1) { //used in easy mode for game.reset() for (let i = 0; i < num; i++) { game.difficulty-- - game.dmgScale -= 0.37; //damage done by mobs increases each level + game.dmgScale -= 0.38; //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 if (game.accelScale > 0.2) game.accelScale /= 1.02 //mob acceleration increases each level @@ -3887,6 +3887,7 @@ const level = { if (level.onLevel > level.levels.length - 1) level.onLevel = 0; level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes if (level.levelsCleared > level.levels.length) level.difficultyIncrease(game.difficultyMode) + if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode) if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1); diff --git a/js/mob.js b/js/mob.js index 993a959..7069aad 100644 --- a/js/mob.js +++ b/js/mob.js @@ -1043,7 +1043,10 @@ const mobs = { b.spore(this.position) } } - if (Math.random() < mod.isBotSpawner) b.randomBot(this.position, false) + if (Math.random() < mod.isBotSpawner) { + b.randomBot(this.position, false) + bullet[bullet.length - 1].endCycle = game.cycle + 1500 + Math.floor(600 * Math.random()) + } if (mod.isExplodeMob) b.explosion(this.position, Math.min(550, Math.sqrt(this.mass + 2.5) * 50)) if (mod.nailsDeathMob) b.targetedNail(this.position, mod.nailsDeathMob, 40 + 7 * Math.random()) } else if (mod.isShieldAmmo && this.shield) { diff --git a/js/mods.js b/js/mods.js index 16c3875..623ce66 100644 --- a/js/mods.js +++ b/js/mods.js @@ -408,7 +408,7 @@ const mod = { maxCount: 9, count: 0, allowed() { - return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1; + return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { @@ -424,7 +424,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1; + return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.boomBotCount > 1 || mod.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { @@ -440,7 +440,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField + return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.haveGunCheck("pulse") || mod.isMissileField || mod.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { @@ -457,7 +457,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob + return mod.haveGunCheck("missiles") || mod.haveGunCheck("flak") || mod.haveGunCheck("grenades") || mod.haveGunCheck("vacuum bomb") || mod.isMissileField || mod.isExplodeMob || mod.isFlechetteExplode }, requires: "an explosive damage source", effect: () => { @@ -469,15 +469,15 @@ const mod = { }, { name: "scrap bots", - description: "11% chance to build a bot after killing a mob
the bot only functions until the end of the level", - maxCount: 6, + description: "19% chance to build a bot after killing a mob
the bot last for about 30 seconds", + maxCount: 3, count: 0, allowed() { return mod.totalBots() > 0 }, requires: "a bot", effect() { - mod.isBotSpawner += 0.11; + mod.isBotSpawner += 0.19; }, remove() { mod.isBotSpawner = 0; @@ -1596,6 +1596,22 @@ const mod = { mod.isDamageFromBulletCount = false } }, + { + name: "critical bifurcation", + description: "nails do 400% more damage
when they strike near the center of a mob", + maxCount: 1, + count: 0, + allowed() { + return mod.haveGunCheck("nail gun") + }, + requires: "nail gun", + effect() { + mod.isNailCrit = true + }, + remove() { + mod.isNailCrit = false + } + }, { name: "pneumatic actuator", description: "nail gun takes 45% less time to ramp up
to it's shortest delay after firing", @@ -1843,15 +1859,31 @@ const mod = { mod.isFastDot = false; } }, + { + name: "supercritical fission", + description: "flechettes can explode
if they strike mobs near their center", + maxCount: 1, + count: 0, + allowed() { + return mod.haveGunCheck("flechettes") && !mod.pierce + }, + requires: "flechettes and not piercing needles", + effect() { + mod.isFlechetteExplode = true + }, + remove() { + mod.isFlechetteExplode = false + } + }, { name: "piercing needles", description: "needles penetrate mobs and blocks
potentially hitting multiple targets", maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("flechettes") + return mod.haveGunCheck("flechettes") && !mod.isFlechetteExplode }, - requires: "flechettes", + requires: "flechettes and not supercritical fission", effect() { mod.pierce = true; }, @@ -2807,7 +2839,7 @@ const mod = { }, { name: "cosmic string", - description: "when you tunnel through a wormhole
damage mobs between the endpoints", + description: "when you tunnel through a wormhole
mobs between the endpoints take damage", maxCount: 1, count: 0, allowed() { @@ -2823,7 +2855,7 @@ const mod = { }, { name: "Penrose process", - description: "after a block falls into a wormhole
overfill your energy to 300% of your maximum
", + description: "after a block falls into a wormhole
your energy overfills to 300% of the maximum", maxCount: 1, count: 0, allowed() { @@ -2837,6 +2869,39 @@ const mod = { mod.isWormholeEnergy = false } }, + { + name: "transdimensional spores", + description: "when blocks fall into a wormhole
higher dimension spores are summoned", + maxCount: 1, + count: 0, + allowed() { + return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" + }, + requires: "wormhole", + effect() { + mod.isWormSpores = true + }, + remove() { + mod.isWormSpores = false + } + }, + { + name: "traversable geodesics", + description: "your bullets can traverse wormholes
spawn a gun power up", + maxCount: 1, + count: 0, + allowed() { + return mech.fieldUpgrades[mech.fieldMode].name === "wormhole" + }, + requires: "wormhole", + effect() { + mod.isWormBullets = true + powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); + }, + remove() { + mod.isWormBullets = false + } + }, { name: "heals", description: "spawn 6 heal power ups", @@ -3074,5 +3139,9 @@ const mod = { isPerfectBrake: null, explosiveRadius: null, isWormholeEnergy: null, - isWormholeDamage: null + isWormholeDamage: null, + isNailCrit: null, + isFlechetteExplode: null, + isWormSpores: null, + isWormBullets: null } \ No newline at end of file diff --git a/js/player.js b/js/player.js index 488f210..b7a4cf4 100644 --- a/js/player.js +++ b/js/player.js @@ -2240,37 +2240,27 @@ const mech = { }, { name: "wormhole", - description: "use energy to tunnel through a wormhole
bullets may also traverse wormholes
blocks and power ups can't exit", + description: "use energy to tunnel through a wormhole
wormholes attract blocks and power ups", //
bullets may also traverse wormholes effect: () => { game.replaceTextLog = true; //allow text over write mech.drop(); // mech.hole = { //this is reset with each new field, but I'm leaving it here for reference // isOn: false, // isReady: true, - // pos1: { - // x: 0, - // y: 0 - // }, - // pos2: { - // x: 0, - // y: 0 - // }, + // pos1: {x: 0,y: 0}, + // pos2: {x: 0,y: 0}, + // angle: 0, + // unit:{x:0,y:0}, // } mech.hold = function () { - if (mech.hole.isOn) { // draw holes mech.fieldRange = 0.97 * mech.fieldRange + 0.03 * (50 + 10 * Math.sin(game.cycle * 0.025)) - - //draw bezier curves between the portals const semiMajorAxis = mech.fieldRange + 30 - const sub = Vector.sub(mech.hole.pos1, mech.hole.pos2) - const unit = Vector.perp(Vector.normalise(sub)) - const edge1a = Vector.add(Vector.mult(unit, semiMajorAxis), mech.hole.pos1) - const edge1b = Vector.add(Vector.mult(unit, -semiMajorAxis), mech.hole.pos1) - const edge2a = Vector.add(Vector.mult(unit, semiMajorAxis), mech.hole.pos2) - const edge2b = Vector.add(Vector.mult(unit, -semiMajorAxis), mech.hole.pos2) - // const opacity = 200 / mech.fieldRange / mech.fieldRange + const edge1a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos1) + const edge1b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos1) + const edge2a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos2) + const edge2b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos2) ctx.beginPath(); ctx.moveTo(edge1a.x, edge1a.y) ctx.bezierCurveTo(mech.hole.pos1.x, mech.hole.pos1.y, mech.hole.pos2.x, mech.hole.pos2.y, edge2a.x, edge2a.y); @@ -2278,10 +2268,9 @@ const mech = { ctx.bezierCurveTo(mech.hole.pos2.x, mech.hole.pos2.y, mech.hole.pos1.x, mech.hole.pos1.y, edge1b.x, edge1b.y); ctx.fillStyle = `rgba(255,255,255,${200 / mech.fieldRange / mech.fieldRange})` //"rgba(0,0,0,0.1)" ctx.fill(); - const angle = Math.atan2(sub.y, sub.x) ctx.beginPath(); - ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, angle, 0, 2 * Math.PI) - ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, angle, 0, 2 * Math.PI) + ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI) + ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI) ctx.fillStyle = `rgba(255,255,255,${32 / mech.fieldRange})` ctx.fill(); @@ -2318,20 +2307,6 @@ const mech = { } } } - //teleport bullets - for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2 - if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots - if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1 - Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position))); - mech.fieldRange += 5 - bullet[i].isInHole = true - } else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1 - Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position))); - mech.fieldRange += 5 - bullet[i].isInHole = true - } - } - } //suck and shrink blocks const suckRange = 500 const shrinkRange = 100 @@ -2354,6 +2329,13 @@ const mech = { body.splice(i, 1); mech.fieldRange *= 0.8 if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3 + if (mod.isWormSpores) { //pandimensionalspermia + b.spore(Vector.add(mech.hole.pos2, Vector.rotate({ + x: mech.fieldRange, + y: 0 + }, 2 * Math.PI * Math.random()))) + Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, -Math.PI / 2), 15)); + } break } } @@ -2370,45 +2352,58 @@ const mech = { body.splice(i, 1); mech.fieldRange *= 0.8 if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3 + if (mod.isWormSpores) { //pandimensionalspermia + b.spore(Vector.add(mech.hole.pos1, Vector.rotate({ + x: mech.fieldRange, + y: 0 + }, 2 * Math.PI * Math.random()))) + Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15)); + + } break } } } } } - //mobs get pushed away - for (let i = 0, len = mob.length; i < len; i++) { - // if (!mob[i].shield && !mob[i].isShielded) { - if (Vector.magnitude(Vector.sub(mech.hole.pos1, mob[i].position)) < 200) { - const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), -0.07) - Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull)); + if (mod.isWormBullets) { + //teleport bullets + for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2 + if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots + if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1 + Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position))); + mech.fieldRange += 5 + bullet[i].isInHole = true + } else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1 + Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position))); + mech.fieldRange += 5 + bullet[i].isInHole = true + } + } } - if (Vector.magnitude(Vector.sub(mech.hole.pos2, mob[i].position)) < 200) { - const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), -0.07) - Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull)); + // mobs get pushed away + for (let i = 0, len = mob.length; i < len; i++) { + if (Vector.magnitude(Vector.sub(mech.hole.pos1, mob[i].position)) < 200) { + const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), -0.07) + Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull)); + } + if (Vector.magnitude(Vector.sub(mech.hole.pos2, mob[i].position)) < 200) { + const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), -0.07) + Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull)); + } } - // } } } - if (mech.isHolding) { - mech.drawHold(mech.holdingTarget); - mech.holding(); - mech.throwBlock(); - } else if ((input.field && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed - // Matter.Query.ray(map, jumpSensor.position, game.mouseInGame).length === 0 || - if ( - mech.hole.isReady && !mech.holdingTarget && - ( - // Matter.Query.ray(map, player.position, game.mouseInGame).length === 0 && - Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 && - Matter.Query.ray(map, mech.pos, Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)).length === 0 - ) + if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed + if (mech.hole.isReady && + (Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 && + Matter.Query.ray(map, mech.pos, Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)).length === 0) ) { const sub = Vector.sub(game.mouseInGame, mech.pos) const mag = Vector.magnitude(sub) const drain = 0.06 + 0.007 * Math.sqrt(mag) - if (mech.energy > drain && mag > 150) { + if (mech.energy > drain && mag > 300) { mech.energy -= drain mech.hole.isReady = false; mech.fieldRange = 0 @@ -2439,6 +2434,8 @@ const mech = { mech.hole.pos1.y = mech.pos.y mech.hole.pos2.x = player.position.x mech.hole.pos2.y = player.position.y + mech.hole.angle = Math.atan2(sub.y, sub.x) + mech.hole.unit = Vector.perp(Vector.normalise(sub)) if (mod.isWormholeDamage) { who = Matter.Query.ray(mob, mech.pos, game.mouseInGame, 60) @@ -2457,14 +2454,12 @@ const mech = { } } } + } else { + mech.grabPowerUp(); } + } else { + mech.grabPowerUp(); } - // mech.grabPowerUp(); - // mech.lookForPickUp(); can't pick things up with this field - // if (mech.energy > 0.05) { //can't use shield - // mech.drawField(); - // mech.pushMobsFacing(); - // } } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released mech.pickUp(); } else { diff --git a/js/powerup.js b/js/powerup.js index 6ec6823..ad69265 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -461,8 +461,8 @@ const powerUps = { }, randomPowerUpCounter: 0, spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades + // if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod powerUps.randomPowerUpCounter++; - if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ... if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { powerUps.randomPowerUpCounter = 0; @@ -470,6 +470,16 @@ const powerUps = { } else { spawnHealthAmmo() } + if (game.difficultyMode === 4) { + powerUps.randomPowerUpCounter++; + const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ... + if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { + powerUps.randomPowerUpCounter = 0; + spawnPowerUps() + } else { + spawnHealthAmmo() + } + } function spawnHealthAmmo() { if (mech.health < 0.65 && !mod.isEnergyHealth) { @@ -511,7 +521,7 @@ const powerUps = { //bonus power ups for clearing runs in the last game if (level.levelsCleared === 0 && !game.isCheating) { for (let i = 0; i < localSettings.levelsClearedLastGame / 4 - 1; i++) { - powerUps.spawn(mech.pos.x, mech.pos.y, "mod", false); //spawn a mod for every 5 levels cleared in last game + powerUps.spawn(mech.pos.x, mech.pos.y, "mod", false); //spawn a mod for levels cleared in last game } localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage diff --git a/todo.txt b/todo.txt index 639d857..e6d78ae 100644 --- a/todo.txt +++ b/todo.txt @@ -1,33 +1,30 @@ -some wormhole bug fixes -wormhole mod: cosmic string - damage mobs when you teleport through them -wormhole mod: Penrose process - overfill energy to 300% of max, with a block gets sucked into a hole +mod: critical bifurcation - nail gun does 400% more damage if it hits very close to the center of a mob +mod: supercritical fission - flechettes explode if they hit very close to the center of a mob + +mod: transdimensional spores - after wormholes eat blocks, they disturb spores +mod: traversable geodesics - your bullets can go through worm holes + +scrap bots now only last only 30 seconds, but they have a 20% chance to spawn from a kill (was 11%) +the difficulty should feel a bit harder after clearing the boss level + (a bit more more damage taken, and fewer mod drops) ************** TODO - n-gon ************** -set mouse 4 and 5 for gun switch +mod - after a mob or shield dies, remaining dots look for a new nearby host add an ending to the game revamp the boss level, or add a new final level - final level requires you to kill something, not skip content + final level requires you to kill something + so skipping content is only smart if you are strong enough to beat the final boss around level 15 game never ends if you have used cheats -field wormhole - store constant info about the holes: unit, angle to save processing - maybe bullets should be able to enter and exit multiple times - or bullets shouldn't get stuck at all? - maybe give bullets an attraction to holes - player: drain energy when near a hole, does damage if no energy - mod: Hawking radiation: do damage, to mobs that get near the end points - this is good because it explains why mobs don't teleport - mod: extend immunity cycle after a teleport //mech.immuneCycle = mech.cycle + 15; - look for mods that could update description text with count and mod.is information can only use variables that change in effect() and remove() this.description = `8% chance to duplicate spawned power ups
chance to duplicate = ${mod.duplicateChance}` -mod (drones or spores) explode after 10 seconds +mod self destruct - drones explode when they die, but they last 1/2 as long mouse event e.which is deprecated