-
+
diff --git a/js/bullets.js b/js/bullets.js
index bdcbeb2..ccf2d1b 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -19,6 +19,7 @@ const b = {
modExtraDmg: null,
annihilation: null,
fullHeal: null,
+ modSquirrelFx: 1,
setModDefaults() {
b.modCount = 0;
b.modFireRate = 1;
@@ -35,6 +36,7 @@ const b = {
b.modExtraDmg = 0;
b.modAnnihilation = false;
b.isModFullHeal = false;
+ b.modSquirrelFx = 1;
mech.Fx = 0.015;
mech.jumpForce = 0.38;
mech.throwChargeRate = 2;
@@ -145,7 +147,7 @@ const b = {
},
{
name: "annihilation",
- description: "after you touch any enemy, they are
annihilatedtouching enemies damages you, but destroys them",
+ description: "after you touch any enemy, they are
annihilatedtouching enemies damages you, but destroys them",
have: false, //12
effect: () => { //good with mods that heal: superconductive healing, entropy transfer
b.modAnnihilation = true
@@ -175,7 +177,8 @@ const b = {
description: "jump higher and move faster",
have: false, //15
effect: () => { //
- mech.Fx = 0.015 * 1.2;
+ b.modSquirrelFx = 1.2;
+ mech.Fx = 0.015 * b.modSquirrelFx;
mech.jumpForce = 0.38 * 1.1;
}
},
@@ -492,40 +495,57 @@ const b = {
World.add(engine.world, bullet[bIndex]); //add bullet to world
},
guns: [{
- name: "laser", //0
- description: "fire a
beam of coherent light
reflects off walls at 75% intensity
uses
energy instead of ammunition",
- ammo: 0,
- // ammoPack: 350,
- ammoPack: Infinity,
- have: false,
- isStarterGun: true,
- fire() {
- // mech.fireCDcycle = mech.cycle + 1
- //laser drains energy as well as bullets
- const FIELD_DRAIN = 0.002
- const damage = 0.05
- if (mech.fieldMeter < FIELD_DRAIN) {
- mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy
- } else {
- mech.fieldMeter -= mech.fieldRegen + FIELD_DRAIN
- let best;
- const color = "#f00";
- const range = 3000;
- 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]);
+ name: "laser", //0
+ description: "fire a
beam of coherent light
reflects off walls at 75% intensity
uses
energy instead of ammunition",
+ ammo: 0,
+ // ammoPack: 350,
+ ammoPack: Infinity,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ // mech.fireCDcycle = mech.cycle + 1
+ //laser drains energy as well as bullets
+ const FIELD_DRAIN = 0.002
+ const damage = 0.05
+ if (mech.fieldMeter < FIELD_DRAIN) {
+ mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy
+ } else {
+ mech.fieldMeter -= mech.fieldRegen + FIELD_DRAIN
+ let best;
+ const color = "#f00";
+ const range = 3000;
+ 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;
@@ -536,332 +556,1113 @@ const b = {
y: results.y,
dist2: dist2,
who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
+ v1: vertices[0],
+ v2: vertices[len]
};
}
}
}
- 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]
- };
- }
+ };
+ const checkForCollisions = function () {
+ best = {
+ x: null,
+ y: null,
+ dist2: Infinity,
+ who: null,
+ v1: null,
+ v2: null
+ };
+ vertexCollision(path[path.length - 2], path[path.length - 1], mob);
+ vertexCollision(path[path.length - 2], path[path.length - 1], map);
+ vertexCollision(path[path.length - 2], path[path.length - 1], body);
+ };
+ const laserHitMob = function (dmg) {
+ if (best.who.alive) {
+ dmg *= b.dmgScale * damage;
+ best.who.damage(dmg);
+ best.who.locatePlayer();
+ //draw mob damage circle
+ ctx.fillStyle = color;
+ ctx.beginPath();
+ ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI);
+ ctx.fill();
}
- }
- };
- const checkforCollisions = function () {
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
};
- vertexCollision(path[path.length - 2], path[path.length - 1], mob);
- vertexCollision(path[path.length - 2], path[path.length - 1], map);
- vertexCollision(path[path.length - 2], path[path.length - 1], body);
- };
- const laserHitMob = function (dmg) {
- if (best.who.alive) {
- dmg *= b.dmgScale * damage;
- best.who.damage(dmg);
- best.who.locatePlayer();
- //draw mob damage circle
- ctx.fillStyle = color;
- ctx.beginPath();
- ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(dmg) * 100, 0, 2 * Math.PI);
- ctx.fill();
- }
- };
- const reflection = function () {
- // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
- const n = Matter.Vector.perp(Matter.Vector.normalise(Matter.Vector.sub(best.v1, best.v2)));
- const d = Matter.Vector.sub(path[path.length - 1], path[path.length - 2]);
- const nn = Matter.Vector.mult(n, 2 * Matter.Vector.dot(d, n));
- const r = Matter.Vector.normalise(Matter.Vector.sub(d, nn));
- path[path.length] = Matter.Vector.add(Matter.Vector.mult(r, range), path[path.length - 1]);
- };
- //beam before reflection
- checkforCollisions();
- if (best.dist2 != Infinity) {
- //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
+ const reflection = function () {
+ // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
+ const n = Matter.Vector.perp(Matter.Vector.normalise(Matter.Vector.sub(best.v1, best.v2)));
+ const d = Matter.Vector.sub(path[path.length - 1], path[path.length - 2]);
+ const nn = Matter.Vector.mult(n, 2 * Matter.Vector.dot(d, n));
+ const r = Matter.Vector.normalise(Matter.Vector.sub(d, nn));
+ path[path.length] = Matter.Vector.add(Matter.Vector.mult(r, range), path[path.length - 1]);
};
- laserHitMob(1);
-
- //1st reflection beam
- reflection();
- //ugly bug fix: this stops the reflection on a bug where the beam gets trapped inside a body
- let who = best.who;
- checkforCollisions();
+ //beam before reflection
+ checkForCollisions();
if (best.dist2 != Infinity) {
//if hitting something
path[path.length - 1] = {
x: best.x,
y: best.y
};
- laserHitMob(0.75);
+ laserHitMob(1);
- //2nd reflection beam
+ //1st reflection beam
+ reflection();
//ugly bug fix: this stops the reflection on a bug where the beam gets trapped inside a body
- if (who !== best.who) {
- reflection();
- checkforCollisions();
- if (best.dist2 != Infinity) {
- //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
- laserHitMob(0.5);
+ let who = best.who;
+ checkForCollisions();
+ if (best.dist2 != Infinity) {
+ //if hitting something
+ path[path.length - 1] = {
+ x: best.x,
+ y: best.y
+ };
+ laserHitMob(0.75);
+
+ //2nd reflection beam
+ //ugly bug fix: this stops the reflection on a bug where the beam gets trapped inside a body
+ if (who !== best.who) {
+ reflection();
+ checkForCollisions();
+ if (best.dist2 != Infinity) {
+ //if hitting something
+ path[path.length - 1] = {
+ x: best.x,
+ y: best.y
+ };
+ laserHitMob(0.5);
+ }
}
}
}
- }
- ctx.fillStyle = color;
- ctx.strokeStyle = color;
- ctx.lineWidth = 2;
- ctx.lineDashOffset = 300 * Math.random()
- // ctx.setLineDash([200 * Math.random(), 250 * Math.random()]);
+ ctx.fillStyle = color;
+ ctx.strokeStyle = color;
+ ctx.lineWidth = 2;
+ ctx.lineDashOffset = 300 * Math.random()
+ // ctx.setLineDash([200 * Math.random(), 250 * Math.random()]);
- ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
- for (let i = 1, len = path.length; i < len; ++i) {
- ctx.beginPath();
- ctx.moveTo(path[i - 1].x, path[i - 1].y);
- ctx.lineTo(path[i].x, path[i].y);
- ctx.stroke();
- ctx.globalAlpha *= 0.5; //reflections are less intense
- // ctx.globalAlpha -= 0.1; //reflections are less intense
+ ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
+ for (let i = 1, len = path.length; i < len; ++i) {
+ ctx.beginPath();
+ ctx.moveTo(path[i - 1].x, path[i - 1].y);
+ ctx.lineTo(path[i].x, path[i].y);
+ ctx.stroke();
+ ctx.globalAlpha *= 0.5; //reflections are less intense
+ // ctx.globalAlpha -= 0.1; //reflections are less intense
+ }
+ ctx.setLineDash([0, 0]);
+ ctx.globalAlpha = 1;
}
- ctx.setLineDash([0, 0]);
- ctx.globalAlpha = 1;
}
- }
- }, {
- name: "rail gun", //15
- description: "
hold left mouse to charge and release to fire
charging repels enemies and drains
field energycrouching improves charging and reduces recoil",
- ammo: 0,
- ammoPack: 9,
- have: false,
- isStarterGun: false,
- fire() {
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(9, -90, 0.01 * b.modBulletSize, 0.0015 * b.modBulletSize, {
- // density: 0.0015, //frictionAir: 0.01, //restitution: 0,
- angle: 0,
- friction: 0.5,
- frictionAir: 0,
- dmg: 3 + b.modExtraDmg, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: 0x000000,
- mask: 0x010011 //mask: 0x000101, //for self collision
- },
- minDmgSpeed: 5,
- onDmg() {}, //this.endCycle = 0 //triggers despawn
- onEnd() {}
- });
- mech.fireCDcycle = Infinity; // cool down
- World.add(engine.world, bullet[me]); //add bullet to world
- bullet[me].endCycle = Infinity
- bullet[me].isCharging = true;
- bullet[me].charge = 0;
- bullet[me].do = function () {
- if (this.isCharging) {
- const DRAIN = 0.0001 + mech.fieldRegen
- if ((!game.mouseDown && this.charge > 0.5) || mech.fieldMeter < DRAIN) { //fire on mouse release
- this.isCharging = false
- if (mech.fieldMeter < DRAIN) {
- mech.fireCDcycle = mech.cycle + 120; // long CD if out of mana
- } else {
+ },
+ {
+ name: "rail gun", //1
+ description: "
hold left mouse to charge and release to fire
charging repels small enemies
crouching charges quicker and reduces recoil",
+ ammo: 0,
+ ammoPack: 12,
+ have: false,
+ isStarterGun: false,
+ fire() {
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(9, -90, 0.01 * b.modBulletSize, 0.0017 * b.modBulletSize, {
+ // density: 0.0015, //frictionAir: 0.01, //restitution: 0,
+ angle: 0,
+ friction: 0.5,
+ frictionAir: 0,
+ dmg: 3 + b.modExtraDmg, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: 0x000000,
+ mask: 0x010011 //mask: 0x000101, //for self collision
+ },
+ minDmgSpeed: 5,
+ onDmg() {}, //this.endCycle = 0 //triggers despawn
+ onEnd() {}
+ });
+ mech.fireCDcycle = Infinity; // cool down
+ World.add(engine.world, bullet[me]); //add bullet to world
+ bullet[me].endCycle = Infinity
+ bullet[me].isCharging = true;
+ bullet[me].charge = 0;
+ bullet[me].do = function () {
+ if (this.isCharging) {
+ if ((!game.mouseDown && this.charge > 0.5)) { //fire on mouse release
+ this.isCharging = false
mech.fireCDcycle = mech.cycle + 2; // set fire cool down
- }
- Matter.Body.scale(this, 10000, 10000) // un hide the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
- this.endCycle = game.cycle + Math.floor(140 * b.isModBulletsLastLonger)
- this.collisionFilter.category = 0x000100
- Matter.Body.setPosition(this, {
- x: mech.pos.x,
- y: mech.pos.y
- })
- Matter.Body.setAngle(this, mech.angle)
- const speed = 80
- Matter.Body.setVelocity(this, {
- x: mech.Vx / 2 + speed * this.charge * Math.cos(mech.angle),
- y: mech.Vy / 2 + speed * this.charge * Math.sin(mech.angle)
- });
+ Matter.Body.scale(this, 8000, 8000) // show the bullet by scaling it up (don't judge me... I know this is a bad way to do it)
+ this.endCycle = game.cycle + Math.floor(140 * b.isModBulletsLastLonger)
+ this.collisionFilter.category = 0x000100
+ Matter.Body.setPosition(this, {
+ x: mech.pos.x,
+ y: mech.pos.y
+ })
+ Matter.Body.setAngle(this, mech.angle)
+ const speed = 80
+ Matter.Body.setVelocity(this, {
+ x: mech.Vx / 2 + speed * this.charge * Math.cos(mech.angle),
+ y: mech.Vy / 2 + speed * this.charge * Math.sin(mech.angle)
+ });
- //knock back
- const KNOCK = ((mech.crouch) ? 0.1 : 0.7) * b.modBulletSize * b.modBulletSize * this.charge * this.charge
- player.force.x -= KNOCK * Math.cos(mech.angle)
- player.force.y -= KNOCK * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
+ //knock back
+ const KNOCK = ((mech.crouch) ? 0.1 : 0.5) * b.modBulletSize * b.modBulletSize * this.charge * this.charge
+ player.force.x -= KNOCK * Math.cos(mech.angle)
+ player.force.y -= KNOCK * Math.sin(mech.angle) * 0.35 //reduce knock back in vertical direction to stop super jumps
- //push away blocks on fire
- const RANGE = 450 * this.charge
- for (let i = 0, len = body.length; i < len; ++i) {
- const SUB = Matter.Vector.sub(body[i].position, mech.pos)
- const DISTANCE = Matter.Vector.magnitude(SUB)
- if (DISTANCE < RANGE) {
- const DEPTH = RANGE - DISTANCE
- const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.005 * Math.sqrt(DEPTH) * Math.sqrt(body[i].mass))
- body[i].force.x += FORCE.x
- body[i].force.y += FORCE.y - body[i].mass * (game.g * 25); //kick up a bit to give them some arc
+ //push away blocks when firing
+ const RANGE = 450 * this.charge
+ for (let i = 0, len = body.length; i < len; ++i) {
+ const SUB = Matter.Vector.sub(body[i].position, mech.pos)
+ const DISTANCE = Matter.Vector.magnitude(SUB)
+ if (DISTANCE < RANGE) {
+ const DEPTH = Math.max(RANGE - DISTANCE, 100)
+ const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.005 * Math.sqrt(DEPTH) * Math.sqrt(body[i].mass))
+ body[i].force.x += FORCE.x
+ body[i].force.y += FORCE.y - body[i].mass * (game.g * 1.5); //kick up a bit to give them some arc
+ }
}
- }
-
- } else { // charging on mouse down
- mech.fieldMeter -= DRAIN;
- mech.fireCDcycle = Infinity //can't fire until mouse is released
- if (mech.crouch) {
- this.charge = this.charge * 0.97 + 0.03 // this.charge converges to 1
- } else {
- this.charge = this.charge * 0.99 + 0.01 // this.charge converges to 1
- }
-
- //gently push away mobs while charging
- const RANGE = 300 * this.charge
- for (let i = 0, len = mob.length; i < len; ++i) {
- const SUB = Matter.Vector.sub(mob[i].position, mech.pos)
- const DISTANCE = Matter.Vector.magnitude(SUB)
- // if (DISTANCE < RANGE) {
- // Matter.Body.setVelocity(mob[i], Matter.Vector.rotate(mob[i].velocity, 0.1))
+ //push mobs around player when firing
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // const SUB = Matter.Vector.sub(mob[i].position, mech.pos)
+ // const DISTANCE = Matter.Vector.magnitude(SUB)
+ // if (DISTANCE < RANGE) {
+ // const DEPTH = RANGE - DISTANCE
+ // const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.00000001 * DEPTH * DEPTH * DEPTH * Math.sqrt(mob[i].mass))
+ // mob[i].force.x += FORCE.x
+ // mob[i].force.y += FORCE.y
+ // }
// }
- if (DISTANCE < RANGE) {
- const DEPTH = RANGE - DISTANCE
- const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.000000001 * DEPTH * DEPTH * DEPTH * Math.sqrt(mob[i].mass))
- mob[i].force.x += FORCE.x
- mob[i].force.y += FORCE.y
+
+
+ } else { // charging on mouse down
+ mech.fireCDcycle = Infinity //can't fire until mouse is released
+ if (mech.crouch) {
+ this.charge = this.charge * 0.97 + 0.03 // this.charge converges to 1
+ } else {
+ this.charge = this.charge * 0.98 + 0.02 // this.charge converges to 1
+ }
+
+ //gently push away mobs while charging
+ const RANGE = 350 * this.charge
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ const SUB = Matter.Vector.sub(mob[i].position, mech.pos)
+ const DISTANCE = Matter.Vector.magnitude(SUB)
+ // if (DISTANCE < RANGE) {
+ // Matter.Body.setVelocity(mob[i], Matter.Vector.rotate(mob[i].velocity, 0.1))
+ // }
+ if (DISTANCE < RANGE) {
+ const DEPTH = RANGE - DISTANCE
+ const FORCE = Matter.Vector.mult(Matter.Vector.normalise(SUB), 0.000000001 * DEPTH * DEPTH * DEPTH * Math.sqrt(mob[i].mass))
+ mob[i].force.x += FORCE.x
+ mob[i].force.y += FORCE.y
+ }
+ }
+
+ // //draw laser targeting
+ // let best;
+ // let range = 3000
+ // const dir = mech.angle
+ // const path = [{
+ // x: mech.pos.x + 20 * Math.cos(dir),
+ // y: mech.pos.y + 20 * Math.sin(dir)
+ // },
+ // {
+ // x: mech.pos.x + range * Math.cos(dir),
+ // y: mech.pos.y + range * Math.sin(dir)
+ // }
+ // ];
+ // 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) {
+ // best = {
+ // x: results.x,
+ // y: results.y,
+ // dist2: dist2,
+ // who: domain[i],
+ // v1: vertices[j],
+ // v2: vertices[j + 1]
+ // };
+ // }
+ // }
+ // }
+ // results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
+ // if (results.onLine1 && results.onLine2) {
+ // const dx = v1.x - results.x;
+ // const dy = v1.y - results.y;
+ // const dist2 = dx * dx + dy * dy;
+ // if (dist2 < best.dist2) {
+ // best = {
+ // x: results.x,
+ // y: results.y,
+ // dist2: dist2,
+ // who: domain[i],
+ // v1: vertices[0],
+ // v2: vertices[len]
+ // };
+ // }
+ // }
+ // }
+ // };
+
+ // //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
+ // };
+ // }
+
+ // //draw laser beam
+ // ctx.beginPath();
+ // ctx.moveTo(path[0].x, path[0].y);
+ // ctx.lineTo(path[1].x, path[1].y);
+ // ctx.strokeStyle = `rgba(50,0,100,0.1)`;
+ // ctx.lineWidth = this.charge * 3
+ // ctx.stroke();
+
+ //draw magnetic field
+ const X = mech.pos.x
+ const Y = mech.pos.y
+ const unitVector = Matter.Vector.normalise(Matter.Vector.sub(game.mouseInGame, mech.pos))
+ const unitVectorPerp = Matter.Vector.perp(unitVector)
+
+ function magField(mag, arc) {
+ ctx.moveTo(X, Y);
+ ctx.bezierCurveTo(
+ X + unitVector.x * mag, Y + unitVector.y * mag,
+ X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
+ X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
+ ctx.bezierCurveTo(
+ X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
+ X - unitVector.x * mag, Y - unitVector.y * mag,
+ X, Y)
+ }
+ ctx.fillStyle = `rgba(50,0,100,0.05)`;
+ for (let i = 3; i < 7; i++) {
+ const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ ctx.beginPath();
+ magField(MAG, ARC)
+ magField(MAG, -ARC)
+ ctx.fill();
+ }
+ }
+ } else { //normal bullet behavior
+ this.force.y += this.mass * 0.00015 / this.charge; // low gravity that scales with charge
+ }
+ }
+ }
+ },
+ {
+ name: "minigun", //2
+ description: "rapidly fire a stream of small
bullets",
+ ammo: 0,
+ ammoPack: 105,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ const me = bullet.length;
+ b.muzzleFlash(15);
+ // if (Math.random() > 0.2) mobs.alert(500);
+ const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.03 : 0.14);
+ bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 17 * b.modBulletSize, 5 * b.modBulletSize, b.fireAttributes(dir));
+ b.fireProps(mech.crouch ? 11 : 5, mech.crouch ? 44 : 36, dir, me); //cd , speed
+ bullet[me].endCycle = game.cycle + Math.floor(65 * b.isModBulletsLastLonger);
+ bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01;
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.0005;
+ };
+ }
+ }, {
+ name: "wave beam", //3
+ description: "fire a stream of oscillating particles
propagates through solids",
+ ammo: 0,
+ ammoPack: 85,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ const me = bullet.length;
+ const DIR = mech.angle
+ const SCALE = (mech.crouch ? 0.963 : 0.95)
+ const wiggleMag = ((mech.flipLegs === 1) ? 1 : -1) * ((mech.crouch) ? 0.004 : 0.005)
+ bullet[me] = Bodies.circle(mech.pos.x + 25 * Math.cos(DIR), mech.pos.y + 25 * Math.sin(DIR), 10 * b.modBulletSize, {
+ angle: DIR,
+ cycle: -0.43, //adjust this number until the bullets line up with the cross hairs
+ endCycle: game.cycle + Math.floor((mech.crouch ? 155 : 120) * b.isModBulletsLastLonger),
+ inertia: Infinity,
+ frictionAir: 0,
+ minDmgSpeed: 0,
+ dmg: 0.13 + b.modExtraDmg, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: 0x000100,
+ mask: 0x000010
+ },
+ onDmg() {},
+ onEnd() {},
+ do() {
+ if (!mech.isBodiesAsleep) {
+ this.cycle++
+ const THRUST = wiggleMag * Math.cos(this.cycle * 0.3)
+ this.force = Matter.Vector.mult(Matter.Vector.normalise(this.direction), this.mass * THRUST) //wiggle
+
+ if (this.cycle > 0 && !(Math.floor(this.cycle) % 6)) Matter.Body.scale(this, SCALE, SCALE); //shrink
+ }
+ }
+ });
+ World.add(engine.world, bullet[me]); //add bullet to world
+ mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 8 : 4) * b.modFireRate); // cool down
+ const SPEED = mech.crouch ? 5.2 : 4.5;
+ Matter.Body.setVelocity(bullet[me], {
+ x: SPEED * Math.cos(DIR),
+ y: SPEED * Math.sin(DIR)
+ });
+ bullet[me].direction = Matter.Vector.perp(bullet[me].velocity)
+ // if (mech.angle + Math.PI / 2 > 0) {
+ // bullet[me].direction = Matter.Vector.perp(bullet[me].velocity, true)
+ // } else {
+ // bullet[me].direction = Matter.Vector.perp(bullet[me].velocity)
+ // }
+
+ World.add(engine.world, bullet[me]); //add bullet to world
+ }
+ }, {
+ name: "super balls", //4
+ description: "fire 3 very
bouncy balls",
+ ammo: 0,
+ ammoPack: 11,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ b.muzzleFlash(20);
+ // mobs.alert(450);
+ const SPREAD = mech.crouch ? 0.04 : 0.14
+ let dir = mech.angle - SPREAD;
+ for (let i = 0; i < 3; i++) {
+ const me = bullet.length;
+ bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 7 * b.modBulletSize, b.fireAttributes(dir, false));
+ b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 34 : 26, dir, me); //cd , speed
+ Matter.Body.setDensity(bullet[me], 0.0001);
+ bullet[me].endCycle = game.cycle + Math.floor(360 * b.isModBulletsLastLonger);
+ bullet[me].dmg = 0.5 + b.modExtraDmg;
+ bullet[me].minDmgSpeed = 0;
+ bullet[me].restitution = 0.96;
+ bullet[me].friction = 0;
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.001;
+ };
+ dir += SPREAD;
+ }
+ }
+ }, {
+ name: "shotgun", //5
+ description: "fire a
burst of bullets
crouch to reduce recoil",
+ ammo: 0,
+ ammoPack: 8,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ b.muzzleFlash(35);
+ // mobs.alert(650);
+ const side = 11 * b.modBulletSize
+ for (let i = 0; i < 9; i++) {
+ const me = bullet.length;
+ const dir = mech.angle + (Math.random() - 0.5) * (mech.crouch ? 0.22 : 0.7)
+ bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle) + 15 * (Math.random() - 0.5), mech.pos.y + 35 * Math.sin(mech.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir));
+ b.fireProps(mech.crouch ? 60 : 30, 40 + Math.random() * 11, dir, me); //cd , speed
+ bullet[me].endCycle = game.cycle + Math.floor(55 * b.isModBulletsLastLonger);
+ bullet[me].frictionAir = 0.03;
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.001;
+ };
+ }
+
+ //knock back
+ const KNOCK = ((mech.crouch) ? 0.015 : 0.15) * b.modBulletSize * b.modBulletSize
+ player.force.x -= KNOCK * Math.cos(mech.angle)
+ player.force.y -= KNOCK * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
+ }
+ }, {
+ name: "fléchettes", //6
+ description: "fire accurate high speed needles",
+ ammo: 0,
+ ammoPack: 25,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ function spawnFlechette(dir = mech.angle, speed, size = 1) {
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(dir), mech.pos.y + 40 * Math.sin(dir), 32 * size * b.modBulletSize, 0.8 * size * b.modBulletSize, b.fireAttributes(dir));
+ bullet[me].endCycle = game.cycle + Math.floor(180 * b.isModBulletsLastLonger);
+ bullet[me].dmg = 0.15 * size + b.modExtraDmg;
+ b.drawOneBullet(bullet[me].vertices);
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.0002; //low gravity
+ };
+ Matter.Body.setVelocity(bullet[me], {
+ x: mech.Vx / 2 + speed * Math.cos(dir),
+ y: mech.Vy / 2 + speed * Math.sin(dir)
+ });
+ World.add(engine.world, bullet[me]); //add bullet to world
+ }
+
+ if (mech.crouch) {
+ for (let i = 0; i < 3; i++) {
+ spawnFlechette(mech.angle + 0.02 * (Math.random() - 0.5), 35 + 4 * i, 1.55)
+ }
+ } else {
+ for (let i = 0; i < 9; i++) {
+ spawnFlechette(mech.angle + 0.12 * (Math.random() - 0.5), 30 + 8 * Math.random())
+ }
+ }
+ mech.fireCDcycle = mech.cycle + Math.floor(40 * b.modFireRate); // cool down
+ }
+ }, {
+ name: "missiles", //7
+ description: "fire a missile that accelerates towards nearby targets
explodes when near target",
+ ammo: 0,
+ ammoPack: 8,
+ have: false,
+ isStarterGun: false,
+ fireCycle: 0,
+ ammoLoaded: 0,
+ fire() {
+ const thrust = 0.0003;
+ let dir = mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2);
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle) - 3, 30 * b.modBulletSize, 4 * b.modBulletSize, b.fireAttributes(dir));
+ b.fireProps(mech.crouch ? 70 : 30, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed
+
+ b.drawOneBullet(bullet[me].vertices);
+ // Matter.Body.setDensity(bullet[me], 0.01) //doesn't help with reducing explosion knock backs
+ bullet[me].force.y += 0.00045; //a small push down at first to make it seem like the missile is briefly falling
+ bullet[me].frictionAir = 0
+ bullet[me].endCycle = game.cycle + Math.floor((265 + Math.random() * 20) * b.isModBulletsLastLonger);
+ bullet[me].explodeRad = 170 + 60 * Math.random();
+ bullet[me].lookFrequency = Math.floor(8 + Math.random() * 7);
+ bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end
+ bullet[me].onDmg = function () {
+ this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
+ };
+ bullet[me].lockedOn = null;
+ bullet[me].do = function () {
+ if (!mech.isBodiesAsleep) {
+ if (!(mech.cycle % this.lookFrequency)) {
+ this.closestTarget = null;
+ this.lockedOn = null;
+ let closeDist = Infinity;
+
+ //look for targets
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (
+ mob[i].alive &&
+ mob[i].dropPowerUp &&
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0
+ ) {
+ const dist = Matter.Vector.magnitude(Matter.Vector.sub(this.position, mob[i].position));
+ if (dist < closeDist) {
+ this.closestTarget = mob[i].position;
+ closeDist = dist;
+ this.lockedOn = mob[i];
+ }
+ }
+ }
+ //explode when bullet is close enough to target
+ if (this.closestTarget && closeDist < this.explodeRad) {
+ this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
+ }
+
+ if (this.lockedOn) {
+ this.frictionAir = 0.04; //extra friction
+
+ //draw locked on targeting
+ ctx.beginPath();
+ const vertices = this.lockedOn.vertices;
+ ctx.moveTo(this.position.x, this.position.y);
+ const mod = Math.floor((game.cycle / 3) % vertices.length);
+ ctx.lineTo(vertices[mod].x, vertices[mod].y);
+ ctx.strokeStyle = "rgba(0,0,155,0.35)"; //"#2f6";
+ ctx.lineWidth = 1;
+ ctx.stroke();
}
}
- // //draw laser targeting
- // let best;
- // let range = 3000
- // const dir = mech.angle
- // const path = [{
- // x: mech.pos.x + 20 * Math.cos(dir),
- // y: mech.pos.y + 20 * Math.sin(dir)
- // },
- // {
- // x: mech.pos.x + range * Math.cos(dir),
- // y: mech.pos.y + range * Math.sin(dir)
- // }
- // ];
- // 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) {
- // best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[j],
- // v2: vertices[j + 1]
- // };
- // }
- // }
- // }
- // results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- // if (results.onLine1 && results.onLine2) {
- // const dx = v1.x - results.x;
- // const dy = v1.y - results.y;
- // const dist2 = dx * dx + dy * dy;
- // if (dist2 < best.dist2) {
- // best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[0],
- // v2: vertices[len]
- // };
- // }
- // }
- // }
- // };
-
- // //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
- // };
- // }
-
- // //draw laser beam
- // ctx.beginPath();
- // ctx.moveTo(path[0].x, path[0].y);
- // ctx.lineTo(path[1].x, path[1].y);
- // ctx.strokeStyle = `rgba(50,0,100,0.1)`;
- // ctx.lineWidth = this.charge * 3
- // ctx.stroke();
-
- //draw magnetic field
- const X = mech.pos.x
- const Y = mech.pos.y
- const unitVector = Matter.Vector.normalise(Matter.Vector.sub(game.mouseInGame, mech.pos))
- const unitVectorPerp = Matter.Vector.perp(unitVector)
-
- function magField(mag, arc) {
- ctx.moveTo(X, Y);
- ctx.bezierCurveTo(
- X + unitVector.x * mag, Y + unitVector.y * mag,
- X + unitVector.x * mag + unitVectorPerp.x * arc, Y + unitVector.y * mag + unitVectorPerp.y * arc,
- X + unitVectorPerp.x * arc, Y + unitVectorPerp.y * arc)
- ctx.bezierCurveTo(
- X - unitVector.x * mag + unitVectorPerp.x * arc, Y - unitVector.y * mag + unitVectorPerp.y * arc,
- X - unitVector.x * mag, Y - unitVector.y * mag,
- X, Y)
+ //rotate missile towards the target
+ if (this.closestTarget) {
+ const face = {
+ x: Math.cos(this.angle),
+ y: Math.sin(this.angle)
+ };
+ const target = Matter.Vector.normalise(Matter.Vector.sub(this.position, this.closestTarget));
+ if (Matter.Vector.dot(target, face) > -0.98) {
+ if (Matter.Vector.cross(target, face) > 0) {
+ Matter.Body.rotate(this, 0.08);
+ } else {
+ Matter.Body.rotate(this, -0.08);
+ }
+ }
}
- ctx.fillStyle = `rgba(50,0,100,0.05)`;
- for (let i = 3; i < 7; i++) {
- const MAG = 8 * i * i * this.charge * (0.93 + 0.07 * Math.random())
- const ARC = 6 * i * i * this.charge * (0.93 + 0.07 * Math.random())
+ //accelerate in direction bullet is facing
+ const dir = this.angle; // + (Math.random() - 0.5);
+ this.force.x += Math.cos(dir) * thrust;
+ this.force.y += Math.sin(dir) * thrust;
+
+ //draw rocket
+ ctx.beginPath();
+ ctx.arc(this.position.x - Math.cos(this.angle) * 27 + (Math.random() - 0.5) * 4, this.position.y - Math.sin(this.angle) * 27 + (Math.random() - 0.5) * 4, 11, 0, 2 * Math.PI);
+ ctx.fillStyle = "rgba(255,155,0,0.5)";
+ ctx.fill();
+ } else {
+ //draw rocket with time stop
+ ctx.beginPath();
+ ctx.arc(this.position.x - Math.cos(this.angle) * 27, this.position.y - Math.sin(this.angle) * 27, 11, 0, 2 * Math.PI);
+ ctx.fillStyle = "rgba(255,155,0,0.5)";
+ ctx.fill();
+ }
+ }
+ }
+ }, {
+ name: "flak", //8
+ description: "fire a cluster of short range projectiles
explode on contact or after half a second",
+ ammo: 0,
+ ammoPack: 20,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ b.muzzleFlash(30);
+ const totalBullets = 5
+ const angleStep = (mech.crouch ? 0.06 : 0.15) / totalBullets
+ const SPEED = mech.crouch ? 30 : 25
+ const CD = mech.crouch ? 45 : 11
+ const END = Math.floor((mech.crouch ? 30 : 18) * b.isModBulletsLastLonger);
+ let dir = mech.angle - angleStep * totalBullets / 2;
+ const side1 = 17 * b.modBulletSize
+ const side2 = 4 * b.modBulletSize
+
+ for (let i = 0; i < totalBullets; i++) { //5 -> 7
+ dir += angleStep
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(mech.pos.x + 50 * Math.cos(mech.angle), mech.pos.y + 50 * Math.sin(mech.angle), side1, side2, b.fireAttributes(dir));
+ b.fireProps(CD, SPEED + 15 * Math.random() - 2 * i, dir, me); //cd , speed
+ // Matter.Body.setDensity(bullet[me], 0.005);
+ bullet[me].endCycle = 2 * i + game.cycle + END
+ bullet[me].restitution = 0;
+ bullet[me].friction = 1;
+ // bullet[me].dmg = 0.15;
+ bullet[me].explodeRad = (mech.crouch ? 70 : 45) + (Math.random() - 0.5) * 50;
+ bullet[me].onEnd = b.explode;
+ bullet[me].onDmg = function () {
+ this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
+ };
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.0004;
+ // if (this.speed < 10) { //if slow explode
+ // for (let i = 0, len = bullet.length; i < len; i++) {
+ // bullet[i].endCycle = 0 //all other bullets explode
+ // }
+ // }
+ }
+ }
+ }
+ }, {
+ name: "grenades", //9
+ description: "fire a projectile that
explodes on contact or after one second",
+ ammo: 0,
+ ammoPack: 9,
+ have: false,
+ isStarterGun: false,
+ fire() {
+ const me = bullet.length;
+ const dir = mech.angle; // + Math.random() * 0.05;
+ bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15 * b.modBulletSize, b.fireAttributes(dir, false));
+ b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed
+ b.drawOneBullet(bullet[me].vertices);
+ // Matter.Body.setDensity(bullet[me], 0.000001);
+ bullet[me].totalCycles = 100;
+ bullet[me].endCycle = game.cycle + Math.floor((mech.crouch ? 120 : 60) * b.isModBulletsLastLonger);
+ bullet[me].restitution = 0.5;
+ bullet[me].explodeRad = 210;
+ bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
+ bullet[me].minDmgSpeed = 1;
+ bullet[me].onDmg = function () {
+ this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
+ };
+ bullet[me].do = function () {
+ //extra gravity for harder arcs
+ this.force.y += this.mass * 0.002;
+ };
+ }
+ }, {
+ name: "vacuum bomb", //10
+ description: "fire a huge
bomb that sucks before it
explodesclick left mouse
again to detonate",
+ ammo: 0,
+ ammoPack: 5,
+ have: false,
+ isStarterGun: false,
+ fire() {
+ const me = bullet.length;
+ const dir = mech.angle;
+ bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 26 * b.modBulletSize, b.fireAttributes(dir, false));
+ bullet[me].radius = 22; //used from drawing timer
+ b.fireProps(10, mech.crouch ? 42 : 26, dir, me); //cd , speed
+
+ b.drawOneBullet(bullet[me].vertices);
+ bullet[me].endCycle = Infinity
+ // bullet[me].restitution = 0.3;
+ // bullet[me].frictionAir = 0.01;
+ // bullet[me].friction = 0.15;
+ bullet[me].inertia = Infinity; //prevents rotation
+ bullet[me].restitution = 0;
+ bullet[me].friction = 1;
+
+ bullet[me].explodeRad = 380 + Math.floor(Math.random() * 60);
+ bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
+ bullet[me].onDmg = function () {
+ // this.endCycle = 0; //bullet ends cycle after doing damage //this triggers explosion
+ };
+ bullet[me].isArmed = false;
+ bullet[me].isSucking = false;
+ bullet[me].do = function () {
+ //extra gravity for harder arcs
+ this.force.y += this.mass * 0.0022;
+ mech.fireCDcycle = mech.cycle + 10 //can't fire until after the explosion
+
+ //set armed and sucking status
+ if (!this.isArmed && !game.mouseDown) {
+ this.isArmed = true
+ } else if (this.isArmed && game.mouseDown && !this.isSucking) {
+ this.isSucking = true;
+ this.endCycle = game.cycle + 35;
+ }
+
+ if (this.isSucking) {
+ if (!mech.isBodiesAsleep) {
+ const that = this
+ let mag = 0.1
+
+ function suck(who, radius = that.explodeRad * 2) {
+ for (i = 0, len = who.length; i < len; i++) {
+ const sub = Matter.Vector.sub(that.position, who[i].position);
+ const dist = Matter.Vector.magnitude(sub);
+ if (dist < radius && dist > 150) {
+ knock = Matter.Vector.mult(Matter.Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
+ who[i].force.x += knock.x;
+ who[i].force.y += knock.y;
+ }
+ }
+ }
+ if (game.cycle > this.endCycle - 5) {
+ mag = -0.22
+ suck(body)
+ suck(mob)
+ suck(powerUp)
+ suck(bullet)
+ suck([player])
+ } else {
+ mag = 0.1
+ suck(body)
+ suck(mob)
+ suck(powerUp)
+ suck(bullet)
+ suck([player])
+ }
+ //keep bomb in place
+ Matter.Body.setVelocity(this, {
+ x: 0,
+ y: 0
+ });
+ //draw suck
+ const radius = 2.5 * this.explodeRad * (this.endCycle - game.cycle) / 35
+ ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.beginPath();
- magField(MAG, ARC)
- magField(MAG, -ARC)
+ ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
+ ctx.fill();
+ }
+ } else {
+ // flashing lights to show armed
+ if (!(game.cycle % 10)) {
+ if (this.isFlashOn) {
+ this.isFlashOn = false;
+ } else {
+ this.isFlashOn = true;
+ }
+ }
+ if (this.isFlashOn) {
+ ctx.fillStyle = "#000";
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
+ ctx.fill();
+ //draw clock on timer
+ ctx.fillStyle = "#f04";
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, this.radius * 0.5, 0, 2 * Math.PI);
ctx.fill();
}
}
- } else { //normal bullet behavior
- this.force.y += this.mass * 0.00015 / this.charge; // low gravity that scales with charge
}
}
- }
- // }, {
+ }, {
+ name: "ferro frag", //11
+ description: "fire a
grenade that ejects
magnetized nails
nails are
attracted to enemy targets",
+ ammo: 0,
+ ammoPack: 8,
+ have: false,
+ isStarterGun: false,
+ fire() {
+ const me = bullet.length;
+ const dir = mech.angle;
+ bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15 * b.modBulletSize, b.fireAttributes(dir, false));
+ b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 34 : 22, dir, me); //cd , speed
+ b.drawOneBullet(bullet[me].vertices);
+ bullet[me].endCycle = game.cycle + Math.floor(60 * b.isModBulletsLastLonger);
+ bullet[me].restitution = 0.3;
+ // bullet[me].frictionAir = 0.01;
+ // bullet[me].friction = 0.15;
+ // bullet[me].friction = 1;
+ bullet[me].onEnd = () => {}
+ bullet[me].do = function () {
+ this.force.y += this.mass * 0.0018; //extra gravity for grenades
+
+ if (game.cycle > this.endCycle - 1) {
+ if (!mech.isBodiesAsleep) {
+ //target nearby mobs
+ const targets = []
+ for (let i = 0, len = mob.length; i < len; i++) {
+ const sub = Matter.Vector.sub(this.position, mob[i].position);
+ const dist = Matter.Vector.magnitude(sub);
+ if (dist < 1400 &&
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
+ targets.push(mob[i].position)
+ }
+ }
+ for (let i = 0; i < 14; i++) {
+ const SPEED = 35 + 20 * Math.random()
+ if (targets.length > 0) { // aim near a random target
+ const SPREAD = 100
+ const INDEX = Math.floor(Math.random() * targets.length)
+ const WHERE = {
+ x: targets[INDEX].x + SPREAD * (Math.random() - 0.5),
+ y: targets[INDEX].y + SPREAD * (Math.random() - 0.5)
+ }
+ needle(this.position, Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(WHERE, this.position)), SPEED))
+ } else { // aim in random direction
+ const ANGLE = 2 * Math.PI * Math.random()
+ needle(this.position, {
+ x: SPEED * Math.cos(ANGLE),
+ y: SPEED * Math.sin(ANGLE)
+ })
+ }
+
+ function needle(pos, velocity) {
+ const me = bullet.length;
+ bullet[me] = Bodies.rectangle(pos.x, pos.y, 23 * b.modBulletSize, 2 * b.modBulletSize, 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 + Math.floor(15 * Math.random());
+ // bullet[me].dmg = 1.1+b.modExtraDmg;
+ bullet[me].do = function () {};
+ }
+ }
+ }
+ }
+ }
+ }
+ }, {
+ name: "spores", //12
+ description: "release an orb that discharges
spores after 2 seconds
seeks out targets
passes through blocks",
+ ammo: 0,
+ ammoPack: 5,
+ have: false,
+ isStarterGun: false,
+ fire() {
+ const me = bullet.length;
+ const dir = mech.angle;
+ bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, 4.5, b.fireAttributes(dir, false));
+ b.fireProps(mech.crouch ? 75 : 55, mech.crouch ? 25 : 14, dir, me); //cd , speed
+ b.drawOneBullet(bullet[me].vertices);
+ Matter.Body.setDensity(bullet[me], 0.000001);
+ bullet[me].endCycle = game.cycle + 100;
+ bullet[me].frictionAir = 0;
+ bullet[me].friction = 0.5;
+ bullet[me].restitution = 0.3;
+ bullet[me].minDmgSpeed = 0;
+ bullet[me].onDmg = function () {};
+ bullet[me].do = function () {
+ if (!mech.isBodiesAsleep) {
+ const SCALE = 1.017
+ Matter.Body.scale(this, SCALE, SCALE);
+ this.frictionAir += 0.00023;
+ }
+
+ this.force.y += this.mass * 0.00045;
+
+ //draw green glow
+ ctx.fillStyle = "rgba(0,200,125,0.16)";
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, 26, 0, 2 * Math.PI);
+ ctx.fill();
+ };
+
+ //spawn bullets on end
+ bullet[me].onEnd = function () {
+ const NUM = 9;
+ for (let i = 0; i < NUM; i++) {
+ const bIndex = bullet.length;
+ const RADIUS = 3 * b.modBulletSize;
+ bullet[bIndex] = Bodies.circle(this.position.x, this.position.y, RADIUS, {
+ // density: 0.0015, //frictionAir: 0.01,
+ inertia: Infinity,
+ restitution: 0.5,
+ angle: dir,
+ friction: 0,
+ frictionAir: 0.011,
+ dmg: 1.8 + b.modExtraDmg, //damage done in addition to the damage from momentum
+ classType: "bullet",
+ collisionFilter: {
+ category: 0x000100,
+ mask: 0x000011 //no collide with body
+ },
+ endCycle: game.cycle + Math.floor((360 + Math.floor(Math.random() * 240)) * b.isModBulletsLastLonger),
+ minDmgSpeed: 0,
+ onDmg() {
+ this.endCycle = 0; //bullet ends cycle after doing damage
+ },
+ onEnd() {},
+ lookFrequency: 67 + Math.floor(47 * Math.random()),
+ do() {
+ //find mob targets
+ if (!(game.cycle % this.lookFrequency)) {
+ this.closestTarget = null;
+ this.lockedOn = null;
+ let closeDist = Infinity;
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ // Matter.Query.ray(body, this.position, mob[i].position).length === 0
+ const targetVector = Matter.Vector.sub(this.position, mob[i].position)
+ const dist = Matter.Vector.magnitude(targetVector);
+ if (dist < closeDist) {
+ this.closestTarget = mob[i].position;
+ closeDist = dist;
+ this.lockedOn = Matter.Vector.normalise(targetVector);
+ if (0.3 > Math.random()) break //doesn't always target the closest mob
+ }
+ }
+ }
+ }
+ //accelerate towards mobs
+ const THRUST = this.mass * 0.0009
+ if (this.lockedOn) {
+ this.force.x -= THRUST * this.lockedOn.x
+ this.force.y -= THRUST * this.lockedOn.y
+ } else {
+ this.force.y += this.mass * 0.00025; //gravity
+ }
+ },
+ });
+ const SPEED = 9;
+ const ANGLE = 2 * Math.PI * Math.random()
+ Matter.Body.setVelocity(bullet[bIndex], {
+ x: SPEED * Math.cos(ANGLE),
+ y: SPEED * Math.sin(ANGLE)
+ });
+ World.add(engine.world, bullet[bIndex]); //add bullet to world
+ }
+ }
+
+ }
+ }, {
+ name: "drones", //13
+ description: "release
drones that seek out targets for 16 seconds
follows mouse if no targets are found",
+ ammo: 0,
+ ammoPack: 20,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ const THRUST = 0.0015
+ const dir = mech.angle + 0.2 * (Math.random() - 0.5);
+ const me = bullet.length;
+ const RADIUS = (4.5 + 3 * Math.random()) * b.modBulletSize
+ bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, {
+ angle: dir,
+ inertia: Infinity,
+ friction: 0.05,
+ frictionAir: 0.0005,
+ restitution: 1,
+ dmg: 0.14 + b.modExtraDmg, //damage done in addition to the damage from momentum
+ lookFrequency: 79 + Math.floor(37 * Math.random()),
+ endCycle: game.cycle + Math.floor((960 + 360 * Math.random()) * b.isModBulletsLastLonger),
+ classType: "bullet",
+ collisionFilter: {
+ category: 0x000100,
+ mask: 0x010111 //self collide
+ },
+ minDmgSpeed: 0,
+ lockedOn: null,
+ isFollowMouse: true,
+ onDmg() {
+ this.lockedOn = null
+ },
+ onEnd() {},
+ do() {
+ if (game.cycle + 180 > this.endCycle) { //fall and die
+ this.force.y += this.mass * 0.0012;
+ this.restitution = 0.2;
+ } else {
+ this.force.y += this.mass * 0.0002;
+ //find mob targets
+ if (!(game.cycle % this.lookFrequency)) {
+ this.lockedOn = null;
+ let closeDist = Infinity;
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (
+ Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, mob[i].position).length === 0
+ ) {
+ const TARGET_VECTOR = Matter.Vector.sub(this.position, mob[i].position)
+ const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
+ if (DIST < closeDist) {
+ closeDist = DIST;
+ this.lockedOn = mob[i]
+ }
+ }
+ }
+ if (!this.lockedOn) {
+ //grab a power up if it is (ammo) or (a heal when player is low)
+ let closeDist = Infinity;
+ for (let i = 0, len = powerUp.length; i < len; ++i) {
+ if (
+ ((powerUp[i].name !== "field" && powerUp[i].name !== "heal") || (powerUp[i].name === "heal" && mech.health < 0.8)) &&
+ Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 &&
+ Matter.Query.ray(body, this.position, powerUp[i].position).length === 0
+ ) {
+ const TARGET_VECTOR = Matter.Vector.sub(this.position, powerUp[i].position)
+ const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
+ if (DIST < closeDist) {
+ if (DIST < 50) { //eat the power up if close enough
+ powerUp[i].effect();
+ Matter.World.remove(engine.world, powerUp[i]);
+ powerUp.splice(i, 1);
+ break;
+ }
+ closeDist = DIST;
+ this.lockedOn = powerUp[i]
+ }
+ }
+ }
+ }
+ }
+ if (this.lockedOn) { //accelerate towards mobs
+ this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST)
+ } else { //accelerate towards mouse
+ this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, game.mouseInGame)), -this.mass * THRUST)
+ }
+ // speed cap instead of friction to give more agility
+ if (this.speed > 6) {
+ Matter.Body.setVelocity(this, {
+ x: this.velocity.x * 0.97,
+ y: this.velocity.y * 0.97
+ });
+ }
+ }
+ }
+ })
+ b.fireProps(mech.crouch ? 19 : 15, mech.crouch ? 35 : 1, dir, me); //cd , speed
+ b.drawOneBullet(bullet[me].vertices);
+ }
+ },
+ // {
+ // name: "dwarf star", //14
+ // description: "drop a mine that gravitational pulls in matter",
+ // ammo: 0,
+ // ammoPack: 1000,
+ // have: false,
+ // isStarterGun: false,
+ // fire() {
+ // const me = bullet.length;
+ // const dir = mech.angle
+ // const TOTAL_CYCLES = 1020
+ // bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(dir), mech.pos.y + 30 * Math.sin(dir), 3 * b.modBulletSize, {
+ // density: 0.05,
+ // //frictionAir: 0.01,
+ // restitution: 0,
+ // angle: 0,
+ // friction: 1,
+ // // frictionAir: 1,
+ // endCycle: game.cycle + TOTAL_CYCLES,
+ // dmg: b.modExtraDmg, //damage done in addition to the damage from momentum
+ // classType: "bullet",
+ // collisionFilter: {
+ // category: 0x000100,
+ // mask: 0x010011 //mask: 0x000101, //for self collision
+ // },
+ // minDmgSpeed: 5,
+ // range: 0,
+ // onDmg() {
+ // this.endCycle = 0;
+ // }, //this.endCycle = 0 //triggers despawn
+ // onEnd() {},
+ // do() {
+ // this.force.y += this.mass * 0.005;
+ // this.range += 0.5
+
+ // //damage nearby mobs
+ // const dmg = b.dmgScale * 0.02
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // if (mob[i].alive) {
+ // sub = Matter.Vector.sub(this.position, mob[i].position);
+ // dist = Matter.Vector.magnitude(sub) - mob[i].radius;
+ // if (dist < this.range) {
+ // mob[i].damage(dmg);
+ // mob[i].locatePlayer();
+ // }
+ // }
+ // }
+
+ // //pull in body, and power ups?, and bullets?
+ // for (let i = 0, len = body.length; i < len; ++i) {
+ // sub = Matter.Vector.sub(this.position, body[i].position);
+ // dist = Matter.Vector.magnitude(sub)
+ // if (dist < this.range) {
+ // this.range += body[i].mass * 2
+ // Matter.World.remove(engine.world, body[i]);
+ // body.splice(i, 1);
+ // break;
+ // }
+ // }
+
+ // //draw
+ // const opacity = (this.endCycle - game.cycle) / TOTAL_CYCLES
+ // ctx.fillStyle = `rgba(170,220,255,${opacity})`;
+ // ctx.beginPath();
+ // ctx.arc(this.position.x, this.position.y, this.range, 0, 2 * Math.PI);
+ // ctx.fill();
+ // }
+ // });
+ // b.fireProps(60, 0, dir, me); //cd , speed
+ // }
+ // },
+ // {
// name: "kinetic slugs", //1
// description: "fire a large
rod that does excessive physical
damagehigh recoil",
// ammo: 0,
@@ -884,793 +1685,145 @@ const b = {
// const KNOCK = ((mech.crouch) ? 0.025 : 0.25) * b.modBulletSize * b.modBulletSize
// player.force.x -= KNOCK * Math.cos(dir)
// player.force.y -= KNOCK * Math.sin(dir) * 0.3 //reduce knock back in vertical direction to stop super jumps
+ // },
+ // {
+ // name: "triboelectricty", //14
+ // description: "release
particles that quickly seek out targets",
+ // ammo: 0,
+ // ammoPack: 40,
+ // have: false,
+ // isStarterGun: true,
+ // fire() {
+ // const dir = mech.angle + 0.2 * (Math.random() - 0.5);
+ // const me = bullet.length;
+ // const RADIUS = 6 * b.modBulletSize
+ // bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, {
+ // angle: dir,
+ // inertia: Infinity,
+ // // friction: 0.05,
+ // // frictionAir: 0.05,
+ // restitution: 0.8,
+ // dmg: 0.14 + b.modExtraDmg, //damage done in addition to the damage from momentum
+ // lookFrequency: 3,
+ // endCycle: game.cycle + Math.floor(120 * b.isModBulletsLastLonger),
+ // classType: "bullet",
+ // collisionFilter: {
+ // category: 0x000100,
+ // mask: 0x010111 //self collide
+ // },
+ // minDmgSpeed: 0,
+ // lockedOn: null,
+ // isFollowMouse: true,
+ // onDmg() {
+ // this.endCycle = 0;
+ // },
+ // onEnd() {},
+ // do() {
+ // if (this.lockedOn) { //accelerate towards mobs
+ // this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * 0.01)
+ // Matter.Body.setVelocity(this, {
+ // x: this.velocity.x * 0.93,
+ // y: this.velocity.y * 0.93
+ // });
+ // } else {
+ // this.force.y += this.mass * 0.0004;
+ // }
+ // }
+ // })
+
+ // b.fireProps(mech.crouch ? 19 : 15, mech.crouch ? 45 : 30, dir, me); //cd , speed
+ // b.drawOneBullet(bullet[me].vertices);
+
+ // //find mob targets
+ // let closeDist = Infinity;
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // if (
+ // Matter.Query.ray(map, bullet[me].position, mob[i].position).length === 0 &&
+ // Matter.Query.ray(body, bullet[me].position, mob[i].position).length === 0
+ // ) {
+ // const TARGET_VECTOR = Matter.Vector.sub(bullet[me].position, mob[i].position)
+ // const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
+ // if (DIST < closeDist) {
+ // closeDist = DIST;
+ // bullet[me].lockedOn = mob[i]
+ // }
+ // }
+ // }
// }
- }, {
- name: "minigun", //2
- description: "rapidly fire a stream of small
bullets",
- ammo: 0,
- ammoPack: 105,
- have: false,
- isStarterGun: true,
- fire() {
- const me = bullet.length;
- b.muzzleFlash(15);
- // if (Math.random() > 0.2) mobs.alert(500);
- const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.03 : 0.14);
- bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 17 * b.modBulletSize, 5 * b.modBulletSize, b.fireAttributes(dir));
- b.fireProps(mech.crouch ? 11 : 5, mech.crouch ? 44 : 36, dir, me); //cd , speed
- bullet[me].endCycle = game.cycle + Math.floor(65 * b.isModBulletsLastLonger);
- bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01;
- bullet[me].do = function () {
- this.force.y += this.mass * 0.0005;
- };
- }
- }, {
- name: "wave beam", //3
- description: "fire a stream of oscillating particles
propagates through solids",
- ammo: 0,
- ammoPack: 85,
- have: false,
- isStarterGun: true,
- fire() {
- const me = bullet.length;
- const DIR = mech.angle
- const SCALE = (mech.crouch ? 0.963 : 0.95)
- const wiggleMag = ((mech.flipLegs === 1) ? 1 : -1) * ((mech.crouch) ? 0.004 : 0.005)
- bullet[me] = Bodies.circle(mech.pos.x + 25 * Math.cos(DIR), mech.pos.y + 25 * Math.sin(DIR), 10 * b.modBulletSize, {
- angle: DIR,
- cycle: -0.43, //adjust this number until the bullets line up with the cross hairs
- endCycle: game.cycle + Math.floor((mech.crouch ? 155 : 120) * b.isModBulletsLastLonger),
- inertia: Infinity,
- frictionAir: 0,
- minDmgSpeed: 0,
- dmg: 0.13 + b.modExtraDmg, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: 0x000100,
- mask: 0x000010
- },
- onDmg() {},
- onEnd() {},
- do() {
- if (!mech.isBodiesAsleep) {
- this.cycle++
- const THRUST = wiggleMag * Math.cos(this.cycle * 0.3)
- this.force = Matter.Vector.mult(Matter.Vector.normalise(this.direction), this.mass * THRUST) //wiggle
+ // },
+ // {
+ // //draw a halo, since there will only be 1-3 balls
+ // name: "junk-bots", //14
+ // description: "release unreliable
drones that defend the space around the player
collisions may cause
malfunction",
+ // ammo: 0,
+ // ammoPack: 15,
+ // have: false,
+ // isStarterGun: false,
+ // fire() {
+ // const THRUST = 0.004
+ // const dir = mech.angle + 0.2 * (Math.random() - 0.5);
+ // const me = bullet.length;
+ // const RADIUS = (15 + 8 * Math.random()) * b.modBulletSize
+ // const LENGTH = 0.6 + 0.8 * Math.random()
- if (this.cycle > 0 && !(Math.floor(this.cycle) % 6)) Matter.Body.scale(this, SCALE, SCALE); //shrink
- }
- }
- });
- World.add(engine.world, bullet[me]); //add bullet to world
- mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 8 : 4) * b.modFireRate); // cool down
- const SPEED = mech.crouch ? 5.2 : 4.5;
- Matter.Body.setVelocity(bullet[me], {
- x: SPEED * Math.cos(DIR),
- y: SPEED * Math.sin(DIR)
- });
- bullet[me].direction = Matter.Vector.perp(bullet[me].velocity)
- // if (mech.angle + Math.PI / 2 > 0) {
- // bullet[me].direction = Matter.Vector.perp(bullet[me].velocity, true)
- // } else {
- // bullet[me].direction = Matter.Vector.perp(bullet[me].velocity)
- // }
+ // bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS * LENGTH, RADIUS / LENGTH, {
+ // isOrb: true,
+ // angle: dir,
+ // // inertia: Infinity,
+ // // friction: 0,
+ // density: 0.001, //normal is 0.001
+ // frictionAir: 0.06,
+ // restitution: 0.8,
+ // dmg: b.modExtraDmg, // 0.14 //damage done in addition to the damage from momentum
+ // minDmgSpeed: 2,
+ // lookFrequency: 7 + Math.floor(17 * Math.random()),
+ // endCycle: game.cycle + Math.floor((200 + 60 * Math.random()) * b.isModBulletsLastLonger),
+ // classType: "bullet",
+ // collisionFilter: {
+ // category: 0x000100,
+ // mask: 0x010111 //self, mob,map,body collide
+ // },
+ // range: 300,
+ // lockedOn: null,
+ // onDmg() {
+ // this.lockedOn = null
+ // // this.endCycle -= 120; //lose 2 seconds after damage is done
+ // },
+ // onEnd() {},
+ // do() {
+ // if (game.cycle + 120 > this.endCycle) { //fall and die
+ // this.force.y += this.mass * 0.0012;
+ // } else {
+ // if (!(game.cycle % this.lookFrequency)) {
+ // this.lockedOn = null;
+ // let closeDist = Infinity;
+ // for (let i = 0, len = mob.length; i < len; ++i) {
+ // const TARGET_VECTOR = Matter.Vector.sub(mech.pos, mob[i].position)
+ // const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
+ // // DIST - mob[i].radius < this.range &&
+ // if (DIST < closeDist && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
+ // closeDist = DIST;
+ // this.lockedOn = mob[i]
+ // }
+ // }
+ // }
- World.add(engine.world, bullet[me]); //add bullet to world
- }
- }, {
- name: "super balls", //4
- description: "fire 3 very
bouncy balls",
- ammo: 0,
- ammoPack: 11,
- have: false,
- isStarterGun: true,
- fire() {
- b.muzzleFlash(20);
- // mobs.alert(450);
- const SPREAD = mech.crouch ? 0.04 : 0.14
- let dir = mech.angle - SPREAD;
- for (let i = 0; i < 3; i++) {
- const me = bullet.length;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 7 * b.modBulletSize, b.fireAttributes(dir, false));
- b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 34 : 26, dir, me); //cd , speed
- Matter.Body.setDensity(bullet[me], 0.0001);
- bullet[me].endCycle = game.cycle + Math.floor(360 * b.isModBulletsLastLonger);
- bullet[me].dmg = 0.5 + b.modExtraDmg;
- bullet[me].minDmgSpeed = 0;
- bullet[me].restitution = 0.96;
- bullet[me].friction = 0;
- bullet[me].do = function () {
- this.force.y += this.mass * 0.001;
- };
- dir += SPREAD;
- }
- }
- }, {
- name: "shotgun", //5
- description: "fire a
burst of bullets
crouch to reduce recoil",
- ammo: 0,
- ammoPack: 8,
- have: false,
- isStarterGun: true,
- fire() {
- b.muzzleFlash(35);
- // mobs.alert(650);
- const side = 11 * b.modBulletSize
- for (let i = 0; i < 9; i++) {
- const me = bullet.length;
- const dir = mech.angle + (Math.random() - 0.5) * (mech.crouch ? 0.22 : 0.7)
- bullet[me] = Bodies.rectangle(mech.pos.x + 35 * Math.cos(mech.angle) + 15 * (Math.random() - 0.5), mech.pos.y + 35 * Math.sin(mech.angle) + 15 * (Math.random() - 0.5), side, side, b.fireAttributes(dir));
- b.fireProps(mech.crouch ? 60 : 30, 40 + Math.random() * 11, dir, me); //cd , speed
- bullet[me].endCycle = game.cycle + Math.floor(55 * b.isModBulletsLastLonger);
- bullet[me].frictionAir = 0.03;
- bullet[me].do = function () {
- this.force.y += this.mass * 0.001;
- };
- }
-
- //knock back
- const KNOCK = ((mech.crouch) ? 0.015 : 0.15) * b.modBulletSize * b.modBulletSize
- player.force.x -= KNOCK * Math.cos(mech.angle)
- player.force.y -= KNOCK * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
- }
- }, {
- name: "fléchettes", //6
- description: "fire accurate high speed needles",
- ammo: 0,
- ammoPack: 25,
- have: false,
- isStarterGun: true,
- fire() {
- function spawnFlechette(dir = mech.angle, speed, size = 1) {
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(dir), mech.pos.y + 40 * Math.sin(dir), 32 * size * b.modBulletSize, 0.8 * size * b.modBulletSize, b.fireAttributes(dir));
- bullet[me].endCycle = game.cycle + Math.floor(180 * b.isModBulletsLastLonger);
- bullet[me].dmg = 0.15 * size + b.modExtraDmg;
- b.drawOneBullet(bullet[me].vertices);
- bullet[me].do = function () {
- this.force.y += this.mass * 0.0002; //low gravity
- };
- Matter.Body.setVelocity(bullet[me], {
- x: mech.Vx / 2 + speed * Math.cos(dir),
- y: mech.Vy / 2 + speed * Math.sin(dir)
- });
- World.add(engine.world, bullet[me]); //add bullet to world
- }
-
- if (mech.crouch) {
- for (let i = 0; i < 3; i++) {
- spawnFlechette(mech.angle + 0.02 * (Math.random() - 0.5), 35 + 4 * i, 1.55)
- }
- } else {
- for (let i = 0; i < 9; i++) {
- spawnFlechette(mech.angle + 0.12 * (Math.random() - 0.5), 30 + 8 * Math.random())
- }
- }
- mech.fireCDcycle = mech.cycle + Math.floor(40 * b.modFireRate); // cool down
- }
- }, {
- name: "missiles", //7
- description: "fire a missile that accelerates towards nearby targets
explodes when near target",
- ammo: 0,
- ammoPack: 8,
- have: false,
- isStarterGun: false,
- fireCycle: 0,
- ammoLoaded: 0,
- fire() {
- const thrust = 0.0003;
- let dir = mech.angle + (0.5 - Math.random()) * (mech.crouch ? 0 : 0.2);
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle) - 3, 30 * b.modBulletSize, 4 * b.modBulletSize, b.fireAttributes(dir));
- b.fireProps(mech.crouch ? 70 : 30, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed
-
- b.drawOneBullet(bullet[me].vertices);
- // Matter.Body.setDensity(bullet[me], 0.01) //doesn't help with reducing explosion knock backs
- bullet[me].force.y += 0.00045; //a small push down at first to make it seem like the missile is briefly falling
- bullet[me].frictionAir = 0
- bullet[me].endCycle = game.cycle + Math.floor((265 + Math.random() * 20) * b.isModBulletsLastLonger);
- bullet[me].explodeRad = 170 + 60 * Math.random();
- bullet[me].lookFrequency = Math.floor(8 + Math.random() * 7);
- bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end
- bullet[me].onDmg = function () {
- this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
- };
- bullet[me].lockedOn = null;
- bullet[me].do = function () {
- if (!mech.isBodiesAsleep) {
- if (!(mech.cycle % this.lookFrequency)) {
- this.closestTarget = null;
- this.lockedOn = null;
- let closeDist = Infinity;
-
- //look for targets
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (
- mob[i].alive &&
- mob[i].dropPowerUp &&
- Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
- Matter.Query.ray(body, this.position, mob[i].position).length === 0
- ) {
- const dist = Matter.Vector.magnitude(Matter.Vector.sub(this.position, mob[i].position));
- if (dist < closeDist) {
- this.closestTarget = mob[i].position;
- closeDist = dist;
- this.lockedOn = mob[i];
- }
- }
- }
- //explode when bullet is close enough to target
- if (this.closestTarget && closeDist < this.explodeRad) {
- this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
- }
-
- if (this.lockedOn) {
- this.frictionAir = 0.04; //extra friction
-
- //draw locked on targeting
- ctx.beginPath();
- const vertices = this.lockedOn.vertices;
- ctx.moveTo(this.position.x, this.position.y);
- const mod = Math.floor((game.cycle / 3) % vertices.length);
- ctx.lineTo(vertices[mod].x, vertices[mod].y);
- ctx.strokeStyle = "rgba(0,0,155,0.35)"; //"#2f6";
- ctx.lineWidth = 1;
- ctx.stroke();
- }
- }
-
- //rotate missile towards the target
- if (this.closestTarget) {
- const face = {
- x: Math.cos(this.angle),
- y: Math.sin(this.angle)
- };
- const target = Matter.Vector.normalise(Matter.Vector.sub(this.position, this.closestTarget));
- if (Matter.Vector.dot(target, face) > -0.98) {
- if (Matter.Vector.cross(target, face) > 0) {
- Matter.Body.rotate(this, 0.08);
- } else {
- Matter.Body.rotate(this, -0.08);
- }
- }
- }
- //accelerate in direction bullet is facing
- const dir = this.angle; // + (Math.random() - 0.5);
- this.force.x += Math.cos(dir) * thrust;
- this.force.y += Math.sin(dir) * thrust;
-
- //draw rocket
- ctx.beginPath();
- ctx.arc(this.position.x - Math.cos(this.angle) * 27 + (Math.random() - 0.5) * 4, this.position.y - Math.sin(this.angle) * 27 + (Math.random() - 0.5) * 4, 11, 0, 2 * Math.PI);
- ctx.fillStyle = "rgba(255,155,0,0.5)";
- ctx.fill();
- } else {
- //draw rocket with time stop
- ctx.beginPath();
- ctx.arc(this.position.x - Math.cos(this.angle) * 27, this.position.y - Math.sin(this.angle) * 27, 11, 0, 2 * Math.PI);
- ctx.fillStyle = "rgba(255,155,0,0.5)";
- ctx.fill();
- }
- }
- }
- }, {
- name: "flak", //8
- description: "fire a cluster of short range projectiles
explode on contact or after half a second",
- ammo: 0,
- ammoPack: 20,
- have: false,
- isStarterGun: true,
- fire() {
- b.muzzleFlash(30);
- const totalBullets = 5
- const angleStep = (mech.crouch ? 0.06 : 0.15) / totalBullets
- const SPEED = mech.crouch ? 30 : 25
- const CD = mech.crouch ? 45 : 11
- const END = Math.floor((mech.crouch ? 30 : 18) * b.isModBulletsLastLonger);
- let dir = mech.angle - angleStep * totalBullets / 2;
- const side1 = 17 * b.modBulletSize
- const side2 = 4 * b.modBulletSize
-
- for (let i = 0; i < totalBullets; i++) { //5 -> 7
- dir += angleStep
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(mech.pos.x + 50 * Math.cos(mech.angle), mech.pos.y + 50 * Math.sin(mech.angle), side1, side2, b.fireAttributes(dir));
- b.fireProps(CD, SPEED + 15 * Math.random() - 2 * i, dir, me); //cd , speed
- // Matter.Body.setDensity(bullet[me], 0.005);
- bullet[me].endCycle = 2 * i + game.cycle + END
- bullet[me].restitution = 0;
- bullet[me].friction = 1;
- // bullet[me].dmg = 0.15;
- bullet[me].explodeRad = (mech.crouch ? 70 : 45) + (Math.random() - 0.5) * 50;
- bullet[me].onEnd = b.explode;
- bullet[me].onDmg = function () {
- this.endCycle = 0; //bullet ends cycle after hitting a mob and triggers explosion
- };
- bullet[me].do = function () {
- this.force.y += this.mass * 0.0004;
- // if (this.speed < 10) { //if slow explode
- // for (let i = 0, len = bullet.length; i < len; i++) {
- // bullet[i].endCycle = 0 //all other bullets explode
- // }
- // }
- }
- }
- }
- }, {
- name: "grenades", //9
- description: "fire a projectile that
explodes on contact or after one second",
- ammo: 0,
- ammoPack: 9,
- have: false,
- isStarterGun: true,
- fire() {
- const me = bullet.length;
- const dir = mech.angle; // + Math.random() * 0.05;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15 * b.modBulletSize, b.fireAttributes(dir, false));
- b.fireProps(mech.crouch ? 40 : 20, mech.crouch ? 43 : 32, dir, me); //cd , speed
- b.drawOneBullet(bullet[me].vertices);
- // Matter.Body.setDensity(bullet[me], 0.000001);
- bullet[me].totalCycles = 100;
- bullet[me].endCycle = game.cycle + Math.floor((mech.crouch ? 120 : 60) * b.isModBulletsLastLonger);
- bullet[me].restitution = 0.5;
- bullet[me].explodeRad = 210;
- bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
- bullet[me].minDmgSpeed = 1;
- bullet[me].onDmg = function () {
- this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
- };
- bullet[me].do = function () {
- //extra gravity for harder arcs
- this.force.y += this.mass * 0.002;
- };
- }
- }, {
- name: "vacuum bomb", //10
- description: "fire a huge
bomb that sucks before it
explodesclick left mouse
again to detonate",
- ammo: 0,
- ammoPack: 5,
- have: false,
- isStarterGun: false,
- fire() {
- const me = bullet.length;
- const dir = mech.angle;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 26 * b.modBulletSize, b.fireAttributes(dir, false));
- bullet[me].radius = 22; //used from drawing timer
- b.fireProps(10, mech.crouch ? 42 : 26, dir, me); //cd , speed
-
- b.drawOneBullet(bullet[me].vertices);
- bullet[me].endCycle = Infinity
- // bullet[me].restitution = 0.3;
- // bullet[me].frictionAir = 0.01;
- // bullet[me].friction = 0.15;
- bullet[me].inertia = Infinity; //prevents rotation
- bullet[me].restitution = 0;
- bullet[me].friction = 1;
-
- bullet[me].explodeRad = 380 + Math.floor(Math.random() * 60);
- bullet[me].onEnd = b.explode; //makes bullet do explosive damage before despawn
- bullet[me].onDmg = function () {
- // this.endCycle = 0; //bullet ends cycle after doing damage //this triggers explosion
- };
- bullet[me].isArmed = false;
- bullet[me].isSucking = false;
- bullet[me].do = function () {
- //extra gravity for harder arcs
- this.force.y += this.mass * 0.0022;
- mech.fireCDcycle = mech.cycle + 10 //can't fire until after the explosion
-
- //set armed and sucking status
- if (!this.isArmed && !game.mouseDown) {
- this.isArmed = true
- } else if (this.isArmed && game.mouseDown && !this.isSucking) {
- this.isSucking = true;
- this.endCycle = game.cycle + 35;
- }
-
- if (this.isSucking) {
- if (!mech.isBodiesAsleep) {
- const that = this
- let mag = 0.1
-
- function suck(who, radius = that.explodeRad * 2) {
- for (i = 0, len = who.length; i < len; i++) {
- const sub = Matter.Vector.sub(that.position, who[i].position);
- const dist = Matter.Vector.magnitude(sub);
- if (dist < radius && dist > 150) {
- knock = Matter.Vector.mult(Matter.Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
- who[i].force.x += knock.x;
- who[i].force.y += knock.y;
- }
- }
- }
- if (game.cycle > this.endCycle - 5) {
- mag = -0.22
- suck(body)
- suck(mob)
- suck(powerUp)
- suck(bullet)
- suck([player])
- } else {
- mag = 0.1
- suck(body)
- suck(mob)
- suck(powerUp)
- suck(bullet)
- suck([player])
- }
- //keep bomb in place
- Matter.Body.setVelocity(this, {
- x: 0,
- y: 0
- });
- //draw suck
- const radius = 2.5 * this.explodeRad * (this.endCycle - game.cycle) / 35
- ctx.fillStyle = "rgba(0,0,0,0.1)";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
- ctx.fill();
- }
- } else {
- // flashing lights to show armed
- if (!(game.cycle % 10)) {
- if (this.isFlashOn) {
- this.isFlashOn = false;
- } else {
- this.isFlashOn = true;
- }
- }
- if (this.isFlashOn) {
- ctx.fillStyle = "#000";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
- ctx.fill();
- //draw clock on timer
- ctx.fillStyle = "#f04";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.radius * 0.5, 0, 2 * Math.PI);
- ctx.fill();
- }
- }
- }
- }
- }, {
- name: "ferro frag", //11
- description: "fire a
grenade that ejects
magnetized nails
nails are
attracted to enemy targets",
- ammo: 0,
- ammoPack: 8,
- have: false,
- isStarterGun: false,
- fire() {
- const me = bullet.length;
- const dir = mech.angle;
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 15 * b.modBulletSize, b.fireAttributes(dir, false));
- b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 34 : 22, dir, me); //cd , speed
- b.drawOneBullet(bullet[me].vertices);
- bullet[me].endCycle = game.cycle + Math.floor(60 * b.isModBulletsLastLonger);
- bullet[me].restitution = 0.3;
- // bullet[me].frictionAir = 0.01;
- // bullet[me].friction = 0.15;
- // bullet[me].friction = 1;
- bullet[me].onEnd = () => {}
- bullet[me].do = function () {
- this.force.y += this.mass * 0.0018; //extra gravity for grenades
-
- if (game.cycle > this.endCycle - 1) {
- if (!mech.isBodiesAsleep) {
- //target nearby mobs
- const targets = []
- for (let i = 0, len = mob.length; i < len; i++) {
- const sub = Matter.Vector.sub(this.position, mob[i].position);
- const dist = Matter.Vector.magnitude(sub);
- if (dist < 1400 &&
- Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
- Matter.Query.ray(body, this.position, mob[i].position).length === 0) {
- targets.push(mob[i].position)
- }
- }
- for (let i = 0; i < 14; i++) {
- const SPEED = 35 + 20 * Math.random()
- if (targets.length > 0) { // aim near a random target
- const SPREAD = 100
- const INDEX = Math.floor(Math.random() * targets.length)
- const WHERE = {
- x: targets[INDEX].x + SPREAD * (Math.random() - 0.5),
- y: targets[INDEX].y + SPREAD * (Math.random() - 0.5)
- }
- needle(this.position, Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(WHERE, this.position)), SPEED))
- } else { // aim in random direction
- const ANGLE = 2 * Math.PI * Math.random()
- needle(this.position, {
- x: SPEED * Math.cos(ANGLE),
- y: SPEED * Math.sin(ANGLE)
- })
- }
-
- function needle(pos, velocity) {
- const me = bullet.length;
- bullet[me] = Bodies.rectangle(pos.x, pos.y, 23 * b.modBulletSize, 2 * b.modBulletSize, 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 + Math.floor(15 * Math.random());
- // bullet[me].dmg = 1.1+b.modExtraDmg;
- bullet[me].do = function () {};
- }
- }
- }
- }
- }
- }
- }, {
- name: "spores", //12
- description: "release an orb that discharges
spores after 2 seconds
seeks out targets
passes through blocks",
- ammo: 0,
- ammoPack: 5,
- have: false,
- isStarterGun: false,
- fire() {
- const me = bullet.length;
- const dir = mech.angle;
- bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, 4.5, b.fireAttributes(dir, false));
- b.fireProps(mech.crouch ? 75 : 55, mech.crouch ? 25 : 14, dir, me); //cd , speed
- b.drawOneBullet(bullet[me].vertices);
- Matter.Body.setDensity(bullet[me], 0.000001);
- bullet[me].endCycle = game.cycle + 100;
- bullet[me].frictionAir = 0;
- bullet[me].friction = 0.5;
- bullet[me].restitution = 0.3;
- bullet[me].minDmgSpeed = 0;
- bullet[me].onDmg = function () {};
- bullet[me].do = function () {
- if (!mech.isBodiesAsleep) {
- const SCALE = 1.017
- Matter.Body.scale(this, SCALE, SCALE);
- this.frictionAir += 0.00023;
- }
-
- this.force.y += this.mass * 0.00045;
-
- //draw green glow
- ctx.fillStyle = "rgba(0,200,125,0.16)";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, 26, 0, 2 * Math.PI);
- ctx.fill();
- };
-
- //spawn bullets on end
- bullet[me].onEnd = function () {
- const NUM = 9;
- for (let i = 0; i < NUM; i++) {
- const bIndex = bullet.length;
- const RADIUS = 3 * b.modBulletSize;
- bullet[bIndex] = Bodies.circle(this.position.x, this.position.y, RADIUS, {
- // density: 0.0015, //frictionAir: 0.01,
- inertia: Infinity,
- restitution: 0.5,
- angle: dir,
- friction: 0,
- frictionAir: 0.011,
- dmg: 1.8 + b.modExtraDmg, //damage done in addition to the damage from momentum
- classType: "bullet",
- collisionFilter: {
- category: 0x000100,
- mask: 0x000011 //no collide with body
- },
- endCycle: game.cycle + Math.floor((360 + Math.floor(Math.random() * 240)) * b.isModBulletsLastLonger),
- minDmgSpeed: 0,
- onDmg() {
- this.endCycle = 0; //bullet ends cycle after doing damage
- },
- onEnd() {},
- lookFrequency: 67 + Math.floor(47 * Math.random()),
- do() {
- //find mob targets
- if (!(game.cycle % this.lookFrequency)) {
- this.closestTarget = null;
- this.lockedOn = null;
- let closeDist = Infinity;
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
- // Matter.Query.ray(body, this.position, mob[i].position).length === 0
- const targetVector = Matter.Vector.sub(this.position, mob[i].position)
- const dist = Matter.Vector.magnitude(targetVector);
- if (dist < closeDist) {
- this.closestTarget = mob[i].position;
- closeDist = dist;
- this.lockedOn = Matter.Vector.normalise(targetVector);
- if (0.3 > Math.random()) break //doesn't always target the closest mob
- }
- }
- }
- }
- //accelerate towards mobs
- const THRUST = this.mass * 0.0009
- if (this.lockedOn) {
- this.force.x -= THRUST * this.lockedOn.x
- this.force.y -= THRUST * this.lockedOn.y
- } else {
- this.force.y += this.mass * 0.00025; //gravity
- }
- },
- });
- const SPEED = 9;
- const ANGLE = 2 * Math.PI * Math.random()
- Matter.Body.setVelocity(bullet[bIndex], {
- x: SPEED * Math.cos(ANGLE),
- y: SPEED * Math.sin(ANGLE)
- });
- World.add(engine.world, bullet[bIndex]); //add bullet to world
- }
- }
-
- }
- }, {
- name: "drones", //13
- description: "release
drones that seek out targets for 16 seconds
follows mouse if no targets are found",
- ammo: 0,
- ammoPack: 20,
- have: false,
- isStarterGun: true,
- fire() {
- const THRUST = 0.0015
- const dir = mech.angle + 0.2 * (Math.random() - 0.5);
- const me = bullet.length;
- const RADIUS = (4.5 + 3 * Math.random()) * b.modBulletSize
- bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS, {
- angle: dir,
- inertia: Infinity,
- friction: 0,
- frictionAir: 0.0005,
- restitution: 1,
- dmg: 0.14 + b.modExtraDmg, //damage done in addition to the damage from momentum
- lookFrequency: 79 + Math.floor(37 * Math.random()),
- endCycle: game.cycle + Math.floor((780 + 360 * Math.random()) * b.isModBulletsLastLonger),
- classType: "bullet",
- collisionFilter: {
- category: 0x000100,
- mask: 0x010111 //self collide
- },
- minDmgSpeed: 0,
- lockedOn: null,
- isFollowMouse: true,
- onDmg() {
- this.lockedOn = null
- },
- onEnd() {},
- do() {
- this.force.y += this.mass * 0.0002;
- //find mob targets
- if (!(game.cycle % this.lookFrequency)) {
- this.lockedOn = null;
- let closeDist = Infinity;
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (
- Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
- Matter.Query.ray(body, this.position, mob[i].position).length === 0
- ) {
- const TARGET_VECTOR = Matter.Vector.sub(this.position, mob[i].position)
- const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
- if (DIST < closeDist) {
- closeDist = DIST;
- this.lockedOn = mob[i]
- }
- }
- }
- if (!this.lockedOn) {
- //grab a power up if it is (ammo) or (a heal when player is low)
- let closeDist = Infinity;
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- if (
- ((powerUp[i].name !== "field" && powerUp[i].name !== "heal") || (powerUp[i].name === "heal" && mech.health < 0.8)) &&
- Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 &&
- Matter.Query.ray(body, this.position, powerUp[i].position).length === 0
- ) {
- const TARGET_VECTOR = Matter.Vector.sub(this.position, powerUp[i].position)
- const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
- if (DIST < closeDist) {
- if (DIST < 50) { //eat the power up if close enough
- powerUp[i].effect();
- Matter.World.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
- break;
- }
- closeDist = DIST;
- this.lockedOn = powerUp[i]
- }
- }
- }
- }
- }
- if (this.lockedOn) { //accelerate towards mobs
- this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST)
- } else { //accelerate towards mouse
- this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, game.mouseInGame)), -this.mass * THRUST)
- }
- // speed cap instead of friction to give more agility
- if (this.speed > 6) {
- Matter.Body.setVelocity(this, {
- x: this.velocity.x * 0.97,
- y: this.velocity.y * 0.97
- });
- }
- }
- })
- b.fireProps(mech.crouch ? 19 : 15, mech.crouch ? 35 : 1, dir, me); //cd , speed
- b.drawOneBullet(bullet[me].vertices);
- }
- }, {
- //draw a halo, since there will only be 1-3 balls
- name: "junk-bots", //14
- description: "release large
drones that defend the space around the player
despawn after not doing
damage for 3 seconds",
- ammo: 0,
- ammoPack: 20,
- have: false,
- isStarterGun: true,
- fire() {
- const THRUST = 0.004
- const dir = mech.angle + 0.2 * (Math.random() - 0.5);
- const me = bullet.length;
- const RADIUS = (18 + 5 * Math.random()) * b.modBulletSize
- const LENGTH = 0.6 + 0.8 * Math.random()
- bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), RADIUS * LENGTH, RADIUS / LENGTH, {
- isOrb: true,
- angle: dir,
- // inertia: Infinity,
- friction: 0,
- frictionAir: 0.06,
- restitution: 1,
- dmg: b.modExtraDmg, // 0.14 //damage done in addition to the damage from momentum
- minDmgSpeed: 2,
- lookFrequency: 37 + Math.floor(37 * Math.random()),
- endCycle: game.cycle + Math.floor((170 + 120 * Math.random()) * b.isModBulletsLastLonger),
- classType: "bullet",
- collisionFilter: {
- category: 0x000100,
- mask: 0x010111 //self, mob,map,body collide
- },
- range: 700,
- lockedOn: null,
- onDmg() {
- // this.endCycle = 0;
- this.lockedOn = null
- this.endCycle = game.cycle + Math.floor(180 * b.isModBulletsLastLonger)
- },
- onEnd() {},
- do() {
- if (!(game.cycle % this.lookFrequency)) {
- this.lockedOn = null;
- let closeDist = Infinity;
- for (let i = 0, len = mob.length; i < len; ++i) {
- const TARGET_VECTOR = Matter.Vector.sub(mech.pos, mob[i].position)
- const DIST = Matter.Vector.magnitude(TARGET_VECTOR);
- if (DIST < this.range && DIST < closeDist && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
- closeDist = DIST;
- this.lockedOn = mob[i]
- }
- }
- }
-
- const distanceToPlayer = Matter.Vector.magnitude(Matter.Vector.sub(this.position, mech.pos))
- if (this.lockedOn) { //accelerate towards mobs
- this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST)
- this.frictionAir = 0.06
- } else if (distanceToPlayer > 0.2 * this.range) {
- this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, mech.pos)), -this.mass * THRUST * 0.3)
- this.frictionAir = 0.02
- // // speed cap instead of friction to give more agility
- // if (this.speed > 14) {
- // Matter.Body.setVelocity(this, {
- // x: this.velocity.x * 0.97,
- // y: this.velocity.y * 0.97
- // });
- // }
- } else { //must be close to player //add some random motion
- this.frictionAir = 0
- }
- }
- })
- b.fireProps(mech.crouch ? 40 : 10, mech.crouch ? 40 : 10, dir, me); //cd , speed
- b.drawOneBullet(bullet[me].vertices);
- }
- }, ]
+ // const distanceToPlayer = Matter.Vector.magnitude(Matter.Vector.sub(this.position, mech.pos))
+ // if (this.lockedOn) { //accelerate towards mobs
+ // this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, this.lockedOn.position)), -this.mass * THRUST)
+ // this.frictionAir = 0.06
+ // } else if (distanceToPlayer > 100) {
+ // this.force = Matter.Vector.mult(Matter.Vector.normalise(Matter.Vector.sub(this.position, mech.pos)), -this.mass * THRUST * 0.3)
+ // this.frictionAir = 0.02
+ // } else { //must be close to player //add some random motion
+ // this.frictionAir = 0
+ // }
+ // }
+ // }
+ // })
+ // b.fireProps(mech.crouch ? 5 : 10, 15, dir, me); //cd , speed
+ // b.drawOneBullet(bullet[me].vertices);
+ // }
+ // },
+ ]
};
\ No newline at end of file
diff --git a/js/game.js b/js/game.js
index 919edeb..013de3e 100644
--- a/js/game.js
+++ b/js/game.js
@@ -608,7 +608,7 @@ const game = {
}
if (!(mech.cycle % 420)) {
- remove = function (who) {
+ fallCheck = function (who) {
let i = who.length;
while (i--) {
if (who[i].position.y > game.fallHeight) {
@@ -617,9 +617,9 @@ const game = {
}
}
};
- remove(mob);
- remove(body);
- remove(powerUp);
+ fallCheck(mob);
+ fallCheck(body);
+ fallCheck(powerUp);
}
},
testingOutput() {
diff --git a/js/index.js b/js/index.js
index 868c572..602df49 100644
--- a/js/index.js
+++ b/js/index.js
@@ -2,8 +2,15 @@
/* TODO: *******************************************
*****************************************************
-gun: Spirit Bomb
+gun: like drones, but fast moving and short lived
+ dies after doing damage
+
+gun: Spirit Bomb (singularity)
use charge up like rail gun
+ electricity graphics like plasma torch
+ suck in nearby mobs, power ups?, blocks?
+ sucked in stuff increase size
+ uses energy
left and right click mouse icons for text displays
@@ -17,7 +24,7 @@ mod: + move speed and jump height
this could just slow the mobs down instead?
how?
-rework junk bot, or remove it
+rework junk bot
it's behavior is too unpredictable
range is unclear
having the bullets last long after doing dmg isn't fun
diff --git a/js/level.js b/js/level.js
index da81052..2e31592 100644
--- a/js/level.js
+++ b/js/level.js
@@ -14,9 +14,9 @@ const level = {
start() {
if (level.levelsCleared === 0) {
// game.difficulty = 6; //for testing to simulate possible mobs spawns
- // b.giveGuns(1)
- // mech.fieldUpgrades[7].effect();
- b.giveMod(15)
+ // b.giveGuns(14)
+ // mech.fieldUpgrades[2].effect();
+ // b.giveMod(15)
// spawn.pickList = ["ghoster", "ghoster"]
this.intro(); //starting level
diff --git a/js/player.js b/js/player.js
index 548ce6c..3c56e39 100644
--- a/js/player.js
+++ b/js/player.js
@@ -65,12 +65,13 @@ const mech = {
},
defaultMass: 5,
mass: 5,
+ FxNotHolding: 0.015,
Fx: 0.015, //run Force on ground //this is reset in b.setModDefaults()
FxAir: 0.015, //run Force in Air
definePlayerMass(mass = mech.defaultMass) {
Matter.Body.setMass(player, mass);
//reduce air and ground move forces
- this.Fx = 0.075 / mass
+ this.Fx = 0.075 / mass * b.modSquirrelFx
this.FxAir = 0.375 / mass / mass
//make player stand a bit lower when holding heavy masses
this.yOffWhen.stand = Math.max(this.yOffWhen.crouch, Math.min(49, 49 - (mass - 5) * 6))
@@ -212,11 +213,10 @@ const mech = {
this.yOff = this.yOffWhen.jump;
this.hardLandCD = mech.cycle + Math.min(momentum / 6 - 6, 40)
- if (game.isBodyDamage && momentum > 200 && player.velocity.y > 20) { //falling damage
+ if (game.isBodyDamage && player.velocity.y > 26 && momentum > 165) { //falling damage
mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
- let dmg = Math.sqrt(momentum - 200) * 0.01
- console.log(dmg, momentum, player.velocity.y)
- dmg = Math.min(Math.max(dmg, 0.02), 0.15);
+ let dmg = Math.sqrt(momentum - 165) * 0.01
+ dmg = Math.min(Math.max(dmg, 0.02), 0.20);
mech.damage(dmg);
}
} else {
@@ -661,10 +661,6 @@ const mech = {
this.grabRange = 175;
this.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
this.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
- this.jumpForce = 0.38;
- this.Fx = 0.015; //run Force on ground
- this.FxAir = 0.015; //run Force in Air
- this.gravity = 0.0019;
mech.isBodiesAsleep = true;
mech.wakeCheck();
// this.phaseBlocks(0x011111)
diff --git a/js/powerups.js b/js/powerups.js
index 60549bb..c959fb3 100644
--- a/js/powerups.js
+++ b/js/powerups.js
@@ -9,7 +9,7 @@ const powerUps = {
},
effect() {
let heal = (this.size / 40) ** 2
- if (b.isModFullHeal) heal = Infinity
+ if (b.fullHeal) heal = Infinity
heal = Math.min(1 - mech.health, heal)
mech.addHealth(heal);
if (heal > 0) game.makeTextLog("
heal " + (heal * 100).toFixed(0) + "%", 300)
@@ -108,7 +108,7 @@ const powerUps = {
effect() {
//find what guns I don't have
let options = [];
- if (b.activeGun === null) {
+ if (b.activeGun === null && game.difficulty < 3) {
//choose the first gun to be one that is good for the early game
for (let i = 0; i < b.guns.length; ++i) {
if (!b.guns[i].have && b.guns[i].isStarterGun) options.push(i);