diff --git a/js/bullets.js b/js/bullets.js index 27d1ecd..fead1b2 100644 --- a/js/bullets.js +++ b/js/bullets.js @@ -65,6 +65,7 @@ const b = { isModIceCrystals: null, modThrowChargeRate: null, isModBlockStun: null, + isModStunField: null, modOnHealthChange() { //used with acid mod if (b.isModAcidDmg && mech.health > 0.8) { game.playerDmgColor = "rgba(0,80,80,0.9)" @@ -1065,6 +1066,22 @@ const b = { b.modLaserFieldDrain = 0.002; } }, + { + name: "daze", + description: "blocking stuns mobs for 1 second
with the perfect diamagnetism field", + maxCount: 9, + count: 0, + allowed() { + return mech.fieldUpgrades[mech.fieldMode].name === "perfect diamagnetism" + }, + requires: "perfect diamagnetism", + effect() { + b.isModStunField += 60; + }, + remove() { + b.isModStunField = 0; + } + }, { name: "plasma jet", description: "increase plasma torch's range by 33%", @@ -1107,7 +1124,7 @@ const b = { }, requires: "standing wave harmonics
or perfect diamagnetism", effect() { - b.modBlockDmg += 0.6 //if you change this value also update the for loop in the electricity graphics in mech.pushMass + b.modBlockDmg += 0.4 //if you change this value also update the for loop in the electricity graphics in mech.pushMass }, remove() { b.modBlockDmg = 0; @@ -2238,7 +2255,7 @@ const b = { }, { name: "fléchettes", //3 - description: "fire a precise volley of high velocity needles
needles deliver chemical damage over 3 seconds", + description: "fire a precise volley of high velocity needles
that apply chemical damage over 3 seconds", ammo: 0, ammoPack: 23, defaultAmmoPack: 23, @@ -2502,7 +2519,7 @@ const b = { }, { name: "vacuum bomb", //8 - description: "fire a bomb that sucks before exploding
click left mouse again to detonate", + description: "fire a bomb that sucks before exploding
click left mouse again to detonate", ammo: 0, ammoPack: 2, have: false, @@ -3032,7 +3049,7 @@ const b = { }, { name: "laser", //14 - description: "emit a beam of collimated coherent light
drains energy instead of ammunition", + description: "emit a beam of collimated coherent light
drains energy instead of ammunition", ammo: 0, ammoPack: Infinity, have: false, diff --git a/js/engine.js b/js/engine.js index fa8d0e4..83d047b 100644 --- a/js/engine.js +++ b/js/engine.js @@ -184,7 +184,6 @@ function collisionChecks(event) { // console.log(obj.dmg / (0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))) if (b.isModCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5 mob[k].foundPlayer(); - // console.log(dmg) mob[k].damage(dmg); obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn game.drawList.push({ //add dmg to draw queue diff --git a/js/game.js b/js/game.js index 375dd43..e0b63d9 100644 --- a/js/game.js +++ b/js/game.js @@ -658,7 +658,21 @@ const game = { }, checks() { if (mech.pos.y > game.fallHeight) { // if 4000px deep - mech.death(); + if (game.difficultyMode > 2) { + mech.death(); + } else { + Matter.Body.setVelocity(player, { + x: 0, + y: 0 + }); + Matter.Body.setPosition(player, { + x: level.enter.x + 50, + y: level.enter.y - 20 + }); + mech.energy = 0; + if (game.difficultyMode === 2) mech.damage(0.3); + if (game.difficultyMode === 1) mech.damage(0.1); + } } if (!(mech.cycle % 60)) { //once a second @@ -680,18 +694,29 @@ const game = { } if (!(game.cycle % 420)) { //once every 7 seconds - fallCheck = function (who) { + fallCheck = function (who, save = false) { let i = who.length; while (i--) { if (who[i].position.y > game.fallHeight) { - Matter.World.remove(engine.world, who[i]); - who.splice(i, 1); + if (save && game.difficultyMode < 2) { + Matter.Body.setVelocity(who[i], { + x: 0, + y: 0 + }); + Matter.Body.setPosition(who[i], { + x: level.exit.x + 30 * (Math.random() - 0.5), + y: level.exit.y + 30 * (Math.random() - 0.5) + }); + } else { + Matter.World.remove(engine.world, who[i]); + who.splice(i, 1); + } } } }; fallCheck(mob); fallCheck(body); - fallCheck(powerUp); + fallCheck(powerUp, true); } } }, diff --git a/js/player.js b/js/player.js index c2258ea..3387021 100644 --- a/js/player.js +++ b/js/player.js @@ -682,6 +682,7 @@ const mech = { setHoldDefaults() { if (mech.energy < mech.fieldEnergyMax) mech.energy = mech.fieldEnergyMax; mech.fieldRegen = 0.001; + mech.fieldMeterColor = "#0cf" mech.fieldShieldingScale = 1; mech.fieldDamageResistance = 1; mech.fieldFire = false; @@ -694,6 +695,7 @@ const mech = { mech.isBodiesAsleep = true; mech.wakeCheck(); }, + fieldMeterColor: "#0cf", drawFieldMeter(range = 60) { if (mech.energy < mech.fieldEnergyMax) { mech.energy += mech.fieldRegen; @@ -701,7 +703,7 @@ const mech = { const xOff = mech.pos.x - mech.radius * mech.fieldEnergyMax const yOff = mech.pos.y - 50 ctx.fillRect(xOff, yOff, range * mech.fieldEnergyMax, 10); - ctx.fillStyle = "#0cf"; + ctx.fillStyle = mech.fieldMeterColor; ctx.fillRect(xOff, yOff, range * mech.energy, 10); } // else { @@ -817,7 +819,7 @@ const mech = { } else { mech.drop() } - } else if (mech.throwCharge > 0) { + } else if (mech.throwCharge > 0) { //Matter.Query.region(mob, player.bounds) //throw the body mech.fieldCDcycle = mech.cycle + 15; mech.isHolding = false; @@ -838,12 +840,13 @@ const mech = { setTimeout(solid, 150, mech.holdingTarget); const charge = Math.min(mech.throwCharge / 5, 1) - const speed = charge * Math.min(80, 64 / Math.pow(mech.holdingTarget.mass, 0.25)); + let speed = charge * Math.min(80, 64 / Math.pow(mech.holdingTarget.mass, 0.25)); + if (Matter.Query.collides(mech.holdingTarget, map).length !== 0) speed = 0 mech.throwCharge = 0; Matter.Body.setVelocity(mech.holdingTarget, { - x: player.velocity.x + Math.cos(mech.angle) * speed, - y: player.velocity.y + Math.sin(mech.angle) * speed + x: player.velocity.x * 0.5 + Math.cos(mech.angle) * speed, + y: player.velocity.y * 0.5 + Math.sin(mech.angle) * speed }); //player recoil //stronger in x-dir to prevent jump hacking @@ -895,34 +898,6 @@ const mech = { ctx.lineWidth = 1; ctx.stroke(); }, - drawDiamagneticField(wave) { - if (mech.holdingTarget) { - ctx.fillStyle = "rgba(110,170,200," + (0.06 + 0.03 * Math.random()) + ")"; - ctx.strokeStyle = "rgba(110, 200, 235, " + (0.35 + 0.05 * Math.random()) + ")" //"#9bd" //"rgba(110, 200, 235, " + (0.5 + 0.1 * Math.random()) + ")" - } else { - ctx.fillStyle = "rgba(110,170,200," + (0.20 + 0.07 * Math.random() - 0.07 * wave) + ")"; - ctx.strokeStyle = "rgba(110, 200, 235, " + (0.3 + 0.5 * Math.random()) + ")" //"#9bd" //"rgba(110, 200, 235, " + (0.5 + 0.1 * Math.random()) + ")" - } - // const off = 2 * Math.cos(game.cycle * 0.1) - const range = mech.fieldRange; - ctx.beginPath(); - ctx.arc(mech.pos.x, mech.pos.y, range, mech.angle - Math.PI * mech.fieldArc, mech.angle + Math.PI * mech.fieldArc, false); - ctx.lineWidth = 2.5 - 1.5 * wave; - ctx.lineCap = "butt" - ctx.stroke(); - let eye = 20; - const curve = 0.5 + 0.06 * wave - let aMag = (1 - curve * 1.2) * Math.PI * mech.fieldArc - let a = mech.angle + aMag - let cp1x = mech.pos.x + curve * range * Math.cos(a) - let cp1y = mech.pos.y + curve * range * Math.sin(a) - ctx.quadraticCurveTo(cp1x, cp1y, mech.pos.x + eye * Math.cos(mech.angle), mech.pos.y + eye * Math.sin(mech.angle)) - a = mech.angle - aMag - cp1x = mech.pos.x + curve * range * Math.cos(a) - cp1y = mech.pos.y + curve * range * Math.sin(a) - ctx.quadraticCurveTo(cp1x, cp1y, mech.pos.x + 1 * range * Math.cos(mech.angle - Math.PI * mech.fieldArc), mech.pos.y + 1 * range * Math.sin(mech.angle - Math.PI * mech.fieldArc)) - ctx.fill(); - }, grabPowerUp() { //look for power ups to grab with field const grabPowerUpRange2 = 156000 //(mech.fieldRange + 220) * (mech.fieldRange + 220) for (let i = 0, len = powerUp.length; i < len; ++i) { @@ -962,15 +937,14 @@ const mech = { mech.energy -= fieldBlockCost if (mech.energy < 0) mech.energy = 0; if (mech.energy > mech.fieldEnergyMax) mech.energy = mech.fieldEnergyMax; - mech.drawHold(who); - mech.holdingTarget = null + const unit = Vector.normalise(Vector.sub(player.position, who.position)) if (b.modBlockDmg) { who.damage(b.modBlockDmg) //draw electricity const step = 40 ctx.beginPath(); - for (let i = 0, len = 2 * b.modBlockDmg / 0.7; i < len; i++) { + for (let i = 0, len = 2 * b.modBlockDmg; i < len; i++) { let x = mech.pos.x - 20 * unit.x; let y = mech.pos.y - 20 * unit.y; ctx.moveTo(x, y); @@ -980,10 +954,13 @@ const mech = { ctx.lineTo(x, y); } } - ctx.lineWidth = 2.5; + ctx.lineWidth = 3; ctx.strokeStyle = "#f0f"; ctx.stroke(); + } else { + mech.drawHold(who); } + mech.holdingTarget = null //knock backs if (mech.fieldShieldingScale > 0) { const massRoot = Math.sqrt(Math.min(12, Math.max(0.15, who.mass))); // masses above 12 can start to overcome the push back @@ -1004,11 +981,20 @@ const mech = { }); } } else { + if (b.isModStunField) mobs.statusStun(who, b.isModStunField) + // mobs.statusSlow(who, b.isModStunField) const massRoot = Math.sqrt(Math.max(0.15, who.mass)); // masses above 12 can start to overcome the push back Matter.Body.setVelocity(who, { - x: player.velocity.x - (15 * unit.x) / massRoot, - y: player.velocity.y - (15 * unit.y) / massRoot + x: player.velocity.x - (20 * unit.x) / massRoot, + y: player.velocity.y - (20 * unit.y) / massRoot }); + if (who.dropPowerUp && player.speed < 12) { + const massRootCap = Math.sqrt(Math.min(10, Math.max(0.4, who.mass))); // masses above 12 can start to overcome the push back + Matter.Body.setVelocity(player, { + x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap, + y: 0.9 * player.velocity.y + 0.6 * unit.y * massRootCap + }); + } } } }, @@ -1181,23 +1167,55 @@ const mech = { { name: "perfect diamagnetism", // description: "gain energy when blocking
no recoil when blocking", - description: "blocking produces energy
blocking has no recoil or cool down", + description: "blocking does not drain energy
blocking has no cool down and less recoil", isEasyToAim: false, effect: () => { - mech.fieldShieldingScale = -2; + mech.fieldShieldingScale = 0; + 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.025); + const wave = Math.sin(mech.cycle * 0.02); mech.fieldRange = 165 + 10 * wave - mech.fieldArc = 0.31 + 0.03 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) + mech.fieldArc = 0.3 + 0.03 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob) mech.calculateFieldThreshold(); if (mech.isHolding) { mech.drawHold(mech.holdingTarget); mech.holding(); mech.throwBlock(); } else if ((keys[32] || game.mouseDownRight && mech.energy > 0.05 && mech.fieldCDcycle < mech.cycle)) { //not hold but field button is pressed - mech.drawDiamagneticField(wave); + //draw field + if (mech.holdingTarget) { + ctx.fillStyle = "rgba(120,190,255," + (0.06 + 0.03 * Math.random()) + ")"; + ctx.strokeStyle = "rgba(120, 190, 255, " + (0.35 + 0.05 * Math.random()) + ")" + } else { + ctx.fillStyle = "rgba(120,190,255," + (0.3 + 0.13 * Math.random() - 0.15 * wave) + ")"; + ctx.strokeStyle = "rgba(120, 190, 255, " + (0.3 + 0.5 * Math.random()) + ")" + } + // if (mech.holdingTarget) { + // ctx.fillStyle = "rgba(110,175,200," + (0.06 + 0.03 * Math.random()) + ")"; + // ctx.strokeStyle = "rgba(115, 220, 255, " + (0.35 + 0.05 * Math.random()) + ")" + // } else { + // ctx.fillStyle = "rgba(110,175,200," + (0.20 + 0.07 * Math.random() - 0.1 * wave) + ")"; + // ctx.strokeStyle = "rgba(115, 220, 255, " + (0.3 + 0.5 * Math.random()) + ")" + // } + ctx.beginPath(); + ctx.arc(mech.pos.x, mech.pos.y, mech.fieldRange, mech.angle - Math.PI * mech.fieldArc, mech.angle + Math.PI * mech.fieldArc, false); + ctx.lineWidth = 2.5 - 1.5 * wave; + ctx.lineCap = "butt" + ctx.stroke(); + const curve = 0.57 + 0.04 * wave + const aMag = (1 - curve * 1.2) * Math.PI * mech.fieldArc + let a = mech.angle + aMag + let cp1x = mech.pos.x + curve * mech.fieldRange * Math.cos(a) + let cp1y = mech.pos.y + curve * mech.fieldRange * Math.sin(a) + ctx.quadraticCurveTo(cp1x, cp1y, mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle)) + a = mech.angle - aMag + cp1x = mech.pos.x + curve * mech.fieldRange * Math.cos(a) + cp1y = mech.pos.y + curve * mech.fieldRange * Math.sin(a) + ctx.quadraticCurveTo(cp1x, cp1y, mech.pos.x + 1 * mech.fieldRange * Math.cos(mech.angle - Math.PI * mech.fieldArc), mech.pos.y + 1 * mech.fieldRange * Math.sin(mech.angle - Math.PI * mech.fieldArc)) + ctx.fill(); + mech.grabPowerUp(); mech.lookForPickUp(); mech.pushMobsFacing(); @@ -1212,9 +1230,10 @@ const mech = { }, { name: "time dilation field", - description: "use energy to stop time
can fire bullets while field is active", + description: "use energy to stop time
you can move and fire while time is stopped", isEasyToAim: true, effect: () => { + // mech.fieldMeterColor = "#000" mech.fieldFire = true; mech.isBodiesAsleep = false; mech.hold = function () { @@ -1281,6 +1300,8 @@ const mech = { description: "use energy to emit damaging plasma
effective at close range", isEasyToAim: false, effect: () => { + mech.fieldMeterColor = "#f0f" + mech.hold = function () { if (mech.isHolding) { mech.drawHold(mech.holdingTarget); @@ -1449,8 +1470,10 @@ const mech = { effect: () => { mech.fieldFire = true; mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping + // mech.fieldMeterColor = "#000" mech.hold = function () { + mech.drawFieldMeter() mech.fieldDamageResistance = 1; if (mech.isHolding) { mech.drawHold(mech.holdingTarget); @@ -1566,7 +1589,6 @@ const mech = { mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists) this.fieldDrawRadius = 0 } - mech.drawFieldMeter() } } }, @@ -1664,6 +1686,8 @@ const mech = { description: "use energy to become intangible
moving and touching shields amplifies cost", isEasyToAim: true, effect: () => { + mech.fieldMeterColor = "#fff" + mech.hold = function () { mech.isStealth = false //isStealth disables most uses of foundPlayer() player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield //normal collisions diff --git a/todo.txt b/todo.txt index e357ec8..54a112d 100644 --- a/todo.txt +++ b/todo.txt @@ -1,6 +1,17 @@ +perfect diamagnetism balance and graphics +unique energy colors for fields +game info on pause screen +falling off the map, on easy and normal difficulty + sets the player to the entrance + sets power ups to the exit + + + ************** TODO - n-gon ************** +perfect diamagnetism should get larger as it blocks more, and then slowly fad back to the normal size + gun or mod - drones that only last for 2 seconds field - the basic field emitter, but no energy loss and no knock back on blocks