diff --git a/js/bullets.js b/js/bullets.js
index f452d18..e2c6880 100644
--- a/js/bullets.js
+++ b/js/bullets.js
@@ -18,7 +18,7 @@ const b = {
isModDroneOnDamage: null,
modExtraDmg: null,
annihilation: null,
- isModRecursiveHealing: null,
+ modRecursiveHealing: null,
modSquirrelFx: null,
isModCrit: null,
isModBayesian: null,
@@ -28,6 +28,7 @@ const b = {
isModMassEnergy: null,
isModFourOptions: null,
modGuardianCount: null,
+ modCollisionImmuneCycles: null,
setModDefaults() {
b.modCount = 0;
b.modFireRate = 1;
@@ -43,7 +44,7 @@ const b = {
b.modSpores = 0;
b.modExtraDmg = 0;
b.isModAnnihilation = false;
- b.isModRecursiveHealing = false;
+ b.modRecursiveHealing = 1;
b.modSquirrelFx = 1;
b.isModCrit = false;
b.isModBayesian = 0;
@@ -53,26 +54,23 @@ const b = {
b.isModEntanglement = false;
b.isModMassEnergy = false;
b.modGuardianCount = 0;
+ b.modCollisionImmuneCycles = 30;
mech.Fx = 0.015;
mech.jumpForce = 0.38;
- mech.throwChargeRate = 2;
- mech.throwChargeMax = 50;
mech.maxHealth = 1;
+ mech.fieldEnergyMax = 1;
for (let i = 0; i < b.mods.length; i++) {
b.mods[i].count = 0
}
},
mods: [{
name: "depleted uranium rounds",
- description: `your bullets are 11% larger
increased mass and physical damage`,
+ description: `your bullets are +11% larger
increased mass and physical damage`,
//0
count: 0,
maxCount: 4,
- value: 1.11,
effect() {
- b.modBulletSize *= this.value;
- this.value -= 0.01
- this.description = `your bullets are ${Math.floor((this.value-1)*100)}% larger
increased mass and physical damage`
+ b.modBulletSize += 0.11
}
},
{
@@ -118,7 +116,7 @@ const b = {
},
{
name: "auto-loading heuristics",
- description: "your delay after firing is 12% shorter",
+ description: "your delay after firing is +12% shorter",
//5
maxCount: 4,
count: 0,
@@ -138,7 +136,7 @@ const b = {
},
{
name: "Lorentzian topology",
- description: "your bullets last 33% longer",
+ description: "your bullets last +33% longer",
//7
maxCount: 4,
count: 0,
@@ -148,12 +146,12 @@ const b = {
},
{
name: "zoospore vector",
- description: "enemies can discharge spores on death
spores seek out enemies",
+ description: "enemies discharge spores on death
+11% chance",
//8
maxCount: 4,
count: 0,
effect() { //good late game maybe?
- b.modSpores += 0.15;
+ b.modSpores += 0.11;
}
},
{
@@ -166,10 +164,31 @@ const b = {
b.isModDroneOnDamage = true;
}
},
+ {
+ name: "guardian",
+ description: "a bot protects the space around you
uses a short range laser that drains energy",
+ //10
+ maxCount: 4,
+ count: 0,
+ effect() { // good with melee builds, content skipping builds
+ b.modGuardianCount++;
+ b.guardian();
+ }
+ },
+ {
+ name: "piezoelectric plating",
+ description: "immune to harm from collisions for +2 seconds
activates after being harmed from a collision",
+ //11
+ maxCount: 1,
+ count: 0,
+ effect() { // good with melee builds, content skipping builds
+ b.modCollisionImmuneCycles += 120;
+ }
+ },
{
name: "annihilation",
description: "after touching enemies, they are annihilated",
- //10
+ //12
maxCount: 1,
count: 0,
effect() { //good with mods that heal: superconductive healing, entropy transfer
@@ -178,8 +197,8 @@ const b = {
},
{
name: "high explosives",
- description: "the radius of explosions are 20% larger
immune to harm from explosions",
- //11
+ description: "the radius of explosions are +20% larger
immune to harm from explosions",
+ //13
maxCount: 4,
count: 0,
effect: () => {
@@ -190,7 +209,7 @@ const b = {
{
name: "entanglement",
description: "using your first gun reduces harm
scales by 7% for each gun in your inventory",
- //12
+ //14
maxCount: 1,
count: 0,
effect() { // good with laser-bots
@@ -200,7 +219,7 @@ const b = {
{
name: "energy transfer",
description: "gain energy proportional to damage done",
- //13
+ //15
maxCount: 4,
count: 0,
effect() { //good with laser, and all fields
@@ -210,7 +229,7 @@ const b = {
{
name: "entropy transfer",
description: "heal proportional to damage done",
- //14
+ //16
maxCount: 4,
count: 0,
effect() { //good with guns that overkill: one shot, grenade
@@ -219,8 +238,8 @@ const b = {
},
{
name: "overcharge",
- description: "charge energy 33% beyond your maximum",
- //15
+ description: "charge energy +33% beyond your maximum",
+ //17
maxCount: 4,
count: 0,
effect() {
@@ -229,8 +248,8 @@ const b = {
},
{
name: "supersaturation",
- description: "heal 33% beyond your max health",
- //16
+ description: "heal +33% beyond your max health",
+ //18
maxCount: 4,
count: 0,
effect() {
@@ -239,18 +258,18 @@ const b = {
},
{
name: "recursive healing",
- description: "healing power ups are twice as effective",
- //17
- maxCount: 1,
+ description: "healing power ups trigger an extra time.",
+ //19
+ maxCount: 4,
count: 0,
effect() { // good with ablative synthesis, melee builds
- b.isModRecursiveHealing = true
+ b.modRecursiveHealing += 1
}
},
{
name: "mass-energy equivalence",
description: "convert the mass of power ups into energy
power ups fill your energy and heal for +5%",
- //18
+ //20
maxCount: 1,
count: 0,
effect: () => {
@@ -260,7 +279,7 @@ const b = {
{
name: "+1 cardinality",
description: "one extra choice when selecting power ups",
- //19
+ //21
maxCount: 1,
count: 0,
effect: () => {
@@ -270,36 +289,25 @@ const b = {
{
name: "Bayesian inference",
description: "20% chance for double power ups to drop
one fewer choice when selecting power ups",
- //20
+ //22
maxCount: 1,
count: 0,
effect: () => {
b.isModBayesian = 0.20;
}
},
- {
- name: "Gauss rifle",
- description: "launch blocks at much higher speeds
hold onto larger blocks even after getting hit",
- //21
- maxCount: 1,
- count: 0,
- effect() { // good with guns that run out of ammo
- mech.throwChargeRate = 4;
- mech.throwChargeMax = 150;
- mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping
- }
- },
- {
- name: "guardian",
- description: "a bot protects the space around you
uses a short range laser that drains energy",
- //22
- maxCount: 4,
- count: 0,
- effect() { // good with melee builds, content skipping builds
- b.modGuardianCount++;
- b.guardian();
- }
- },
+ // {
+ // name: "Gauss rifle",
+ // description: "launch blocks at much higher speeds
hold onto larger blocks even after getting hit",
+ // //23
+ // maxCount: 1,
+ // count: 0,
+ // effect() { // good with guns that run out of ammo
+ // mech.throwChargeRate = 4;
+ // mech.throwChargeMax = 150;
+ // mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping
+ // }
+ // },
{
name: "squirrel-cage rotor",
description: "jump higher and move faster
reduced harm from falling ",
@@ -658,8 +666,8 @@ const b = {
},
spore(who) { //used with the mod upgrade in mob.death()
const bIndex = bullet.length;
- const RADIUS = 3 * b.modBulletSize;
- bullet[bIndex] = Bodies.circle(who.position.x, who.position.y, RADIUS, {
+ const side = 4 * b.modBulletSize;
+ bullet[bIndex] = Bodies.polygon(who.position.x, who.position.y, 5, side, {
// density: 0.0015, //frictionAir: 0.01,
inertia: Infinity,
restitution: 0.5,
@@ -672,7 +680,7 @@ const b = {
category: cat.bullet,
mask: cat.map | cat.mob | cat.mobBullet | cat.mobShield //no collide with body
},
- endCycle: game.cycle + Math.floor((480 + Math.floor(Math.random() * 240)) * b.isModBulletsLastLonger),
+ endCycle: game.cycle + Math.floor((660 + Math.floor(Math.random() * 240)) * b.isModBulletsLastLonger),
minDmgSpeed: 0,
onDmg() {
this.endCycle = 0; //bullet ends cycle after doing damage
@@ -706,7 +714,7 @@ const b = {
// this.force.x -= THRUST * this.lockedOn.x
// this.force.y -= THRUST * this.lockedOn.y
} else {
- this.force.y += this.mass * 0.00027; //gravity
+ this.force.y += this.mass * 0.0001; //gravity
}
},
});
@@ -821,7 +829,7 @@ const b = {
guardian(speed = 1) {
const me = bullet.length;
const dir = mech.angle;
- const RADIUS = (13 + 10 * Math.random()) * b.modBulletSize //(22 + 10 * Math.random()) * b.modBulletSize
+ const RADIUS = (14 + 6 * Math.random()) * b.modBulletSize
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 3, RADIUS, {
angle: dir,
friction: 0,
@@ -829,7 +837,7 @@ const b = {
restitution: 0.5 + 0.5 * Math.random(),
dmg: 0, // 0.14 //damage done in addition to the damage from momentum
minDmgSpeed: 2,
- lookFrequency: 37 + Math.floor(27 * Math.random()),
+ lookFrequency: 37 + Math.floor(17 * Math.random()),
acceleration: 0.0015 + 0.0013 * Math.random(),
range: 500 + Math.floor(200 * Math.random()),
endCycle: Infinity,
@@ -859,9 +867,9 @@ const b = {
}
if (this.lockedOn && this.lockedOn.alive && mech.fieldMeter > 0.15) { //hit target with laser
- mech.fieldMeter -= 0.001
+ mech.fieldMeter -= 0.0012
- //make sure you can still see target
+ //make sure you can still see vertex
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], this.lockedOn.position));
if (DIST - this.lockedOn.radius < this.range + 150 &&
Matter.Query.ray(map, this.vertices[0], this.lockedOn.position).length === 0 &&
@@ -876,7 +884,7 @@ const b = {
bestVertexDistance = dist
}
}
- const dmg = b.dmgScale * 0.03;
+ const dmg = b.dmgScale * 0.045;
this.lockedOn.damage(dmg);
this.lockedOn.locatePlayer();
@@ -912,7 +920,7 @@ const b = {
y: speed * Math.sin(dir)
});
},
- giveGuns(gun = "random", ammoPacks = 2) {
+ giveGuns(gun = "random", ammoPacks = 6) {
if (gun === "random") {
//find what guns player doesn't have
options = []
@@ -927,8 +935,9 @@ const b = {
b.activeGun = 0;
b.inventoryGun = 0;
for (let i = 0; i < b.guns.length; i++) {
- b.guns[i].ammo = b.guns[i].ammoPack * ammoPacks;
b.inventory[i] = i;
+ b.guns[i].have = true;
+ b.guns[i].ammo = b.guns[i].ammoPack * ammoPacks;
}
} else {
if (!b.guns[gun].have) b.inventory.push(gun);
@@ -942,7 +951,7 @@ const b = {
name: "minigun", //0
description: "rapidly fire a stream of small bullets",
ammo: 0,
- ammoPack: 150,
+ ammoPack: 50,
have: false,
isStarterGun: true,
fire() {
@@ -963,7 +972,7 @@ const b = {
name: "shotgun", //1
description: "fire a burst of short range bullets
crouch to reduce recoil",
ammo: 0,
- ammoPack: 10,
+ ammoPack: 4,
have: false,
isStarterGun: true,
fire() {
@@ -999,7 +1008,7 @@ const b = {
name: "super balls", //2
description: "fire five balls in a wide arc
balls bounce with no momentum loss",
ammo: 0,
- ammoPack: 12,
+ ammoPack: 4,
have: false,
isStarterGun: true,
fire() {
@@ -1034,7 +1043,7 @@ const b = {
name: "fléchettes", //3
description: "fire a volley of precise high velocity needles",
ammo: 0,
- ammoPack: 65,
+ ammoPack: 22,
have: false,
isStarterGun: true,
count: 0, //used to track how many shots are in a volley before a big CD
@@ -1071,7 +1080,7 @@ const b = {
name: "wave beam", //4
description: "emit a sine wave of oscillating particles
particles propagate through walls",
ammo: 0,
- ammoPack: 85,
+ ammoPack: 30,
have: false,
isStarterGun: true,
fire() {
@@ -1125,7 +1134,7 @@ const b = {
name: "rail gun", //5
description: "electro-magnetically launch a dense rod
hold left mouse to charge, release to fire", //and repel enemies
ammo: 0,
- ammoPack: 6,
+ ammoPack: 2,
have: false,
isStarterGun: false,
fire() {
@@ -1357,7 +1366,7 @@ const b = {
name: "missiles", //6
description: "fire missiles that accelerate towards enemies
explodes when near target",
ammo: 0,
- ammoPack: 8,
+ ammoPack: 3,
have: false,
isStarterGun: false,
fireCycle: 0,
@@ -1452,7 +1461,7 @@ const b = {
name: "flak", //7
description: "fire a cluster of short range projectiles
explodes on contact or after half a second",
ammo: 0,
- ammoPack: 14,
+ ammoPack: 5,
have: false,
isStarterGun: true,
fire() {
@@ -1493,7 +1502,7 @@ const b = {
name: "grenades", //8
description: "lob a single bouncy projectile
explodes on contact or after one second",
ammo: 0,
- ammoPack: 12,
+ ammoPack: 4,
have: false,
isStarterGun: false,
fire() {
@@ -1521,7 +1530,7 @@ const b = {
name: "vacuum bomb", //9
description: "fire a bomb that sucks before exploding
click left mouse again to detonate",
ammo: 0,
- ammoPack: 5,
+ ammoPack: 2,
have: false,
isStarterGun: false,
fire() {
@@ -1630,7 +1639,7 @@ const b = {
name: "ferro frag", //10
description: "fire a grenade that ejects nails
nails are magnetically attracted to enemies",
ammo: 0,
- ammoPack: 8,
+ ammoPack: 3,
have: false,
isStarterGun: false,
fire() {
@@ -1700,7 +1709,7 @@ const b = {
name: "spores", //11
description: "fire orbs that discharge spores
spores seek out enemies",
ammo: 0,
- ammoPack: 10,
+ ammoPack: 4,
have: false,
isStarterGun: false,
fire() {
@@ -1745,7 +1754,7 @@ const b = {
name: "drones", //12
description: "deploy drones that crash into enemies
collisions reduce drone cycles by 1 second",
ammo: 0,
- ammoPack: 17,
+ ammoPack: 6,
have: false,
isStarterGun: true,
fire() {
@@ -1853,302 +1862,18 @@ const b = {
// b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 50 : 15, dir, me); //cd , speed
// }
// },
- {
- name: "laser", //14
- description: "drain energy to emit a beam of coherent light
when crouched, initiate a fusion explosion",
- ammo: 0,
- ammoPack: Infinity,
- have: false,
- isStarterGun: true,
- fire() {
- if (mech.crouch) { //crouch fire mode
- //calculate laser collision
- let best;
- let 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;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
-
- //check for collisions
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- vertexCollision(path[0], path[1], mob);
- vertexCollision(path[0], path[1], map);
- vertexCollision(path[0], path[1], body);
- if (best.dist2 != Infinity) { //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
- }
-
- //use energy to explode
- const energy = 0.25 * Math.min(mech.fieldMeter, 1.5)
- mech.fieldMeter -= energy
- if (best.who) b.explosion(path[1], 900 * energy)
- mech.fireCDcycle = mech.cycle + Math.floor(65 * b.modFireRate); // cool down
-
- //draw laser beam
- ctx.beginPath();
- ctx.moveTo(path[0].x, path[0].y);
- ctx.lineTo(path[1].x, path[1].y);
- ctx.strokeStyle = "rgba(255,0,0,0.13)"
- ctx.lineWidth = 60 * energy / 0.2
- ctx.stroke();
- ctx.strokeStyle = "rgba(255,0,0,0.2)"
- ctx.lineWidth = 18
- ctx.stroke();
- ctx.strokeStyle = "#f00";
- ctx.lineWidth = 4
- ctx.stroke();
-
- //draw little dots along the laser path
- const sub = Vector.sub(path[1], path[0])
- const mag = Vector.magnitude(sub)
- for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
- const dist = Math.random()
- game.drawList.push({
- x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
- y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
- radius: 1 + 4 * Math.random(),
- color: "rgba(255,0,0,0.5)",
- time: Math.floor(2 + 33 * Math.random() * Math.random())
- });
- }
- } else { //normal fire mode
- const FIELD_DRAIN = 0.0018 //laser drains energy as well as bullets
- 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;
- 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 reflection = function () {
- // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
- const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
- const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
- const nn = Vector.mult(n, 2 * Vector.dot(d, n));
- const r = Vector.normalise(Vector.sub(d, nn));
- path[path.length] = Vector.add(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
- };
- 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();
- if (best.dist2 != Infinity) {
- //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
- laserHitMob(0.8);
-
- //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.63);
-
-
- 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.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.65; //reflections are less intense
- // ctx.globalAlpha -= 0.1; //reflections are less intense
- }
- ctx.setLineDash([0, 0]);
- ctx.globalAlpha = 1;
- }
- }
- }
- },
// {
// name: "laser", //14
- // description: "emit a beam of collimated coherent light
drains energy instead of ammunition",
+ // description: "drain energy to emit a beam of coherent light
when crouched, initiate a fusion explosion",
// ammo: 0,
// ammoPack: Infinity,
// have: false,
// isStarterGun: true,
// fire() {
- // const FIELD_DRAIN = 0.002 //laser drains energy as well as bullets
- // 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
+ // if (mech.crouch) { //crouch fire mode
+ // //calculate laser collision
// let best;
- // const color = "#f00";
- // const range = 3000;
+ // let range = 3000
// const path = [{
// x: mech.pos.x + 20 * Math.cos(mech.angle),
// y: mech.pos.y + 20 * Math.sin(mech.angle)
@@ -2198,54 +1923,153 @@ const b = {
// }
// }
// };
- // 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 = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
- // const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
- // const nn = Vector.mult(n, 2 * Vector.dot(d, n));
- // const r = Vector.normalise(Vector.sub(d, nn));
- // path[path.length] = Vector.add(Vector.mult(r, range), path[path.length - 1]);
+ // //check for collisions
+ // best = {
+ // x: null,
+ // y: null,
+ // dist2: Infinity,
+ // who: null,
+ // v1: null,
+ // v2: null
// };
- // //beam before reflection
- // checkForCollisions();
- // if (best.dist2 != Infinity) {
- // //if hitting something
+ // 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
// };
- // 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;
+ // //use energy to explode
+ // const energy = 0.25 * Math.min(mech.fieldMeter, 1.5)
+ // mech.fieldMeter -= energy
+ // if (best.who) b.explosion(path[1], 900 * energy)
+ // mech.fireCDcycle = mech.cycle + Math.floor(65 * b.modFireRate); // cool down
+
+ // //draw laser beam
+ // ctx.beginPath();
+ // ctx.moveTo(path[0].x, path[0].y);
+ // ctx.lineTo(path[1].x, path[1].y);
+ // ctx.strokeStyle = "rgba(255,0,0,0.13)"
+ // ctx.lineWidth = 60 * energy / 0.2
+ // ctx.stroke();
+ // ctx.strokeStyle = "rgba(255,0,0,0.2)"
+ // ctx.lineWidth = 18
+ // ctx.stroke();
+ // ctx.strokeStyle = "#f00";
+ // ctx.lineWidth = 4
+ // ctx.stroke();
+
+ // //draw little dots along the laser path
+ // const sub = Vector.sub(path[1], path[0])
+ // const mag = Vector.magnitude(sub)
+ // for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
+ // const dist = Math.random()
+ // game.drawList.push({
+ // x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
+ // y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
+ // radius: 1 + 4 * Math.random(),
+ // color: "rgba(255,0,0,0.5)",
+ // time: Math.floor(2 + 33 * Math.random() * Math.random())
+ // });
+ // }
+ // } else { //normal fire mode
+ // const FIELD_DRAIN = 0.0018 //laser drains energy as well as bullets
+ // 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;
+ // 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 reflection = function () {
+ // // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
+ // const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
+ // const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
+ // const nn = Vector.mult(n, 2 * Vector.dot(d, n));
+ // const r = Vector.normalise(Vector.sub(d, nn));
+ // path[path.length] = Vector.add(Vector.mult(r, range), path[path.length - 1]);
+ // };
+ // //beam before reflection
// checkForCollisions();
// if (best.dist2 != Infinity) {
// //if hitting something
@@ -2253,22 +2077,24 @@ const b = {
// x: best.x,
// y: best.y
// };
- // laserHitMob(0.8);
+ // 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.63);
-
+ // let who = best.who;
+ // checkForCollisions();
+ // if (best.dist2 != Infinity) {
+ // //if hitting something
+ // path[path.length - 1] = {
+ // x: best.x,
+ // y: best.y
+ // };
+ // laserHitMob(0.8);
+ // //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) {
@@ -2277,152 +2103,49 @@ const b = {
// x: best.x,
// y: best.y
// };
- // laserHitMob(0.5);
+ // laserHitMob(0.63);
+
+
+ // 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.65; //reflections are less intense
- // // ctx.globalAlpha -= 0.1; //reflections are less intense
- // }
- // ctx.setLineDash([0, 0]);
- // ctx.globalAlpha = 1;
- // }
- // }
- // },
- // {
- // name: "pulse", //15
- // description: "power a laser that initiates a fusion explosion
each pulse drains 25% of your current energy",
- // ammo: 0,
- // ammoPack: Infinity,
- // have: false,
- // isStarterGun: true,
- // fire() {
- // //calculate laser collision
- // let best;
- // let 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;
- // 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]
- // };
- // }
+ // 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.65; //reflections are less intense
+ // // ctx.globalAlpha -= 0.1; //reflections are less intense
// }
+ // ctx.setLineDash([0, 0]);
+ // ctx.globalAlpha = 1;
// }
- // };
-
- // //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
- // };
- // }
-
- // //use energy to explode
- // const energy = mech.fieldMeter * 0.25
- // mech.fieldMeter -= energy
- // if (best.who) b.explosion(path[1], 1300 * energy)
- // mech.fireCDcycle = mech.cycle + Math.floor(60 * b.modFireRate); // cool down
-
- // //draw laser beam
- // ctx.beginPath();
- // ctx.moveTo(path[0].x, path[0].y);
- // ctx.lineTo(path[1].x, path[1].y);
- // ctx.strokeStyle = "rgba(255,0,0,0.13)"
- // ctx.lineWidth = 60 * energy / 0.2
- // ctx.stroke();
- // ctx.strokeStyle = "rgba(255,0,0,0.2)"
- // ctx.lineWidth = 18
- // ctx.stroke();
- // ctx.strokeStyle = "#f00";
- // ctx.lineWidth = 4
- // ctx.stroke();
-
- // //draw little dots along the laser path
- // const sub = Vector.sub(path[1], path[0])
- // const mag = Vector.magnitude(sub)
- // for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
- // const dist = Math.random()
- // game.drawList.push({
- // x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
- // y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
- // radius: 1 + 4 * Math.random(),
- // color: "rgba(255,0,0,0.5)",
- // time: Math.floor(2 + 33 * Math.random() * Math.random())
- // });
// }
// }
// },
{
- name: "foam", //16
+ name: "foam", //13
description: "spray bubbly foam that sticks to enemies
does damage over time and slows movement",
ammo: 0,
- ammoPack: 100,
+ ammoPack: 35,
have: false,
isStarterGun: true,
fire() {
@@ -2432,7 +2155,7 @@ const b = {
const RADIUS = (8 + 16 * Math.random()) * b.modBulletSize
bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 25, RADIUS, {
angle: dir,
- density: 0.00001, // 0.001 is normal density
+ density: 0.00004, // 0.001 is normal density
inertia: Infinity,
frictionAir: 0.003,
friction: 0.2,
@@ -2512,6 +2235,292 @@ const b = {
});
}
},
+ {
+ name: "laser", //14
+ description: "emit a beam of collimated coherent light
drains energy instead of ammunition",
+ ammo: 0,
+ ammoPack: Infinity,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ const FIELD_DRAIN = 0.002 //laser drains energy as well as bullets
+ 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;
+ 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 reflection = function () {
+ // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
+ const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
+ const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
+ const nn = Vector.mult(n, 2 * Vector.dot(d, n));
+ const r = Vector.normalise(Vector.sub(d, nn));
+ path[path.length] = Vector.add(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
+ };
+ 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();
+ if (best.dist2 != Infinity) {
+ //if hitting something
+ path[path.length - 1] = {
+ x: best.x,
+ y: best.y
+ };
+ laserHitMob(0.8);
+
+ //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.63);
+
+
+ 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.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.65; //reflections are less intense
+ // ctx.globalAlpha -= 0.1; //reflections are less intense
+ }
+ ctx.setLineDash([0, 0]);
+ ctx.globalAlpha = 1;
+ }
+ }
+ },
+ {
+ name: "pulse", //15
+ description: "pump a laser that initiates a fusion explosion
each pulse drains 25% of your current energy",
+ ammo: 0,
+ ammoPack: Infinity,
+ have: false,
+ isStarterGun: true,
+ fire() {
+ //calculate laser collision
+ let best;
+ let 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;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[0],
+ v2: vertices[len]
+ };
+ }
+ }
+ }
+ };
+
+ //check for collisions
+ best = {
+ x: null,
+ y: null,
+ dist2: Infinity,
+ who: null,
+ v1: null,
+ v2: null
+ };
+ vertexCollision(path[0], path[1], mob);
+ vertexCollision(path[0], path[1], map);
+ vertexCollision(path[0], path[1], body);
+ if (best.dist2 != Infinity) { //if hitting something
+ path[path.length - 1] = {
+ x: best.x,
+ y: best.y
+ };
+ }
+
+ //use energy to explode
+ const energy = 0.25 * Math.min(mech.fieldMeter, 1.5)
+ mech.fieldMeter -= energy
+ if (best.who) b.explosion(path[1], 1200 * energy)
+ mech.fireCDcycle = mech.cycle + Math.floor(60 * b.modFireRate); // cool down
+
+ //draw laser beam
+ ctx.beginPath();
+ ctx.moveTo(path[0].x, path[0].y);
+ ctx.lineTo(path[1].x, path[1].y);
+ ctx.strokeStyle = "rgba(255,0,0,0.13)"
+ ctx.lineWidth = 60 * energy / 0.2
+ ctx.stroke();
+ ctx.strokeStyle = "rgba(255,0,0,0.2)"
+ ctx.lineWidth = 18
+ ctx.stroke();
+ ctx.strokeStyle = "#f00";
+ ctx.lineWidth = 4
+ ctx.stroke();
+
+ //draw little dots along the laser path
+ const sub = Vector.sub(path[1], path[0])
+ const mag = Vector.magnitude(sub)
+ for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
+ const dist = Math.random()
+ game.drawList.push({
+ x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
+ y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
+ radius: 1 + 4 * Math.random(),
+ color: "rgba(255,0,0,0.5)",
+ time: Math.floor(2 + 33 * Math.random() * Math.random())
+ });
+ }
+ }
+ },
// {
// name: "dwarf star", //14
// description: "drop a mine that gravitational pulls in matter",
diff --git a/js/engine.js b/js/engine.js
index a19c4b3..40cfbe5 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -79,7 +79,7 @@ function mobCollisionChecks(event) {
for (let i = 0, j = pairs.length; i != j; i++) {
//body + player collision
- if (game.isBodyDamage && mech.damageImmune < mech.cycle) {
+ if (game.isBodyDamage) {
if (pairs[i].bodyA === playerBody || pairs[i].bodyA === playerHead) {
collidePlayer(pairs[i].bodyB)
} else if (pairs[i].bodyB === playerBody || pairs[i].bodyB === playerHead) {
@@ -91,7 +91,6 @@ function mobCollisionChecks(event) {
if (obj.classType === "body" && obj.speed > speedThreshold && obj.mass > massThreshold) { //dmg from hitting a body
const v = Vector.magnitude(Vector.sub(player.velocity, obj.velocity));
if (v > speedThreshold) {
- mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
let dmg = Math.sqrt((v - speedThreshold + 0.1) * (obj.mass - massThreshold)) * 0.01;
dmg = Math.min(Math.max(dmg, 0.02), 0.15);
mech.damage(dmg);
@@ -105,21 +104,6 @@ function mobCollisionChecks(event) {
return;
}
}
- // else if (obj.isStatic && player.speed > speedThreshold * 2) { //falling dmg / hitting map dmg
- // mech.damageImmune = mech.cycle + 30;
- // console.log(player.speed)
- // let dmg = Math.min(Math.max(player.speed * 0.001, 0.02), 0.2);
- // mech.damage(dmg);
- // game.drawList.push({
- // //add dmg to draw queue
- // x: pairs[i].activeContacts[0].vertex.x,
- // y: pairs[i].activeContacts[0].vertex.y,
- // radius: dmg * 500,
- // color: game.mobDmgColor,
- // time: game.drawTime
- // });
- // return;
- // }
}
//mob + (player,bullet,body) collisions
@@ -135,9 +119,9 @@ function mobCollisionChecks(event) {
function collideMob(obj) {
//player + mob collision
- if (obj === playerBody || obj === playerHead) {
- if (mech.damageImmune < mech.cycle) {
- mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
+ if (mech.collisionImmune < mech.cycle) {
+ if (obj === playerBody || obj === playerHead) {
+ mech.collisionImmune = mech.cycle + b.modCollisionImmuneCycles; //player is immune to collision damage for 30 cycles
mob[k].foundPlayer();
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * game.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
mech.damage(dmg);
@@ -163,23 +147,24 @@ function mobCollisionChecks(event) {
});
}
+ //extra kick between player and mob //this section would be better with forces but they don't work...
+ let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x + 8 * Math.cos(angle),
+ y: player.velocity.y + 8 * Math.sin(angle)
+ });
+ Matter.Body.setVelocity(mob[k], {
+ x: mob[k].velocity.x - 8 * Math.cos(angle),
+ y: mob[k].velocity.y - 8 * Math.sin(angle)
+ });
+ return;
}
- //extra kick between player and mob //this section would be better with forces but they don't work...
- let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
- Matter.Body.setVelocity(player, {
- x: player.velocity.x + 8 * Math.cos(angle),
- y: player.velocity.y + 8 * Math.sin(angle)
- });
- Matter.Body.setVelocity(mob[k], {
- x: mob[k].velocity.x - 8 * Math.cos(angle),
- y: mob[k].velocity.y - 8 * Math.sin(angle)
- });
- return;
}
//mob + bullet collisions
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) {
// const dmg = b.dmgScale * (obj.dmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)));
let dmg = b.dmgScale * (obj.dmg + b.modExtraDmg + 0.15 * obj.mass * Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity)))
+ if (mob[k].shield) dmg *= 0.3
if (b.isModCrit && !mob[k].seePlayer.recall) dmg *= 5
mob[k].foundPlayer();
mob[k].damage(dmg);
diff --git a/js/index.js b/js/index.js
index 6c9acdc..82515cd 100644
--- a/js/index.js
+++ b/js/index.js
@@ -2,11 +2,25 @@
/* TODO: *******************************************
*****************************************************
+mod: fields do damage on blocking
+ name: something about radiation?
+
+mod: do something at the end of each level
+ heal to full
+ should still be effected by the heal reduction at higher difficulty
+ give ammo to current gun
+ give goals/quests for each level
+ how to track goals?
+ take no damage
+ don't shoot
+
selection options for field to stay with current
custom mode grey out mods that are bad, like selection based mods
not important
+custom mode can't use recursive mods
+
field graphics too dark at high energy
not important
@@ -19,9 +33,10 @@ game setting for slower computers
fewer debris
fewer mobs
-mod: guardian
- recursive
- spawns at start of level
+mod: gain energy after taking damage
+ use piezoelectric name (already used)
+
+mod: ground stomp on enterLand()
mod: if you fire when out of ammo you gain 1 ammo pack at the cost of
10% max health
@@ -153,6 +168,7 @@ const build = {
list: [],
choosePowerUp(who, index, type) {
//check if matching a current power up
+ // if (type === "field" || type === "gun") {
for (let i = 0; i < build.list.length; i++) {
if (build.list[i].index === index && build.list[i].type === type) { //if already click, toggle off
build.list.splice(i, 1);
@@ -160,7 +176,6 @@ const build = {
return
}
}
-
//check if trying to get a second field
if (type === "field") {
for (let i = 0; i < build.list.length; i++) {
@@ -170,15 +185,47 @@ const build = {
}
}
}
+ // } else { //type is mod
+
+ // //count each mod type to check for recursion caps
+ // let counts = []
+ // for (let i = 0; i < build.list.length; i++) {
+ // if (build.list[i].type === "mod") {
+ // if (!counts[build.list[i].index]) {
+ // counts[build.list[i].index] = 1
+ // } else {
+ // counts[build.list[i].index] = counts[build.list[i].index] + 1
+ // }
+ // }
+ // }
+
+ // for (let i = 0; i < build.list.length; i++) {
+ // //if above max count, toggle off
+ // if (build.list[i].index === index && build.list[i].type === type &&
+ // counts[index] >= b.mods[index].maxCount) {
+ // //remove all versions of mod
+
+
+ // who.style.backgroundColor = "#fff"
+ // return
+ // }
+ // }
+ // }
if (build.list.length < 5) { //add to build array
who.style.backgroundColor = "#919ba8" //"#868f9a"
build.list[build.list.length] = {
who: who,
index: index,
- type: type
+ type: type,
}
}
+ console.log(build.list)
+ },
+ removeMod(index) {
+ for (let i = build.list.length - 1; i > -1; i--) {
+ if (build.list[i].type === "mod" && build.list[i].index === index) build.list.splice(i, 1);
+ }
},
startBuildRun() {
spawn.setSpawnList();
diff --git a/js/level.js b/js/level.js
index cea3deb..c7d0c3a 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(0)
- // mech.setField(2)
- // b.giveMod(20)
+ // b.giveGuns(15)
+ // mech.setField(3)
+ // b.giveMod(10);
level.intro(); //starting level
// level.testingMap();
@@ -114,7 +114,7 @@ const level = {
// spawn.lineBoss(-500, -600, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
// spawn.bodyRect(-135, -50, 50, 50);
// spawn.bodyRect(-140, -100, 50, 50);
- powerUps.spawn(420, -400, "field", false);
+ powerUps.spawn(420, -400, "gun", false);
// powerUps.spawn(420, -400, "field", false);
// powerUps.spawn(420, -400, "field", false);
// powerUps.spawn(420, -400, "field", false);
diff --git a/js/mobs.js b/js/mobs.js
index dfe9319..3d3f034 100644
--- a/js/mobs.js
+++ b/js/mobs.js
@@ -961,7 +961,7 @@ const mobs = {
if (this.dropPowerUp) {
powerUps.spawnRandomPowerUp(this.position.x, this.position.y, this.mass, radius);
if (Math.random() < b.modSpores) {
- for (let i = 0, len = Math.floor(3 + this.mass * Math.random()); i < len; i++) {
+ for (let i = 0, len = Math.floor(4 + this.mass * Math.random()); i < len; i++) {
b.spore(this) //spawn drone
}
}
diff --git a/js/player.js b/js/player.js
index 2a8aa13..69ab13b 100644
--- a/js/player.js
+++ b/js/player.js
@@ -55,7 +55,7 @@ const mech = {
cycle: 0,
width: 50,
radius: 30,
- fillColor: "#fff",
+ fillColor: "#fff", //changed by mod piezoelectric plating (damage immunity)
fillColorDark: "#ccc",
height: 42,
yOffWhen: {
@@ -207,7 +207,6 @@ const mech = {
mech.hardLandCD = mech.cycle + Math.min(momentum / 6 - 6, 40)
if (game.isBodyDamage && player.velocity.y > 26 && momentum > 165 * b.modSquirrelFx) { //falling damage
- mech.damageImmune = mech.cycle + 30; //player is immune to collision damage for 30 cycles
let dmg = Math.sqrt(momentum - 165) * 0.01
dmg = Math.min(Math.max(dmg, 0.02), 0.20);
mech.damage(dmg);
@@ -440,6 +439,7 @@ const mech = {
mech.displayHealth();
},
defaultFPSCycle: 0, //tracks when to return to normal fps
+ collisionImmune: 0, //used in engine
damage(dmg) {
if (b.isModEntanglement && b.inventory[0] === b.activeGun) {
for (let i = 0, len = b.inventory.length; i < len; i++) {
@@ -513,7 +513,6 @@ const mech = {
// };
// requestAnimationFrame(normalFPS);
},
- damageImmune: 0,
hitMob(i, dmg) {
//prevents damage happening too quick
},
@@ -588,11 +587,13 @@ const mech = {
mech.knee.y = (l / d) * (mech.foot.y - mech.hip.y) + (h / d) * (mech.foot.x - mech.hip.x) + mech.hip.y;
},
draw() {
+ // mech.fillColor = (mech.collisionImmune < mech.cycle) ? "#fff" : "rgba(255,255,255,0.1)" //"#cff"
ctx.fillStyle = mech.fillColor;
mech.walk_cycle += mech.flipLegs * mech.Vx;
//draw body
ctx.save();
+ ctx.globalAlpha = (mech.collisionImmune < mech.cycle) ? 1 : 0.7
ctx.translate(mech.pos.x, mech.pos.y);
mech.calcLeg(Math.PI, -3);
mech.drawLeg("#4a4a4a");
@@ -654,8 +655,10 @@ const mech = {
mech.fieldCDcycle = 0;
mech.isStealth = false;
player.collisionFilter.mask = cat.body | cat.map | cat.mob | cat.mobBullet | cat.mobShield
- mech.holdingMassScale = 0.5;
mech.fieldShieldingScale = 1; //scale energy loss after collision with mob
+ mech.holdingMassScale = 0.5;
+ mech.throwChargeRate = 2;
+ mech.throwChargeMax = 50;
mech.grabRange = 175;
mech.fieldArc = 0.2; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
mech.calculateFieldThreshold(); //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
@@ -1311,9 +1314,12 @@ const mech = {
},
{
name: "negative mass field",
- description: "use energy to nullify gravity
can fire bullets while active",
+ description: "use energy to nullify gravity
launch larger blocks at much higher speeds",
effect: () => {
mech.fieldFire = true;
+ mech.throwChargeRate = 4;
+ mech.throwChargeMax = 150;
+ mech.holdingMassScale = 0.05; //can hold heavier blocks with lower cost to jumping
mech.hold = function () {
if (mech.isHolding) {
@@ -1321,11 +1327,11 @@ const mech = {
mech.holding();
mech.throwBlock();
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
- const DRAIN = 0.0004
+ const DRAIN = 0.00025
if (mech.fieldMeter > DRAIN) {
mech.grabPowerUp();
- mech.lookForPickUp(170);
- mech.pushMobs360(200);
+ mech.lookForPickUp(150);
+ mech.pushMobs360(150);
//look for nearby objects to make zero-g
function zeroG(who, mag = 1.06) {
for (let i = 0, len = who.length; i < len; ++i) {
@@ -1339,22 +1345,17 @@ const mech = {
// zeroG(bullet); //works fine, but not that noticeable and maybe not worth the possible performance hit
// zeroG(mob); //mobs are too irregular to make this work?
- Matter.Body.setVelocity(player, {
- x: player.velocity.x,
- y: player.velocity.y * 0.97
- });
-
if (keys[83] || keys[40]) { //down
- player.force.y -= 0.8 * player.mass * mech.gravity;
+ player.force.y -= 0.5 * player.mass * mech.gravity;
mech.grabRange = mech.grabRange * 0.97 + 400 * 0.03;
- zeroG(powerUp, 0.85);
- zeroG(body, 0.85);
+ zeroG(powerUp, 0.7);
+ zeroG(body, 0.7);
} else if (keys[87] || keys[38]) { //up
mech.fieldMeter -= 5 * DRAIN;
- mech.grabRange = mech.grabRange * 0.97 + 750 * 0.03;
- player.force.y -= 1.2 * player.mass * mech.gravity;
- zeroG(powerUp, 1.13);
- zeroG(body, 1.13);
+ mech.grabRange = mech.grabRange * 0.97 + 850 * 0.03;
+ player.force.y -= 1.45 * player.mass * mech.gravity;
+ zeroG(powerUp, 1.38);
+ zeroG(body, 1.38);
} else {
mech.fieldMeter -= DRAIN;
mech.grabRange = mech.grabRange * 0.97 + 650 * 0.03;
@@ -1366,8 +1367,13 @@ const mech = {
//add extra friction for horizontal motion
if (keys[65] || keys[68] || keys[37] || keys[39]) {
Matter.Body.setVelocity(player, {
- x: player.velocity.x * 0.85,
- y: player.velocity.y
+ x: player.velocity.x * 0.95,
+ y: player.velocity.y * 0.97
+ });
+ } else { //slow rise and fall
+ Matter.Body.setVelocity(player, {
+ x: player.velocity.x,
+ y: player.velocity.y * 0.97
});
}
@@ -1443,7 +1449,7 @@ const mech = {
mech.hold = function () {
if (mech.fieldMeter > mech.fieldEnergyMax - 0.02 && mech.fieldCDcycle < mech.cycle) {
mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
- mech.fieldMeter -= 0.32;
+ mech.fieldMeter -= 0.35;
b.drone(1)
}
if (mech.isHolding) {
diff --git a/js/powerups.js b/js/powerups.js
index 7c7bc24..09cfeac 100644
--- a/js/powerups.js
+++ b/js/powerups.js
@@ -22,6 +22,14 @@ const powerUps = {
game.isChoosing = false; //stops p from un pausing on key down
requestAnimationFrame(cycle);
},
+ cancel() {
+ document.body.style.cursor = "none";
+ document.getElementById("choose-grid").style.display = "none"
+ document.getElementById("choose-background").style.display = "none"
+ game.paused = false;
+ game.isChoosing = false; //stops p from un pausing on key down
+ requestAnimationFrame(cycle);
+ },
showDraft() {
document.getElementById("choose-grid").style.display = "grid"
document.getElementById("choose-background").style.display = "inline"
@@ -36,11 +44,10 @@ const powerUps = {
return 40 * Math.sqrt(0.1 + Math.random() * 0.5);
},
effect() {
- let heal = ((this.size / 40) ** 2)
- heal = Math.min(mech.maxHealth - mech.health, heal)
- if (b.isModRecursiveHealing) heal *= 2
+ let heal = 0
+ for (let i = 0; i < b.modRecursiveHealing; i++) heal += ((this.size / 40) ** 2)
+ if (heal > 0) game.makeTextLog("