vaccum bomb grenade mod

gun: vacuum bomb is removed
mod: vacuum bomb - grenades fire slower, explode bigger and, suck everything towards them

laser and diffuse laser graphics are better
mod: output coupler - diffuse laser beam is 30% wider and does 30% more damage
      requires diffuse beam

level number doesn't increase if you skip the boss (in the late game)
This commit is contained in:
landgreen
2020-10-23 16:03:27 -07:00
parent 5bbac02f88
commit e0131fcea1
8 changed files with 219 additions and 193 deletions

View File

@@ -132,7 +132,7 @@
</div> </div>
</details> </details>
</div> </div>
<div id="controls"> <div>
<details id="control-details"> <details id="control-details">
<summary>controls</summary> <summary>controls</summary>
<div id="details-div"> <div id="details-div">
@@ -196,7 +196,7 @@
</div> </div>
</details> </details>
</div> </div>
<div id="controls"> <div>
<details> <details>
<summary>about</summary> <summary>about</summary>
<div id="details-div"> <div id="details-div">

View File

@@ -461,11 +461,18 @@ const b = {
if (best.who.alive) { if (best.who.alive) {
best.who.damage(damage); best.who.damage(damage);
best.who.locatePlayer(); best.who.locatePlayer();
ctx.fillStyle = color; //draw mob damage circle game.drawList.push({ //add dmg to draw queue
ctx.beginPath(); x: path[path.length - 1].x,
ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(damage) * 100, 0, 2 * Math.PI); y: path[path.length - 1].y,
ctx.fill(); radius: Math.sqrt(damage) * 100,
color: "rgba(255,0,0,0.5)",
time: game.drawTime
});
} }
// ctx.fillStyle = color; //draw mob damage circle
// ctx.beginPath();
// ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(damage) * 100, 0, 2 * Math.PI);
// ctx.fill();
}; };
const reflection = function () { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector const reflection = function () { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2))); const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
@@ -510,16 +517,10 @@ const b = {
} }
} }
if (isThickBeam) { if (isThickBeam) {
ctx.strokeStyle = color;
ctx.lineWidth = 8
ctx.globalAlpha = 0.5;
for (let i = 1, len = path.length; i < len; ++i) { for (let i = 1, len = path.length; i < len; ++i) {
ctx.beginPath();
ctx.moveTo(path[i - 1].x, path[i - 1].y); ctx.moveTo(path[i - 1].x, path[i - 1].y);
ctx.lineTo(path[i].x, path[i].y); ctx.lineTo(path[i].x, path[i].y);
ctx.stroke();
} }
ctx.globalAlpha = 1;
} else { } else {
ctx.strokeStyle = color; ctx.strokeStyle = color;
ctx.lineWidth = 2 ctx.lineWidth = 2
@@ -804,9 +805,13 @@ const b = {
mobs.statusSlow(who, 60) mobs.statusSlow(who, 60)
this.endCycle = game.cycle this.endCycle = game.cycle
if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300) if (mod.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
if (mod.iceEnergy && !who.shield && !who.isShielded && who.dropPowerUp && !who.alive) { if (mod.iceEnergy && !who.shield && !who.isShielded && who.dropPowerUp && who.alive) {
mech.energy += mod.iceEnergy * 0.66 * mech.maxEnergy setTimeout(function () {
mech.addHealth(mod.iceEnergy * 0.04) if (!who.alive) {
mech.energy += mod.iceEnergy * 0.66 * mech.maxEnergy
mech.addHealth(mod.iceEnergy * 0.04)
}
}, 10);
} }
}, },
onEnd() {}, onEnd() {},
@@ -2330,6 +2335,9 @@ const b = {
ammoPack: 5, ammoPack: 5,
have: false, have: false,
fire() { fire() {
},
fireNormal() {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; // + Math.random() * 0.05; const dir = mech.angle; // + Math.random() * 0.05;
bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, b.fireAttributes(dir, false)); bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, b.fireAttributes(dir, false));
@@ -2343,7 +2351,6 @@ const b = {
bullet[me].beforeDmg = function () { bullet[me].beforeDmg = function () {
this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion this.endCycle = 0; //bullet ends cycle after doing damage //this also triggers explosion
}; };
if (mod.isRPG) { if (mod.isRPG) {
b.fireProps(35, mech.crouch ? 60 : -15, dir, me); //cd , speed b.fireProps(35, mech.crouch ? 60 : -15, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + 70; bullet[me].endCycle = game.cycle + 70;
@@ -2364,133 +2371,73 @@ const b = {
b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 43 : 32, dir, me); //cd , speed b.fireProps(mech.crouch ? 40 : 30, mech.crouch ? 43 : 32, dir, me); //cd , speed
bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80); bullet[me].endCycle = game.cycle + Math.floor(mech.crouch ? 120 : 80);
bullet[me].restitution = 0.4; bullet[me].restitution = 0.4;
bullet[me].explodeRad = 275;
bullet[me].do = function () { bullet[me].do = function () {
//extra gravity for harder arcs this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
this.force.y += this.mass * 0.0025;
}; };
} }
},
fireVacuum() {
}
},
{
name: "vacuum bomb",
description: "fire a bomb that <strong>sucks</strong> before <strong class='color-e'>exploding</strong><br><strong>click</strong> left mouse again to <strong>detonate</strong>",
ammo: 0,
ammoPack: 2,
have: false,
fire() {
const me = bullet.length; const me = bullet.length;
const dir = mech.angle; const dir = mech.angle; // + Math.random() * 0.05;
bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 35, b.fireAttributes(dir, false)); bullet[me] = Bodies.circle(mech.pos.x + 30 * Math.cos(mech.angle), mech.pos.y + 30 * Math.sin(mech.angle), 20, b.fireAttributes(dir, false));
b.fireProps(10, mech.crouch ? 42 : 28, dir, me); //cd , speed Matter.Body.setDensity(bullet[me], 0.0003);
bullet[me].explodeRad = 400 + Math.floor(Math.random() * 50);;
Matter.Body.setDensity(bullet[me], 0.0002);
bullet[me].restitution = 0.2;
bullet[me].friction = 0.3;
bullet[me].endCycle = Infinity
bullet[me].explodeRad = 450 + Math.floor(Math.random() * 50);
bullet[me].onEnd = function () { bullet[me].onEnd = function () {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
if (mod.grenadeFragments) b.targetedNail(this.position, mod.grenadeFragments)
//also damage all mobs
if (mod.isVacuumShield) {
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].shield) {
const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius;
if (dist < this.explodeRad) mob[i].health *= 0.2
}
}
const dist = Vector.magnitude(Vector.sub(this.position, player.position))
if (dist < this.explodeRad) mech.energy = 0 //remove player energy
}
} }
bullet[me].beforeDmg = function () { bullet[me].beforeDmg = function () {};
// this.endCycle = 0; //bullet ends cycle after doing damage //this triggers explosion const cd = mech.crouch ? 90 : 75
}; b.fireProps(cd, mech.crouch ? 46 : 35, dir, me); //cd , speed
bullet[me].radius = 22; //used from drawing timer bullet[me].endCycle = game.cycle + cd;
bullet[me].isArmed = false; bullet[me].restitution = 0.4;
bullet[me].isSucking = false;
bullet[me].do = function () { bullet[me].do = function () {
//extra gravity for harder arcs this.force.y += this.mass * 0.0025; //extra gravity for harder arcs
this.force.y += this.mass * 0.0022;
//set armed and sucking status const suckCycles = 40
if (!this.isArmed && !input.fire) { if (game.cycle > this.endCycle - suckCycles) { //suck
this.isArmed = true const that = this
} else if (this.isArmed && input.fire && !this.isSucking) {
this.isSucking = true;
this.endCycle = game.cycle + 50;
}
if (this.isSucking) { function suck(who, radius = that.explodeRad * 3.2) {
if (!mech.isBodiesAsleep) { for (i = 0, len = who.length; i < len; i++) {
const that = this const sub = Vector.sub(that.position, who[i].position);
let mag = 0.1 const dist = Vector.magnitude(sub);
if (dist < radius && dist > 150) {
function suck(who, radius = that.explodeRad * 3.5) { knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
for (i = 0, len = who.length; i < len; i++) { who[i].force.x += knock.x;
const sub = Vector.sub(that.position, who[i].position); who[i].force.y += knock.y;
const dist = Vector.magnitude(sub);
if (dist < radius && dist > 150) {
knock = Vector.mult(Vector.normalise(sub), mag * who[i].mass / Math.sqrt(dist));
who[i].force.x += knock.x;
who[i].force.y += knock.y;
}
} }
} }
if (game.cycle > this.endCycle - 5) {
mag = -0.22
suck(mob, this.explodeRad * 3)
suck(body, this.explodeRad * 2)
suck(powerUp, this.explodeRad * 1.5)
suck(bullet, this.explodeRad * 1.5)
suck([player], this.explodeRad * 1.3)
} else {
mag = 0.1
suck(mob, this.explodeRad * 3)
suck(body, this.explodeRad * 2)
suck(powerUp, this.explodeRad * 1.5)
suck(bullet, this.explodeRad * 1.5)
suck([player], this.explodeRad * 1.3)
}
//keep bomb in place
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
//draw suck
const radius = 3 * this.explodeRad * (this.endCycle - game.cycle) / 50
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
ctx.fill();
} }
} else { let mag = 0.1
mech.fireCDcycle = mech.cycle + 10 //can't fire until after the explosion if (game.cycle > this.endCycle - 5) {
mag = -0.22
// flashing lights to show armed suck(mob, this.explodeRad * 3)
if (!(game.cycle % 10)) { suck(body, this.explodeRad * 2)
if (this.isFlashOn) { suck(powerUp, this.explodeRad * 1.5)
this.isFlashOn = false; suck(bullet, this.explodeRad * 1.5)
} else { suck([player], this.explodeRad * 1.3)
this.isFlashOn = true; } else {
} mag = 0.11
} suck(mob, this.explodeRad * 3)
if (this.isFlashOn) { suck(body, this.explodeRad * 2)
ctx.fillStyle = "#000"; suck(powerUp, this.explodeRad * 1.5)
ctx.beginPath(); suck(bullet, this.explodeRad * 1.5)
ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI); suck([player], this.explodeRad * 1.3)
ctx.fill();
//draw clock on timer
ctx.fillStyle = "#f04";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, this.radius * 0.7, 0, 2 * Math.PI);
ctx.fill();
} }
//keep bomb in place
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
//draw suck
const radius = 2.75 * this.explodeRad * (this.endCycle - game.cycle) / suckCycles
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.beginPath();
ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
ctx.fill();
} }
} };
} }
}, },
{ {
@@ -2994,10 +2941,10 @@ const b = {
} }
} }
Matter.Body.setVelocity(this, { Matter.Body.setVelocity(this, {
x: -0.1 * this.velocity.x, x: -0.5 * this.velocity.x,
y: -0.1 * this.velocity.y y: -0.5 * this.velocity.y
}); });
Matter.Body.setDensity(this, 0.001); // Matter.Body.setDensity(this, 0.001);
} }
if (mod.isRailNails && this.speed > 10) { if (mod.isRailNails && this.speed > 10) {
b.targetedNail(this.position, Math.min(40, this.speed) - 10) b.targetedNail(this.position, Math.min(40, this.speed) - 10)
@@ -3212,8 +3159,13 @@ const b = {
} else { } else {
mech.fireCDcycle = mech.cycle mech.fireCDcycle = mech.cycle
mech.energy -= mech.fieldRegen + mod.laserFieldDrain * mod.isLaserDiode mech.energy -= mech.fieldRegen + mod.laserFieldDrain * mod.isLaserDiode
if (mod.isWideLaser) { if (mod.wideLaser) {
const off = 8 ctx.strokeStyle = "#f00";
ctx.lineWidth = 8
ctx.globalAlpha = 0.5;
ctx.beginPath();
const off = 7.5
const dmg = 0.55 * mod.laserDamage // 3.5 * 0.55 = 200% more damage const dmg = 0.55 * mod.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { const where = {
x: mech.pos.x + 20 * Math.cos(mech.angle), x: mech.pos.x + 20 * Math.cos(mech.angle),
@@ -3223,7 +3175,7 @@ const b = {
x: where.x + 3000 * Math.cos(mech.angle), x: where.x + 3000 * Math.cos(mech.angle),
y: where.y + 3000 * Math.sin(mech.angle) y: where.y + 3000 * Math.sin(mech.angle)
}, dmg, 0, true) }, dmg, 0, true)
for (let i = 1; i < 3; i++) { for (let i = 1; i < mod.wideLaser; i++) {
let whereOff = Vector.add(where, { let whereOff = Vector.add(where, {
x: i * off * Math.cos(mech.angle + Math.PI / 2), x: i * off * Math.cos(mech.angle + Math.PI / 2),
y: i * off * Math.sin(mech.angle + Math.PI / 2) y: i * off * Math.sin(mech.angle + Math.PI / 2)
@@ -3241,6 +3193,8 @@ const b = {
y: whereOff.y + 3000 * Math.sin(mech.angle) y: whereOff.y + 3000 * Math.sin(mech.angle)
}, dmg, 0, true) }, dmg, 0, true)
} }
ctx.stroke();
ctx.globalAlpha = 1;
} else if (mod.beamSplitter) { } else if (mod.beamSplitter) {
let dmg = mod.laserDamage * 0.9 let dmg = mod.laserDamage * 0.9
const where = { const where = {

View File

@@ -7,6 +7,7 @@ const level = {
defaultZoom: 1400, defaultZoom: 1400,
onLevel: 0, onLevel: 0,
levelsCleared: 0, levelsCleared: 0,
bossKilled: false,
levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"], levels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"],
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
@@ -16,11 +17,11 @@ const level = {
// game.setZoom(); // game.setZoom();
// mech.isCloak = true; // mech.isCloak = true;
// mech.setField("wormhole") // mech.setField("wormhole")
// b.giveGuns("flechettes") // b.giveGuns("grenades")
// for (let i = 0; i < 10; i++) { // for (let i = 0; i < 10; i++) {
// mod.giveMod("laser-bot"); // mod.giveMod("laser-bot");
// } // }
// mod.giveMod("supercritical fission") // mod.giveMod("vacuum bomb")
level.intro(); //starting level level.intro(); //starting level
@@ -544,7 +545,7 @@ const level = {
spawn.bodyRect(6800, 2490, 50, 50); spawn.bodyRect(6800, 2490, 50, 50);
spawn.bodyRect(6800, 2540, 50, 50); spawn.bodyRect(6800, 2540, 50, 50);
spawn.bodyRect(6800, 2590, 50, 50); spawn.bodyRect(6800, 2590, 50, 50);
spawn.bodyRect(8225, 2225, 50, 375); spawn.bodyRect(8225, 2225, 100, 100);
spawn.mapRect(6250, 1875, 700, 150); spawn.mapRect(6250, 1875, 700, 150);
spawn.mapRect(8000, 1875, 600, 150); spawn.mapRect(8000, 1875, 600, 150);
@@ -578,6 +579,7 @@ const level = {
powerUps.addRerollToLevel() //needs to run after mobs are spawned powerUps.addRerollToLevel() //needs to run after mobs are spawned
}, },
bosses() { bosses() {
level.bossKilled = true; //if there is no boss this needs to be true to increase levels
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
}; };
@@ -639,6 +641,7 @@ const level = {
powerUps.addRerollToLevel() //needs to run after mobs are spawned powerUps.addRerollToLevel() //needs to run after mobs are spawned
}, },
intro() { intro() {
level.bossKilled = true; //if there is no boss this needs to be true to increase levels
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
}; };
@@ -1477,7 +1480,7 @@ const level = {
spawn.randomMob(3600, -500, 0.8); spawn.randomMob(3600, -500, 0.8);
spawn.randomMob(3400, -200, 0.8); spawn.randomMob(3400, -200, 0.8);
spawn.randomMob(1650, -1300, 0.7) spawn.randomMob(1650, -1300, 0.7)
spawn.randomMob(-4100, -50, 0.7); spawn.randomMob(4100, -50, 0.7);
spawn.randomMob(4100, -50, 0.5); spawn.randomMob(4100, -50, 0.5);
spawn.randomMob(1700, -50, 0.3) spawn.randomMob(1700, -50, 0.3)
spawn.randomMob(2350, -900, 0.3) spawn.randomMob(2350, -900, 0.3)
@@ -3882,15 +3885,18 @@ const level = {
}, },
custom() {}, //each level runs it's own custom code (level exits, ...) custom() {}, //each level runs it's own custom code (level exits, ...)
nextLevel() { nextLevel() {
level.levelsCleared++; if (level.bossKilled || level.levelsCleared < level.levels.length) {
level.onLevel++; //cycles map to next level level.levelsCleared++;
if (level.onLevel > level.levels.length - 1) level.onLevel = 0; level.onLevel++; //cycles map to next level
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
}
level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes level.difficultyIncrease(game.difficultyMode) //increase difficulty based on modes
if (level.levelsCleared > level.levels.length) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length) level.difficultyIncrease(game.difficultyMode)
if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 1.25) level.difficultyIncrease(game.difficultyMode)
if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 1.5) level.difficultyIncrease(game.difficultyMode)
if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode) if (level.levelsCleared > level.levels.length * 2) level.difficultyIncrease(game.difficultyMode)
if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1); if (game.isEasyMode && level.levelsCleared % 2) level.difficultyDecrease(1);
level.bossKilled = false;
//reset lost mod display //reset lost mod display
for (let i = 0; i < mod.mods.length; i++) { for (let i = 0; i < mod.mods.length; i++) {
if (mod.mods[i].isLost) mod.mods[i].isLost = false; if (mod.mods[i].isLost) mod.mods[i].isLost = false;

View File

@@ -1104,7 +1104,7 @@ const mobs = {
//replace dead mob with a regular body //replace dead mob with a regular body
replace(i) { replace(i) {
//if there are too many bodies don't turn into blocks to help performance //if there are too many bodies don't turn into blocks to help performance
if (this.leaveBody && body.length < 60 && this.mass < 200) { if (this.leaveBody && body.length < 60 && this.mass < 200 && this.radius > 18) {
const len = body.length; const len = body.length;
const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v); body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v);

View File

@@ -320,9 +320,9 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return true return mech.fieldUpgrades[mech.fieldMode].name !== "wormhole"
}, },
requires: "", requires: "not wormhole",
effect() { effect() {
mod.throwChargeRate = 2 mod.throwChargeRate = 2
}, },
@@ -832,7 +832,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.totalBots() > 1 || mod.haveGunCheck("drone") || mod.haveGunCheck("mine") || mod.haveGunCheck("spores") || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" return (mod.totalBots() > 1 || mod.haveGunCheck("drone") || mod.haveGunCheck("mine") || mod.haveGunCheck("spores") || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing") && !mod.isEnergyHealth
}, },
requires: "drones, spores, mines, or bots", requires: "drones, spores, mines, or bots",
effect() { effect() {
@@ -850,7 +850,7 @@ const mod = {
allowed() { allowed() {
return mod.isNoFireDefense return mod.isNoFireDefense
}, },
requires: "full annealing", requires: "decorrelation",
effect() { effect() {
mod.isNoFireDamage = true mod.isNoFireDamage = true
}, },
@@ -2015,9 +2015,9 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("grenades") return mod.haveGunCheck("grenades") && !mod.isVacuumBomb
}, },
requires: "grenades", requires: "grenades, not vacuum bomb",
effect() { effect() {
mod.isRPG = true; mod.isRPG = true;
}, },
@@ -2026,21 +2026,43 @@ const mod = {
} }
}, },
{ {
name: "electromagnetic pulse", name: "vacuum bomb",
description: "<strong>vacuum bomb's </strong> <strong class='color-e'>explosion</strong> removes<br><strong>80%</strong> of <strong>shields</strong> and <strong>100%</strong> of <strong class='color-f'>energy</strong>", description: "<strong>grenades</strong> fire slower, <strong class='color-e'>explode</strong> bigger<br> and, <strong>suck</strong> everything towards them",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return mod.haveGunCheck("vacuum bomb") return mod.haveGunCheck("grenades") && !mod.isRPG
}, },
requires: "vacuum bomb", requires: "grenades, not rocket-propelled",
effect() { effect() {
mod.isVacuumShield = true; mod.isVacuumBomb = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireVacuum
}
}, },
remove() { remove() {
mod.isVacuumShield = false; mod.isVacuumBomb = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "grenades") b.guns[i].fire = b.guns[i].fireNormal
}
} }
}, },
// {
// name: "electromagnetic pulse",
// description: "<strong>vacuum bomb's </strong> <strong class='color-e'>explosion</strong> removes<br><strong>80%</strong> of <strong>shields</strong> and <strong>100%</strong> of <strong class='color-f'>energy</strong>",
// maxCount: 1,
// count: 0,
// allowed() {
// return mod.haveGunCheck("vacuum bomb")
// },
// requires: "vacuum bomb",
// effect() {
// mod.isVacuumShield = true;
// },
// remove() {
// mod.isVacuumShield = false;
// }
// },
{ {
name: "water shielding", name: "water shielding",
description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>player is <strong>immune</strong> to its harmful effects", description: "increase <strong>neutron bomb's</strong> range by <strong>20%</strong><br>player is <strong>immune</strong> to its harmful effects",
@@ -2268,7 +2290,7 @@ const mod = {
}, },
{ {
name: "thermoelectric effect", name: "thermoelectric effect",
description: "<strong>killing</strong> mobs with <strong>ice IX</strong> gives <strong>4%</strong> <strong class='color-h'>health</strong><br>and overloads <strong class='color-f'>energy</strong> by <strong>100%</strong> of your max", description: "<strong>killing</strong> mobs with <strong>ice IX</strong> gives <strong>4%</strong> <strong class='color-h'>health</strong><br>and overloads <strong class='color-f'>energy</strong> by <strong>166%</strong> of your max",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
@@ -2442,13 +2464,34 @@ const mod = {
}, },
requires: "laser, not specular reflection", requires: "laser, not specular reflection",
effect() { effect() {
mod.isWideLaser = true if (mod.wideLaser === 0) mod.wideLaser = 3
mod.isWideLaser = true;
}, },
remove() { remove() {
mod.isWideLaser = false mod.wideLaser = 0
mod.isWideLaser = false;
}
},
{
name: "output coupler",
description: "diffuse <strong>laser</strong> beam is <strong>30%</strong> <strong>wider</strong><br> and the full beam does <strong>30%</strong> more <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
allowed() {
return mod.haveGunCheck("laser") && mod.isWideLaser
},
requires: "laser, not specular reflection",
effect() {
mod.wideLaser = 4
},
remove() {
if (mod.isWideLaser) {
mod.wideLaser = 3
} else {
mod.wideLaser = 0
}
} }
}, },
// { // {
// name: "waste heat recovery", // name: "waste heat recovery",
// description: "<strong>laser</strong> <strong class='color-d'>damage</strong> grows by <strong>400%</strong> as you fire<br>but you periodically <strong>eject</strong> your <strong class='color-h'>health</strong>", // description: "<strong>laser</strong> <strong class='color-d'>damage</strong> grows by <strong>400%</strong> as you fire<br>but you periodically <strong>eject</strong> your <strong class='color-h'>health</strong>",
@@ -2855,7 +2898,7 @@ const mod = {
}, },
{ {
name: "Penrose process", name: "Penrose process",
description: "after a <strong>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>your <strong class='color-f'>energy</strong> overfills to <strong>300%</strong> of the maximum", description: "after a <strong>block</strong> falls into a <strong class='color-worm'>wormhole</strong><br>your <strong class='color-f'>energy</strong> overfills to <strong>200%</strong> of the maximum",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -3057,7 +3100,7 @@ const mod = {
isHarmDamage: null, isHarmDamage: null,
isHeavyWater: null, isHeavyWater: null,
energyRegen: null, energyRegen: null,
isVacuumShield: null, isVacuumBomb: null,
renormalization: null, renormalization: null,
grenadeFragments: null, grenadeFragments: null,
isEnergyDamage: null, isEnergyDamage: null,
@@ -3143,5 +3186,7 @@ const mod = {
isNailCrit: null, isNailCrit: null,
isFlechetteExplode: null, isFlechetteExplode: null,
isWormSpores: null, isWormSpores: null,
isWormBullets: null isWormBullets: null,
isWideLaser: null,
wideLaser: null
} }

View File

@@ -785,8 +785,15 @@ const mech = {
ctx.fillRect(xOff, yOff, range * mech.maxEnergy, 10); ctx.fillRect(xOff, yOff, range * mech.maxEnergy, 10);
ctx.fillStyle = mech.fieldMeterColor; ctx.fillStyle = mech.fieldMeterColor;
ctx.fillRect(xOff, yOff, range * mech.energy, 10); ctx.fillRect(xOff, yOff, range * mech.energy, 10);
if (mech.energy < 0) mech.energy = 0
} else if (mech.energy > mech.maxEnergy + 0.05) {
ctx.fillStyle = bgColor;
const xOff = mech.pos.x - mech.radius * mech.energy
const yOff = mech.pos.y - 50
// ctx.fillRect(xOff, yOff, range * mech.maxEnergy, 10);
ctx.fillStyle = mech.fieldMeterColor;
ctx.fillRect(xOff, yOff, range * mech.energy, 10);
} }
if (mech.energy < 0) mech.energy = 0
// else { // else {
// mech.energy = mech.maxEnergy // mech.energy = mech.maxEnergy
// } // }
@@ -2328,7 +2335,7 @@ const mech = {
Matter.World.remove(engine.world, body[i]); Matter.World.remove(engine.world, body[i]);
body.splice(i, 1); body.splice(i, 1);
mech.fieldRange *= 0.8 mech.fieldRange *= 0.8
if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3 if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 2) mech.energy = mech.maxEnergy * 2
if (mod.isWormSpores) { //pandimensionalspermia if (mod.isWormSpores) { //pandimensionalspermia
b.spore(Vector.add(mech.hole.pos2, Vector.rotate({ b.spore(Vector.add(mech.hole.pos2, Vector.rotate({
x: mech.fieldRange, x: mech.fieldRange,
@@ -2351,7 +2358,7 @@ const mech = {
Matter.World.remove(engine.world, body[i]); Matter.World.remove(engine.world, body[i]);
body.splice(i, 1); body.splice(i, 1);
mech.fieldRange *= 0.8 mech.fieldRange *= 0.8
if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 3) mech.energy = mech.maxEnergy * 3 if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 2) mech.energy = mech.maxEnergy * 2
if (mod.isWormSpores) { //pandimensionalspermia if (mod.isWormSpores) { //pandimensionalspermia
b.spore(Vector.add(mech.hole.pos1, Vector.rotate({ b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
x: mech.fieldRange, x: mech.fieldRange,
@@ -2396,13 +2403,30 @@ const mech = {
} }
if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)
const scale = 60
// console.log(Matter.Query.region(map, bounds))
if (mech.hole.isReady && if (mech.hole.isReady &&
(Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 && (
Matter.Query.ray(map, mech.pos, Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)).length === 0) Matter.Query.region(map, {
min: {
x: game.mouseInGame.x - scale,
y: game.mouseInGame.y - scale
},
max: {
x: game.mouseInGame.x + scale,
y: game.mouseInGame.y + scale
}
}).length === 0 &&
Matter.Query.ray(map, mech.pos, justPastMouse).length === 0
// Matter.Query.ray(map, mech.pos, game.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, game.mouseInGame).length === 0 &&
// Matter.Query.ray(map, player.position, justPastMouse).length === 0
)
) { ) {
const sub = Vector.sub(game.mouseInGame, mech.pos) const sub = Vector.sub(game.mouseInGame, mech.pos)
const mag = Vector.magnitude(sub) const mag = Vector.magnitude(sub)
const drain = 0.06 + 0.007 * Math.sqrt(mag) const drain = 0.07 + 0.008 * Math.sqrt(mag)
if (mech.energy > drain && mag > 300) { if (mech.energy > drain && mag > 300) {
mech.energy -= drain mech.energy -= drain
mech.hole.isReady = false; mech.hole.isReady = false;

View File

@@ -461,6 +461,7 @@ const powerUps = {
}, },
randomPowerUpCounter: 0, randomPowerUpCounter: 0,
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
level.bossKilled = true;
// if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod // if (game.difficultyMode === 4) powerUps.spawn(x, y, "mod") //why mode gets a free mod
powerUps.randomPowerUpCounter++; powerUps.randomPowerUpCounter++;
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ... const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ...
@@ -471,8 +472,8 @@ const powerUps = {
spawnHealthAmmo() spawnHealthAmmo()
} }
if (game.difficultyMode === 4) { if (game.difficultyMode === 4) {
powerUps.randomPowerUpCounter++; powerUps.randomPowerUpCounter + 0.6;
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ... const chanceToFail = Math.max(level.levelsCleared, 6) * 0.1 //1 until level 8
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0; powerUps.randomPowerUpCounter = 0;
spawnPowerUps() spawnPowerUps()

View File

@@ -1,13 +1,29 @@
gun: vacuum bomb is removed
mod: vacuum bomb - grenades fire slower, explode bigger and, suck everything towards them
laser and diffuse laser graphics are better
mod: output coupler - diffuse laser beam is 30% wider and does 30% more damage
requires diffuse beam
level number doesn't increase if you skip the boss (in the late game)
************** TODO - n-gon ************** ************** TODO - n-gon **************
foam bullet on dmg shrink effect add an ending to the game
revamp the boss level, or add a new final level
final level requires you to kill something
so skipping content is only smart if you are strong enough to beat the final boss
around level 15
game never ends if you have used cheats
new status effect - apply status effect to mobs that makes blocks attracted to them
only lasts a few cycles
foam or spore bullet on dmg shrink effect
it might mess with the foam position of other bullets on the mob it might mess with the foam position of other bullets on the mob
shrink when foam bullets end while attached, or shrink on collision? shrink when foam bullets end while attached, or shrink on collision?
effect - shrink or grow things
time dilation mod rework / buff (time dilation is cool, but it can feel like a chore) time dilation mod rework / buff (time dilation is cool, but it can feel like a chore)
redistribute effects redistribute effects
take no damage take no damage
@@ -16,13 +32,7 @@ time dilation mod rework / buff (time dilation is cool, but it can feel like a c
33% move jump fire always 33% move jump fire always
mod - after a mob or shield dies, remaining dots look for a new nearby host mod - after a mob or shield dies, remaining dots look for a new nearby host
or mod: radiation effects can spread to nearby mobs
add an ending to the game
revamp the boss level, or add a new final level
final level requires you to kill something
so skipping content is only smart if you are strong enough to beat the final boss
around level 15
game never ends if you have used cheats
look for mods that could update description text with count and mod.is information look for mods that could update description text with count and mod.is information
can only use variables that change in effect() and remove() can only use variables that change in effect() and remove()
@@ -32,8 +42,6 @@ mod self destruct - drones explode when they die, but they last 1/2 as long
mouse event e.which is deprecated mouse event e.which is deprecated
vacuum bomb applies status effect to mobs that makes blocks attracted to them
mod: take less harm if you are moving fast mod: take less harm if you are moving fast
require squirrel cage rotor require squirrel cage rotor
@@ -74,8 +82,6 @@ a bot that eats up health and ammo, but poops a reroll after picking up 2 power
disable crystalized armor? disable crystalized armor?
could convert rerolls, ammo, and health into mods instead could convert rerolls, ammo, and health into mods instead
mod: radiation effects can spread to nearby mobs
mod: foam is attracted to mobs mod: foam is attracted to mobs
use a gravitational attraction model? use a gravitational attraction model?
could foam be attracted to other foam bullets too? could foam be attracted to other foam bullets too?
@@ -229,18 +235,8 @@ an effect when canceling a power up
add player Scent Trails for mob navigation add player Scent Trails for mob navigation
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
settings - custom keys binding
css transition for pause menu css transition for pause menu
gun: Spirit Bomb (singularity)
use charge up like rail gun
electricity graphics like plasma torch
suck in nearby mobs, power ups?, blocks?
sucked in stuff increase size
uses energy
hold above the player's head
animate new level spawn by having the map aspects randomly fly into place animate new level spawn by having the map aspects randomly fly into place
n-gon outreach ideas n-gon outreach ideas