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,
modGuardianCount: null,
modCollisionImmuneCycles: null,
modBlockDmg: null,
modPiezo: null,
setModDefaults() {
b.modCount = 0;
b.modFireRate = 1;
@@ -55,6 +57,8 @@ const b = {
b.isModMassEnergy = false;
b.modGuardianCount = 0;
b.modCollisionImmuneCycles = 30;
b.modBlockDmg = 0;
b.modPiezo = 0;
mech.Fx = 0.015;
mech.jumpForce = 0.38;
mech.maxHealth = 1;
@@ -64,9 +68,8 @@ const b = {
}
},
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>`,
//0
count: 0,
maxCount: 4,
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",
//1
maxCount: 4,
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
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>",
//2
maxCount: 1,
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;
}
},
{
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>",
//3
maxCount: 1,
count: 0,
effect() { // good with annihilation, melee builds
effect() {
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>",
//4
maxCount: 1,
count: 0,
effect() { // good with annihilation, melee builds
effect() {
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>",
//5
maxCount: 4,
count: 0,
effect() { //good for guns with extra ammo: needles, M80, rapid fire, flak, super balls
effect() {
b.modFireRate *= 0.88
}
},
{
name: "desublimated ammunition",
name: "desublimated ammunition", //6
description: "use 50% less <strong>ammo</strong> when <strong>crouching</strong>",
//6
maxCount: 1,
count: 0,
effect() { //good with guns that have less ammo: one shot, grenades, missiles, super balls, spray
effect() {
b.modNoAmmo = 1
}
},
{
name: "Lorentzian topology",
name: "Lorentzian topology", //7
description: "your <strong>bullets</strong> last +33% <strong>longer</strong>",
//7
maxCount: 4,
count: 0,
effect() { //good with: drones, super balls, spore, missiles, wave beam(range), rapid fire(range), flak(range)
effect() {
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",
//8
maxCount: 4,
count: 0,
effect() { //good late game maybe?
effect() {
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>",
//9
maxCount: 1,
count: 0,
effect() { //makes dangerous situations more survivable
effect() {
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>",
//10
maxCount: 4,
count: 0,
effect() { // good with melee builds, content skipping builds
effect() {
b.modGuardianCount++;
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",
//11
maxCount: 1,
count: 0,
effect() { // good with melee builds, content skipping builds
effect() {
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",
//12
maxCount: 1,
count: 0,
effect() { //good with mods that heal: superconductive healing, entropy transfer
effect() {
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>",
//13
maxCount: 4,
count: 0,
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",
//14
maxCount: 1,
count: 0,
effect() { // good with laser-bots
effect() {
b.isModEntanglement = true
}
},
{
name: "energy transfer",
description: "gain <strong class='color-f'>energy</strong> proportional to <strong class='color-d'>damage</strong> done",
//15
name: "piezoelectricity", //16
description: "gain <strong class='color-f'>energy</strong> proportional to <strong>harm</strong> received",
maxCount: 4,
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;
}
},
{
name: "entropy transfer",
name: "entropy exchange", //18
description: "<strong class='color-h'>heal</strong> proportional to <strong class='color-d'>damage</strong> done",
//16
maxCount: 4,
count: 0,
effect() { //good with guns that overkill: one shot, grenade
effect() {
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>",
//17
maxCount: 4,
count: 0,
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>",
//18
maxCount: 4,
count: 0,
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.",
//19
maxCount: 4,
count: 0,
effect() { // good with ablative synthesis, melee builds
effect() {
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%",
//20
maxCount: 1,
count: 0,
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>",
//21
maxCount: 1,
count: 0,
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>",
//22
maxCount: 1,
count: 0,
effect: () => {
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> ",
//23
maxCount: 1,
count: 0,
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>",
//24
maxCount: 1,
count: 0,
effect() {
@@ -488,7 +473,7 @@ const b = {
time: game.drawTime
});
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
//add alert to draw queue
@@ -549,20 +534,21 @@ const b = {
//mob damage and knock back with alert
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) {
if (mob[i].alive) {
if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(where, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) {
if (mob[i].shield) dmg *= 3 //balancing explosion dmg to shields
mob[i].damage(dmg * damageScale);
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.y += knock.y;
radius *= 0.93 //reduced range for each additional explosion target
damageScale *= 0.8 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
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.y += knock.y;
}
@@ -581,7 +567,7 @@ const b = {
time: game.drawTime
});
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
//add alert to draw queue
@@ -642,20 +628,21 @@ const b = {
//mob damage and knock back with alert
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) {
if (mob[i].alive) {
if (mob[i].alive && !mob[i].isShielded) {
sub = Vector.sub(bullet[me].position, mob[i].position);
dist = Vector.magnitude(sub) - mob[i].radius;
if (dist < radius) {
if (mob[i].shield) dmg *= 3 //balancing explosion dmg to shields
mob[i].damage(dmg * damageScale);
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.y += knock.y;
radius *= 0.93 //reduced range for each additional explosion target
damageScale *= 0.8 //reduced damage for each additional explosion target
} else if (!mob[i].seePlayer.recall && dist < alertRange) {
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.y += knock.y;
}
@@ -837,7 +824,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(17 * Math.random()),
lookFrequency: 31 + Math.floor(17 * Math.random()),
acceleration: 0.0015 + 0.0013 * Math.random(),
range: 500 + Math.floor(200 * Math.random()),
endCycle: Infinity,
@@ -858,6 +845,7 @@ const b = {
for (let i = 0, len = mob.length; i < len; ++i) {
const DIST = Vector.magnitude(Vector.sub(this.vertices[0], mob[i].position));
if (DIST - mob[i].radius < closeDist &&
!mob[i].isShielded &&
Matter.Query.ray(map, this.vertices[0], mob[i].position).length === 0 &&
Matter.Query.ray(body, this.vertices[0], mob[i].position).length === 0) {
closeDist = DIST;
@@ -951,17 +939,18 @@ const b = {
name: "minigun", //0
description: "rapidly fire a stream of small <strong>bullets</strong>",
ammo: 0,
ammoPack: 50,
ammoPack: 55,
have: false,
isStarterGun: true,
fire() {
const me = bullet.length;
b.muzzleFlash(15);
// if (Math.random() > 0.2) mobs.alert(500);
const dir = mech.angle + (Math.random() - 0.5) * ((mech.crouch) ? 0.04 : 0.12);
bullet[me] = Bodies.rectangle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 17 * b.modBulletSize, 5 * b.modBulletSize, b.fireAttributes(dir));
b.fireProps(mech.crouch ? 10 : 5, mech.crouch ? 50 : 36, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + 65;
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), 20 * b.modBulletSize, 6 * b.modBulletSize, b.fireAttributes(dir));
b.fireProps(mech.crouch ? 8 : 4, mech.crouch ? 52 : 38, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + 70;
bullet[me].dmg = 0.07;
bullet[me].frictionAir = mech.crouch ? 0.007 : 0.01;
bullet[me].do = function () {
this.force.y += this.mass * 0.0005;
@@ -972,7 +961,7 @@ const b = {
name: "shotgun", //1
description: "fire a <strong>burst</strong> of short range bullets<br><em>crouch to reduce recoil</em>",
ammo: 0,
ammoPack: 4,
ammoPack: 5,
have: false,
isStarterGun: true,
fire() {
@@ -999,7 +988,7 @@ const b = {
}
//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.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
description: "fire a volley of <strong>precise</strong> high velocity needles",
ammo: 0,
ammoPack: 22,
ammoPack: 20,
have: false,
isStarterGun: true,
count: 0, //used to track how many shots are in a volley before a big CD
@@ -1095,7 +1084,7 @@ const b = {
inertia: Infinity,
frictionAir: 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",
collisionFilter: {
category: cat.bullet,
@@ -1134,7 +1123,7 @@ const b = {
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
ammo: 0,
ammoPack: 2,
ammoPack: 1,
have: false,
isStarterGun: false,
fire() {
@@ -1208,18 +1197,6 @@ const b = {
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
mech.fireCDcycle = Infinity //can't fire until mouse is released
if (mech.crouch) {
@@ -1227,25 +1204,6 @@ const b = {
} else {
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
let best;
let range = 3000
@@ -1377,30 +1335,25 @@ const b = {
const me = bullet.length;
bullet[me] = Bodies.rectangle(mech.pos.x + 40 * Math.cos(mech.angle), mech.pos.y + 40 * Math.sin(mech.angle) - 3, 30 * b.modBulletSize, 4 * b.modBulletSize, b.fireAttributes(dir));
b.fireProps(mech.crouch ? 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
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].endCycle = game.cycle + Math.floor((280 + 40 * Math.random()) * b.isModBulletsLastLonger);
bullet[me].explodeRad = 160 + 60 * Math.random();
bullet[me].lookFrequency = Math.floor(15 + Math.random() * 5);
bullet[me].explodeRad = 170 + 60 * Math.random();
bullet[me].lookFrequency = Math.floor(31 + Math.random() * 11);
bullet[me].onEnd = b.explode; //makes bullet do explosive damage at end
bullet[me].onDmg = function () {
this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
this.tryToLockOn();
// this.endCycle = 0; //bullet ends cycle after doing damage // also triggers explosion
};
bullet[me].lockedOn = null;
bullet[me].do = function () {
if (!mech.isBodiesAsleep) {
if (!(mech.cycle % this.lookFrequency)) {
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))
// 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 &&
@@ -1416,11 +1369,17 @@ const b = {
}
}
//explode when bullet is close enough to target
if (this.lockedOn && Vector.magnitude(Vector.sub(this.position, this.lockedOn.position)) < this.explodeRad * 0.7) {
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 * 3;
const dmg = b.dmgScale * 5;
this.lockedOn.damage(dmg); //does extra damage to target
}
};
bullet[me].do = function () {
if (!mech.isBodiesAsleep) {
if (!(mech.cycle % this.lookFrequency)) {
this.tryToLockOn();
}
//rotate missile towards the target
@@ -1754,12 +1713,12 @@ const b = {
name: "drones", //12
description: "deploy drones that <strong>crash</strong> into enemies<br>collisions reduce drone <strong>cycles</strong> by 1 second",
ammo: 0,
ammoPack: 6,
ammoPack: 5,
have: false,
isStarterGun: true,
fire() {
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
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.00004, // 0.001 is normal density
density: 0.00005, // 0.001 is normal density
inertia: Infinity,
frictionAir: 0.003,
friction: 0.2,
@@ -2173,7 +2132,7 @@ const b = {
target: null,
targetVertex: null,
onDmg(who) {
if (!this.target && who.alive && who.dropPowerUp) {
if (!this.target && who.alive && who.dropPowerUp && !who.isShielded) {
this.target = who;
this.collisionFilter.category = cat.body;
this.collisionFilter.mask = null;
@@ -2216,9 +2175,9 @@ const b = {
if (this.target && this.target.alive) { //if stuck to a target
Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.94))
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.94)
this.target.damage(b.dmgScale * 0.0045);
Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.9))
Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
this.target.damage(b.dmgScale * 0.005);
} else if (this.target !== null) { //look for a new target
this.target = null
this.collisionFilter.category = cat.bullet;
@@ -2301,6 +2260,7 @@ const b = {
}
}
};
const checkForCollisions = function () {
best = {
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
mech.damage(dmg);
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();
game.drawList.push({
//add dmg to draw queue
@@ -164,8 +164,7 @@ function mobCollisionChecks(event) {
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
if (b.isModCrit && !mob[k].seePlayer.recall && !mob[k].shield) dmg *= 5
mob[k].foundPlayer();
mob[k].damage(dmg);
obj.onDmg(mob[k]); //some bullets do actions when they hits things, like despawn

View File

@@ -81,7 +81,8 @@ const game = {
isBodyDamage: true,
levelsCleared: 0,
difficultyMode: 1,
difficulty: 1,
isEasyMode: false,
difficulty: 0,
dmgScale: null, //set in levels.setDifficulty
healScale: 1,
accelScale: null, //set in levels.setDifficulty
@@ -416,24 +417,6 @@ const game = {
},
wipe() {
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() {
function addGravity(bodies, magnitude) {
@@ -474,8 +457,10 @@ const game = {
game.accelScale = 1;
game.lookFreqScale = 1;
game.CDScale = 1;
game.difficulty = 0;
game.difficultyMode = Number(document.getElementById("difficulty-select").value)
if (game.difficultyMode === 0) {
game.isEasyMode = true;
game.difficultyMode = 1
level.difficultyDecrease(6);
}
@@ -693,7 +678,7 @@ const game = {
testingOutput() {
ctx.textAlign = "right";
ctx.fillStyle = "#000";
let line = 140;
let line = 500;
const x = canvas.width - 5;
ctx.fillText("T: exit testing mode", x, line);
line += 20;
@@ -712,38 +697,38 @@ const game = {
ctx.fillText("1-7: spawn things", x, line);
line += 30;
ctx.fillText("cycle: " + game.cycle, x, line);
line += 20;
ctx.fillText("player cycle: " + mech.cycle, x, line);
line += 20;
ctx.fillText("x: " + player.position.x.toFixed(0), x, line);
line += 20;
ctx.fillText("y: " + player.position.y.toFixed(0), x, line);
line += 20;
ctx.fillText("Vx: " + mech.Vx.toFixed(2), x, line);
line += 20;
ctx.fillText("Vy: " + mech.Vy.toFixed(2), x, line);
line += 20;
ctx.fillText("Fx: " + player.force.x.toFixed(3), x, line);
line += 20;
ctx.fillText("Fy: " + player.force.y.toFixed(3), x, line);
line += 20;
ctx.fillText("yOff: " + mech.yOff.toFixed(1), x, line);
line += 20;
ctx.fillText("mass: " + player.mass.toFixed(1), x, line);
line += 20;
ctx.fillText("onGround: " + mech.onGround, x, line);
line += 20;
ctx.fillText("crouch: " + mech.crouch, x, line);
line += 20;
ctx.fillText("isHeadClear: " + mech.isHeadClear, x, line);
line += 20;
ctx.fillText("frictionAir: " + player.frictionAir.toFixed(3), x, line);
line += 20;
ctx.fillText("stepSize: " + mech.stepSize.toFixed(2), x, line);
line += 20;
ctx.fillText("zoom: " + game.zoom.toFixed(4), x, line);
line += 20;
// ctx.fillText("cycle: " + game.cycle, x, line);
// line += 20;
// ctx.fillText("player cycle: " + mech.cycle, x, line);
// line += 20;
// ctx.fillText("x: " + player.position.x.toFixed(0), x, line);
// line += 20;
// ctx.fillText("y: " + player.position.y.toFixed(0), x, line);
// line += 20;
// ctx.fillText("Vx: " + mech.Vx.toFixed(2), x, line);
// line += 20;
// ctx.fillText("Vy: " + mech.Vy.toFixed(2), x, line);
// line += 20;
// ctx.fillText("Fx: " + player.force.x.toFixed(3), x, line);
// line += 20;
// ctx.fillText("Fy: " + player.force.y.toFixed(3), x, line);
// line += 20;
// ctx.fillText("yOff: " + mech.yOff.toFixed(1), x, line);
// line += 20;
// ctx.fillText("mass: " + player.mass.toFixed(1), x, line);
// line += 20;
// ctx.fillText("onGround: " + mech.onGround, x, line);
// line += 20;
// ctx.fillText("crouch: " + mech.crouch, x, line);
// line += 20;
// ctx.fillText("isHeadClear: " + mech.isHeadClear, x, line);
// line += 20;
// ctx.fillText("frictionAir: " + player.frictionAir.toFixed(3), x, line);
// line += 20;
// ctx.fillText("stepSize: " + mech.stepSize.toFixed(2), x, line);
// line += 20;
// ctx.fillText("zoom: " + game.zoom.toFixed(4), x, line);
// line += 20;
ctx.textAlign = "center";
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: *******************************************
*****************************************************
mod: fields do damage on blocking
name: something about radiation?
add new power up class: rerolls
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
heal to full

View File

@@ -16,7 +16,7 @@ const level = {
// game.difficulty = 6; //for testing to simulate possible mobs spawns
// b.giveGuns(15)
// mech.setField(3)
// b.giveMod(10);
b.giveMod(16);
level.intro(); //starting level
// level.testingMap();
@@ -45,18 +45,18 @@ const level = {
// if (level.isBuildRun) num++
for (let i = 0; i < num; i++) {
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
game.accelScale *= 1.03 //mob acceleration increases each level
game.lookFreqScale *= 0.97 //mob cycles between looks 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()
for (let i = 0; i < num; i++) {
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;
b.dmgScale /= 0.94; //damage done by player decreases 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
}
if (game.difficulty < 1) game.difficulty = 1;
game.healScale = 1 / (1 + game.difficulty * 0.05)
game.healScale = 1 / (1 + game.difficulty * 0.06)
},
//******************************************************************************************************************
//******************************************************************************************************************
testingMap() {
//start with all guns
level.difficultyIncrease(8)
game.zoomScale = 1400 //1400 is normal
level.difficultyIncrease(9) //level 7 on normal, level 4 on hard, level 1.2 on why?
game.zoomScale = 1700 //1400 is normal
spawn.setSpawnList();
mech.setPosToSpawn(-75, -60); //normal spawn
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.bodyRect(-135, -50, 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(450, -400, "mod", false, 6);
// powerUps.spawn(450, -400, "mod", false);
// spawn.bodyRect(-45, -100, 40, 50);
// spawn.groupBoss(800, -1050);
// spawn.starter(400, -1050);
// spawn.bomber(800, -450);
spawn.hopper(400, -1050);
// spawn.starter(1200, -1050);
// spawn.groupBoss(-600, -550);
// spawn.nodeBoss(-600, -550, "starter");
// spawn.starter(800, -150);
// spawn.beamer(800, -150);
// spawn.grower(800, -250);
@@ -203,14 +203,14 @@ const level = {
spawn.mapRect(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
for (let i = 0; i < 5; ++i) {
if (game.difficulty * Math.random() > 3 * i) {
for (let i = 0; i < 3; ++i) {
if (game.difficulty * Math.random() > 15 * i) {
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);
}
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);
}
}
@@ -1468,13 +1468,12 @@ const level = {
nextLevel() {
//enter when player isn't falling
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.onLevel++;
level.onLevel++; //cycles map to next level
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
}
},

View File

@@ -932,17 +932,18 @@ const mobs = {
}
},
damage(dmg) {
if (!this.isShielded) {
dmg /= Math.sqrt(this.mass)
if (this.shield) dmg *= 0.04
if (b.isModLowHealthDmg) dmg *= (3 / (2 + mech.health)) //up to 50% dmg at zero player health
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 (dmg !== Infinity) {
if (b.modEnergySiphon) mech.fieldMeter += Math.min(this.health, dmg) * b.modEnergySiphon
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 + ')';
if (this.health < 0.05) this.death();
this.onDamage(this); //custom damage effects
if (this.health < 0.05) this.death();
}
},
onDamage() {
// a placeholder for custom effects on mob damage

View File

@@ -326,11 +326,7 @@ const mech = {
}
function randomizeField() {
if (game.difficulty * (Math.random() + 0.27) > 2) {
mech.setField(Math.floor(Math.random() * (mech.fieldUpgrades.length)))
} else {
mech.setField(0)
}
}
function randomizeHealth() {
@@ -446,6 +442,9 @@ const mech = {
dmg *= 0.93
}
}
if (b.modPiezo) {
mech.fieldMeter += dmg * b.modPiezo
}
mech.health -= dmg;
if (mech.health < 0) {
mech.health = 0;
@@ -792,8 +791,8 @@ const mech = {
mech.fieldCDcycle = mech.cycle + 15;
mech.isHolding = false;
//bullet-like collisions
mech.holdingTarget.collisionFilter.category = cat.body;
mech.holdingTarget.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
mech.holdingTarget.collisionFilter.category = cat.bullet;
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
const solid = function (that) {
const dx = that.position.x - player.position.x;
@@ -900,6 +899,9 @@ const mech = {
mech.drawHold(who);
mech.fieldCDcycle = mech.cycle + 10;
mech.holdingTarget = null
if (b.modBlockDmg) {
who.damage(b.modBlockDmg)
}
//knock backs
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
@@ -1327,7 +1329,7 @@ const mech = {
mech.holding();
mech.throwBlock();
} else if ((keys[32] || game.mouseDownRight) && mech.fieldCDcycle < mech.cycle) { //push away
const DRAIN = 0.00025
const DRAIN = 0.00035
if (mech.fieldMeter > DRAIN) {
mech.grabPowerUp();
mech.lookForPickUp(150);

View File

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

View File

@@ -19,23 +19,25 @@ const spawn = {
"sneaker",
],
allowedBossList: ["chaser", "spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter"],
setSpawnList() {
//this is run at the start of each new level to determine the possible mobs for the level
setSpawnList() { //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
spawn.pickList.splice(0, 1);
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) {
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)];
this[pick](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),
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) {
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);
@@ -43,7 +45,7 @@ const spawn = {
}
},
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
let pick = this.pickList[Math.floor(Math.random() * this.pickList.length)];
//is the pick able to be a boss?
@@ -233,7 +235,7 @@ const spawn = {
me.accelMag = 0.001 * game.accelScale;;
me.g = me.accelMag * 0.6; //required if using 'gravity'
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 () {
this.gravity();
this.seePlayerCheck();
@@ -293,32 +295,12 @@ const spawn = {
me.onDeath = function () {
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 () {
this.gravity();
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)) {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1];
@@ -329,6 +311,7 @@ const spawn = {
me.delay = 110;
me.randomHopFrequency = 50 + Math.floor(Math.random() * 1000);
me.randomHopCD = game.cycle + me.randomHopFrequency;
spawn.shield(me, x, y);
me.do = function () {
this.gravity();
this.seePlayerCheck();
@@ -361,6 +344,7 @@ const spawn = {
me.frictionAir = 0.022;
me.lookTorque = 0.0000014;
me.restitution = 0;
spawn.shield(me, x, y);
me.do = function () {
this.seePlayerByLookingAt();
//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");
let me = mob[mob.length - 1];
me.stroke = "transparent"; //used for drawSneaker
@@ -493,16 +477,11 @@ const spawn = {
toMe(mob, this.position, this.eventHorizon)
toMe(bullet, this.position, this.eventHorizon)
//push everything away
// function push(who, pos, range) {
// for (let i = 0, len = who.length; i < len; ++i) {
// const SUB = Vector.sub(who[i].position, pos)
// const DISTANCE = Vector.magnitude(SUB)
// if (DISTANCE < range) {
// const depth = range - DISTANCE
// 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(bullet, this.position, this.eventHorizon)
// push([player], this.position, this.eventHorizon)
// 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());
// Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -600,7 +577,7 @@ const spawn = {
me.accelMag = 0.0005 * game.accelScale;
me.frictionStatic = 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 () {
this.seePlayerByLookingAt();
this.attraction();
@@ -623,7 +600,7 @@ const spawn = {
me.onDamage = function () {
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 () {
if (!mech.isBodiesAsleep) {
this.seePlayerByLookingAt();
@@ -698,6 +675,7 @@ const spawn = {
me.friction = 0;
me.delay = 100;
Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
me.onDamage = function () {
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
mobs.spawn(x, y, 3, radius, "transparent");
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.seeAtDistance2 = 1500000;
@@ -874,7 +852,7 @@ const spawn = {
// me.memory = 300;
// Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001
me.collisionFilter.mask = cat.player | cat.bullet
spawn.shield(me, x, y);
spawn.shield(me, x, y, 1);
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
@@ -900,30 +878,30 @@ const spawn = {
x: 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 () {
this.seePlayerByLookingAt();
this.fire();
};
},
shooterBoss(x, y, radius = 85 + Math.ceil(Math.random() * 50)) {
shooterBoss(x, y, radius = 130) {
//boss spawns on skyscraper level
mobs.spawn(x, y, 3, radius, "rgb(255,70,180)");
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.memory = 240;
me.fireFreq = 0.02;
me.fireFreq = 0.025;
me.noseLength = 0;
me.fireAngle = 0;
me.accelMag = 0.005 * game.accelScale;
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 = {
x: 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
spawn.shield(me, x, y);
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, 1);
me.onDeath = function () {
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 () {
this.gravity();
this.seePlayerCheck();
@@ -1018,8 +996,7 @@ const spawn = {
me.memory = 200;
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
spawn.shield(me, x, y);
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y);
spawn.shield(me, x, y, 1);
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
};
@@ -1059,9 +1036,7 @@ const spawn = {
me.accelMag = 0.002 * game.accelScale;
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
spawn.shield(me, x, y);
if (Math.random() < Math.min((game.difficulty - 1) * 0.05, 0.3)) spawn.shield(me, x, y);
spawn.shield(me, x, y, 1);
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint
@@ -1072,46 +1047,57 @@ const spawn = {
this.attraction();
};
},
shield(target, x, y, stiffness = 0.4) {
if (this.allowShields) {
mobs.spawn(x, y, 9, target.radius + 20, "rgba(220,220,255,0.6)");
shield(target, x, y, chance = Math.min(0.01 + game.difficulty * 0.01, 0.3)) {
if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1];
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.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
//attach shield to last spawned mob
bodyA: me,
bodyB: target,
stiffness: stiffness,
bodyB: target, //attach shield to target
stiffness: 0.4,
damping: 0.1
});
me.onDamage = function () {
//make 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.leaveBody = false;
me.dropPowerUp = 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
mob[mob.length - 1] = mob[mob.length - 2];
mob[mob.length - 2] = me;
me.do = function () {};
}
},
bossShield(nodes, x, y, radius) {
mobs.spawn(x, y, 9, radius, "rgba(220,220,255,0.65)");
bossShield(targets, x, y, radius) {
const nodes = targets.length
mobs.spawn(x, y, 9, radius, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1];
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.shield = true;
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
//constrain to all mob nodes in boss
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({
bodyA: me,
bodyB: mob[mob.length - i - 2],
@@ -1120,8 +1106,16 @@ const spawn = {
});
}
me.onDamage = function () {
//make sure the mob that owns the shield can tell when damage is done
this.alertNearByMobs();
this.alertNearByMobs(); //makes sure the mob that owns the shield can tell when damage is done
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.dropPowerUp = false;
@@ -1143,8 +1137,9 @@ const spawn = {
sideLength = Math.ceil(Math.random() * 100) + 70, // distance between each node mob
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
let targets = []
for (let i = 0; i < nodes; ++i) {
let whoSpawn = spawn;
if (spawn === "random") {
@@ -1153,6 +1148,7 @@ const spawn = {
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);
targets.push(mob[mob.length - 1].id) //track who is in the node boss, for shields
}
if (Math.random() < 0.3) {
this.constrain2AdjacentMobs(nodes, stiffness * 2, true);
@@ -1161,8 +1157,7 @@ const spawn = {
}
//spawn shield for entire boss
if (nodes > 2 && Math.random() < 0.998) {
this.bossShield(nodes, x, y, sideLength + 2.5 * radius + nodes * 6 - 25);
// this.bossShield(nodes, x, y, sideLength / (2 * Math.sin(Math.PI / nodes)));
this.bossShield(targets, x, y, sideLength + 2.5 * radius + nodes * 6 - 25);
}
this.allowShields = true;
},
@@ -1176,7 +1171,7 @@ const spawn = {
l = Math.ceil(Math.random() * 80) + 30,
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) {
let whoSpawn = spawn;
if (spawn === "random") {