shield rebalance, difficulty rebalance, piezo and static mods

This commit is contained in:
landgreen
2020-01-05 17:31:30 -08:00
parent 42b2cde9a2
commit 7ef99c13e9
9 changed files with 278 additions and 333 deletions

View File

@@ -29,6 +29,8 @@ const b = {
isModFourOptions: null, isModFourOptions: null,
modGuardianCount: null, modGuardianCount: null,
modCollisionImmuneCycles: null, modCollisionImmuneCycles: null,
modBlockDmg: null,
modPiezo: null,
setModDefaults() { setModDefaults() {
b.modCount = 0; b.modCount = 0;
b.modFireRate = 1; b.modFireRate = 1;
@@ -55,6 +57,8 @@ const b = {
b.isModMassEnergy = false; b.isModMassEnergy = false;
b.modGuardianCount = 0; b.modGuardianCount = 0;
b.modCollisionImmuneCycles = 30; b.modCollisionImmuneCycles = 30;
b.modBlockDmg = 0;
b.modPiezo = 0;
mech.Fx = 0.015; mech.Fx = 0.015;
mech.jumpForce = 0.38; mech.jumpForce = 0.38;
mech.maxHealth = 1; mech.maxHealth = 1;
@@ -64,9 +68,8 @@ const b = {
} }
}, },
mods: [{ mods: [{
name: "depleted uranium rounds", name: "depleted uranium rounds", //0
description: `your <strong>bullets</strong> are +11% larger<br>increased mass and physical <strong class='color-d'>damage</strong>`, description: `your <strong>bullets</strong> are +11% larger<br>increased mass and physical <strong class='color-d'>damage</strong>`,
//0
count: 0, count: 0,
maxCount: 4, maxCount: 4,
effect() { effect() {
@@ -74,131 +77,127 @@ const b = {
} }
}, },
{ {
name: "fluoroantimonic acid", name: "fluoroantimonic acid", //1
description: "each <strong>bullet</strong> does extra chemical <strong class='color-d'>damage</strong><br>instant damage, unaffected by momentum", description: "each <strong>bullet</strong> does extra chemical <strong class='color-d'>damage</strong><br>instant damage, unaffected by momentum",
//1
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good with guns that fire many bullets at low speeds, minigun, drones, junk-bots, shotgun, superballs, wavebeam effect() {
b.modExtraDmg += 0.25 b.modExtraDmg += 0.25
game.playerDmgColor = "rgba(0,80,80,0.9)" game.playerDmgColor = "rgba(0,80,80,0.9)"
} }
}, },
{ {
name: "fracture analysis", name: "fracture analysis", //2
description: "<strong>5x</strong> physical <strong class='color-d'>damage</strong> to unaware enemies<br><em>unaware enemies don't have a health bar</em>", description: "<strong>5x</strong> physical <strong class='color-d'>damage</strong> to unaware enemies<br><em>unaware enemies don't have a health bar</em>",
//2
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with high damage guns that strike from a distance: rail gun, drones, flechettes, spores, grenade, vacuum bomb effect() {
b.isModCrit = true; b.isModCrit = true;
} }
}, },
{ {
name: "kinetic bombardment", name: "kinetic bombardment", //3
description: "do extra <strong class='color-d'>damage</strong> from a distance<br><em>up to 50% increase at about 30 steps away</em>", description: "do extra <strong class='color-d'>damage</strong> from a distance<br><em>up to 50% increase at about 30 steps away</em>",
//3
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with annihilation, melee builds effect() {
b.isModFarAwayDmg = true; //used in mob.damage() b.isModFarAwayDmg = true; //used in mob.damage()
} }
}, },
{ {
name: "quasistatic equilibrium", name: "quasistatic equilibrium", //4
description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to 50% increase when near death</em>", description: "do extra <strong class='color-d'>damage</strong> at low health<br><em>up to 50% increase when near death</em>",
//4
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with annihilation, melee builds effect() {
b.isModLowHealthDmg = true; //used in mob.damage() b.isModLowHealthDmg = true; //used in mob.damage()
} }
}, },
{ {
name: "auto-loading heuristics", name: "auto-loading heuristics", //5
description: "your <strong>delay</strong> after firing is +12% <strong>shorter</strong>", description: "your <strong>delay</strong> after firing is +12% <strong>shorter</strong>",
//5
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls effect() {
b.modFireRate *= 0.88 b.modFireRate *= 0.88
} }
}, },
{ {
name: "desublimated ammunition", name: "desublimated ammunition", //6
description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>", description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>",
//6
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray effect() {
b.modNoAmmo = 1 b.modNoAmmo = 1
} }
}, },
{ {
name: "Lorentzian topology", name: "Lorentzian topology", //7
description: "your <strong>bullets</strong> last +33% <strong>longer</strong>", description: "your <strong>bullets</strong> last +33% <strong>longer</strong>",
//7
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range) effect() {
b.isModBulletsLastLonger += 0.33 b.isModBulletsLastLonger += 0.33
} }
}, },
{ {
name: "zoospore vector", name: "zoospore vector", //8
description: "enemies discharge <strong style='letter-spacing: 2px;'>spores</strong> on <strong>death</strong><br>+11% chance", description: "enemies discharge <strong style='letter-spacing: 2px;'>spores</strong> on <strong>death</strong><br>+11% chance",
//8
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good late game maybe? effect() {
b.modSpores += 0.11; b.modSpores += 0.11;
} }
}, },
{ {
name: "ablative synthesis", name: "ablative synthesis", //9
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after being <strong>harmed</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after being <strong>harmed</strong>",
//9
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { //makes dangerous situations more survivable effect() {
b.isModDroneOnDamage = true; b.isModDroneOnDamage = true;
} }
}, },
{ {
name: "guardian", name: "guardian", //10
description: "a bot <strong>protects</strong> the space around you<br>uses a <strong>short range</strong> laser that drains <strong class='color-f'>energy</strong>", description: "a bot <strong>protects</strong> the space around you<br>uses a <strong>short range</strong> laser that drains <strong class='color-f'>energy</strong>",
//10
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { // good with melee builds, content skipping builds effect() {
b.modGuardianCount++; b.modGuardianCount++;
b.guardian(); b.guardian();
} }
}, },
{ {
name: "piezoelectric plating", name: "electrostatic repulsion", //11
description: "<strong>immune</strong> to harm from <strong>collisions</strong> for +2 seconds<br>activates after being <strong>harmed</strong> from a collision", description: "<strong>immune</strong> to harm from <strong>collisions</strong> for +2 seconds<br>activates after being <strong>harmed</strong> from a collision",
//11
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with melee builds, content skipping builds effect() {
b.modCollisionImmuneCycles += 120; b.modCollisionImmuneCycles += 120;
} }
}, },
{ {
name: "annihilation", name: "bremsstrahlung radiation", //12
description: "when your <strong>field blocks</strong> it also does <strong class='color-d'>damage</strong>",
maxCount: 4,
count: 0,
effect() {
b.modBlockDmg += 0.7
}
},
{
name: "annihilation", //13
description: "after <strong>touching</strong> enemies, they are annihilated", description: "after <strong>touching</strong> enemies, they are annihilated",
//12
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { //good with mods that heal: superconductive healing, entropy transfer effect() {
b.isModAnnihilation = true b.isModAnnihilation = true
} }
}, },
{ {
name: "high explosives", name: "high explosives", //14
description: "the radius of <strong class='color-e'>explosions</strong> are +20% <strong>larger</strong><br>immune to <strong>harm</strong> from <strong class='color-e'>explosions</strong>", description: "the radius of <strong class='color-e'>explosions</strong> are +20% <strong>larger</strong><br>immune to <strong>harm</strong> from <strong class='color-e'>explosions</strong>",
//13
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect: () => { effect: () => {
@@ -207,39 +206,44 @@ const b = {
} }
}, },
{ {
name: "entanglement", name: "entanglement", //15
description: "using your first gun reduces <strong>harm</strong><br>scales by <strong>7%</strong> for each gun in your inventory", description: "using your first gun reduces <strong>harm</strong><br>scales by <strong>7%</strong> for each gun in your inventory",
//14
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with laser-bots effect() {
b.isModEntanglement = true b.isModEntanglement = true
} }
}, },
{ {
name: "energy transfer", name: "piezoelectricity", //16
description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done", description: "gain <strong class='color-f'>energy</strong> proportional to <strong>harm</strong> received",
//15
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good with laser, and all fields effect() {
b.modPiezo += 2
}
},
{
name: "energy conservation", //17
description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done",
maxCount: 4,
count: 0,
effect() {
b.modEnergySiphon += 0.18; b.modEnergySiphon += 0.18;
} }
}, },
{ {
name: "entropy transfer", name: "entropy exchange", //18
description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done", description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done",
//16
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { //good with guns that overkill: one shot, grenade effect() {
b.modHealthDrain += 0.015; b.modHealthDrain += 0.015;
} }
}, },
{ {
name: "overcharge", name: "overcharge", //19
description: "charge <strong class='color-f'>energy</strong> <strong>+33%</strong> beyond your <strong>maximum</strong>", description: "charge <strong class='color-f'>energy</strong> <strong>+33%</strong> beyond your <strong>maximum</strong>",
//17
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { effect() {
@@ -247,9 +251,8 @@ const b = {
} }
}, },
{ {
name: "supersaturation", name: "supersaturation", //20
description: "<strong class='color-h'>heal</strong> <strong>+33%</strong> beyond your <strong>max health</strong>", description: "<strong class='color-h'>heal</strong> <strong>+33%</strong> beyond your <strong>max health</strong>",
//18
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { effect() {
@@ -257,19 +260,17 @@ const b = {
} }
}, },
{ {
name: "recursive healing", name: "recursive healing", //21
description: "<strong class='color-h'>healing</strong> power ups trigger an extra time.", description: "<strong class='color-h'>healing</strong> power ups trigger an extra time.",
//19
maxCount: 4, maxCount: 4,
count: 0, count: 0,
effect() { // good with ablative synthesis, melee builds effect() {
b.modRecursiveHealing += 1 b.modRecursiveHealing += 1
} }
}, },
{ {
name: "mass-energy equivalence", name: "mass-energy equivalence", //22
description: "convert the mass of <strong>power ups</strong> into <strong class='color-f'>energy</strong><br>power ups fill your <strong class='color-f'>energy</strong> and <strong class='color-h'>heal</strong> for +5%", description: "convert the mass of <strong>power ups</strong> into <strong class='color-f'>energy</strong><br>power ups fill your <strong class='color-f'>energy</strong> and <strong class='color-h'>heal</strong> for +5%",
//20
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect: () => { effect: () => {
@@ -277,9 +278,8 @@ const b = {
} }
}, },
{ {
name: "+1 cardinality", name: "+1 cardinality", //23
description: "one extra <strong>choice</strong> when selecting <strong>power ups</strong>", description: "one extra <strong>choice</strong> when selecting <strong>power ups</strong>",
//21
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect: () => { effect: () => {
@@ -287,31 +287,17 @@ const b = {
} }
}, },
{ {
name: "Bayesian inference", name: "Bayesian inference", //24
description: "<strong>20%</strong> chance for double <strong>power ups</strong> to drop<br>one fewer <strong>choice</strong> when selecting <strong>power ups</strong>", description: "<strong>20%</strong> chance for double <strong>power ups</strong> to drop<br>one fewer <strong>choice</strong> when selecting <strong>power ups</strong>",
//22
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect: () => { effect: () => {
b.isModBayesian = 0.20; b.isModBayesian = 0.20;
} }
}, },
// {
// name: "Gauss rifle",
// description: "<strong>launch blocks</strong> at much higher speeds<br><em>hold onto larger blocks even after getting hit</em>",
// //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", name: "squirrel-cage rotor", //25
description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ", description: "<strong>jump</strong> higher and <strong>move</strong> faster<br>reduced <strong>harm</strong> from <strong>falling</strong> ",
//23
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { // good with melee builds, content skipping builds effect() { // good with melee builds, content skipping builds
@@ -321,9 +307,8 @@ const b = {
} }
}, },
{ {
name: "quantum immortality", name: "quantum immortality", //26
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br><em>guns, ammo, and field are randomized</em>", description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br><em>guns, ammo, and field are randomized</em>",
//24
maxCount: 1, maxCount: 1,
count: 0, count: 0,
effect() { effect() {
@@ -488,7 +473,7 @@ const b = {
time: game.drawTime time: game.drawTime
}); });
let dist, sub, knock; let dist, sub, knock;
const dmg = b.dmgScale * radius * 0.009; let dmg = b.dmgScale * radius * 0.009;
const alertRange = 100 + radius * 2; //alert range const alertRange = 100 + radius * 2; //alert range
//add alert to draw queue //add alert to draw queue
@@ -549,20 +534,21 @@ const b = {
//mob damage and knock back with alert //mob damage and knock back with alert
let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive) { if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(where, mob[i].position); sub = Vector.sub(where, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius; dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) { if (dist < radius) {
if (mob[i].shield) dmg *= 3 //balancing explosion dmg to shields
mob[i].damage(dmg * damageScale); mob[i].damage(dmg * damageScale);
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 30); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50);
mob[i].force.x += knock.x; mob[i].force.x += knock.x;
mob[i].force.y += knock.y; mob[i].force.y += knock.y;
radius *= 0.93 //reduced range for each additional explosion target radius *= 0.93 //reduced range for each additional explosion target
damageScale *= 0.8 //reduced damage for each additional explosion target damageScale *= 0.8 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) { } else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 80);
mob[i].force.x += knock.x; mob[i].force.x += knock.x;
mob[i].force.y += knock.y; mob[i].force.y += knock.y;
} }
@@ -581,7 +567,7 @@ const b = {
time: game.drawTime time: game.drawTime
}); });
let dist, sub, knock; let dist, sub, knock;
const dmg = b.dmgScale * radius * 0.009; let dmg = b.dmgScale * radius * 0.009;
const alertRange = 100 + radius * 2; //alert range const alertRange = 100 + radius * 2; //alert range
//add alert to draw queue //add alert to draw queue
@@ -642,20 +628,21 @@ const b = {
//mob damage and knock back with alert //mob damage and knock back with alert
let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive) { if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(bullet[me].position, mob[i].position); sub = Vector.sub(bullet[me].position, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius; dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) { if (dist < radius) {
if (mob[i].shield) dmg *= 3 //balancing explosion dmg to shields
mob[i].damage(dmg * damageScale); mob[i].damage(dmg * damageScale);
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 30); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50);
mob[i].force.x += knock.x; mob[i].force.x += knock.x;
mob[i].force.y += knock.y; mob[i].force.y += knock.y;
radius *= 0.93 //reduced range for each additional explosion target radius *= 0.93 //reduced range for each additional explosion target
damageScale *= 0.8 //reduced damage for each additional explosion target damageScale *= 0.8 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) { } else if (!mob[i].seePlayer.recall && dist < alertRange) {
mob[i].locatePlayer(); mob[i].locatePlayer();
knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 50); knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) / 80);
mob[i].force.x += knock.x; mob[i].force.x += knock.x;
mob[i].force.y += knock.y; mob[i].force.y += knock.y;
} }
@@ -837,7 +824,7 @@ const b = {
restitution: 0.5 + 0.5 * Math.random(), restitution: 0.5 + 0.5 * Math.random(),
dmg: 0, // 0.14 //damage done in addition to the damage from momentum dmg: 0, // 0.14 //damage done in addition to the damage from momentum
minDmgSpeed: 2, minDmgSpeed: 2,
lookFrequency: 37 + Math.floor(17 * Math.random()), lookFrequency: 31 + Math.floor(17 * Math.random()),
acceleration: 0.0015 + 0.0013 * Math.random(), acceleration: 0.0015 + 0.0013 * Math.random(),
range: 500 + Math.floor(200 * Math.random()), range: 500 + Math.floor(200 * Math.random()),
endCycle: Infinity, endCycle: Infinity,
@@ -858,6 +845,7 @@ const b = {
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position)); const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position));
if (DIST - mob[i].radius < closeDist && if (DIST - mob[i].radius < closeDist &&
!mob[i].isShielded &&
Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 && Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) { Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) {
closeDist = DIST; closeDist = DIST;
@@ -951,17 +939,18 @@ const b = {
name: "minigun", //0 name: "minigun", //0
description: "rapidly fire a stream of small <strong>bullets</strong>", description: "rapidly fire a stream of small <strong>bullets</strong>",
ammo: 0, ammo: 0,
ammoPack: 50, ammoPack: 55,
have: false, have: false,
isStarterGun: true, isStarterGun: true,
fire() { fire() {
const me = bullet.length; const me = bullet.length;
b.muzzleFlash(15); b.muzzleFlash(15);
// if (Math.random() > 0.2) mobs.alert(500); // if (Math.random() > 0.2) mobs.alert(500);
const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.04 : 0.12); const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.03 : 0.1);
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)); bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20 * b.modBulletSize, 6 * b.modBulletSize, b.fireAttributes(dir));
b.fireProps(mech.crouch ? 10 : 5, mech.crouch ? 50 : 36, dir, me); //cd , speed b.fireProps(mech.crouch ? 8 : 4, mech.crouch ? 52 : 38, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + 65; bullet[me].endCycle = game.cycle + 70;
bullet[me].dmg = 0.07;
bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01; bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01;
bullet[me].do = function () { bullet[me].do = function () {
this.force.y += this.mass * 0.0005; this.force.y += this.mass * 0.0005;
@@ -972,7 +961,7 @@ const b = {
name: "shotgun", //1 name: "shotgun", //1
description: "fire a <strong>burst</strong> of short range bullets<br><em>crouch to reduce recoil</em>", description: "fire a <strong>burst</strong> of short range bullets<br><em>crouch to reduce recoil</em>",
ammo: 0, ammo: 0,
ammoPack: 4, ammoPack: 5,
have: false, have: false,
isStarterGun: true, isStarterGun: true,
fire() { fire() {
@@ -999,7 +988,7 @@ const b = {
} }
//knock back //knock back
const KNOCK = ((mech.crouch) ? 0.017 : 0.17) * b.modBulletSize * b.modBulletSize const KNOCK = ((mech.crouch) ? 0.013 : 0.15) * b.modBulletSize * b.modBulletSize
player.force.x -= KNOCK * Math.cos(mech.angle) 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 player.force.y -= KNOCK * Math.sin(mech.angle) * 0.3 //reduce knock back in vertical direction to stop super jumps
} }
@@ -1043,7 +1032,7 @@ const b = {
name: "fléchettes", //3 name: "fléchettes", //3
description: "fire a volley of <strong>precise</strong> high velocity needles", description: "fire a volley of <strong>precise</strong> high velocity needles",
ammo: 0, ammo: 0,
ammoPack: 22, ammoPack: 20,
have: false, have: false,
isStarterGun: true, isStarterGun: true,
count: 0, //used to track how many shots are in a volley before a big CD count: 0, //used to track how many shots are in a volley before a big CD
@@ -1095,7 +1084,7 @@ const b = {
inertia: Infinity, inertia: Infinity,
frictionAir: 0, frictionAir: 0,
minDmgSpeed: 0, minDmgSpeed: 0,
dmg: 0.13, //damage done in addition to the damage from momentum dmg: 0.2, //damage done in addition to the damage from momentum
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
category: cat.bullet, category: cat.bullet,
@@ -1134,7 +1123,7 @@ const b = {
name: "rail gun", //5 name: "rail gun", //5
description: "electro-magnetically launch a dense rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire", //and <strong>repel</strong> enemies description: "electro-magnetically launch a dense rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire", //and <strong>repel</strong> enemies
ammo: 0, ammo: 0,
ammoPack: 2, ammoPack: 1,
have: false, have: false,
isStarterGun: false, isStarterGun: false,
fire() { fire() {
@@ -1208,18 +1197,6 @@ const b = {
mob[i].force.y += 1.5 * FORCE.y; mob[i].force.y += 1.5 * FORCE.y;
} }
} }
//push mobs around player when firing
// range = 600 * this.charge
// for (let i = 0, len = mob.length; i < len; ++i) {
// const SUB = Vector.sub(mob[i].position, mech.pos)
// const DISTANCE = Vector.magnitude(SUB)
// if (DISTANCE < range) {
// const DEPTH = range - DISTANCE
// const FORCE = Vector.mult(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
// }
// }
} else { // charging on mouse down } else { // charging on mouse down
mech.fireCDcycle = Infinity //can't fire until mouse is released mech.fireCDcycle = Infinity //can't fire until mouse is released
if (mech.crouch) { if (mech.crouch) {
@@ -1227,25 +1204,6 @@ const b = {
} else { } else {
this.charge = this.charge * 0.985 + 0.015 // this.charge converges to 1 this.charge = this.charge * 0.985 + 0.015 // this.charge converges to 1
} }
//gently push away mobs while charging
// const RANGE = 270 * this.charge
// for (let i = 0, len = mob.length; i < len; ++i) {
// const SUB = Vector.sub(mob[i].position, mech.pos)
// const DISTANCE = Vector.magnitude(SUB)
// // if (DISTANCE < RANGE) {
// // Matter.Body.setVelocity(mob[i], Vector.rotate(mob[i].velocity, 0.1))
// // }
// // const DRAIN = 0.0002 //&& mech.fieldMeter > DRAIN
// if (DISTANCE < RANGE) {
// // mech.fieldMeter -= DRAIN + mech.fieldRegen;
// const DEPTH = RANGE - DISTANCE
// const FORCE = Vector.mult(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 //draw laser targeting
let best; let best;
let range = 3000 let range = 3000
@@ -1377,50 +1335,51 @@ const b = {
const me = bullet.length; 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)); 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 ? 55 : 30, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed b.fireProps(mech.crouch ? 55 : 30, -3 * (0.5 - Math.random()) + (mech.crouch ? 25 : -8), dir, me); //cd , speed
// bullet[me].collisionFilter.mask = cat.map | cat.body | cat.mobBullet
// Matter.Body.setDensity(bullet[me], 0.01) //doesn't help with reducing explosion knock backs // Matter.Body.setDensity(bullet[me], 0.01) //doesn't help with reducing explosion knock backs
bullet[me].force.y += 0.0005; //a small push down at first to make it seem like the missile is briefly falling bullet[me].force.y += 0.0005; //a small push down at first to make it seem like the missile is briefly falling
bullet[me].frictionAir = 0.023 bullet[me].frictionAir = 0.023
bullet[me].endCycle = game.cycle + Math.floor((280 + 40 * Math.random()) * b.isModBulletsLastLonger); bullet[me].endCycle = game.cycle + Math.floor((280 + 40 * Math.random()) * b.isModBulletsLastLonger);
bullet[me].explodeRad = 160 + 60 * Math.random(); bullet[me].explodeRad = 170 + 60 * Math.random();
bullet[me].lookFrequency = Math.floor(15 + Math.random() * 5); bullet[me].lookFrequency = Math.floor(31 + Math.random() * 11);
bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end
bullet[me].onDmg = function () { bullet[me].onDmg = function () {
this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion this.tryToLockOn();
// this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
}; };
bullet[me].lockedOn = null; bullet[me].lockedOn = null;
bullet[me].tryToLockOn = function () {
this.lockedOn = null;
let closeDist = Infinity;
//look for closest target to where the missile will be in 30 cycles
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30))
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 futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position));
if (futureDist < closeDist) {
closeDist = futureDist;
this.lockedOn = mob[i];
this.frictionAir = 0.05; //extra friction once a target it locked
}
}
}
//explode when bullet is close enough to target
if (this.lockedOn && Vector.magnitude(Vector.sub(this.position, this.lockedOn.position)) < this.explodeRad * 0.95) {
// console.log('hit')
this.endCycle = 0; //bullet ends cycle after doing damage //also triggers explosion
const dmg = b.dmgScale * 5;
this.lockedOn.damage(dmg); //does extra damage to target
}
};
bullet[me].do = function () { bullet[me].do = function () {
if (!mech.isBodiesAsleep) { if (!mech.isBodiesAsleep) {
if (!(mech.cycle % this.lookFrequency)) { if (!(mech.cycle % this.lookFrequency)) {
this.lockedOn = null; this.tryToLockOn();
let closeDist = Infinity;
//look for closest target to where the missile will be in 30 cycles
const futurePos = Vector.add(this.position, Vector.mult(this.velocity, 30))
// ctx.beginPath(); //draw future pos
// ctx.arc(futurePos.x, futurePos.y, 20, 0, 2 * Math.PI);
// ctx.fillStyle = "rgba(0,0,0,0.5)";
// ctx.fill();
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 futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position));
if (futureDist < closeDist) {
closeDist = futureDist;
this.lockedOn = mob[i];
this.frictionAir = 0.05; //extra friction once a target it locked
}
}
}
//explode when bullet is close enough to target
if (this.lockedOn && Vector.magnitude(Vector.sub(this.position, this.lockedOn.position)) < this.explodeRad * 0.7) {
this.endCycle = 0; //bullet ends cycle after doing damage //also triggers explosion
const dmg = b.dmgScale * 3;
this.lockedOn.damage(dmg); //does extra damage to target
}
} }
//rotate missile towards the target //rotate missile towards the target
@@ -1754,12 +1713,12 @@ const b = {
name: "drones", //12 name: "drones", //12
description: "deploy drones that <strong>crash</strong> into enemies<br>collisions reduce drone <strong>cycles</strong> by 1 second", description: "deploy drones that <strong>crash</strong> into enemies<br>collisions reduce drone <strong>cycles</strong> by 1 second",
ammo: 0, ammo: 0,
ammoPack: 6, ammoPack: 5,
have: false, have: false,
isStarterGun: true, isStarterGun: true,
fire() { fire() {
b.drone(mech.crouch ? 45 : 1) b.drone(mech.crouch ? 45 : 1)
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 10) * b.modFireRate); // cool down mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 25 : 5) * b.modFireRate); // cool down
} }
}, },
// { // {
@@ -2155,7 +2114,7 @@ const b = {
const RADIUS = (8 + 16 * Math.random()) * b.modBulletSize 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, { bullet[me] = Bodies.polygon(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 25, RADIUS, {
angle: dir, angle: dir,
density: 0.00004, // 0.001 is normal density density: 0.00005, // 0.001 is normal density
inertia: Infinity, inertia: Infinity,
frictionAir: 0.003, frictionAir: 0.003,
friction: 0.2, friction: 0.2,
@@ -2173,7 +2132,7 @@ const b = {
target: null, target: null,
targetVertex: null, targetVertex: null,
onDmg(who) { onDmg(who) {
if (!this.target && who.alive && who.dropPowerUp) { if (!this.target && who.alive && who.dropPowerUp && !who.isShielded) {
this.target = who; this.target = who;
this.collisionFilter.category = cat.body; this.collisionFilter.category = cat.body;
this.collisionFilter.mask = null; this.collisionFilter.mask = null;
@@ -2216,9 +2175,9 @@ const b = {
if (this.target && this.target.alive) { //if stuck to a target if (this.target && this.target.alive) { //if stuck to a target
Matter.Body.setPosition(this, this.target.vertices[this.targetVertex]) Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.94)) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9))
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.94) Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
this.target.damage(b.dmgScale * 0.0045); this.target.damage(b.dmgScale * 0.005);
} else if (this.target !== null) { //look for a new target } else if (this.target !== null) { //look for a new target
this.target = null this.target = null
this.collisionFilter.category = cat.bullet; this.collisionFilter.category = cat.bullet;
@@ -2301,6 +2260,7 @@ const b = {
} }
} }
}; };
const checkForCollisions = function () { const checkForCollisions = function () {
best = { best = {
x: null, x: null,

View File

@@ -126,7 +126,7 @@ function mobCollisionChecks(event) {
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 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); mech.damage(dmg);
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
if (b.isModAnnihilation && mob[k].dropPowerUp) { if (b.isModAnnihilation && mob[k].dropPowerUp && !mob[k].isShielded) {
mob[k].death(); mob[k].death();
game.drawList.push({ game.drawList.push({
//add dmg to draw queue //add dmg to draw queue
@@ -164,8 +164,7 @@ function mobCollisionChecks(event) {
if (obj.classType === "bullet" && obj.speed > obj.minDmgSpeed) { 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))); // 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))) 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 && !mob[k].shield) dmg *= 5
if (b.isModCrit && !mob[k].seePlayer.recall) dmg *= 5
mob[k].foundPlayer(); mob[k].foundPlayer();
mob[k].damage(dmg); mob[k].damage(dmg);
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn

View File

@@ -81,7 +81,8 @@ const game = {
isBodyDamage: true, isBodyDamage: true,
levelsCleared: 0, levelsCleared: 0,
difficultyMode: 1, difficultyMode: 1,
difficulty: 1, isEasyMode: false,
difficulty: 0,
dmgScale: null, //set in levels.setDifficulty dmgScale: null, //set in levels.setDifficulty
healScale: 1, healScale: 1,
accelScale: null, //set in levels.setDifficulty accelScale: null, //set in levels.setDifficulty
@@ -416,24 +417,6 @@ const game = {
}, },
wipe() { wipe() {
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
// ctx.fillStyle = "rgba(255,255,255,1)";
// ctx.globalCompositeOperation = "difference";
// ctx.fillRect(0, 0, canvas.width, canvas.height);
// ctx.globalCompositeOperation = "source-over";
// ctx.globalAlpha = (mech.health < 0.7) ? (mech.health+0.3)*(mech.health+0.3) : 1
// if (mech.health < 0.7) {
// ctx.globalAlpha= 0.3 + mech.health
// ctx.fillStyle = document.body.style.backgroundColor
// ctx.fillRect(0, 0, canvas.width, canvas.height);
// ctx.globalAlpha=1;
// } else {
// ctx.clearRect(0, 0, canvas.width, canvas.height);
// }
//ctx.fillStyle = "rgba(255,255,255," + (1 - Math.sqrt(player.speed)*0.1) + ")";
//ctx.fillStyle = "rgba(255,255,255,0.4)";
//ctx.fillRect(0, 0, canvas.width, canvas.height);
}, },
gravity() { gravity() {
function addGravity(bodies, magnitude) { function addGravity(bodies, magnitude) {
@@ -474,8 +457,10 @@ const game = {
game.accelScale = 1; game.accelScale = 1;
game.lookFreqScale = 1; game.lookFreqScale = 1;
game.CDScale = 1; game.CDScale = 1;
game.difficulty = 0;
game.difficultyMode = Number(document.getElementById("difficulty-select").value) game.difficultyMode = Number(document.getElementById("difficulty-select").value)
if (game.difficultyMode === 0) { if (game.difficultyMode === 0) {
game.isEasyMode = true;
game.difficultyMode = 1 game.difficultyMode = 1
level.difficultyDecrease(6); level.difficultyDecrease(6);
} }
@@ -693,7 +678,7 @@ const game = {
testingOutput() { testingOutput() {
ctx.textAlign = "right"; ctx.textAlign = "right";
ctx.fillStyle = "#000"; ctx.fillStyle = "#000";
let line = 140; let line = 500;
const x = canvas.width - 5; const x = canvas.width - 5;
ctx.fillText("T: exit testing mode", x, line); ctx.fillText("T: exit testing mode", x, line);
line += 20; line += 20;
@@ -712,38 +697,38 @@ const game = {
ctx.fillText("1-7: spawn things", x, line); ctx.fillText("1-7: spawn things", x, line);
line += 30; line += 30;
ctx.fillText("cycle: " + game.cycle, x, line); // ctx.fillText("cycle: " + game.cycle, x, line);
line += 20; // line += 20;
ctx.fillText("player cycle: " + mech.cycle, x, line); // ctx.fillText("player cycle: " + mech.cycle, x, line);
line += 20; // line += 20;
ctx.fillText("x: " + player.position.x.toFixed(0), x, line); // ctx.fillText("x: " + player.position.x.toFixed(0), x, line);
line += 20; // line += 20;
ctx.fillText("y: " + player.position.y.toFixed(0), x, line); // ctx.fillText("y: " + player.position.y.toFixed(0), x, line);
line += 20; // line += 20;
ctx.fillText("Vx: " + mech.Vx.toFixed(2), x, line); // ctx.fillText("Vx: " + mech.Vx.toFixed(2), x, line);
line += 20; // line += 20;
ctx.fillText("Vy: " + mech.Vy.toFixed(2), x, line); // ctx.fillText("Vy: " + mech.Vy.toFixed(2), x, line);
line += 20; // line += 20;
ctx.fillText("Fx: " + player.force.x.toFixed(3), x, line); // ctx.fillText("Fx: " + player.force.x.toFixed(3), x, line);
line += 20; // line += 20;
ctx.fillText("Fy: " + player.force.y.toFixed(3), x, line); // ctx.fillText("Fy: " + player.force.y.toFixed(3), x, line);
line += 20; // line += 20;
ctx.fillText("yOff: " + mech.yOff.toFixed(1), x, line); // ctx.fillText("yOff: " + mech.yOff.toFixed(1), x, line);
line += 20; // line += 20;
ctx.fillText("mass: " + player.mass.toFixed(1), x, line); // ctx.fillText("mass: " + player.mass.toFixed(1), x, line);
line += 20; // line += 20;
ctx.fillText("onGround: " + mech.onGround, x, line); // ctx.fillText("onGround: " + mech.onGround, x, line);
line += 20; // line += 20;
ctx.fillText("crouch: " + mech.crouch, x, line); // ctx.fillText("crouch: " + mech.crouch, x, line);
line += 20; // line += 20;
ctx.fillText("isHeadClear: " + mech.isHeadClear, x, line); // ctx.fillText("isHeadClear: " + mech.isHeadClear, x, line);
line += 20; // line += 20;
ctx.fillText("frictionAir: " + player.frictionAir.toFixed(3), x, line); // ctx.fillText("frictionAir: " + player.frictionAir.toFixed(3), x, line);
line += 20; // line += 20;
ctx.fillText("stepSize: " + mech.stepSize.toFixed(2), x, line); // ctx.fillText("stepSize: " + mech.stepSize.toFixed(2), x, line);
line += 20; // line += 20;
ctx.fillText("zoom: " + game.zoom.toFixed(4), x, line); // ctx.fillText("zoom: " + game.zoom.toFixed(4), x, line);
line += 20; // line += 20;
ctx.textAlign = "center"; ctx.textAlign = "center";
ctx.fillText(`(${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)})`, game.mouse.x, game.mouse.y - 20); ctx.fillText(`(${game.mouseInGame.x.toFixed(1)}, ${game.mouseInGame.y.toFixed(1)})`, game.mouse.x, game.mouse.y - 20);
}, },

View File

@@ -2,8 +2,12 @@
/* TODO: ******************************************* /* TODO: *******************************************
***************************************************** *****************************************************
mod: fields do damage on blocking add new power up class: rerolls
name: something about radiation? let you repopulate a power up selection menu
weekly random challenge where everyone playing each week gets the same random setup.
The randomness would be determined by the date so it would sync everyone.
powerups still drop, but the drops are determined by a preset list that changes each week.
mod: do something at the end of each level mod: do something at the end of each level
heal to full heal to full

View File

@@ -16,7 +16,7 @@ const level = {
// game.difficulty = 6; //for testing to simulate possible mobs spawns // game.difficulty = 6; //for testing to simulate possible mobs spawns
// b.giveGuns(15) // b.giveGuns(15)
// mech.setField(3) // mech.setField(3)
// b.giveMod(10); b.giveMod(16);
level.intro(); //starting level level.intro(); //starting level
// level.testingMap(); // level.testingMap();
@@ -45,18 +45,18 @@ const level = {
// if (level.isBuildRun) num++ // if (level.isBuildRun) num++
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
game.difficulty++ game.difficulty++
game.dmgScale += 0.1; //damage done by mobs increases each level game.dmgScale += 0.11; //damage done by mobs increases each level
b.dmgScale *= 0.94; //damage done by player decreases each level b.dmgScale *= 0.94; //damage done by player decreases each level
game.accelScale *= 1.03 //mob acceleration increases each level game.accelScale *= 1.03 //mob acceleration increases each level
game.lookFreqScale *= 0.97 //mob cycles between looks decreases each level game.lookFreqScale *= 0.97 //mob cycles between looks decreases each level
game.CDScale *= 0.97 //mob CD time decreases each level game.CDScale *= 0.97 //mob CD time decreases each level
} }
game.healScale = 1 / (1 + game.difficulty * 0.05) game.healScale = 1 / (1 + game.difficulty * 0.06) //a higher denominator makes for lower heals // mech.health += heal * game.healScale;
}, },
difficultyDecrease(num = 1) { //used in easy mode for game.reset() difficultyDecrease(num = 1) { //used in easy mode for game.reset()
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
game.difficulty-- game.difficulty--
game.dmgScale -= 0.1; //damage done by mobs increases each level game.dmgScale -= 0.11; //damage done by mobs increases each level
if (game.dmgScale < 0.1) game.dmgScale = 0.1; if (game.dmgScale < 0.1) game.dmgScale = 0.1;
b.dmgScale /= 0.94; //damage done by player decreases each level b.dmgScale /= 0.94; //damage done by player decreases each level
game.accelScale /= 1.03 //mob acceleration increases each level game.accelScale /= 1.03 //mob acceleration increases each level
@@ -64,14 +64,14 @@ const level = {
game.CDScale /= 0.97 //mob CD time decreases each level game.CDScale /= 0.97 //mob CD time decreases each level
} }
if (game.difficulty < 1) game.difficulty = 1; if (game.difficulty < 1) game.difficulty = 1;
game.healScale = 1 / (1 + game.difficulty * 0.05) game.healScale = 1 / (1 + game.difficulty * 0.06)
}, },
//****************************************************************************************************************** //******************************************************************************************************************
//****************************************************************************************************************** //******************************************************************************************************************
testingMap() { testingMap() {
//start with all guns //start with all guns
level.difficultyIncrease(8) level.difficultyIncrease(9) //level 7 on normal, level 4 on hard, level 1.2 on why?
game.zoomScale = 1400 //1400 is normal game.zoomScale = 1700 //1400 is normal
spawn.setSpawnList(); spawn.setSpawnList();
mech.setPosToSpawn(-75, -60); //normal spawn mech.setPosToSpawn(-75, -60); //normal spawn
level.enter.x = mech.spawnPos.x - 50; level.enter.x = mech.spawnPos.x - 50;
@@ -114,17 +114,17 @@ const level = {
// spawn.lineBoss(-500, -600, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]); // spawn.lineBoss(-500, -600, spawn.allowedBossList[Math.floor(Math.random() * spawn.allowedBossList.length)]);
// spawn.bodyRect(-135, -50, 50, 50); // spawn.bodyRect(-135, -50, 50, 50);
// spawn.bodyRect(-140, -100, 50, 50); // spawn.bodyRect(-140, -100, 50, 50);
powerUps.spawn(420, -400, "gun", 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); // powerUps.spawn(420, -400, "field", false);
// powerUps.spawn(420, -400, "field", false); // powerUps.spawn(420, -400, "field", false);
// powerUps.spawn(450, -400, "mod", false, 6); // powerUps.spawn(450, -400, "mod", false, 6);
// powerUps.spawn(450, -400, "mod", false); // powerUps.spawn(450, -400, "mod", false);
// spawn.bodyRect(-45, -100, 40, 50); // spawn.bodyRect(-45, -100, 40, 50);
// spawn.groupBoss(800, -1050); // spawn.bomber(800, -450);
// spawn.starter(400, -1050); spawn.hopper(400, -1050);
// spawn.starter(1200, -1050); // spawn.starter(1200, -1050);
// spawn.groupBoss(-600, -550); // spawn.nodeBoss(-600, -550, "starter");
// spawn.starter(800, -150); // spawn.starter(800, -150);
// spawn.beamer(800, -150); // spawn.beamer(800, -150);
// spawn.grower(800, -250); // spawn.grower(800, -250);
@@ -203,14 +203,14 @@ const level = {
spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
for (let i = 0; i < 5; ++i) { for (let i = 0; i < 3; ++i) {
if (game.difficulty * Math.random() > 3 * i) { if (game.difficulty * Math.random() > 15 * i) {
spawn.randomBoss(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); spawn.randomBoss(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
} }
if (game.difficulty * Math.random() > 2.6 * i) { if (game.difficulty * Math.random() > 10 * i) {
spawn.randomBoss(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); spawn.randomBoss(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
} }
if (game.difficulty * Math.random() > 2.4 * i) { if (game.difficulty * Math.random() > 7 * i) {
spawn.randomBoss(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); spawn.randomBoss(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
} }
} }
@@ -1468,13 +1468,12 @@ const level = {
nextLevel() { nextLevel() {
//enter when player isn't falling //enter when player isn't falling
if (player.velocity.y < 0.1) { if (player.velocity.y < 0.1) {
//increase difficulty based on modes
level.difficultyIncrease(game.difficultyMode + level.isBuildRun)
//cycles map to next level
level.levelsCleared++; level.levelsCleared++;
level.onLevel++; level.onLevel++; //cycles map to next level
if (level.onLevel > level.levels.length - 1) level.onLevel = 0; if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
level.difficultyIncrease(game.difficultyMode + level.isBuildRun) //increase difficulty based on modes
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map game.clearNow = true; //triggers in game.clearMap to remove all physics bodies and setup for new map
} }
}, },

View File

@@ -932,17 +932,18 @@ const mobs = {
} }
}, },
damage(dmg) { damage(dmg) {
dmg /= Math.sqrt(this.mass) if (!this.isShielded) {
if (b.isModLowHealthDmg) dmg *= (3 / (2 + mech.health)) //up to 50% dmg at zero player health dmg /= Math.sqrt(this.mass)
if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(1000, Math.min(3500, this.distanceToPlayer())) - 1000) * 0.01 //up to 50% dmg at max range of 3500 if (this.shield) dmg *= 0.04
if (dmg !== Infinity) { if (b.isModLowHealthDmg) dmg *= (3 / (2 + mech.health)) //up to 50% dmg at zero player health
if (b.modEnergySiphon) mech.fieldMeter += Math.min(this.health, dmg) * b.modEnergySiphon if (b.isModFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(1000, Math.min(3500, this.distanceToPlayer())) - 1000) * 0.01 //up to 50% dmg at max range of 3500
if (b.modHealthDrain) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain) if (b.modEnergySiphon && dmg !== Infinity) mech.fieldMeter += Math.min(this.health, dmg) * b.modEnergySiphon
if (b.modHealthDrain && dmg !== Infinity) mech.addHealth(Math.min(this.health, dmg) * b.modHealthDrain)
this.health -= dmg
//this.fill = this.color + this.health + ')';
this.onDamage(this); //custom damage effects
if (this.health < 0.05) this.death();
} }
this.health -= dmg
//this.fill = this.color + this.health + ')';
if (this.health < 0.05) this.death();
this.onDamage(this); //custom damage effects
}, },
onDamage() { onDamage() {
// a placeholder for custom effects on mob damage // a placeholder for custom effects on mob damage

View File

@@ -326,11 +326,7 @@ const mech = {
} }
function randomizeField() { function randomizeField() {
if (game.difficulty * (Math.random() + 0.27) > 2) { mech.setField(Math.floor(Math.random() * (mech.fieldUpgrades.length)))
mech.setField(Math.floor(Math.random() * (mech.fieldUpgrades.length)))
} else {
mech.setField(0)
}
} }
function randomizeHealth() { function randomizeHealth() {
@@ -446,6 +442,9 @@ const mech = {
dmg *= 0.93 dmg *= 0.93
} }
} }
if (b.modPiezo) {
mech.fieldMeter += dmg * b.modPiezo
}
mech.health -= dmg; mech.health -= dmg;
if (mech.health < 0) { if (mech.health < 0) {
mech.health = 0; mech.health = 0;
@@ -792,8 +791,8 @@ const mech = {
mech.fieldCDcycle = mech.cycle + 15; mech.fieldCDcycle = mech.cycle + 15;
mech.isHolding = false; mech.isHolding = false;
//bullet-like collisions //bullet-like collisions
mech.holdingTarget.collisionFilter.category = cat.body; mech.holdingTarget.collisionFilter.category = cat.bullet;
mech.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet; mech.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet | cat.mobShield;
//check every second to see if player is away from thrown body, and make solid //check every second to see if player is away from thrown body, and make solid
const solid = function (that) { const solid = function (that) {
const dx = that.position.x - player.position.x; const dx = that.position.x - player.position.x;
@@ -900,6 +899,9 @@ const mech = {
mech.drawHold(who); mech.drawHold(who);
mech.fieldCDcycle = mech.cycle + 10; mech.fieldCDcycle = mech.cycle + 10;
mech.holdingTarget = null mech.holdingTarget = null
if (b.modBlockDmg) {
who.damage(b.modBlockDmg)
}
//knock backs //knock backs
const unit = Vector.normalise(Vector.sub(player.position, who.position)) const unit = Vector.normalise(Vector.sub(player.position, who.position))
const massRoot = Math.sqrt(Math.min(12, Math.max(0.15, who.mass))); // masses above 12 can start to overcome the push back const massRoot = Math.sqrt(Math.min(12, Math.max(0.15, who.mass))); // masses above 12 can start to overcome the push back
@@ -1327,7 +1329,7 @@ const mech = {
mech.holding(); mech.holding();
mech.throwBlock(); mech.throwBlock();
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away } else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
const DRAIN = 0.00025 const DRAIN = 0.00035
if (mech.fieldMeter > DRAIN) { if (mech.fieldMeter > DRAIN) {
mech.grabPowerUp(); mech.grabPowerUp();
mech.lookForPickUp(150); mech.lookForPickUp(150);

View File

@@ -300,7 +300,7 @@ const powerUps = {
size: size size: size
}); });
if (mode) { if (mode) {
console.log(mode) // console.log(mode)
powerUp[index].mode = mode powerUp[index].mode = mode
} }
if (moving) { if (moving) {

View File

@@ -19,23 +19,25 @@ const spawn = {
"sneaker", "sneaker",
], ],
allowedBossList: ["chaser", "spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter"], allowedBossList: ["chaser", "spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter"],
setSpawnList() { setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
//this is run at the start of each new level to determine the possible mobs for the level
//each level has 2 mobs: one new mob and one from the last level //each level has 2 mobs: one new mob and one from the last level
spawn.pickList.splice(0, 1); spawn.pickList.splice(0, 1);
spawn.pickList.push(spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]); spawn.pickList.push(spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]);
}, },
spawnChance(chance) {
return Math.random() < chance + 0.07 * game.difficulty && mob.length < -1 + 16 * Math.log10(game.difficulty + 1)
},
randomMob(x, y, chance = 1) { randomMob(x, y, chance = 1) {
if (Math.random() < chance + 0.09 * (game.difficulty - 1) && mob.length < 4 + game.difficulty * 1.7) { if (spawn.spawnChance(chance)) {
const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)]; const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
this[pick](x, y); this[pick](x, y);
} }
}, },
randomSmallMob(x, y, randomSmallMob(x, y,
num = Math.max(Math.min(Math.round(Math.random() * (game.difficulty - 1) * 0.45 - 0.4), 4), 0), num = Math.max(Math.min(Math.round(Math.random() * game.difficulty * 0.2), 4), 0),
size = 16 + Math.ceil(Math.random() * 15), size = 16 + Math.ceil(Math.random() * 15),
chance = 1) { chance = 1) {
if (Math.random() < chance + (game.difficulty - 1) * 0.03 && mob.length < 4 + game.difficulty * 1.7) { if (spawn.spawnChance(chance)) {
for (let i = 0; i < num; ++i) { for (let i = 0; i < num; ++i) {
const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)]; const pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
this[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size); this[pick](x + Math.round((Math.random() - 0.5) * 20) + i * size * 2.5, y + Math.round((Math.random() - 0.5) * 20), size);
@@ -43,7 +45,7 @@ const spawn = {
} }
}, },
randomBoss(x, y, chance = 1) { randomBoss(x, y, chance = 1) {
if (Math.random() < chance + (game.difficulty - 1) * 0.14 && game.difficulty !== 1 && mob.length < 4 + game.difficulty * 2 || chance == Infinity) { if (spawn.spawnChance(chance) && game.difficulty > 2 || chance == Infinity) {
//choose from the possible picklist //choose from the possible picklist
let pick = this.pickList[Math.floor(Math.random() * this.pickList.length)]; let pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
//is the pick able to be a boss? //is the pick able to be a boss?
@@ -233,7 +235,7 @@ const spawn = {
me.accelMag = 0.001 * game.accelScale;; me.accelMag = 0.001 * game.accelScale;;
me.g = me.accelMag * 0.6; //required if using 'gravity' me.g = me.accelMag * 0.6; //required if using 'gravity'
me.memory = 50; me.memory = 50;
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.gravity(); this.gravity();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -293,32 +295,12 @@ const spawn = {
me.onDeath = function () { me.onDeath = function () {
this.removeCons(); this.removeCons();
}; };
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.gravity(); this.gravity();
this.searchSpring(); this.searchSpring();
}; };
}, },
// zoomer(x, y, radius = 20 + Math.ceil(Math.random() * 30)) {
// mobs.spawn(x, y, 6, radius, "#ffe2fd");
// let me = mob[mob.length - 1];
// me.trailLength = 20; //required for trails
// me.setupTrail(); //fill trails array up with the current position of mob
// me.trailFill = "#ff00f0";
// me.g = 0.001; //required if using 'gravity'
// me.frictionAir = 0.02;
// me.accelMag = 0.004 * game.accelScale;
// me.memory = 30;
// me.zoomMode = 150;
// me.onHit = function () {
// this.zoomMode = 150;
// };
// me.do = function () {
// this.seePlayerByDistAndLOS();
// this.zoom();
// this.gravity();
// };
// },
hopper(x, y, radius = 30 + Math.ceil(Math.random() * 30)) { hopper(x, y, radius = 30 + Math.ceil(Math.random() * 30)) {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)"); mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -329,6 +311,7 @@ const spawn = {
me.delay = 110; me.delay = 110;
me.randomHopFrequency = 50 + Math.floor(Math.random() * 1000); me.randomHopFrequency = 50 + Math.floor(Math.random() * 1000);
me.randomHopCD = game.cycle + me.randomHopFrequency; me.randomHopCD = game.cycle + me.randomHopFrequency;
spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.gravity(); this.gravity();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -361,6 +344,7 @@ const spawn = {
me.frictionAir = 0.022; me.frictionAir = 0.022;
me.lookTorque = 0.0000014; me.lookTorque = 0.0000014;
me.restitution = 0; me.restitution = 0;
spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
//accelerate towards the player after a delay //accelerate towards the player after a delay
@@ -464,7 +448,7 @@ const spawn = {
} }
} }
}, },
suckerBoss(x, y, radius = 20) { suckerBoss(x, y, radius = 25) {
mobs.spawn(x, y, 12, radius, "#000"); mobs.spawn(x, y, 12, radius, "#000");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; //used for drawSneaker me.stroke = "transparent"; //used for drawSneaker
@@ -493,16 +477,11 @@ const spawn = {
toMe(mob, this.position, this.eventHorizon) toMe(mob, this.position, this.eventHorizon)
toMe(bullet, this.position, this.eventHorizon) toMe(bullet, this.position, this.eventHorizon)
//push everything away //push everything away
// function push(who, pos, range) { // function push(who, pos, range) {
// for (let i = 0, len = who.length; i < len; ++i) { // for (let i = 0, len = who.length; i < len; ++i) {
// const SUB = Vector.sub(who[i].position, pos) // const SUB = Vector.sub(who[i].position, pos)
// const DISTANCE = Vector.magnitude(SUB) // const DISTANCE = Vector.magnitude(SUB)
// if (DISTANCE < range) { // if (DISTANCE < range) {
// const depth = range - DISTANCE // const depth = range - DISTANCE
// const force = Vector.mult(Vector.normalise(SUB), 30 * who[i].mass / depth) // const force = Vector.mult(Vector.normalise(SUB), 30 * who[i].mass / depth)
@@ -515,8 +494,6 @@ const spawn = {
// push(mob, this.position, this.eventHorizon) // push(mob, this.position, this.eventHorizon)
// push(bullet, this.position, this.eventHorizon) // push(bullet, this.position, this.eventHorizon)
// push([player], this.position, this.eventHorizon) // push([player], this.position, this.eventHorizon)
// for (let i = 0; i < (game.difficulty - 3); ++i) { // for (let i = 0; i < (game.difficulty - 3); ++i) {
// spawn.sucker(this.position.x + (Math.random() - 0.5) * radius * 2, this.position.y + (Math.random() - 0.5) * radius * 2, 70 * Math.random()); // spawn.sucker(this.position.x + (Math.random() - 0.5) * radius * 2, this.position.y + (Math.random() - 0.5) * radius * 2, 70 * Math.random());
// Matter.Body.setVelocity(mob[mob.length - 1], { // Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -600,7 +577,7 @@ const spawn = {
me.accelMag = 0.0005 * game.accelScale; me.accelMag = 0.0005 * game.accelScale;
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
if (Math.random() < Math.min(0.2 + (game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
this.attraction(); this.attraction();
@@ -623,7 +600,7 @@ const spawn = {
me.onDamage = function () { me.onDamage = function () {
this.laserPos = this.position; this.laserPos = this.position;
}; };
// if (Math.random() < Math.min(0.2 + game.difficulty * 0.1, 0.7)) spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
if (!mech.isBodiesAsleep) { if (!mech.isBodiesAsleep) {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
@@ -698,6 +675,7 @@ const spawn = {
me.friction = 0; me.friction = 0;
me.delay = 100; me.delay = 100;
Matter.Body.rotate(me, Math.PI * 0.1); Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
me.onDamage = function () { me.onDamage = function () {
this.cd = game.cycle + this.delay; this.cd = game.cycle + this.delay;
}; };
@@ -858,7 +836,7 @@ const spawn = {
//boss that drops bombs from above and holds a set distance from player //boss that drops bombs from above and holds a set distance from player
mobs.spawn(x, y, 3, radius, "transparent"); mobs.spawn(x, y, 3, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0015 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0015 + 0.0004 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "rgba(255,0,200)"; //used for drawGhost me.stroke = "rgba(255,0,200)"; //used for drawGhost
me.seeAtDistance2 = 1500000; me.seeAtDistance2 = 1500000;
@@ -874,7 +852,7 @@ const spawn = {
// me.memory = 300; // me.memory = 300;
// Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 // Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001
me.collisionFilter.mask = cat.player | cat.bullet me.collisionFilter.mask = cat.player | cat.bullet
spawn.shield(me, x, y); spawn.shield(me, x, y, 1);
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
@@ -900,30 +878,30 @@ const spawn = {
x: 0, x: 0,
y: 0 y: 0
}; };
if (Math.random() < Math.min(0.15 + (game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y); // spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
this.fire(); this.fire();
}; };
}, },
shooterBoss(x, y, radius = 85 + Math.ceil(Math.random() * 50)) { shooterBoss(x, y, radius = 130) {
//boss spawns on skyscraper level //boss spawns on skyscraper level
mobs.spawn(x, y, 3, radius, "rgb(255,70,180)"); mobs.spawn(x, y, 3, radius, "rgb(255,70,180)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.memory = 240; me.memory = 240;
me.fireFreq = 0.02; me.fireFreq = 0.025;
me.noseLength = 0; me.noseLength = 0;
me.fireAngle = 0; me.fireAngle = 0;
me.accelMag = 0.005 * game.accelScale; me.accelMag = 0.005 * game.accelScale;
me.frictionAir = 0.1; me.frictionAir = 0.1;
me.lookTorque = 0.000005 * (Math.random() > 0.5 ? -1 : 1); me.lookTorque = 0.000007 * (Math.random() > 0.5 ? -1 : 1);
me.fireDir = { me.fireDir = {
x: 0, x: 0,
y: 0 y: 0
}; };
Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.02 + 0.001 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y); // spawn.shield(me, x, y, 1);
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
@@ -970,7 +948,7 @@ const spawn = {
}); });
} }
}; };
if (Math.random() < Math.min((game.difficulty - 1) * 0.04, 0.2)) spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.gravity(); this.gravity();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -1018,8 +996,7 @@ const spawn = {
me.memory = 200; me.memory = 200;
me.laserRange = 500; me.laserRange = 500;
Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y); spawn.shield(me, x, y, 1);
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y);
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
@@ -1059,9 +1036,7 @@ const spawn = {
me.accelMag = 0.002 * game.accelScale; me.accelMag = 0.002 * game.accelScale;
me.memory = 20; me.memory = 20;
Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.001 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
spawn.shield(me, x, y); spawn.shield(me, x, y, 1);
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y);
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint this.removeCons(); //remove constraint
@@ -1072,46 +1047,57 @@ const spawn = {
this.attraction(); this.attraction();
}; };
}, },
shield(target, x, y, stiffness = 0.4) { shield(target, x, y, chance = Math.min(0.01 + game.difficulty * 0.01, 0.3)) {
if (this.allowShields) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 20, "rgba(220,220,255,0.6)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.0001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
//attach shield to last spawned mob
bodyA: me, bodyA: me,
bodyB: target, bodyB: target, //attach shield to target
stiffness: stiffness, stiffness: 0.4,
damping: 0.1 damping: 0.1
}); });
me.onDamage = function () { me.onDamage = function () {
//make sure the mob that owns the shield can tell when damage is done //make sure the mob that owns the shield can tell when damage is done
this.alertNearByMobs(); this.alertNearByMobs();
this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})`
}; };
me.leaveBody = false; me.leaveBody = false;
me.dropPowerUp = false; me.dropPowerUp = false;
me.showHealthBar = false; me.showHealthBar = false;
me.shieldTargetID = target.id
target.isShielded = true;
me.onDeath = function () {
//clear isShielded status from target
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].id === this.shieldTargetID) mob[i].isShielded = false;
}
};
//swap order of shield and mob, so that mob is behind shield graphically //swap order of shield and mob, so that mob is behind shield graphically
mob[mob.length - 1] = mob[mob.length - 2]; mob[mob.length - 1] = mob[mob.length - 2];
mob[mob.length - 2] = me; mob[mob.length - 2] = me;
me.do = function () {}; me.do = function () {};
} }
}, },
bossShield(nodes, x, y, radius) { bossShield(targets, x, y, radius) {
mobs.spawn(x, y, 9, radius, "rgba(220,220,255,0.65)"); const nodes = targets.length
mobs.spawn(x, y, 9, radius, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00005) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.frictionAir = 0; me.frictionAir = 0;
me.shield = true; me.shield = true;
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
//constrain to all mob nodes in boss
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
mob[mob.length - i - 2].isShielded = true;
//constrain to all mob nodes in boss
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
bodyA: me, bodyA: me,
bodyB: mob[mob.length - i - 2], bodyB: mob[mob.length - i - 2],
@@ -1120,8 +1106,16 @@ const spawn = {
}); });
} }
me.onDamage = function () { me.onDamage = function () {
//make sure the mob that owns the shield can tell when damage is done this.alertNearByMobs(); //makes sure the mob that owns the shield can tell when damage is done
this.alertNearByMobs(); this.fill = `rgba(220,220,255,${0.3 + 0.6 *this.health})`
};
me.onDeath = function () {
//clear isShielded status from target
for (let j = 0; j < targets.length; j++) {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].id === targets[j]) mob[i].isShielded = false;
}
}
}; };
me.leaveBody = false; me.leaveBody = false;
me.dropPowerUp = false; me.dropPowerUp = false;
@@ -1143,8 +1137,9 @@ const spawn = {
sideLength = Math.ceil(Math.random() * 100) + 70, // distance between each node mob sideLength = Math.ceil(Math.random() * 100) + 70, // distance between each node mob
stiffness = Math.random() * 0.03 + 0.005 stiffness = Math.random() * 0.03 + 0.005
) { ) {
this.allowShields = false; //don't want shields on boss mobs this.allowShields = false; //don't want shields on individual boss mobs
const angle = 2 * Math.PI / nodes const angle = 2 * Math.PI / nodes
let targets = []
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
let whoSpawn = spawn; let whoSpawn = spawn;
if (spawn === "random") { if (spawn === "random") {
@@ -1153,6 +1148,7 @@ const spawn = {
whoSpawn = this.pickList[Math.floor(Math.random() * this.pickList.length)]; whoSpawn = this.pickList[Math.floor(Math.random() * this.pickList.length)];
} }
this[whoSpawn](x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), radius); this[whoSpawn](x + sideLength * Math.sin(i * angle), y + sideLength * Math.cos(i * angle), radius);
targets.push(mob[mob.length - 1].id) //track who is in the node boss, for shields
} }
if (Math.random() < 0.3) { if (Math.random() < 0.3) {
this.constrain2AdjacentMobs(nodes, stiffness * 2, true); this.constrain2AdjacentMobs(nodes, stiffness * 2, true);
@@ -1161,8 +1157,7 @@ const spawn = {
} }
//spawn shield for entire boss //spawn shield for entire boss
if (nodes > 2 && Math.random() < 0.998) { if (nodes > 2 && Math.random() < 0.998) {
this.bossShield(nodes, x, y, sideLength + 2.5 * radius + nodes * 6 - 25); this.bossShield(targets, x, y, sideLength + 2.5 * radius + nodes * 6 - 25);
// this.bossShield(nodes, x, y, sideLength / (2 * Math.sin(Math.PI / nodes)));
} }
this.allowShields = true; this.allowShields = true;
}, },
@@ -1176,7 +1171,7 @@ const spawn = {
l = Math.ceil(Math.random() * 80) + 30, l = Math.ceil(Math.random() * 80) + 30,
stiffness = Math.random() * 0.06 + 0.01 stiffness = Math.random() * 0.06 + 0.01
) { ) {
this.allowShields = false; //don't want shields on boss mobs this.allowShields = false; //don't want shields on individual boss mobs
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
let whoSpawn = spawn; let whoSpawn = spawn;
if (spawn === "random") { if (spawn === "random") {