From 92c5670369d5f30a62e3dd97adad3b0c8aa4747d Mon Sep 17 00:00:00 2001 From: landgreen Date: Sun, 13 Dec 2020 14:41:07 -0800 Subject: [PATCH] extruder wave beam damage works better vs. high mass mobs also more damage and ammo mod plasma torch: extruder - plasma torch ejects a thin hot wire, does more damage, but drains more energy mod: Bose Einstein condensate - freeze mobs inside your field pilot wave, negative mass field, time dilation field difficulty - after you clear the finalBoss, difficulty increase per level is now lower but, when the finalBoss dies difficulty immediately increases greatly difficulty used to work like this: (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies) (+2,3,4 per level) 12,14,16,19,22,25,29,33,37,41, (final boss dies) (+4 per level) 44,48,52,56 ... difficulty works like this now: (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies +5) (+2 per level) 17,19,21,23,25,27,29,31,33,35, (final boss dies +5) (+3 per level) 43,46,49,52 ... difficulty mode scales these numbers easy: x1, normal: x2, hard: x4, why: x6 each time difficulty increases: game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level b.dmgScale *= 0.93; // your damage goes down game.healScale = 1 / (1 + game.difficulty * 0.06) //healing goes down if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level, but is capped if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level, but is capped if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob ability cooldown time decreases each level, but is capped --- js/bullet.js | 264 ++++++++++++++++++++++++++++++++++++++++++++++++++- js/level.js | 29 +++--- js/mods.js | 152 ++++++++++++++++------------- js/player.js | 154 ++++-------------------------- js/spawn.js | 12 ++- todo.txt | 53 +++++++++-- 6 files changed, 435 insertions(+), 229 deletions(-) diff --git a/js/bullet.js b/js/bullet.js index d9a8ec3..7f2c513 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -678,6 +678,262 @@ const b = { }); World.add(engine.world, bullet[me]); //add bullet to world }, + lastAngle: 0, + extruder() { + const color = "#f07" + const DRAIN = 0.00014 + mech.fieldRegen + if (mech.energy > DRAIN) { + mech.energy -= DRAIN + if (mech.energy < 0) { + mech.fieldCDcycle = mech.cycle + 120; + mech.energy = 0; + } + ctx.lineWidth = 5; + ctx.strokeStyle = color + ctx.beginPath(); //draw all the wave bullets + for (let i = 0, len = bullet.length; i < len; i++) { + if (bullet[i].isBranch) { + ctx.stroke(); + ctx.beginPath(); //draw all the wave bullets + } else if (bullet[i].isWave) ctx.lineTo(bullet[i].position.x, bullet[i].position.y) + } + ctx.lineTo(mech.pos.x + 15 * Math.cos(mech.angle), mech.pos.y + 15 * Math.sin(mech.angle)) + ctx.stroke(); + } else { + mech.fireCDcycle = mech.cycle + 60; // cool down + for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets + if (bullet[i].isWave) { + bullet[i].isWave = false + bullet[i].endCycle = 0 + } + } + return + } + + const SPEED = 13 + const me = bullet.length; + const where = Vector.add(mech.pos, player.velocity) + bullet[me] = Bodies.polygon(where.x + 20 * Math.cos(mech.angle), where.y + 20 * Math.sin(mech.angle), 3, 0.01, { + cycle: -0.5, + isWave: true, + endCycle: game.cycle + 50 * mod.isPlasmaRange, + inertia: Infinity, + frictionAir: 0, + isInHole: true, //this keeps the bullet from entering wormholes + minDmgSpeed: 0, + dmg: b.dmgScale * 1.4, //damage also changes when you divide by mob.mass on in .do() + isJustReflected: false, + classType: "bullet", + isBranch: false, + restitution: 0, + collisionFilter: { + // category: 0, + // mask: 0, //cat.mob | cat.mobBullet | cat.mobShield + category: cat.bullet, + mask: cat.map, //cat.mob | cat.mobBullet | cat.mobShield + }, + beforeDmg() {}, + onEnd() {}, + do() { + mech.fireCDcycle = mech.cycle //this is here to trigger cloaking field + if (!input.field) { + this.endCycle = 0; + this.isWave = false + return + } + if (!mech.isBodiesAsleep) { + if (this.endCycle < game.cycle + 1) this.isWave = false + if (Matter.Query.point(map, this.position).length) { //check if inside map + this.isBranch = true; + // for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets + // if (bullet[i].isWave && bullet[i].cycle > this.cycle) { + // bullet[i].isWave = false + // bullet[i].endCycle = 0 + // } + // } + } else { //check if inside a body + const q = Matter.Query.point(mob, this.position) + for (let i = 0; i < q.length; i++) { + Matter.Body.setVelocity(q[i], { + x: q[i].velocity.x * 0.7, + y: q[i].velocity.y * 0.7 + }); + Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium + let dmg = this.dmg / Math.min(10, q[i].mass) + q[i].damage(dmg); + q[i].foundPlayer(); + game.drawList.push({ //add dmg to draw queue + x: this.position.x, + y: this.position.y, + radius: Math.log(2 * dmg + 1.4) * 40, + color: color, + time: game.drawTime + }); + } + } + this.cycle++ + const wiggleMag = (mech.crouch ? 6 : 12) * Math.cos(game.cycle * 0.09) + const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.36)) //+ wiggleMag * Math.cos(game.cycle * 0.3)) + const velocity = Vector.mult(player.velocity, 0.3) //move with player + Matter.Body.setPosition(this, Vector.add(velocity, Vector.add(this.position, wiggle))) + // Matter.Body.setPosition(this, Vector.add(this.position, wiggle)) + } + } + }); + World.add(engine.world, bullet[me]); //add bullet to world + Matter.Body.setVelocity(bullet[me], { + x: SPEED * Math.cos(mech.angle), + y: SPEED * Math.sin(mech.angle) + }); + const transverse = Vector.normalise(Vector.perp(bullet[me].velocity)) + const angleDifference = 180 - Math.abs(Math.abs(b.lastAngle - mech.angle) - 180); //find the difference between current and previous angle + b.lastAngle = mech.angle + if (angleDifference > 0.5) { //don't draw stroke for this bullet + bullet[me].isBranch = true; + // for (let i = 0, len = bullet.length; i < len; i++) { //remove all bullets + // if (bullet[i].isWave) { + // bullet[i].isWave = false + // bullet[i].endCycle = 0 + // } + // } + // return + } + }, + plasma() { + const DRAIN = 0.00008 + mech.fieldRegen + if (mech.energy > DRAIN) { + mech.energy -= DRAIN; + if (mech.energy < 0) { + mech.fieldCDcycle = mech.cycle + 120; + mech.energy = 0; + } + + //calculate laser collision + let best; + let range = mod.isPlasmaRange * (120 + (mech.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(mech.cycle * 0.3); + // const dir = mech.angle // + 0.04 * (Math.random() - 0.5) + const path = [{ + x: mech.pos.x + 20 * Math.cos(mech.angle), + y: mech.pos.y + 20 * Math.sin(mech.angle) + }, + { + x: mech.pos.x + range * Math.cos(mech.angle), + y: mech.pos.y + range * Math.sin(mech.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 && (!domain[i].mob || domain[i].alive)) { + best = { + x: results.x, + y: results.y, + dist2: dist2, + who: domain[i], + v1: vertices[0], + v2: vertices[len] + }; + } + } + } + }; + + //check for collisions + best = { + x: null, + y: null, + dist2: Infinity, + who: null, + v1: null, + v2: null + }; + vertexCollision(path[0], path[1], mob); + vertexCollision(path[0], path[1], map); + vertexCollision(path[0], path[1], body); + if (best.dist2 != Infinity) { //if hitting something + path[path.length - 1] = { + x: best.x, + y: best.y + }; + if (best.who.alive) { + const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* + best.who.damage(dmg); + best.who.locatePlayer(); + + //push mobs away + const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) + Matter.Body.applyForce(best.who, path[1], force) + Matter.Body.setVelocity(best.who, { //friction + x: best.who.velocity.x * 0.7, + y: best.who.velocity.y * 0.7 + }); + //draw mob damage circle + game.drawList.push({ + x: path[1].x, + y: path[1].y, + radius: Math.sqrt(dmg) * 50, + color: "rgba(255,0,255,0.2)", + time: game.drawTime * 4 + }); + } else if (!best.who.isStatic) { + //push blocks away + const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass))) + Matter.Body.applyForce(best.who, path[1], force) + } + } + + //draw blowtorch laser beam + ctx.strokeStyle = "rgba(255,0,255,0.1)" + ctx.lineWidth = 14 + ctx.beginPath(); + ctx.moveTo(path[0].x, path[0].y); + ctx.lineTo(path[1].x, path[1].y); + ctx.stroke(); + ctx.strokeStyle = "#f0f"; + ctx.lineWidth = 2 + ctx.stroke(); + + //draw electricity + const Dx = Math.cos(mech.angle); + const Dy = Math.sin(mech.angle); + let x = mech.pos.x + 20 * Dx; + let y = mech.pos.y + 20 * Dy; + ctx.beginPath(); + ctx.moveTo(x, y); + const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10 + for (let i = 0; i < 8; i++) { + x += step * (Dx + 1.5 * (Math.random() - 0.5)) + y += step * (Dy + 1.5 * (Math.random() - 0.5)) + ctx.lineTo(x, y); + } + ctx.lineWidth = 2 * Math.random(); + ctx.stroke(); + } + }, laser(where = { x: mech.pos.x + 20 * Math.cos(mech.angle), y: mech.pos.y + 20 * Math.sin(mech.angle) @@ -2565,7 +2821,7 @@ const b = { frictionAir: 0, slow: 0, minDmgSpeed: 0, - dmg: 0, + dmg: b.dmgScale * (mod.waveHelix === 1 ? 0.6 : 0.75), //control damage also when you divide by mob.mass isJustReflected: false, classType: "bullet", collisionFilter: { @@ -2580,7 +2836,7 @@ const b = { // check if inside a mob q = Matter.Query.point(mob, this.position) for (let i = 0; i < q.length; i++) { - let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction + let dmg = this.dmg / Math.min(10, q[i].mass) q[i].damage(dmg); q[i].foundPlayer(); game.drawList.push({ //add dmg to draw queue @@ -2613,7 +2869,7 @@ const b = { for (let i = 0; i < q.length; i++) { slowCheck = 0.3; Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium - let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction + let dmg = this.dmg / Math.min(10, q[i].mass) q[i].damage(dmg); q[i].foundPlayer(); game.drawList.push({ //add dmg to draw queue @@ -2632,6 +2888,8 @@ const b = { } } this.cycle++ + //6 * Math.cos(this.cycle * 0.1) + + // Math.cos(game.cycle * 0.09) * const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.35) * ((i % 2) ? -1 : 1)) Matter.Body.setPosition(this, Vector.add(this.position, wiggle)) } diff --git a/js/level.js b/js/level.js index bab3a02..c7ff0a9 100644 --- a/js/level.js +++ b/js/level.js @@ -13,15 +13,15 @@ const level = { start() { if (level.levelsCleared === 0) { //this code only runs on the first level // game.enableConstructMode() //used to build maps in testing mode - // level.difficultyIncrease(99) + // level.difficultyIncrease(19) // game.zoomScale = 1000; // game.setZoom(); - // mech.setField("wormhole") - // b.giveGuns("grenades") - // mod.isIncendiary = true - // mod.is3Missiles = true - // mod.giveMod("neutron bomb") - // mod.giveMod("causality bombs") + // mech.setField("plasma torch") + // b.giveGuns("wave beam") + // mod.giveMod("micro-extruder") + // for (let i = 0; i < 15; i++) mod.giveMod("supply chain") + + level.intro(); //starting level // level.testing(); //not in rotation @@ -155,8 +155,8 @@ const level = { spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump // spawn.boost(1500, 0, 900); - // spawn.starter(1900, -500, 320) - spawn.exploder(2900, -500) + spawn.starter(1900, -500, 200) + // spawn.exploder(2900, -500) // spawn.launcherBoss(1200, -500) // spawn.laserTargetingBoss(1600, -400) // spawn.striker(1600, -500) @@ -3805,11 +3805,12 @@ const level = { }, nextLevel() { if (level.bossKilled) level.levelsCleared++; - 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) + // level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes + + //difficulty is increased 5 times when finalBoss dies + const len = level.levelsCleared / level.levels.length //add 1 extra difficulty step for each time you have cleared all the levels + for (let i = 0; i < len; i++) level.difficultyIncrease(game.difficultyMode) + level.onLevel++; //cycles map to next level if (level.onLevel > level.levels.length - 1) level.onLevel = 0; //reset lost mod display diff --git a/js/mods.js b/js/mods.js index 4ab8ffd..0188f40 100644 --- a/js/mods.js +++ b/js/mods.js @@ -6,6 +6,12 @@ const mod = { mod.mods[i].isLost = false mod.mods[i].count = 0 } + // mod.nailBotCount = 0; + // mod.foamBotCount = 0; + // mod.boomBotCount = 0; + // mod.laserBotCount = 0; + // mod.orbitalBotCount = 0; + // mod.plasmaBotCount = 0; mod.armorFromPowerUps = 0; mod.totalCount = 0; game.updateModHUD(); @@ -46,6 +52,14 @@ const mod = { game.updateModHUD(); } }, + setModToNonRefundable(name) { + for (let i = 0; i < mod.mods.length; i++) { + if (mod.mods.name === name) { + mod.mods[i].isNonRefundable = true; + return + } + } + }, // giveBasicMod(index = 'random') { // // if (isNaN(index)) { //find index by name // // let found = false; @@ -92,7 +106,7 @@ const mod = { if (mod.isEnergyLoss) dmg *= 1.5; if (mod.isAcidDmg && mech.health > 1) dmg *= 1.4; if (mod.restDamage > 1 && player.speed < 1) dmg *= mod.restDamage - if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 7; + if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 8; if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038 if (mod.isRerollDamage) dmg *= 1 + 0.04 * powerUps.reroll.rerolls if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.25 @@ -109,7 +123,7 @@ const mod = { }, mods: [{ name: "capacitor", - description: "increase damage by 1%
for every 7 stored energy", + description: "increase damage by 1%
for every 8 stored energy", maxCount: 1, count: 0, allowed() { @@ -1028,7 +1042,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.isStunField || mod.isPulseStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage + return mod.isStunField || mod.isPulseStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1 || mod.isWormholeDamage }, requires: "a freezing or stunning effect", effect() { @@ -1145,7 +1159,7 @@ const mod = { allowed() { return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field" }, - requires: "not piezoelectricity, acute stress response, 1st law, negative mass field", + requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass field", effect: () => { mech.health = 0 // mech.displayHealth(); @@ -1428,9 +1442,9 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.duplicationChance() > 0 && !mod.isDeterminism + return !mod.isDeterminism }, - requires: "a chance to duplicate power ups, not determinism", + requires: "not determinism", effect() { mod.isCancelDuplication = true mod.cancelCount = 0 @@ -1823,7 +1837,6 @@ const mod = { //remove active bullets //to get rid of bots for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]); bullet = []; - let count = 0 //count mods for (let i = 0, len = mod.mods.length; i < len; i++) { // spawn new mods power ups if (!mod.mods[i].isNonRefundable) count += mod.mods[i].count @@ -2304,7 +2317,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("wave beam") + return mod.haveGunCheck("wave beam") && !mod.isExtruder }, requires: "wave beam", effect() { @@ -2320,7 +2333,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("wave beam") && !mod.isWaveReflect + return mod.haveGunCheck("wave beam") && !mod.isWaveReflect && !mod.isExtruder }, requires: "wave beam", effect() { @@ -2338,7 +2351,7 @@ const mod = { maxCount: 1, count: 0, allowed() { - return mod.haveGunCheck("wave beam") && mod.waveSpeedMap !== 3 + return mod.haveGunCheck("wave beam") && mod.waveSpeedMap !== 3 && !mod.isExtruder }, requires: "wave beam", effect() { @@ -3128,36 +3141,46 @@ const mod = { mech.energy = 0.01; //fill array of available bots const notUpgradedBots = [] - if (!mod.isNailBotUpgrade) { - notUpgradedBots.push(() => { - mod.giveMod("nail-bot upgrade") - for (let i = 0; i < 2; i++) mod.giveMod("nail-bot") - }) - } - if (!mod.isFoamBotUpgrade) { - notUpgradedBots.push(() => { - mod.giveMod("foam-bot upgrade") - for (let i = 0; i < 2; i++) mod.giveMod("foam-bot") - }) - } - if (!mod.isBoomBotUpgrade) { - notUpgradedBots.push(() => { - mod.giveMod("boom-bot upgrade") - for (let i = 0; i < 2; i++) mod.giveMod("boom-bot") - }) - } - if (!mod.isLaserBotUpgrade) { - notUpgradedBots.push(() => { - mod.giveMod("laser-bot upgrade") - for (let i = 0; i < 2; i++) mod.giveMod("laser-bot") - }) - } - if (!mod.isOrbitBotUpgrade) { - notUpgradedBots.push(() => { - mod.giveMod("orbital-bot upgrade") - for (let i = 0; i < 2; i++) mod.giveMod("orbital-bot") - }) - } + if (!mod.isNailBotUpgrade) notUpgradedBots.push(() => { + mod.giveMod("nail-bot upgrade") + mod.setModToNonRefundable("nail-bot upgrade") + for (let i = 0; i < 2; i++) { + b.nailBot() + mod.nailBotCount++; + } + }) + if (!mod.isFoamBotUpgrade) notUpgradedBots.push(() => { + mod.giveMod("foam-bot upgrade") + mod.setModToNonRefundable("foam-bot upgrade") + for (let i = 0; i < 2; i++) { + b.foamBot() + mod.foamBotCount++; + } + }) + if (!mod.isBoomBotUpgrade) notUpgradedBots.push(() => { + mod.giveMod("boom-bot upgrade") + mod.setModToNonRefundable("boom-bot upgrade") + for (let i = 0; i < 2; i++) { + b.boomBot() + mod.boomBotCount++; + } + }) + if (!mod.isLaserBotUpgrade) notUpgradedBots.push(() => { + mod.giveMod("laser-bot upgrade") + mod.setModToNonRefundable("laser-bot upgrade") + for (let i = 0; i < 2; i++) { + b.laserBot() + mod.laserBotCount++; + } + }) + if (!mod.isOrbitBotUpgrade) notUpgradedBots.push(() => { + mod.giveMod("orbital-bot upgrade") + mod.setModToNonRefundable("orbital-bot upgrade") + for (let i = 0; i < 2; i++) { + b.orbitalBot() + mod.orbitalBotCount++; + } + }) //choose random function from the array and run it notUpgradedBots[Math.floor(Math.random() * notUpgradedBots.length)]() }, @@ -3225,7 +3248,6 @@ const mod = { }, remove() { mod.isHarmReduce = false; - // if (mech.fieldUpgrades[mech.fieldMode].name === "negative mass field") mech.setField("negative mass field") //reset harm reduction } }, { @@ -3245,19 +3267,19 @@ const mod = { } }, { - name: "negative temperature", - description: "negative mass field uses energy
to freeze each mob caught in it's effect", + name: "Bose Einstein condensate", + description: "mobs inside your field are frozen
pilot wave, negative mass, time dilation", maxCount: 1, count: 0, allowed() { - return mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" + return mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" || mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" || mech.fieldUpgrades[mech.fieldMode].name === "time dilation field" }, - requires: "negative mass field", + requires: "pilot wave, negative mass field, time dilation field", effect() { - mod.isFreezeMobs = true; + mod.isFreezeMobs = true }, remove() { - mod.isFreezeMobs = false; + mod.isFreezeMobs = false } }, { @@ -3293,6 +3315,22 @@ const mod = { mod.plasmaBotCount = 0; } }, + { + name: "micro-extruder", + description: "plasma torch ejects a thin hot wire
increases damage, and energy drain", + maxCount: 1, + count: 0, + allowed() { + return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" + }, + requires: "plasma torch", + effect() { + mod.isExtruder = true; + }, + remove() { + mod.isExtruder = false; + } + }, { name: "timelike world line", description: "time dilation doubles your relative time rate
and makes you immune to harm", @@ -3401,22 +3439,6 @@ const mod = { b.setFireCD(); } }, - { - name: "Bose Einstein condensate", - description: "mobs in superposition with the pilot wave
are frozen for 2 seconds", - maxCount: 1, - count: 0, - allowed() { - return mech.fieldUpgrades[mech.fieldMode].name === "pilot wave" - }, - requires: "pilot wave", - effect() { - mod.isPilotFreeze = true - }, - remove() { - mod.isPilotFreeze = false - } - }, { name: "cosmic string", description: "stun and do radioactive damage to mobs
if you tunnel through them with a wormhole", @@ -3647,7 +3669,6 @@ const mod = { isNailPoison: null, isEnergyHealth: null, isPulseStun: null, - isPilotFreeze: null, restDamage: null, isRPG: null, is3Missiles: null, @@ -3750,5 +3771,6 @@ const mod = { isMaxEnergyMod: null, isLowEnergyDamage: null, isRewindBot: null, - isRewindGrenade: null + isRewindGrenade: null, + isExtruder: null } \ No newline at end of file diff --git a/js/player.js b/js/player.js index 909c28f..4cbad6a 100644 --- a/js/player.js +++ b/js/player.js @@ -491,7 +491,7 @@ const mech = { }, rewind(steps) { if (mod.isRewindGrenade) { - for (let i = 1, len = Math.floor(1.5 + steps / 40); i < len; i++) { + for (let i = 1, len = Math.floor(2 + steps / 40); i < len; i++) { b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade const who = bullet[bullet.length - 1] if (mod.isVacuumBomb) { @@ -1163,6 +1163,8 @@ const mech = { } else { mech.drawHold(who); } + // if (mod.isFreezeMobs) mobs.statusSlow(who, 60) //this works but doesn't have a fun effect + // mech.holdingTarget = null //knock backs if (mech.fieldShieldingScale > 0) { @@ -1293,7 +1295,14 @@ const mech = { } } } - wake(mob); + if (mod.isFreezeMobs) { + for (let i = 0, len = mob.length; i < len; ++i) { + Matter.Sleeping.set(mob[i], false) + mobs.statusSlow(mob[i], 60) + } + } else { + wake(mob); + } wake(body); wake(bullet); for (let i = 0, len = cons.length; i < len; i++) { @@ -1396,10 +1405,6 @@ const mech = { effect: () => { mech.fieldShieldingScale = 0; mech.grabPowerUpRange2 = 10000000 - // mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping - // mech.fieldMeterColor = "#0af" - // mech.fieldArc = 0.3; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) - // mech.calculateFieldThreshold(); mech.hold = function() { const wave = Math.sin(mech.cycle * 0.022); mech.fieldRange = 170 + 12 * wave @@ -1643,137 +1648,10 @@ const mech = { } else if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed mech.grabPowerUp(); mech.lookForPickUp(); - const DRAIN = 0.0012 - if (mech.energy > DRAIN) { - mech.energy -= DRAIN; - if (mech.energy < 0) { - mech.fieldCDcycle = mech.cycle + 120; - mech.energy = 0; - } - //calculate laser collision - let best; - let range = mod.isPlasmaRange * (120 + (mech.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(mech.cycle * 0.3); - // const dir = mech.angle // + 0.04 * (Math.random() - 0.5) - const path = [{ - x: mech.pos.x + 20 * Math.cos(mech.angle), - y: mech.pos.y + 20 * Math.sin(mech.angle) - }, - { - x: mech.pos.x + range * Math.cos(mech.angle), - y: mech.pos.y + range * Math.sin(mech.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 && (!domain[i].mob || domain[i].alive)) { - best = { - x: results.x, - y: results.y, - dist2: dist2, - who: domain[i], - v1: vertices[0], - v2: vertices[len] - }; - } - } - } - }; - - //check for collisions - best = { - x: null, - y: null, - dist2: Infinity, - who: null, - v1: null, - v2: null - }; - vertexCollision(path[0], path[1], mob); - vertexCollision(path[0], path[1], map); - vertexCollision(path[0], path[1], body); - if (best.dist2 != Infinity) { //if hitting something - path[path.length - 1] = { - x: best.x, - y: best.y - }; - if (best.who.alive) { - const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE ********************* - best.who.damage(dmg); - best.who.locatePlayer(); - - //push mobs away - const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) - Matter.Body.applyForce(best.who, path[1], force) - Matter.Body.setVelocity(best.who, { //friction - x: best.who.velocity.x * 0.7, - y: best.who.velocity.y * 0.7 - }); - //draw mob damage circle - game.drawList.push({ - x: path[1].x, - y: path[1].y, - radius: Math.sqrt(dmg) * 50, - color: "rgba(255,0,255,0.2)", - time: game.drawTime * 4 - }); - } else if (!best.who.isStatic) { - //push blocks away - const force = Vector.mult(Vector.normalise(Vector.sub(mech.pos, path[1])), -0.007 * Math.sqrt(Math.sqrt(best.who.mass))) - Matter.Body.applyForce(best.who, path[1], force) - } - } - - //draw blowtorch laser beam - ctx.strokeStyle = "rgba(255,0,255,0.1)" - ctx.lineWidth = 14 - ctx.beginPath(); - ctx.moveTo(path[0].x, path[0].y); - ctx.lineTo(path[1].x, path[1].y); - ctx.stroke(); - ctx.strokeStyle = "#f0f"; - ctx.lineWidth = 2 - ctx.stroke(); - - //draw electricity - const Dx = Math.cos(mech.angle); - const Dy = Math.sin(mech.angle); - let x = mech.pos.x + 20 * Dx; - let y = mech.pos.y + 20 * Dy; - ctx.beginPath(); - ctx.moveTo(x, y); - const step = Vector.magnitude(Vector.sub(path[0], path[1])) / 10 - for (let i = 0; i < 8; i++) { - x += step * (Dx + 1.5 * (Math.random() - 0.5)) - y += step * (Dy + 1.5 * (Math.random() - 0.5)) - ctx.lineTo(x, y); - } - ctx.lineWidth = 2 * Math.random(); - ctx.stroke(); + if (mod.isExtruder) { + b.extruder(); + } else { + b.plasma(); } } else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released mech.pickUp(); @@ -2270,7 +2148,7 @@ const mech = { } } - if (mod.isPilotFreeze) { + if (mod.isFreezeMobs) { for (let i = 0, len = mob.length; i < len; ++i) { if (Vector.magnitude(Vector.sub(mob[i].position, mech.fieldPosition)) < mech.fieldRadius) { mobs.statusSlow(mob[i], 120) diff --git a/js/spawn.js b/js/spawn.js index b3b0faa..bba1cb6 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -101,6 +101,16 @@ const spawn = { level.bossKilled = true; level.exit.x = 5500; level.exit.y = -330; + + //pull in particles + for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally + const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65) + const pushUp = Vector.add(velocity, { x: 0, y: -0.3 }) + Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp)); + } + //ramp up damage + for (let i = 0; i < 5; i++) level.difficultyIncrease(game.difficultyMode) + }; me.onDamage = function() {}; me.cycle = 420; @@ -132,7 +142,7 @@ const spawn = { Matter.Body.scale(this, 10, 10); Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger if (!this.isShielded) spawn.shield(this, x, y, 1); // regen shield to also prevent stun - for (let i = 0, len = body.length; i < len; ++i) { + for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally if (body[i].position.x > this.position.x) { body[i].force.x = 0.5 } else { diff --git a/todo.txt b/todo.txt index 2c84171..cedf11b 100644 --- a/todo.txt +++ b/todo.txt @@ -1,17 +1,43 @@ ******************************************************** NEXT PATCH ******************************************************** -catabolism - 2% (was 2.3%) of max health removed -many worlds - spawns 2 rerolls (was 1) -pilot wave field- now has access to several mods that normally require other fields - this plus the fragmenting block mod are a big buff for late game pilot wave - let me know if it is too strong +wave beam damage works better vs. high mass mobs + also more damage and ammo + +mod plasma torch: extruder - plasma torch ejects a thin hot wire, does more damage, but drains more energy + +mod: Bose Einstein condensate - freeze mobs inside your field + pilot wave, negative mass field, time dilation field + +difficulty - after you clear the finalBoss, difficulty increase per level is now lower + but, when the finalBoss dies difficulty immediately increases greatly + + difficulty used to work like this: + (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies) + (+2,3,4 per level) 12,14,16,19,22,25,29,33,37,41, (final boss dies) + (+4 per level) 44,48,52,56 ... + + difficulty works like this now: + (+1 per level) 0,1,2,3,4,5,6,7,8,9,10, (final boss dies +5) + (+2 per level) 17,19,21,23,25,27,29,31,33,35, (final boss dies +5) + (+3 per level) 43,46,49,52 ... + + difficulty mode scales these numbers + easy: x1, normal: x2, hard: x4, why: x6 + + each time difficulty increases: + game.dmgScale = 0.38 * game.difficulty //damage done by mobs increases each level + b.dmgScale *= 0.93; // your damage goes down + game.healScale = 1 / (1 + game.difficulty * 0.06) //healing goes down + if (game.accelScale < 5) game.accelScale *= 1.02 //mob acceleration increases each level, but is capped + if (game.lookFreqScale > 0.2) game.lookFreqScale *= 0.98 //mob cycles between looks decreases each level, but is capped + if (game.CDScale > 0.2) game.CDScale *= 0.97 //mob ability cooldown time decreases each level, but is capped -mod nano-scale: bot prototypes - upgrade a bot type and build 2 of that bot -mod nano-scale: bot manufacturing - build 3 random bots - these mods don't show up in custom ******************************************************** BUGS ******************************************************** +entering custom, after dieing makes all mods look white (not disabled) + this goes away after clicking something so it seems to be only a graphical issue + (not able to reproduce, might be fixed) possible bug with neutron rewind status doesn't apply correctly for spawned neutron bombs that are stuck to a shield also saw neutron bombs bounce off shield, for normal bullets @@ -42,6 +68,17 @@ mod and mob are too similar ******************************************************** TODO ******************************************************** + +mod plasma torch: extruder speed is improved + +color/highlight field or gun mods in selection menu (or custom) + to show that they are special + +mechanic - Your energy regen is only active when field and gun have not been used for 5 seconds. + +divide supercapacitator into 2-3 stacks + smaller effect for stack 1, but overall bigger effect at 3 + be able to open up custom mode in the normal game might need to be rebuilt from scratch while in through testing mode?