CPT gun
new level boss that fires 2 streams of small bullets that chase you mod: add a CPT gun to your inventory that rewinds your history, reverts your health, position, velocity for 10 seconds I expect that spamming rewind has some overpowered combos. Let me know what you find, and your ideas on balance.
This commit is contained in:
307
js/bullet.js
307
js/bullet.js
@@ -274,6 +274,132 @@ const b = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
pulse(energy, angle = mech.angle) {
|
||||||
|
let best;
|
||||||
|
let explosionRange = 1560 * energy
|
||||||
|
let range = 3000
|
||||||
|
const path = [{
|
||||||
|
x: mech.pos.x + 20 * Math.cos(angle),
|
||||||
|
y: mech.pos.y + 20 * Math.sin(angle)
|
||||||
|
},
|
||||||
|
{
|
||||||
|
x: mech.pos.x + range * Math.cos(angle),
|
||||||
|
y: mech.pos.y + range * Math.sin(angle)
|
||||||
|
}
|
||||||
|
];
|
||||||
|
const vertexCollision = function(v1, v1End, domain) {
|
||||||
|
for (let i = 0; i < domain.length; ++i) {
|
||||||
|
let vertices = domain[i].vertices;
|
||||||
|
const len = vertices.length - 1;
|
||||||
|
for (let j = 0; j < len; j++) {
|
||||||
|
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
|
||||||
|
if (results.onLine1 && results.onLine2) {
|
||||||
|
const dx = v1.x - results.x;
|
||||||
|
const dy = v1.y - results.y;
|
||||||
|
const dist2 = dx * dx + dy * dy;
|
||||||
|
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
||||||
|
best = {
|
||||||
|
x: results.x,
|
||||||
|
y: results.y,
|
||||||
|
dist2: dist2,
|
||||||
|
who: domain[i],
|
||||||
|
v1: vertices[j],
|
||||||
|
v2: vertices[j + 1]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
|
||||||
|
if (results.onLine1 && results.onLine2) {
|
||||||
|
const dx = v1.x - results.x;
|
||||||
|
const dy = v1.y - results.y;
|
||||||
|
const dist2 = dx * dx + dy * dy;
|
||||||
|
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
||||||
|
best = {
|
||||||
|
x: results.x,
|
||||||
|
y: results.y,
|
||||||
|
dist2: dist2,
|
||||||
|
who: domain[i],
|
||||||
|
v1: vertices[0],
|
||||||
|
v2: vertices[len]
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//check for collisions
|
||||||
|
best = {
|
||||||
|
x: null,
|
||||||
|
y: null,
|
||||||
|
dist2: Infinity,
|
||||||
|
who: null,
|
||||||
|
v1: null,
|
||||||
|
v2: null
|
||||||
|
};
|
||||||
|
if (mod.isPulseAim) { //find mobs in line of sight
|
||||||
|
let dist = 2200
|
||||||
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
|
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
|
||||||
|
if (explosionRange < newDist &&
|
||||||
|
newDist < dist &&
|
||||||
|
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
|
||||||
|
Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
|
||||||
|
dist = newDist
|
||||||
|
best.who = mob[i]
|
||||||
|
path[path.length - 1] = mob[i].position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!best.who) {
|
||||||
|
vertexCollision(path[0], path[1], mob);
|
||||||
|
vertexCollision(path[0], path[1], map);
|
||||||
|
vertexCollision(path[0], path[1], body);
|
||||||
|
if (best.dist2 != Infinity) { //if hitting something
|
||||||
|
path[path.length - 1] = {
|
||||||
|
x: best.x,
|
||||||
|
y: best.y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (best.who) b.explosion(path[1], explosionRange, true)
|
||||||
|
|
||||||
|
if (mod.isPulseStun) {
|
||||||
|
const range = 100 + 2000 * energy
|
||||||
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
|
if (mob[i].alive && !mob[i].isShielded) {
|
||||||
|
dist = Vector.magnitude(Vector.sub(path[1], mob[i].position)) - mob[i].radius;
|
||||||
|
if (dist < range) mobs.statusStun(mob[i], 30 + Math.floor(energy * 60))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//draw laser beam
|
||||||
|
ctx.beginPath();
|
||||||
|
ctx.moveTo(path[0].x, path[0].y);
|
||||||
|
ctx.lineTo(path[1].x, path[1].y);
|
||||||
|
ctx.strokeStyle = "rgba(255,0,0,0.13)"
|
||||||
|
ctx.lineWidth = 60 * energy / 0.2
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.strokeStyle = "rgba(255,0,0,0.2)"
|
||||||
|
ctx.lineWidth = 18
|
||||||
|
ctx.stroke();
|
||||||
|
ctx.strokeStyle = "#f00";
|
||||||
|
ctx.lineWidth = 4
|
||||||
|
ctx.stroke();
|
||||||
|
|
||||||
|
//draw little dots along the laser path
|
||||||
|
const sub = Vector.sub(path[1], path[0])
|
||||||
|
const mag = Vector.magnitude(sub)
|
||||||
|
for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
|
||||||
|
const dist = Math.random()
|
||||||
|
game.drawList.push({
|
||||||
|
x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
|
||||||
|
y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
|
||||||
|
radius: 1 + 4 * Math.random(),
|
||||||
|
color: "rgba(255,0,0,0.5)",
|
||||||
|
time: Math.floor(2 + 33 * Math.random() * Math.random())
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
grenade() {
|
grenade() {
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -550,7 +676,7 @@ const b = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
slow(body, this.damageRadius)
|
slow(body, this.damageRadius)
|
||||||
slow([player], this.damageRadius)
|
if (!mod.isNeutronImmune) slow([player], this.damageRadius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -591,6 +717,7 @@ const b = {
|
|||||||
},
|
},
|
||||||
onEnd() {
|
onEnd() {
|
||||||
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
|
b.explosion(this.position, this.explodeRad * size); //makes bullet do explosive damage at end
|
||||||
|
if (mod.fragments) b.targetedNail(this.position, mod.fragments * 5)
|
||||||
if (spawn) {
|
if (spawn) {
|
||||||
for (let i = 0; i < mod.recursiveMissiles; i++) {
|
for (let i = 0; i < mod.recursiveMissiles; i++) {
|
||||||
if (0.2 - 0.02 * i > Math.random()) {
|
if (0.2 - 0.02 * i > Math.random()) {
|
||||||
@@ -724,8 +851,8 @@ const b = {
|
|||||||
const q = Matter.Query.point(mob, this.position)
|
const q = Matter.Query.point(mob, this.position)
|
||||||
for (let i = 0; i < q.length; i++) {
|
for (let i = 0; i < q.length; i++) {
|
||||||
Matter.Body.setVelocity(q[i], {
|
Matter.Body.setVelocity(q[i], {
|
||||||
x: q[i].velocity.x * 0.7,
|
x: q[i].velocity.x * 0.6,
|
||||||
y: q[i].velocity.y * 0.7
|
y: q[i].velocity.y * 0.6
|
||||||
});
|
});
|
||||||
Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium
|
Matter.Body.setPosition(this, Vector.add(this.position, q[i].velocity)) //move with the medium
|
||||||
let dmg = this.dmg / Math.min(10, q[i].mass)
|
let dmg = this.dmg / Math.min(10, q[i].mass)
|
||||||
@@ -743,9 +870,9 @@ const b = {
|
|||||||
this.cycle++
|
this.cycle++
|
||||||
const wiggleMag = (mech.crouch ? 6 : 12) * Math.cos(game.cycle * 0.09)
|
const wiggleMag = (mech.crouch ? 6 : 12) * Math.cos(game.cycle * 0.09)
|
||||||
const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.36)) //+ wiggleMag * Math.cos(game.cycle * 0.3))
|
const wiggle = Vector.mult(transverse, wiggleMag * Math.cos(this.cycle * 0.36)) //+ wiggleMag * Math.cos(game.cycle * 0.3))
|
||||||
// const velocity = Vector.mult(player.velocity, 0.25) //move with player
|
const velocity = Vector.mult(player.velocity, 0.3) //move with player
|
||||||
// Matter.Body.setPosition(this, Vector.add(velocity, Vector.add(this.position, wiggle)))
|
Matter.Body.setPosition(this, Vector.add(velocity, Vector.add(this.position, wiggle)))
|
||||||
Matter.Body.setPosition(this, Vector.add(this.position, wiggle))
|
// Matter.Body.setPosition(this, Vector.add(this.position, wiggle))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -2089,11 +2216,11 @@ const b = {
|
|||||||
const DIST = Vector.magnitude(sub);
|
const DIST = Vector.magnitude(sub);
|
||||||
const unit = Vector.normalise(sub)
|
const unit = Vector.normalise(sub)
|
||||||
if (DIST < mod.isPlasmaRange * 450 && mech.energy > this.drainThreshold) {
|
if (DIST < mod.isPlasmaRange * 450 && mech.energy > this.drainThreshold) {
|
||||||
mech.energy -= 0.0012;
|
mech.energy -= 0.005;
|
||||||
if (mech.energy < 0) {
|
// if (mech.energy < 0) {
|
||||||
mech.fieldCDcycle = mech.cycle + 120;
|
// mech.fieldCDcycle = mech.cycle + 120;
|
||||||
mech.energy = 0;
|
// mech.energy = 0;
|
||||||
}
|
// }
|
||||||
//calculate laser collision
|
//calculate laser collision
|
||||||
let best;
|
let best;
|
||||||
let range = mod.isPlasmaRange * (120 + 300 * Math.sqrt(Math.random()))
|
let range = mod.isPlasmaRange * (120 + 300 * Math.sqrt(Math.random()))
|
||||||
@@ -2164,7 +2291,7 @@ const b = {
|
|||||||
y: best.y
|
y: best.y
|
||||||
};
|
};
|
||||||
if (best.who.alive) {
|
if (best.who.alive) {
|
||||||
const dmg = 0.8 * b.dmgScale; //********** SCALE DAMAGE HERE *********************
|
const dmg = 0.6 * b.dmgScale; //********** SCALE DAMAGE HERE *********************
|
||||||
best.who.damage(dmg);
|
best.who.damage(dmg);
|
||||||
best.who.locatePlayer();
|
best.who.locatePlayer();
|
||||||
//push mobs away
|
//push mobs away
|
||||||
@@ -3612,13 +3739,13 @@ const b = {
|
|||||||
y: mech.pos.y + 3000 * Math.sin(mech.angle)
|
y: mech.pos.y + 3000 * Math.sin(mech.angle)
|
||||||
}, dmg, 0, true);
|
}, dmg, 0, true);
|
||||||
for (let i = 1; i < len; i++) {
|
for (let i = 1; i < len; i++) {
|
||||||
const history = mech.history[(mech.cycle - i * spacing) % 300]
|
const history = mech.history[(mech.cycle - i * spacing) % 600]
|
||||||
b.laser({
|
b.laser({
|
||||||
x: history.position.x + 20 * Math.cos(history.angle),
|
x: history.position.x + 20 * Math.cos(history.angle),
|
||||||
y: history.position.y + 20 * Math.sin(history.angle)
|
y: history.position.y + 20 * Math.sin(history.angle) - mech.yPosDifference
|
||||||
}, {
|
}, {
|
||||||
x: history.position.x + 3000 * Math.cos(history.angle),
|
x: history.position.x + 3000 * Math.cos(history.angle),
|
||||||
y: history.position.y + 3000 * Math.sin(history.angle)
|
y: history.position.y + 3000 * Math.sin(history.angle) - mech.yPosDifference
|
||||||
}, dmg, 0, true);
|
}, dmg, 0, true);
|
||||||
}
|
}
|
||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
@@ -3642,130 +3769,38 @@ const b = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
pulse(energy, angle = mech.angle) {
|
gunRewind: { //this gun is added with a mod
|
||||||
let best;
|
name: "CPT gun",
|
||||||
let explosionRange = 1560 * energy
|
description: "use <strong class='color-f'>energy</strong> to <strong>rewind</strong> your <strong class='color-h'>health</strong>, <strong>velocity</strong>,<br> and <strong>position</strong> up to <strong>10</strong> seconds",
|
||||||
let range = 3000
|
ammo: 0,
|
||||||
const path = [{
|
ammoPack: Infinity,
|
||||||
x: mech.pos.x + 20 * Math.cos(angle),
|
have: false,
|
||||||
y: mech.pos.y + 20 * Math.sin(angle)
|
isRewinding: false,
|
||||||
},
|
lastFireCycle: 0,
|
||||||
{
|
holdCount: 0,
|
||||||
x: mech.pos.x + range * Math.cos(angle),
|
fire() {
|
||||||
y: mech.pos.y + range * Math.sin(angle)
|
if (this.lastFireCycle === mech.cycle - 1) { //button has been held down
|
||||||
}
|
this.rewindCount += 7;
|
||||||
];
|
const DRAIN = 0.01
|
||||||
const vertexCollision = function(v1, v1End, domain) {
|
if (this.rewindCount > 599 || mech.energy < DRAIN) {
|
||||||
for (let i = 0; i < domain.length; ++i) {
|
this.rewindCount = 0;
|
||||||
let vertices = domain[i].vertices;
|
mech.resetHistory();
|
||||||
const len = vertices.length - 1;
|
mech.fireCDcycle = mech.cycle + Math.floor(60 * b.fireCD); // cool down
|
||||||
for (let j = 0; j < len; j++) {
|
} else {
|
||||||
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
|
mech.energy -= DRAIN
|
||||||
if (results.onLine1 && results.onLine2) {
|
mech.immuneCycle = mech.cycle + 5; //player is immune to collision damage for 5 cycles
|
||||||
const dx = v1.x - results.x;
|
let history = mech.history[(mech.cycle - this.rewindCount) % 600]
|
||||||
const dy = v1.y - results.y;
|
Matter.Body.setPosition(player, history.position);
|
||||||
const dist2 = dx * dx + dy * dy;
|
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
|
||||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
if (mech.health !== history.health) {
|
||||||
best = {
|
mech.health = history.health
|
||||||
x: results.x,
|
mech.displayHealth();
|
||||||
y: results.y,
|
|
||||||
dist2: dist2,
|
|
||||||
who: domain[i],
|
|
||||||
v1: vertices[j],
|
|
||||||
v2: vertices[j + 1]
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
|
|
||||||
if (results.onLine1 && results.onLine2) {
|
|
||||||
const dx = v1.x - results.x;
|
|
||||||
const dy = v1.y - results.y;
|
|
||||||
const dist2 = dx * dx + dy * dy;
|
|
||||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
|
||||||
best = {
|
|
||||||
x: results.x,
|
|
||||||
y: results.y,
|
|
||||||
dist2: dist2,
|
|
||||||
who: domain[i],
|
|
||||||
v1: vertices[0],
|
|
||||||
v2: vertices[len]
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else { //button is held the first time
|
||||||
|
this.rewindCount = 0;
|
||||||
}
|
}
|
||||||
};
|
this.lastFireCycle = mech.cycle;
|
||||||
//check for collisions
|
|
||||||
best = {
|
|
||||||
x: null,
|
|
||||||
y: null,
|
|
||||||
dist2: Infinity,
|
|
||||||
who: null,
|
|
||||||
v1: null,
|
|
||||||
v2: null
|
|
||||||
};
|
|
||||||
if (mod.isPulseAim) { //find mobs in line of sight
|
|
||||||
let dist = 2200
|
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
|
||||||
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
|
|
||||||
if (explosionRange < newDist &&
|
|
||||||
newDist < dist &&
|
|
||||||
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
|
|
||||||
Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
|
|
||||||
dist = newDist
|
|
||||||
best.who = mob[i]
|
|
||||||
path[path.length - 1] = mob[i].position
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!best.who) {
|
|
||||||
vertexCollision(path[0], path[1], mob);
|
|
||||||
vertexCollision(path[0], path[1], map);
|
|
||||||
vertexCollision(path[0], path[1], body);
|
|
||||||
if (best.dist2 != Infinity) { //if hitting something
|
|
||||||
path[path.length - 1] = {
|
|
||||||
x: best.x,
|
|
||||||
y: best.y
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (best.who) b.explosion(path[1], explosionRange, true)
|
|
||||||
|
|
||||||
if (mod.isPulseStun) {
|
|
||||||
const range = 100 + 2000 * energy
|
|
||||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
|
||||||
if (mob[i].alive && !mob[i].isShielded) {
|
|
||||||
dist = Vector.magnitude(Vector.sub(path[1], mob[i].position)) - mob[i].radius;
|
|
||||||
if (dist < range) mobs.statusStun(mob[i], 30 + Math.floor(energy * 60))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//draw laser beam
|
|
||||||
ctx.beginPath();
|
|
||||||
ctx.moveTo(path[0].x, path[0].y);
|
|
||||||
ctx.lineTo(path[1].x, path[1].y);
|
|
||||||
ctx.strokeStyle = "rgba(255,0,0,0.13)"
|
|
||||||
ctx.lineWidth = 60 * energy / 0.2
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.strokeStyle = "rgba(255,0,0,0.2)"
|
|
||||||
ctx.lineWidth = 18
|
|
||||||
ctx.stroke();
|
|
||||||
ctx.strokeStyle = "#f00";
|
|
||||||
ctx.lineWidth = 4
|
|
||||||
ctx.stroke();
|
|
||||||
|
|
||||||
//draw little dots along the laser path
|
|
||||||
const sub = Vector.sub(path[1], path[0])
|
|
||||||
const mag = Vector.magnitude(sub)
|
|
||||||
for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
|
|
||||||
const dist = Math.random()
|
|
||||||
game.drawList.push({
|
|
||||||
x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
|
|
||||||
y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
|
|
||||||
radius: 1 + 4 * Math.random(),
|
|
||||||
color: "rgba(255,0,0,0.5)",
|
|
||||||
time: Math.floor(2 + 33 * Math.random() * Math.random())
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
48
js/game.js
48
js/game.js
@@ -596,7 +596,17 @@ const game = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mod.isEndLevelPowerUp) {
|
if (mod.isEndLevelPowerUp) {
|
||||||
for (let i = 0; i < powerUp.length; i++) powerUp[i].effect();
|
for (let i = 0; i < powerUp.length; i++) {
|
||||||
|
if (powerUp[i].name === "mod") {
|
||||||
|
mod.giveMod()
|
||||||
|
} else if (powerUp[i].name === "gun") {
|
||||||
|
if (!mod.isOneGun) b.giveGuns("random")
|
||||||
|
} else if (powerUp[i].name === "field") {
|
||||||
|
if (mech.fieldMode === 0) mech.setField(Math.ceil(Math.random() * (mech.fieldUpgrades.length - 1))) //pick a random field, but not field 0
|
||||||
|
} else {
|
||||||
|
powerUp[i].effect();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
powerUps.totalPowerUps = powerUp.length
|
powerUps.totalPowerUps = powerUp.length
|
||||||
|
|
||||||
@@ -761,24 +771,24 @@ const game = {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 40
|
y: 40
|
||||||
});
|
});
|
||||||
if ((playerHead.position.y - player.position.y) > 0) {
|
// if ((playerHead.position.y - player.position.y) > 0) {
|
||||||
Matter.Body.translate(playerHead, {
|
// Matter.Body.translate(playerHead, {
|
||||||
x: 0,
|
// x: 0,
|
||||||
y: 40
|
// y: 40
|
||||||
});
|
// });
|
||||||
if ((playerHead.position.y - player.position.y) > 0) {
|
// if ((playerHead.position.y - player.position.y) > 0) {
|
||||||
Matter.Body.translate(playerHead, {
|
// Matter.Body.translate(playerHead, {
|
||||||
x: 0,
|
// x: 0,
|
||||||
y: 40
|
// y: 40
|
||||||
});
|
// });
|
||||||
if ((playerHead.position.y - player.position.y) > 0) {
|
// if ((playerHead.position.y - player.position.y) > 0) {
|
||||||
Matter.Body.translate(playerHead, {
|
// Matter.Body.translate(playerHead, {
|
||||||
x: 0,
|
// x: 0,
|
||||||
y: 40
|
// y: 40
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
} else if (mech.crouch && ((playerHead.position.y - player.position.y) > 10)) {
|
} else if (mech.crouch && ((playerHead.position.y - player.position.y) > 10)) {
|
||||||
Matter.Body.translate(playerHead, {
|
Matter.Body.translate(playerHead, {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
|||||||
24
js/index.js
24
js/index.js
@@ -787,7 +787,7 @@ window.addEventListener("keydown", function(event) {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (game.testing) {
|
if (game.testing) {
|
||||||
switch (event.key) {
|
switch (event.key.toLowerCase()) {
|
||||||
case "o":
|
case "o":
|
||||||
game.isAutoZoom = false;
|
game.isAutoZoom = false;
|
||||||
game.zoomScale /= 0.9;
|
game.zoomScale /= 0.9;
|
||||||
@@ -1081,4 +1081,24 @@ function cycle() {
|
|||||||
// loop[i]()
|
// loop[i]()
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//display console logs in game
|
||||||
|
|
||||||
|
// function proxy(context, method, message) {
|
||||||
|
// return function() {
|
||||||
|
// // method.apply(context, [message].concat(Array.prototype.slice.apply(arguments)))
|
||||||
|
// game.makeTextLog(arguments[0], 300)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// console.log = proxy(console, console.log, 'n-gon: ')
|
||||||
|
// console.error = proxy(console, console.error, 'Error:')
|
||||||
|
// console.warn = proxy(console, console.warn, 'Warning:')
|
||||||
|
|
||||||
|
// let's test
|
||||||
|
// console.log('im from console.log', level, 2, 3);
|
||||||
|
// console.error('im from console.error', 1, 2, 3);
|
||||||
|
// console.warn('im from console.warn', 1, 2, 3);
|
||||||
20
js/level.js
20
js/level.js
@@ -13,17 +13,15 @@ const level = {
|
|||||||
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
|
||||||
// game.enableConstructMode() //used to build maps in testing mode
|
// game.enableConstructMode() //used to build maps in testing mode
|
||||||
// level.difficultyIncrease(19)
|
// level.difficultyIncrease(1)
|
||||||
// game.zoomScale = 1000;
|
// game.zoomScale = 1000;
|
||||||
// game.setZoom();
|
// game.setZoom();
|
||||||
// mech.setField("plasma torch")
|
// mech.setField("plasma torch")
|
||||||
// b.giveGuns("wave beam")
|
// b.giveGuns("wave beam")
|
||||||
// mod.giveMod("micro-extruder")
|
// mod.giveMod("CPT reversal")
|
||||||
// mod.giveMod("piezoelectricity")
|
// mod.giveMod("CPT gun")
|
||||||
// for (let i = 0; i < 15; i++) mod.giveMod("plasma jet")
|
// for (let i = 0; i < 15; i++) mod.giveMod("plasma jet")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
level.intro(); //starting level
|
level.intro(); //starting level
|
||||||
// level.testing(); //not in rotation
|
// level.testing(); //not in rotation
|
||||||
// level.finalBoss() //final boss level
|
// level.finalBoss() //final boss level
|
||||||
@@ -163,12 +161,12 @@ const level = {
|
|||||||
// spawn.launcherBoss(1200, -500)
|
// spawn.launcherBoss(1200, -500)
|
||||||
// spawn.laserTargetingBoss(1600, -400)
|
// spawn.laserTargetingBoss(1600, -400)
|
||||||
// spawn.striker(1600, -500)
|
// spawn.striker(1600, -500)
|
||||||
spawn.shooter(1700, -120)
|
// spawn.shooter(1700, -120)
|
||||||
// spawn.bomberBoss(1400, -500)
|
// spawn.bomberBoss(1400, -500)
|
||||||
// spawn.sniper(1800, -120)
|
// spawn.sniper(1800, -120)
|
||||||
// spawn.cellBossCulture(1600, -500)
|
// spawn.cellBossCulture(1600, -500)
|
||||||
// spawn.spiderBoss(1600, -500)
|
spawn.streamBoss(1600, -500)
|
||||||
// spawn.laser(1200, -500)
|
// spawn.beamer(1200, -500)
|
||||||
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
|
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
|
||||||
|
|
||||||
// spawn.nodeBoss(1200, -500, "launcher")
|
// spawn.nodeBoss(1200, -500, "launcher")
|
||||||
@@ -793,9 +791,9 @@ const level = {
|
|||||||
powerUps.spawnBossPowerUp(-125, -1760);
|
powerUps.spawnBossPowerUp(-125, -1760);
|
||||||
} else {
|
} else {
|
||||||
if (Math.random() < 0.5) {
|
if (Math.random() < 0.5) {
|
||||||
spawn.randomLevelBoss(700, -1550, ["shooterBoss", "launcherBoss", "laserTargetingBoss"]);
|
spawn.randomLevelBoss(700, -1550, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]);
|
||||||
} else {
|
} else {
|
||||||
spawn.randomLevelBoss(675, -2775, ["shooterBoss", "launcherBoss", "laserTargetingBoss"]);
|
spawn.randomLevelBoss(675, -2775, ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
powerUps.addRerollToLevel() //needs to run after mobs are spawned
|
powerUps.addRerollToLevel() //needs to run after mobs are spawned
|
||||||
@@ -942,7 +940,7 @@ const level = {
|
|||||||
spawn.randomMob(3600, 1725, 0.9);
|
spawn.randomMob(3600, 1725, 0.9);
|
||||||
spawn.randomMob(4100, 1225, 0.9);
|
spawn.randomMob(4100, 1225, 0.9);
|
||||||
spawn.randomMob(2825, 400, 0.9);
|
spawn.randomMob(2825, 400, 0.9);
|
||||||
if (game.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss"]);
|
if (game.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss"]);
|
||||||
powerUps.addRerollToLevel() //needs to run after mobs are spawned
|
powerUps.addRerollToLevel() //needs to run after mobs are spawned
|
||||||
},
|
},
|
||||||
satellite() {
|
satellite() {
|
||||||
|
|||||||
@@ -481,7 +481,7 @@ const mobs = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if (this.seePlayer.recall) {
|
if (this.seePlayer.recall && !this.isSlowed) {
|
||||||
this.torque = this.lookTorque * this.inertia * 2;
|
this.torque = this.lookTorque * this.inertia * 2;
|
||||||
|
|
||||||
const seeRange = 2500;
|
const seeRange = 2500;
|
||||||
|
|||||||
134
js/mods.js
134
js/mods.js
@@ -386,22 +386,6 @@ const mod = {
|
|||||||
mod.throwChargeRate = 1
|
mod.throwChargeRate = 1
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "fragmentation",
|
|
||||||
description: "detonation or collisions with mobs eject <strong>nails</strong><br><em>blocks, rail gun, grenades, shotgun slugs</em>",
|
|
||||||
maxCount: 9,
|
|
||||||
count: 0,
|
|
||||||
allowed() {
|
|
||||||
return (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("rail gun") || (mod.haveGunCheck("shotgun") && mod.isSlugShot) || mod.throwChargeRate > 1
|
|
||||||
},
|
|
||||||
requires: "grenades, rail gun, shotgun slugs, or mass driver",
|
|
||||||
effect() {
|
|
||||||
mod.fragments++
|
|
||||||
},
|
|
||||||
remove() {
|
|
||||||
mod.fragments = 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "ammonium nitrate",
|
name: "ammonium nitrate",
|
||||||
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>20%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>20%</strong>",
|
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>20%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>20%</strong>",
|
||||||
@@ -569,7 +553,7 @@ const mod = {
|
|||||||
b.nailBot();
|
b.nailBot();
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.nailBotCount = 0;
|
mod.nailBotCount -= this.count;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -608,7 +592,7 @@ const mod = {
|
|||||||
b.foamBot();
|
b.foamBot();
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.foamBotCount = 0;
|
mod.foamBotCount -= this.count;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -647,7 +631,7 @@ const mod = {
|
|||||||
b.boomBot();
|
b.boomBot();
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.boomBotCount = 0;
|
mod.boomBotCount -= this.count;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -686,7 +670,7 @@ const mod = {
|
|||||||
b.laserBot();
|
b.laserBot();
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.laserBotCount = 0;
|
mod.laserBotCount -= this.count;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -725,7 +709,7 @@ const mod = {
|
|||||||
mod.orbitBotCount++;
|
mod.orbitBotCount++;
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
mod.orbitBotCount = 0;
|
mod.orbitBotCount -= this.count;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1074,9 +1058,9 @@ const mod = {
|
|||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() { //&& (mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" || mech.maxEnergy > 1)
|
allowed() { //&& (mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" || mech.maxEnergy > 1)
|
||||||
return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !mod.isEnergyHealth
|
return mech.maxEnergy > 0.99 && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !mod.isEnergyHealth && !mod.isRewindGun
|
||||||
},
|
},
|
||||||
requires: "standing wave, mass-energy, piezoelectricity, max energy reduction",
|
requires: "not standing wave, mass-energy, piezo, max energy reduction, CPT gun",
|
||||||
effect() {
|
effect() {
|
||||||
mod.isRewindAvoidDeath = true;
|
mod.isRewindAvoidDeath = true;
|
||||||
},
|
},
|
||||||
@@ -1135,13 +1119,13 @@ const mod = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "ground state",
|
name: "ground state",
|
||||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>66%</strong><br>you <strong>no longer</strong> passively regenerate <strong class='color-f'>energy</strong>",
|
description: "reduce <strong class='color-harm'>harm</strong> by <strong>60%</strong><br>you <strong>no longer</strong> passively regenerate <strong class='color-f'>energy</strong>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
return mod.isPiezo && mod.energyRegen !== 0.004
|
return (mod.iceEnergy || mod.isWormholeEnergy || mod.isPiezo || mod.isRailEnergyGain) && mod.energyRegen !== 0.004
|
||||||
},
|
},
|
||||||
requires: "piezoelectricity, not time crystals",
|
requires: "piezoelectricity, Penrose, half-wave, or thermoelectric, but not time crystals",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
mod.energyRegen = 0;
|
mod.energyRegen = 0;
|
||||||
mech.fieldRegen = mod.energyRegen;
|
mech.fieldRegen = mod.energyRegen;
|
||||||
@@ -1157,7 +1141,7 @@ const mod = {
|
|||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field"
|
return !mod.isEnergyLoss && !mod.isPiezo && !mod.isRewindAvoidDeath && !mod.isRewindGun && !mod.isSpeedHarm && mech.fieldUpgrades[mech.fieldMode].name !== "negative mass field"
|
||||||
},
|
},
|
||||||
requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass",
|
requires: "not exothermic process, piezoelectricity, CPT, 1st law, negative mass",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
@@ -1328,13 +1312,13 @@ const mod = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "transceiver chip",
|
name: "transceiver chip",
|
||||||
description: "at the end of each <strong>level</strong><br>gain the full <strong>effect</strong> of unused <strong>power ups</strong>",
|
description: "unused <strong>power ups</strong> at the end of each <strong>level</strong><br>are still activated <em>(selections are random)</em>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
allowed() {
|
allowed() {
|
||||||
return mod.isArmorFromPowerUps
|
return mod.isArmorFromPowerUps
|
||||||
},
|
},
|
||||||
requires: "crystallized armor",
|
requires: "inductive coupling",
|
||||||
effect() {
|
effect() {
|
||||||
mod.isEndLevelPowerUp = true;
|
mod.isEndLevelPowerUp = true;
|
||||||
},
|
},
|
||||||
@@ -1535,7 +1519,7 @@ const mod = {
|
|||||||
if (mod.mods[i].count > 0) have.push(i)
|
if (mod.mods[i].count > 0) have.push(i)
|
||||||
}
|
}
|
||||||
const choose = have[Math.floor(Math.random() * have.length)]
|
const choose = have[Math.floor(Math.random() * have.length)]
|
||||||
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> removed by reallocation`, 300)
|
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> removed by monte carlo experiment`, 300)
|
||||||
for (let i = 0; i < mod.mods[choose].count; i++) {
|
for (let i = 0; i < mod.mods[choose].count; i++) {
|
||||||
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
||||||
}
|
}
|
||||||
@@ -1935,10 +1919,50 @@ const mod = {
|
|||||||
//**************************************************
|
//**************************************************
|
||||||
//************************************************** gun
|
//************************************************** gun
|
||||||
//************************************************** mods
|
//************************************************** mods
|
||||||
//**************************************************
|
//**************************************************
|
||||||
|
{
|
||||||
|
name: "CPT gun",
|
||||||
|
description: "adds the <strong>CPT</strong> <strong class='color-g'>gun</strong> to your inventory<br>it <strong>rewinds</strong> your <strong class='color-h'>health</strong>, <strong>velocity</strong>, and <strong>position</strong>",
|
||||||
|
isGunMod: true,
|
||||||
|
maxCount: 1,
|
||||||
|
count: 0,
|
||||||
|
allowed() {
|
||||||
|
return (mod.totalBots() > 5 || mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" || mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" || mech.fieldUpgrades[mech.fieldMode].name === "pilot wave") && !mod.isEnergyHealth && !mod.isRewindAvoidDeath
|
||||||
|
},
|
||||||
|
requires: "bots > 5, plasma torch, nano-scale, pilot wave, not mass-energy equivalence, CPT",
|
||||||
|
effect() {
|
||||||
|
mod.isRewindGun = true
|
||||||
|
b.guns.push(b.gunRewind)
|
||||||
|
b.giveGuns("CPT gun");
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
if (mod.isRewindGun) {
|
||||||
|
for (let i = 0; i < b.guns.length; i++) {
|
||||||
|
if (b.guns[i].name === "CPT gun") {
|
||||||
|
for (let j = 0; j < b.inventory.length; j++) {
|
||||||
|
if (b.inventory[j] === i) {
|
||||||
|
b.inventory.splice(j, 1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (b.inventory.length) {
|
||||||
|
b.activeGun = b.inventory[0];
|
||||||
|
} else {
|
||||||
|
b.activeGun = null;
|
||||||
|
}
|
||||||
|
game.makeGunHUD();
|
||||||
|
|
||||||
|
b.guns.splice(i, 1) //also remove CPT gun from gun pool array
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mod.isRewindGun = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "incendiary ammunition",
|
name: "incendiary ammunition",
|
||||||
description: "<strong>bullets</strong> are loaded with <strong class='color-e'>explosives</strong><br><em style = 'font-size: 90%'>nail gun, shotgun, super balls, drones</em>",
|
description: "some <strong>bullets</strong> are loaded with <strong class='color-e'>explosives</strong><br><em style = 'font-size: 90%'>nail gun, shotgun, super balls, drones</em>",
|
||||||
isGunMod: true,
|
isGunMod: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -1953,9 +1977,26 @@ const mod = {
|
|||||||
mod.isIncendiary = false;
|
mod.isIncendiary = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "fragmentation",
|
||||||
|
description: "some <strong class='color-e'>detonations</strong> and collisions eject <strong>nails</strong><br><em style = 'font-size: 90%'>blocks, rail gun, grenades, missiles, shotgun slugs</em>",
|
||||||
|
isGunMod: true,
|
||||||
|
maxCount: 9,
|
||||||
|
count: 0,
|
||||||
|
allowed() {
|
||||||
|
return (mod.haveGunCheck("grenades") && !mod.isNeutronBomb) || mod.haveGunCheck("missiles") || mod.haveGunCheck("rail gun") || (mod.haveGunCheck("shotgun") && mod.isSlugShot) || mod.throwChargeRate > 1
|
||||||
|
},
|
||||||
|
requires: "grenades, missiles, rail gun, shotgun slugs, or mass driver",
|
||||||
|
effect() {
|
||||||
|
mod.fragments++
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
mod.fragments = 0
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "Lorentzian topology",
|
name: "Lorentzian topology",
|
||||||
description: "<strong>bullets</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, ice IX, neutron</em>",
|
description: "some <strong>bullets</strong> last <strong>30% longer</strong><br><em style = 'font-size: 83%'>drones, spores, missiles, foam, wave, ice IX, neutron</em>",
|
||||||
isGunMod: true,
|
isGunMod: true,
|
||||||
maxCount: 3,
|
maxCount: 3,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -2783,7 +2824,7 @@ const mod = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "colloidal foam",
|
name: "colloidal foam",
|
||||||
description: "increase <strong>foam</strong> <strong class='color-d'>damage</strong> by <strong>200%</strong><br><strong>foam</strong> dissipates <strong>40%</strong> faster",
|
description: "increase <strong>foam</strong> <strong class='color-d'>damage</strong> by <strong>366%</strong><br><strong>foam</strong> dissipates <strong>40%</strong> faster",
|
||||||
isGunMod: true,
|
isGunMod: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -3259,8 +3300,8 @@ const mod = {
|
|||||||
mod.giveMod("orbital-bot upgrade")
|
mod.giveMod("orbital-bot upgrade")
|
||||||
mod.setModToNonRefundable("orbital-bot upgrade")
|
mod.setModToNonRefundable("orbital-bot upgrade")
|
||||||
for (let i = 0; i < 2; i++) {
|
for (let i = 0; i < 2; i++) {
|
||||||
b.orbitalBot()
|
b.orbitBot()
|
||||||
mod.orbitalBotCount++;
|
mod.orbitBotCount++;
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
//choose random function from the array and run it
|
//choose random function from the array and run it
|
||||||
@@ -3370,6 +3411,23 @@ const mod = {
|
|||||||
mod.isFreezeMobs = false
|
mod.isFreezeMobs = false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// name: "thermal reservoir",
|
||||||
|
// description: "increase your <strong class='color-plasma'>plasma</strong> <strong class='color-d'>damage</strong> by <strong>100%</strong><br><strong class='color-plasma'>plasma</strong> temporarily lowers health not <strong class='color-f'>energy</strong>",
|
||||||
|
// isFieldMod: true,
|
||||||
|
// maxCount: 1,
|
||||||
|
// count: 0,
|
||||||
|
// allowed() {
|
||||||
|
// return mech.fieldUpgrades[mech.fieldMode].name === "plasma torch" && !mod.isEnergyHealth
|
||||||
|
// },
|
||||||
|
// requires: "plasma torch, not mass-energy equivalence",
|
||||||
|
// effect() {
|
||||||
|
// mod.isPlasmaRange += 0.27;
|
||||||
|
// },
|
||||||
|
// remove() {
|
||||||
|
// mod.isPlasmaRange = 1;
|
||||||
|
// }
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
name: "plasma jet",
|
name: "plasma jet",
|
||||||
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>27%</strong>",
|
description: "increase <strong class='color-plasma'>plasma</strong> <strong>torch's</strong> range by <strong>27%</strong>",
|
||||||
@@ -3874,5 +3932,7 @@ const mod = {
|
|||||||
isRewindBot: null,
|
isRewindBot: null,
|
||||||
isRewindGrenade: null,
|
isRewindGrenade: null,
|
||||||
isExtruder: null,
|
isExtruder: null,
|
||||||
isEndLevelPowerUp: null
|
isEndLevelPowerUp: null,
|
||||||
|
isRewindGun: null
|
||||||
|
|
||||||
}
|
}
|
||||||
507
js/player.js
507
js/player.js
@@ -103,6 +103,7 @@ const mech = {
|
|||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
},
|
},
|
||||||
|
yPosDifference: 24.285923217549026, //player.position.y - mech.pos.y
|
||||||
Sy: 0, //adds a smoothing effect to vertical only
|
Sy: 0, //adds a smoothing effect to vertical only
|
||||||
Vx: 0,
|
Vx: 0,
|
||||||
Vy: 0,
|
Vy: 0,
|
||||||
@@ -135,11 +136,11 @@ const mech = {
|
|||||||
transY: 0,
|
transY: 0,
|
||||||
history: [], //tracks the last second of player position
|
history: [], //tracks the last second of player position
|
||||||
resetHistory() {
|
resetHistory() {
|
||||||
for (let i = 0; i < 300; i++) { //reset history
|
for (let i = 0; i < 600; i++) { //reset history
|
||||||
mech.history[i] = {
|
mech.history[i] = {
|
||||||
position: {
|
position: {
|
||||||
x: mech.pos.x,
|
x: player.position.x,
|
||||||
y: mech.pos.y,
|
y: player.position.y,
|
||||||
},
|
},
|
||||||
velocity: {
|
velocity: {
|
||||||
x: player.velocity.x,
|
x: player.velocity.x,
|
||||||
@@ -159,10 +160,10 @@ const mech = {
|
|||||||
|
|
||||||
//tracks the last second of player information
|
//tracks the last second of player information
|
||||||
// console.log(mech.history)
|
// console.log(mech.history)
|
||||||
mech.history.splice(mech.cycle % 300, 1, {
|
mech.history.splice(mech.cycle % 600, 1, {
|
||||||
position: {
|
position: {
|
||||||
x: mech.pos.x,
|
x: player.position.x,
|
||||||
y: mech.pos.y,
|
y: player.position.y,
|
||||||
},
|
},
|
||||||
velocity: {
|
velocity: {
|
||||||
x: player.velocity.x,
|
x: player.velocity.x,
|
||||||
@@ -461,14 +462,14 @@ const mech = {
|
|||||||
if (mod.isBotArmor) dmg *= 0.97 ** mod.totalBots()
|
if (mod.isBotArmor) dmg *= 0.97 ** mod.totalBots()
|
||||||
if (mod.isHarmArmor && mech.lastHarmCycle + 600 > mech.cycle) dmg *= 0.33;
|
if (mod.isHarmArmor && mech.lastHarmCycle + 600 > mech.cycle) dmg *= 0.33;
|
||||||
if (mod.isNoFireDefense && mech.cycle > mech.fireCDcycle + 120) dmg *= 0.6
|
if (mod.isNoFireDefense && mech.cycle > mech.fireCDcycle + 120) dmg *= 0.6
|
||||||
if (mod.energyRegen === 0) dmg *= 0.33 //0.22 + 0.78 * mech.energy //77% damage reduction at zero energy
|
if (mod.energyRegen === 0) dmg *= 0.4
|
||||||
if (mod.isTurret && mech.crouch) dmg *= 0.5;
|
if (mod.isTurret && mech.crouch) dmg *= 0.5;
|
||||||
if (mod.isEntanglement && b.inventory[0] === b.activeGun) {
|
if (mod.isEntanglement && b.inventory[0] === b.activeGun) {
|
||||||
for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15
|
for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15
|
||||||
}
|
}
|
||||||
return dmg
|
return dmg
|
||||||
},
|
},
|
||||||
rewind(steps) {
|
rewind(steps) { // mech.rewind(Math.floor(Math.min(599, 137 * mech.energy)))
|
||||||
if (mod.isRewindGrenade) {
|
if (mod.isRewindGrenade) {
|
||||||
for (let i = 1, len = Math.floor(2 + steps / 40); i < len; i++) {
|
for (let i = 1, len = Math.floor(2 + steps / 40); i < len; i++) {
|
||||||
b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
|
b.grenade(Vector.add(mech.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
|
||||||
@@ -494,7 +495,7 @@ const mech = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let history = mech.history[(mech.cycle - steps) % 300]
|
let history = mech.history[(mech.cycle - steps) % 600]
|
||||||
Matter.Body.setPosition(player, history.position);
|
Matter.Body.setPosition(player, history.position);
|
||||||
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
|
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
|
||||||
// move bots to follow player
|
// move bots to follow player
|
||||||
@@ -529,7 +530,7 @@ const mech = {
|
|||||||
ctx.scale(game.zoom / game.edgeZoomOutSmooth, game.zoom / game.edgeZoomOutSmooth); //zoom in once centered
|
ctx.scale(game.zoom / game.edgeZoomOutSmooth, game.zoom / game.edgeZoomOutSmooth); //zoom in once centered
|
||||||
ctx.translate(-canvas.width2 + mech.transX, -canvas.height2 + mech.transY); //translate
|
ctx.translate(-canvas.width2 + mech.transX, -canvas.height2 + mech.transY); //translate
|
||||||
for (let i = 1; i < steps; i++) {
|
for (let i = 1; i < steps; i++) {
|
||||||
history = mech.history[(mech.cycle - i) % 300]
|
history = mech.history[(mech.cycle - i) % 600]
|
||||||
mech.pos.x = history.position.x
|
mech.pos.x = history.position.x
|
||||||
mech.pos.y = history.position.y
|
mech.pos.y = history.position.y
|
||||||
mech.draw();
|
mech.draw();
|
||||||
@@ -547,7 +548,7 @@ const mech = {
|
|||||||
if (mod.isRewindBot) {
|
if (mod.isRewindBot) {
|
||||||
const len = steps * 0.042 * mod.isRewindBot
|
const len = steps * 0.042 * mod.isRewindBot
|
||||||
for (let i = 0; i < len; i++) {
|
for (let i = 0; i < len; i++) {
|
||||||
const where = mech.history[Math.abs(mech.cycle - i * 40) % 300].position //spread out spawn locations along past history
|
const where = mech.history[Math.abs(mech.cycle - i * 40) % 600].position //spread out spawn locations along past history
|
||||||
b.randomBot({
|
b.randomBot({
|
||||||
x: where.x + 100 * (Math.random() - 0.5),
|
x: where.x + 100 * (Math.random() - 0.5),
|
||||||
y: where.y + 100 * (Math.random() - 0.5)
|
y: where.y + 100 * (Math.random() - 0.5)
|
||||||
@@ -558,8 +559,7 @@ const mech = {
|
|||||||
},
|
},
|
||||||
damage(dmg) {
|
damage(dmg) {
|
||||||
if (mod.isRewindAvoidDeath && mech.energy > 0.66) {
|
if (mod.isRewindAvoidDeath && mech.energy > 0.66) {
|
||||||
const steps = Math.floor(Math.min(299, 137 * mech.energy))
|
mech.rewind(Math.floor(Math.min(299, 137 * mech.energy)))
|
||||||
mech.rewind(steps)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
mech.lastHarmCycle = mech.cycle
|
mech.lastHarmCycle = mech.cycle
|
||||||
@@ -764,7 +764,7 @@ const mech = {
|
|||||||
ctx.stroke();
|
ctx.stroke();
|
||||||
// ctx.beginPath();
|
// ctx.beginPath();
|
||||||
// ctx.arc(15, 0, 3, 0, 2 * Math.PI);
|
// ctx.arc(15, 0, 3, 0, 2 * Math.PI);
|
||||||
// ctx.fillStyle = '#9cf' //'#0cf';
|
// ctx.fillStyle = '#0cf';
|
||||||
// ctx.fill()
|
// ctx.fill()
|
||||||
ctx.restore();
|
ctx.restore();
|
||||||
mech.yOff = mech.yOff * 0.85 + mech.yOffGoal * 0.15; //smoothly move leg height towards height goal
|
mech.yOff = mech.yOff * 0.85 + mech.yOffGoal * 0.15; //smoothly move leg height towards height goal
|
||||||
@@ -2194,11 +2194,104 @@ const mech = {
|
|||||||
{
|
{
|
||||||
name: "wormhole",
|
name: "wormhole",
|
||||||
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract blocks and power ups<br><strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
|
||||||
effect: () => {
|
effect: function() {
|
||||||
game.replaceTextLog = true; //allow text over write
|
game.replaceTextLog = true; //allow text over write
|
||||||
mech.drop();
|
mech.drop();
|
||||||
mech.duplicateChance = 0.1
|
mech.duplicateChance = 0.1
|
||||||
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
||||||
|
|
||||||
|
// if (mod.isRewindGun) {
|
||||||
|
// mech.hold = this.rewind
|
||||||
|
// } else {
|
||||||
|
mech.hold = this.teleport
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
rewindCount: 0,
|
||||||
|
// rewind: function() {
|
||||||
|
// if (input.down) {
|
||||||
|
// if (input.field && mech.fieldCDcycle < mech.cycle) { //not hold but field button is pressed
|
||||||
|
// const DRAIN = 0.01
|
||||||
|
// if (this.rewindCount < 289 && mech.energy > DRAIN) {
|
||||||
|
// mech.energy -= DRAIN
|
||||||
|
|
||||||
|
|
||||||
|
// if (this.rewindCount === 0) {
|
||||||
|
// const shortPause = function() {
|
||||||
|
// if (mech.defaultFPSCycle < mech.cycle) { //back to default values
|
||||||
|
// game.fpsCap = game.fpsCapDefault
|
||||||
|
// game.fpsInterval = 1000 / game.fpsCap;
|
||||||
|
// // document.getElementById("dmg").style.transition = "opacity 1s";
|
||||||
|
// // document.getElementById("dmg").style.opacity = "0";
|
||||||
|
// } else {
|
||||||
|
// requestAnimationFrame(shortPause);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
|
||||||
|
// game.fpsCap = 4 //1 is longest pause, 4 is standard
|
||||||
|
// game.fpsInterval = 1000 / game.fpsCap;
|
||||||
|
// mech.defaultFPSCycle = mech.cycle
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
// this.rewindCount += 10;
|
||||||
|
// game.wipe = function() { //set wipe to have trails
|
||||||
|
// // ctx.fillStyle = "rgba(255,255,255,0)";
|
||||||
|
// ctx.fillStyle = `rgba(221,221,221,${0.004})`;
|
||||||
|
// ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||||
|
// }
|
||||||
|
// let history = mech.history[(mech.cycle - this.rewindCount) % 300]
|
||||||
|
// Matter.Body.setPosition(player, history.position);
|
||||||
|
// Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
|
||||||
|
// if (history.health > mech.health) {
|
||||||
|
// mech.health = history.health
|
||||||
|
// mech.displayHealth();
|
||||||
|
// }
|
||||||
|
// //grab power ups
|
||||||
|
// for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||||
|
// const dxP = player.position.x - powerUp[i].position.x;
|
||||||
|
// const dyP = player.position.y - powerUp[i].position.y;
|
||||||
|
// if (dxP * dxP + dyP * dyP < 50000 && !game.isChoosing && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
||||||
|
// powerUps.onPickUp(player.position);
|
||||||
|
// powerUp[i].effect();
|
||||||
|
// Matter.World.remove(engine.world, powerUp[i]);
|
||||||
|
// powerUp.splice(i, 1);
|
||||||
|
// const shortPause = function() {
|
||||||
|
// if (mech.defaultFPSCycle < mech.cycle) { //back to default values
|
||||||
|
// game.fpsCap = game.fpsCapDefault
|
||||||
|
// game.fpsInterval = 1000 / game.fpsCap;
|
||||||
|
// // document.getElementById("dmg").style.transition = "opacity 1s";
|
||||||
|
// // document.getElementById("dmg").style.opacity = "0";
|
||||||
|
// } else {
|
||||||
|
// requestAnimationFrame(shortPause);
|
||||||
|
// }
|
||||||
|
// };
|
||||||
|
// if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
|
||||||
|
// game.fpsCap = 3 //1 is longest pause, 4 is standard
|
||||||
|
// game.fpsInterval = 1000 / game.fpsCap;
|
||||||
|
// mech.defaultFPSCycle = mech.cycle
|
||||||
|
// break; //because the array order is messed up after splice
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// mech.immuneCycle = mech.cycle + 5; //player is immune to collision damage for 30 cycles
|
||||||
|
// } else {
|
||||||
|
// mech.fieldCDcycle = mech.cycle + 30;
|
||||||
|
// // mech.resetHistory();
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// if (this.rewindCount !== 0) {
|
||||||
|
// mech.fieldCDcycle = mech.cycle + 30;
|
||||||
|
// mech.resetHistory();
|
||||||
|
// this.rewindCount = 0;
|
||||||
|
// game.wipe = function() { //set wipe to normal
|
||||||
|
// ctx.clearRect(0, 0, canvas.width, canvas.height);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// mech.drawFieldMeter()
|
||||||
|
// },
|
||||||
|
teleport: function() {
|
||||||
// mech.hole = { //this is reset with each new field, but I'm leaving it here for reference
|
// mech.hole = { //this is reset with each new field, but I'm leaving it here for reference
|
||||||
// isOn: false,
|
// isOn: false,
|
||||||
// isReady: true,
|
// isReady: true,
|
||||||
@@ -2207,237 +2300,235 @@ const mech = {
|
|||||||
// angle: 0,
|
// angle: 0,
|
||||||
// unit:{x:0,y:0},
|
// unit:{x:0,y:0},
|
||||||
// }
|
// }
|
||||||
mech.hold = function() {
|
if (mech.hole.isOn) {
|
||||||
if (mech.hole.isOn) {
|
// draw holes
|
||||||
// draw holes
|
mech.fieldRange = 0.97 * mech.fieldRange + 0.03 * (50 + 10 * Math.sin(game.cycle * 0.025))
|
||||||
mech.fieldRange = 0.97 * mech.fieldRange + 0.03 * (50 + 10 * Math.sin(game.cycle * 0.025))
|
const semiMajorAxis = mech.fieldRange + 30
|
||||||
const semiMajorAxis = mech.fieldRange + 30
|
const edge1a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos1)
|
||||||
const edge1a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos1)
|
const edge1b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos1)
|
||||||
const edge1b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos1)
|
const edge2a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos2)
|
||||||
const edge2a = Vector.add(Vector.mult(mech.hole.unit, semiMajorAxis), mech.hole.pos2)
|
const edge2b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos2)
|
||||||
const edge2b = Vector.add(Vector.mult(mech.hole.unit, -semiMajorAxis), mech.hole.pos2)
|
ctx.beginPath();
|
||||||
ctx.beginPath();
|
ctx.moveTo(edge1a.x, edge1a.y)
|
||||||
ctx.moveTo(edge1a.x, edge1a.y)
|
ctx.bezierCurveTo(mech.hole.pos1.x, mech.hole.pos1.y, mech.hole.pos2.x, mech.hole.pos2.y, edge2a.x, edge2a.y);
|
||||||
ctx.bezierCurveTo(mech.hole.pos1.x, mech.hole.pos1.y, mech.hole.pos2.x, mech.hole.pos2.y, edge2a.x, edge2a.y);
|
ctx.lineTo(edge2b.x, edge2b.y)
|
||||||
ctx.lineTo(edge2b.x, edge2b.y)
|
ctx.bezierCurveTo(mech.hole.pos2.x, mech.hole.pos2.y, mech.hole.pos1.x, mech.hole.pos1.y, edge1b.x, edge1b.y);
|
||||||
ctx.bezierCurveTo(mech.hole.pos2.x, mech.hole.pos2.y, mech.hole.pos1.x, mech.hole.pos1.y, edge1b.x, edge1b.y);
|
ctx.fillStyle = `rgba(255,255,255,${200 / mech.fieldRange / mech.fieldRange})` //"rgba(0,0,0,0.1)"
|
||||||
ctx.fillStyle = `rgba(255,255,255,${200 / mech.fieldRange / mech.fieldRange})` //"rgba(0,0,0,0.1)"
|
ctx.fill();
|
||||||
ctx.fill();
|
ctx.beginPath();
|
||||||
ctx.beginPath();
|
ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
||||||
ctx.ellipse(mech.hole.pos1.x, mech.hole.pos1.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
||||||
ctx.ellipse(mech.hole.pos2.x, mech.hole.pos2.y, mech.fieldRange, semiMajorAxis, mech.hole.angle, 0, 2 * Math.PI)
|
ctx.fillStyle = `rgba(255,255,255,${32 / mech.fieldRange})`
|
||||||
ctx.fillStyle = `rgba(255,255,255,${32 / mech.fieldRange})`
|
ctx.fill();
|
||||||
ctx.fill();
|
|
||||||
|
|
||||||
//suck power ups
|
//suck power ups
|
||||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||||
//which hole is closer
|
//which hole is closer
|
||||||
const dxP1 = mech.hole.pos1.x - powerUp[i].position.x;
|
const dxP1 = mech.hole.pos1.x - powerUp[i].position.x;
|
||||||
const dyP1 = mech.hole.pos1.y - powerUp[i].position.y;
|
const dyP1 = mech.hole.pos1.y - powerUp[i].position.y;
|
||||||
const dxP2 = mech.hole.pos2.x - powerUp[i].position.x;
|
const dxP2 = mech.hole.pos2.x - powerUp[i].position.x;
|
||||||
const dyP2 = mech.hole.pos2.y - powerUp[i].position.y;
|
const dyP2 = mech.hole.pos2.y - powerUp[i].position.y;
|
||||||
let dxP, dyP, dist2
|
let dxP, dyP, dist2
|
||||||
if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
|
if (dxP1 * dxP1 + dyP1 * dyP1 < dxP2 * dxP2 + dyP2 * dyP2) {
|
||||||
dxP = dxP1
|
dxP = dxP1
|
||||||
dyP = dyP1
|
dyP = dyP1
|
||||||
} else {
|
} else {
|
||||||
dxP = dxP2
|
dxP = dxP2
|
||||||
dyP = dyP2
|
dyP = dyP2
|
||||||
}
|
}
|
||||||
dist2 = dxP * dxP + dyP * dyP;
|
dist2 = dxP * dxP + dyP * dyP;
|
||||||
if (dist2 < 600000 && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
if (dist2 < 600000 && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
||||||
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
|
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
|
||||||
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
||||||
Matter.Body.setVelocity(powerUp[i], { //extra friction
|
Matter.Body.setVelocity(powerUp[i], { //extra friction
|
||||||
x: powerUp[i].velocity.x * 0.05,
|
x: powerUp[i].velocity.x * 0.05,
|
||||||
y: powerUp[i].velocity.y * 0.05
|
y: powerUp[i].velocity.y * 0.05
|
||||||
});
|
});
|
||||||
if (dist2 < 1000 && !game.isChoosing) { //use power up if it is close enough
|
if (dist2 < 1000 && !game.isChoosing) { //use power up if it is close enough
|
||||||
mech.fieldRange *= 0.8
|
mech.fieldRange *= 0.8
|
||||||
powerUps.onPickUp(powerUp[i].position);
|
powerUps.onPickUp(powerUp[i].position);
|
||||||
powerUp[i].effect();
|
powerUp[i].effect();
|
||||||
Matter.World.remove(engine.world, powerUp[i]);
|
Matter.World.remove(engine.world, powerUp[i]);
|
||||||
powerUp.splice(i, 1);
|
powerUp.splice(i, 1);
|
||||||
break; //because the array order is messed up after splice
|
break; //because the array order is messed up after splice
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//suck and shrink blocks
|
}
|
||||||
const suckRange = 500
|
//suck and shrink blocks
|
||||||
const shrinkRange = 100
|
const suckRange = 500
|
||||||
const shrinkScale = 0.97;
|
const shrinkRange = 100
|
||||||
const slowScale = 0.9
|
const shrinkScale = 0.97;
|
||||||
for (let i = 0, len = body.length; i < len; i++) {
|
const slowScale = 0.9
|
||||||
if (!body[i].isNotHoldable) {
|
for (let i = 0, len = body.length; i < len; i++) {
|
||||||
const dist1 = Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position))
|
if (!body[i].isNotHoldable) {
|
||||||
const dist2 = Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position))
|
const dist1 = Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position))
|
||||||
if (dist1 < dist2) {
|
const dist2 = Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position))
|
||||||
if (dist1 < suckRange) {
|
if (dist1 < dist2) {
|
||||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, body[i].position)), 1)
|
if (dist1 < suckRange) {
|
||||||
const slow = Vector.mult(body[i].velocity, slowScale)
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, body[i].position)), 1)
|
||||||
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
|
||||||
//shrink
|
|
||||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position)) < shrinkRange) {
|
|
||||||
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
|
||||||
if (body[i].mass < 0.05) {
|
|
||||||
Matter.World.remove(engine.world, body[i]);
|
|
||||||
body.splice(i, 1);
|
|
||||||
mech.fieldRange *= 0.8
|
|
||||||
if (mod.isWormholeEnergy) mech.energy += 0.5
|
|
||||||
if (mod.isWormSpores) { //pandimensionalspermia
|
|
||||||
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
|
|
||||||
b.spore(Vector.add(mech.hole.pos2, Vector.rotate({
|
|
||||||
x: mech.fieldRange * 0.4,
|
|
||||||
y: 0
|
|
||||||
}, 2 * Math.PI * Math.random())))
|
|
||||||
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), -15));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dist2 < suckRange) {
|
|
||||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, body[i].position)), 1)
|
|
||||||
const slow = Vector.mult(body[i].velocity, slowScale)
|
const slow = Vector.mult(body[i].velocity, slowScale)
|
||||||
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
||||||
//shrink
|
//shrink
|
||||||
if (Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position)) < shrinkRange) {
|
if (Vector.magnitude(Vector.sub(mech.hole.pos1, body[i].position)) < shrinkRange) {
|
||||||
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
||||||
if (body[i].mass < 0.05) {
|
if (body[i].mass < 0.05) {
|
||||||
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 * 2) mech.energy = mech.maxEnergy * 2
|
|
||||||
if (mod.isWormholeEnergy) mech.energy += 0.5
|
if (mod.isWormholeEnergy) mech.energy += 0.5
|
||||||
if (mod.isWormSpores) { //pandimensionalspermia
|
if (mod.isWormSpores) { //pandimensionalspermia
|
||||||
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
|
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
|
||||||
b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
|
b.spore(Vector.add(mech.hole.pos2, Vector.rotate({
|
||||||
x: mech.fieldRange * 0.4,
|
x: mech.fieldRange * 0.4,
|
||||||
y: 0
|
y: 0
|
||||||
}, 2 * Math.PI * Math.random())))
|
}, 2 * Math.PI * Math.random())))
|
||||||
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15));
|
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), -15));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if (dist2 < suckRange) {
|
||||||
}
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, body[i].position)), 1)
|
||||||
if (mod.isWormBullets) {
|
const slow = Vector.mult(body[i].velocity, slowScale)
|
||||||
//teleport bullets
|
Matter.Body.setVelocity(body[i], Vector.add(slow, pull));
|
||||||
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
|
//shrink
|
||||||
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
|
if (Vector.magnitude(Vector.sub(mech.hole.pos2, body[i].position)) < shrinkRange) {
|
||||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
Matter.Body.scale(body[i], shrinkScale, shrinkScale);
|
||||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position)));
|
if (body[i].mass < 0.05) {
|
||||||
mech.fieldRange += 5
|
Matter.World.remove(engine.world, body[i]);
|
||||||
bullet[i].isInHole = true
|
body.splice(i, 1);
|
||||||
} else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
mech.fieldRange *= 0.8
|
||||||
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position)));
|
// if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 2) mech.energy = mech.maxEnergy * 2
|
||||||
mech.fieldRange += 5
|
if (mod.isWormholeEnergy) mech.energy += 0.5
|
||||||
bullet[i].isInHole = true
|
if (mod.isWormSpores) { //pandimensionalspermia
|
||||||
|
for (let i = 0, len = Math.ceil(3 * Math.random()); i < len; i++) {
|
||||||
|
b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
|
||||||
|
x: mech.fieldRange * 0.4,
|
||||||
|
y: 0
|
||||||
|
}, 2 * Math.PI * Math.random())))
|
||||||
|
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// mobs get pushed away
|
|
||||||
for (let i = 0, len = mob.length; i < len; i++) {
|
|
||||||
if (Vector.magnitude(Vector.sub(mech.hole.pos1, mob[i].position)) < 200) {
|
|
||||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), -0.07)
|
|
||||||
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
|
||||||
}
|
|
||||||
if (Vector.magnitude(Vector.sub(mech.hole.pos2, mob[i].position)) < 200) {
|
|
||||||
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), -0.07)
|
|
||||||
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (mod.isWormBullets) {
|
||||||
|
//teleport bullets
|
||||||
|
for (let i = 0, len = bullet.length; i < len; ++i) { //teleport bullets from hole1 to hole2
|
||||||
|
if (!bullet[i].botType && !bullet[i].isInHole) { //don't teleport bots
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos1, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||||
|
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos2, Vector.sub(mech.hole.pos1, bullet[i].position)));
|
||||||
|
mech.fieldRange += 5
|
||||||
|
bullet[i].isInHole = true
|
||||||
|
} else if (Vector.magnitude(Vector.sub(mech.hole.pos2, bullet[i].position)) < mech.fieldRange) { //find if bullet is touching hole1
|
||||||
|
Matter.Body.setPosition(bullet[i], Vector.add(mech.hole.pos1, Vector.sub(mech.hole.pos2, bullet[i].position)));
|
||||||
|
mech.fieldRange += 5
|
||||||
|
bullet[i].isInHole = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// mobs get pushed away
|
||||||
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos1, mob[i].position)) < 200) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos1, mob[i].position)), -0.07)
|
||||||
|
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
||||||
|
}
|
||||||
|
if (Vector.magnitude(Vector.sub(mech.hole.pos2, mob[i].position)) < 200) {
|
||||||
|
const pull = Vector.mult(Vector.normalise(Vector.sub(mech.hole.pos2, mob[i].position)), -0.07)
|
||||||
|
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, pull));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
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 justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(game.mouseInGame, mech.pos)), 50), game.mouseInGame)
|
||||||
const scale = 60
|
const scale = 60
|
||||||
// console.log(Matter.Query.region(map, bounds))
|
// console.log(Matter.Query.region(map, bounds))
|
||||||
if (mech.hole.isReady &&
|
if (mech.hole.isReady &&
|
||||||
(
|
(
|
||||||
Matter.Query.region(map, {
|
Matter.Query.region(map, {
|
||||||
min: {
|
min: {
|
||||||
x: game.mouseInGame.x - scale,
|
x: game.mouseInGame.x - scale,
|
||||||
y: game.mouseInGame.y - scale
|
y: game.mouseInGame.y - scale
|
||||||
},
|
},
|
||||||
max: {
|
max: {
|
||||||
x: game.mouseInGame.x + scale,
|
x: game.mouseInGame.x + scale,
|
||||||
y: game.mouseInGame.y + scale
|
y: game.mouseInGame.y + scale
|
||||||
}
|
}
|
||||||
}).length === 0 &&
|
}).length === 0 &&
|
||||||
Matter.Query.ray(map, mech.pos, justPastMouse).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, mech.pos, game.mouseInGame).length === 0 &&
|
||||||
// Matter.Query.ray(map, player.position, game.mouseInGame).length === 0 &&
|
// Matter.Query.ray(map, player.position, game.mouseInGame).length === 0 &&
|
||||||
// Matter.Query.ray(map, player.position, justPastMouse).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.03 + 0.005 * Math.sqrt(mag)
|
const drain = 0.03 + 0.005 * 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;
|
||||||
mech.fieldRange = 0
|
mech.fieldRange = 0
|
||||||
Matter.Body.setPosition(player, game.mouseInGame);
|
Matter.Body.setPosition(player, game.mouseInGame);
|
||||||
mech.buttonCD_jump = 0 //this might fix a bug with jumping
|
mech.buttonCD_jump = 0 //this might fix a bug with jumping
|
||||||
const velocity = Vector.mult(Vector.normalise(sub), 18)
|
const velocity = Vector.mult(Vector.normalise(sub), 18)
|
||||||
Matter.Body.setVelocity(player, {
|
Matter.Body.setVelocity(player, {
|
||||||
x: velocity.x,
|
x: velocity.x,
|
||||||
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
|
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
|
||||||
});
|
});
|
||||||
mech.immuneCycle = mech.cycle + 15; //player is immune to collision damage
|
mech.immuneCycle = mech.cycle + 15; //player is immune to collision damage
|
||||||
// move bots to follow player
|
// move bots to follow player
|
||||||
for (let i = 0; i < bullet.length; i++) {
|
for (let i = 0; i < bullet.length; i++) {
|
||||||
if (bullet[i].botType) {
|
if (bullet[i].botType) {
|
||||||
Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
|
Matter.Body.setPosition(bullet[i], Vector.add(player.position, {
|
||||||
x: 250 * (Math.random() - 0.5),
|
x: 250 * (Math.random() - 0.5),
|
||||||
y: 250 * (Math.random() - 0.5)
|
y: 250 * (Math.random() - 0.5)
|
||||||
}));
|
}));
|
||||||
Matter.Body.setVelocity(bullet[i], {
|
Matter.Body.setVelocity(bullet[i], {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0
|
y: 0
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//set holes
|
||||||
|
mech.hole.isOn = true;
|
||||||
|
mech.hole.pos1.x = mech.pos.x
|
||||||
|
mech.hole.pos1.y = mech.pos.y
|
||||||
|
mech.hole.pos2.x = player.position.x
|
||||||
|
mech.hole.pos2.y = player.position.y
|
||||||
|
mech.hole.angle = Math.atan2(sub.y, sub.x)
|
||||||
|
mech.hole.unit = Vector.perp(Vector.normalise(sub))
|
||||||
|
|
||||||
|
if (mod.isWormholeDamage) {
|
||||||
|
who = Matter.Query.ray(mob, mech.pos, game.mouseInGame, 80)
|
||||||
|
for (let i = 0; i < who.length; i++) {
|
||||||
|
if (who[i].body.alive) {
|
||||||
|
mobs.statusDoT(who[i].body, 0.6, 420)
|
||||||
|
mobs.statusStun(who[i].body, 240)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//set holes
|
|
||||||
mech.hole.isOn = true;
|
|
||||||
mech.hole.pos1.x = mech.pos.x
|
|
||||||
mech.hole.pos1.y = mech.pos.y
|
|
||||||
mech.hole.pos2.x = player.position.x
|
|
||||||
mech.hole.pos2.y = player.position.y
|
|
||||||
mech.hole.angle = Math.atan2(sub.y, sub.x)
|
|
||||||
mech.hole.unit = Vector.perp(Vector.normalise(sub))
|
|
||||||
|
|
||||||
if (mod.isWormholeDamage) {
|
|
||||||
who = Matter.Query.ray(mob, mech.pos, game.mouseInGame, 80)
|
|
||||||
for (let i = 0; i < who.length; i++) {
|
|
||||||
if (who[i].body.alive) {
|
|
||||||
mobs.statusDoT(who[i].body, 0.6, 420)
|
|
||||||
mobs.statusStun(who[i].body, 240)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mech.grabPowerUp();
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
mech.grabPowerUp();
|
mech.grabPowerUp();
|
||||||
}
|
}
|
||||||
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
|
|
||||||
mech.pickUp();
|
|
||||||
} else {
|
} else {
|
||||||
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
mech.grabPowerUp();
|
||||||
mech.hole.isReady = true;
|
|
||||||
}
|
}
|
||||||
mech.drawFieldMeter()
|
} else if (mech.holdingTarget && mech.fieldCDcycle < mech.cycle) { //holding, but field button is released
|
||||||
|
mech.pickUp();
|
||||||
|
} else {
|
||||||
|
mech.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||||
|
mech.hole.isReady = true;
|
||||||
}
|
}
|
||||||
}
|
mech.drawFieldMeter()
|
||||||
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
145
js/spawn.js
145
js/spawn.js
@@ -81,7 +81,7 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
randomLevelBoss(x, y, options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss"]) {
|
randomLevelBoss(x, y, options = ["shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss"]) {
|
||||||
// other bosses: suckerBoss, laserBoss, tetherBoss, //all need a particular level to work so they are not included
|
// other bosses: suckerBoss, laserBoss, tetherBoss, //all need a particular level to work so they are not included
|
||||||
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
|
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
|
||||||
},
|
},
|
||||||
@@ -101,15 +101,34 @@ const spawn = {
|
|||||||
level.bossKilled = true;
|
level.bossKilled = true;
|
||||||
level.exit.x = 5500;
|
level.exit.x = 5500;
|
||||||
level.exit.y = -330;
|
level.exit.y = -330;
|
||||||
|
//ramp up damage
|
||||||
|
for (let i = 0; i < 4; i++) level.difficultyIncrease(game.difficultyMode)
|
||||||
|
|
||||||
|
|
||||||
//pull in particles
|
//pull in particles
|
||||||
for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally
|
for (let i = 0, len = body.length; i < len; ++i) {
|
||||||
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
|
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
|
||||||
const pushUp = Vector.add(velocity, { x: 0, y: -0.3 })
|
const pushUp = Vector.add(velocity, { x: 0, y: -0.5 })
|
||||||
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
|
Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
|
||||||
}
|
}
|
||||||
//ramp up damage
|
//push away mobs
|
||||||
for (let i = 0; i < 5; i++) level.difficultyIncrease(game.difficultyMode)
|
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||||
|
if (mob[i] !== this) {
|
||||||
|
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, mob[i].position)), -65)
|
||||||
|
Matter.Body.setVelocity(mob[i], Vector.add(mob[i].velocity, velocity));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//draw stuff
|
||||||
|
for (let i = 0, len = 22; i < len; i++) {
|
||||||
|
game.drawList.push({ //add dmg to draw queue
|
||||||
|
x: this.position.x,
|
||||||
|
y: this.position.y,
|
||||||
|
radius: (i + 1) * 150,
|
||||||
|
color: `rgba(255,255,255,0.17)`,
|
||||||
|
time: 5 * (len - i + 1)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
me.onDamage = function() {};
|
me.onDamage = function() {};
|
||||||
@@ -761,7 +780,7 @@ const spawn = {
|
|||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
me.stroke = "transparent"; //used for drawSneaker
|
me.stroke = "transparent"; //used for drawSneaker
|
||||||
me.eventHorizon = radius * 23; //required for blackhole
|
me.eventHorizon = radius * 23; //required for blackhole
|
||||||
me.seeAtDistance2 = (me.eventHorizon + 300) * (me.eventHorizon + 300); //vision limit is event horizon
|
me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon
|
||||||
me.accelMag = 0.00009 * game.accelScale;
|
me.accelMag = 0.00009 * game.accelScale;
|
||||||
me.frictionAir = 0.025;
|
me.frictionAir = 0.025;
|
||||||
me.collisionFilter.mask = cat.player | cat.bullet
|
me.collisionFilter.mask = cat.player | cat.bullet
|
||||||
@@ -775,8 +794,15 @@ const spawn = {
|
|||||||
y: this.velocity.y * 0.99
|
y: this.velocity.y * 0.99
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// this.seePlayerByDistOrLOS();
|
// this.seePlayerCheckByDistance()
|
||||||
this.seePlayerCheckByDistance()
|
if (!(game.cycle % this.seePlayerFreq)) {
|
||||||
|
if (this.distanceToPlayer2() < this.seeAtDistance2) { //&& !mech.isCloak ignore cloak for black holes
|
||||||
|
this.locatePlayer();
|
||||||
|
if (!this.seePlayer.yes) this.seePlayer.yes = true;
|
||||||
|
} else if (this.seePlayer.recall) {
|
||||||
|
this.lostPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
if (this.seePlayer.recall) {
|
if (this.seePlayer.recall) {
|
||||||
//eventHorizon waves in and out
|
//eventHorizon waves in and out
|
||||||
@@ -832,7 +858,7 @@ const spawn = {
|
|||||||
me.isBoss = true;
|
me.isBoss = true;
|
||||||
me.stroke = "transparent"; //used for drawSneaker
|
me.stroke = "transparent"; //used for drawSneaker
|
||||||
me.eventHorizon = 1100; //required for black hole
|
me.eventHorizon = 1100; //required for black hole
|
||||||
me.seeAtDistance2 = (me.eventHorizon + 1000) * (me.eventHorizon + 1000); //vision limit is event horizon
|
me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon
|
||||||
me.accelMag = 0.00003 * game.accelScale;
|
me.accelMag = 0.00003 * game.accelScale;
|
||||||
me.collisionFilter.mask = cat.player | cat.bullet
|
me.collisionFilter.mask = cat.player | cat.bullet
|
||||||
// me.frictionAir = 0.005;
|
// me.frictionAir = 0.005;
|
||||||
@@ -865,7 +891,14 @@ const spawn = {
|
|||||||
y: this.velocity.y * 0.95
|
y: this.velocity.y * 0.95
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
this.seePlayerByDistOrLOS();
|
if (!(game.cycle % this.seePlayerFreq)) {
|
||||||
|
if (this.distanceToPlayer2() < this.seeAtDistance2) { //&& !mech.isCloak ignore cloak for black holes
|
||||||
|
this.locatePlayer();
|
||||||
|
if (!this.seePlayer.yes) this.seePlayer.yes = true;
|
||||||
|
} else if (this.seePlayer.recall) {
|
||||||
|
this.lostPlayer();
|
||||||
|
}
|
||||||
|
}
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
if (this.seePlayer.recall) {
|
if (this.seePlayer.recall) {
|
||||||
//accelerate towards the player
|
//accelerate towards the player
|
||||||
@@ -1865,7 +1898,7 @@ const spawn = {
|
|||||||
me.onHit = function() {
|
me.onHit = function() {
|
||||||
this.explode(this.mass * 20);
|
this.explode(this.mass * 20);
|
||||||
};
|
};
|
||||||
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
|
Matter.Body.setDensity(me, 0.00004); //normal is 0.001
|
||||||
me.timeLeft = 200;
|
me.timeLeft = 200;
|
||||||
me.g = 0.001; //required if using 'gravity'
|
me.g = 0.001; //required if using 'gravity'
|
||||||
me.frictionAir = 0;
|
me.frictionAir = 0;
|
||||||
@@ -2106,7 +2139,7 @@ const spawn = {
|
|||||||
me.frictionStatic = 0;
|
me.frictionStatic = 0;
|
||||||
me.friction = 0;
|
me.friction = 0;
|
||||||
me.frictionAir = 0.02;
|
me.frictionAir = 0.02;
|
||||||
me.memory = 420 * game.CDScale;
|
me.memory = 420;
|
||||||
me.repulsionRange = 1200000; //squared
|
me.repulsionRange = 1200000; //squared
|
||||||
spawn.shield(me, x, y, 1);
|
spawn.shield(me, x, y, 1);
|
||||||
Matter.Body.setDensity(me, 0.004 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
Matter.Body.setDensity(me, 0.004 + 0.0005 * Math.sqrt(game.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
|
||||||
@@ -2124,7 +2157,7 @@ const spawn = {
|
|||||||
Matter.Body.setAngularVelocity(this, 0.11)
|
Matter.Body.setAngularVelocity(this, 0.11)
|
||||||
//fire a bullet from each vertex
|
//fire a bullet from each vertex
|
||||||
for (let i = 0, len = this.vertices.length; i < len; i++) {
|
for (let i = 0, len = this.vertices.length; i < len; i++) {
|
||||||
spawn.seeker(this.vertices[i].x, this.vertices[i].y, 7)
|
spawn.seeker(this.vertices[i].x, this.vertices[i].y, 6)
|
||||||
//give the bullet a rotational velocity as if they were attached to a vertex
|
//give the bullet a rotational velocity as if they were attached to a vertex
|
||||||
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -10)
|
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -10)
|
||||||
Matter.Body.setVelocity(mob[mob.length - 1], {
|
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||||
@@ -2135,7 +2168,84 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
seeker(x, y, radius = 5, sides = 0) {
|
streamBoss(x, y, radius = 110) {
|
||||||
|
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
|
||||||
|
let me = mob[mob.length - 1];
|
||||||
|
me.isBoss = true;
|
||||||
|
// me.accelMag = 0.00023 * game.accelScale;
|
||||||
|
me.accelMag = 0.00008 * game.accelScale;
|
||||||
|
// me.fireFreq = Math.floor(30 * game.CDScale)
|
||||||
|
me.canFire = false;
|
||||||
|
me.closestVertex1 = 0;
|
||||||
|
me.closestVertex2 = 1;
|
||||||
|
me.cycle = 0
|
||||||
|
me.frictionStatic = 0;
|
||||||
|
me.friction = 0;
|
||||||
|
me.frictionAir = 0.022;
|
||||||
|
me.memory = 240;
|
||||||
|
me.repulsionRange = 1200000; //squared
|
||||||
|
spawn.shield(me, x, y, 1);
|
||||||
|
Matter.Body.setDensity(me, 0.025); //extra dense //normal is 0.001 //makes effective life much larger
|
||||||
|
me.onDeath = function() {
|
||||||
|
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||||
|
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
|
||||||
|
};
|
||||||
|
me.onDamage = function() {};
|
||||||
|
me.do = function() {
|
||||||
|
this.seePlayerCheck();
|
||||||
|
this.checkStatus();
|
||||||
|
this.attraction();
|
||||||
|
this.repulsion();
|
||||||
|
|
||||||
|
this.cycle++
|
||||||
|
if (this.seePlayer.recall && ((this.cycle % 15) === 0) && !mech.isBodiesAsleep) {
|
||||||
|
if (this.canFire) {
|
||||||
|
if (this.cycle > 120) {
|
||||||
|
this.cycle = 0
|
||||||
|
this.canFire = false
|
||||||
|
// Matter.Body.setAngularVelocity(this, 0.1)
|
||||||
|
// const forceMag = 0.01 * this.mass;
|
||||||
|
// const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
|
||||||
|
// this.force.x -= 2 * forceMag * Math.cos(angle);
|
||||||
|
// this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity
|
||||||
|
}
|
||||||
|
spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 4)
|
||||||
|
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
|
||||||
|
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10)
|
||||||
|
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||||
|
x: this.velocity.x + velocity.x,
|
||||||
|
y: this.velocity.y + velocity.y
|
||||||
|
});
|
||||||
|
spawn.seeker(this.vertices[this.closestVertex2].x, this.vertices[this.closestVertex2].y, 4)
|
||||||
|
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
|
||||||
|
const velocity2 = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex2])), -10)
|
||||||
|
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||||
|
x: this.velocity.x + velocity2.x,
|
||||||
|
y: this.velocity.y + velocity2.y
|
||||||
|
});
|
||||||
|
} else if (this.cycle > 210) {
|
||||||
|
this.cycle = 0
|
||||||
|
this.canFire = true
|
||||||
|
|
||||||
|
//find closest 2 vertexes
|
||||||
|
let distance2 = Infinity
|
||||||
|
for (let i = 0; i < this.vertices.length; i++) {
|
||||||
|
const d = Vector.magnitudeSquared(Vector.sub(this.vertices[i], player.position))
|
||||||
|
if (d < distance2) {
|
||||||
|
distance2 = d
|
||||||
|
this.closestVertex2 = this.closestVertex1
|
||||||
|
this.closestVertex1 = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.closestVertex2 === this.closestVertex1) {
|
||||||
|
this.closestVertex2++
|
||||||
|
if (this.closestVertex2 === this.vertices.length) this.closestVertex2 = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
},
|
||||||
|
seeker(x, y, radius = 5, sides = 6) {
|
||||||
//bullets
|
//bullets
|
||||||
mobs.spawn(x, y, sides, radius, "rgb(255,0,255)");
|
mobs.spawn(x, y, sides, radius, "rgb(255,0,255)");
|
||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
@@ -2143,10 +2253,10 @@ const spawn = {
|
|||||||
me.onHit = function() {
|
me.onHit = function() {
|
||||||
this.explode(this.mass * 20);
|
this.explode(this.mass * 20);
|
||||||
};
|
};
|
||||||
Matter.Body.setDensity(me, 0.00002); //normal is 0.001
|
Matter.Body.setDensity(me, 0.000015); //normal is 0.001
|
||||||
me.timeLeft = 420 * (0.8 + 0.4 * Math.random());
|
me.timeLeft = 420 * (0.8 + 0.4 * Math.random());
|
||||||
me.accelMag = 0.00017 * (0.8 + 0.4 * Math.random()) * game.accelScale;
|
me.accelMag = 0.00017 * game.accelScale; //* (0.8 + 0.4 * Math.random())
|
||||||
me.frictionAir = 0.01 * (0.8 + 0.4 * Math.random());
|
me.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
|
||||||
me.restitution = 0.5;
|
me.restitution = 0.5;
|
||||||
me.leaveBody = false;
|
me.leaveBody = false;
|
||||||
me.dropPowerUp = false;
|
me.dropPowerUp = false;
|
||||||
@@ -2190,6 +2300,7 @@ const spawn = {
|
|||||||
//run this function on hitting player
|
//run this function on hitting player
|
||||||
this.explode();
|
this.explode();
|
||||||
};
|
};
|
||||||
|
Matter.Body.setDensity(me, 0.0005); //normal is 0.001
|
||||||
me.g = 0.0001; //required if using 'gravity'
|
me.g = 0.0001; //required if using 'gravity'
|
||||||
me.accelMag = 0.0003 * game.accelScale;
|
me.accelMag = 0.0003 * game.accelScale;
|
||||||
me.memory = 30;
|
me.memory = 30;
|
||||||
|
|||||||
@@ -587,6 +587,7 @@ em {
|
|||||||
/* background: rgb(116, 102, 238); */
|
/* background: rgb(116, 102, 238); */
|
||||||
/* background: hsl(253, 57%, 52%); */
|
/* background: hsl(253, 57%, 52%); */
|
||||||
background: hsl(255, 100%, 71%);
|
background: hsl(255, 100%, 71%);
|
||||||
|
/* background: hsl(282, 100%, 64%); */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .grey {
|
/* .grey {
|
||||||
|
|||||||
85
todo.txt
85
todo.txt
@@ -1,22 +1,16 @@
|
|||||||
******************************************************** NEXT PATCH ********************************************************
|
******************************************************** NEXT PATCH ********************************************************
|
||||||
|
|
||||||
your build url can now be copied in the pause screen
|
new level boss that fires 2 streams of small bullets that chase you
|
||||||
|
|
||||||
mod: inductive coupling - 4 max health per power up, but limited to 44 max health per level (replaces crystalized armor)
|
mod: add a CPT gun to your inventory that rewinds your history, reverts your health, position, velocity for 10 seconds
|
||||||
mod: transceiver chip - use all the power ups left over at the end of a level
|
I expect that spamming rewind has some overpowered combos.
|
||||||
mod: catabolism - does a flat 5 damage to your health for 3 ammo (was 2% of max health for 1 ammo)
|
Let me know what you find, and your ideas on balance.
|
||||||
|
|
||||||
|
|
||||||
******************************************************** BUGS ********************************************************
|
******************************************************** BUGS ********************************************************
|
||||||
|
|
||||||
give worm hole pair production?
|
check for crouch after rewind
|
||||||
|
CPT, tesseract
|
||||||
2nd mod for crystalized armor
|
|
||||||
no cap for health power ups?
|
|
||||||
|
|
||||||
(not able to reproduce, might be fixed) possible bug with neutron rewind
|
|
||||||
status doesn't apply correctly for spawned neutron bombs that are stuck to a shield
|
|
||||||
also saw neutron bombs bounce off shield, for normal bullets
|
|
||||||
test this more
|
|
||||||
|
|
||||||
mod and mob are too similar
|
mod and mob are too similar
|
||||||
|
|
||||||
@@ -26,13 +20,15 @@ mod and mob are too similar
|
|||||||
trigger a short term non-collide if that occurs
|
trigger a short term non-collide if that occurs
|
||||||
|
|
||||||
(12+ reports) bug - crouch and worm hole? -> crouch locked in
|
(12+ reports) bug - crouch and worm hole? -> crouch locked in
|
||||||
doesn't occur on my computer?
|
***try checking the date of the first bug, and then look at what patches came out right before that***
|
||||||
|
doesn't occur on my computer? but it does occur on fast computers
|
||||||
you can spoof it with mech.crouch = true in console
|
you can spoof it with mech.crouch = true in console
|
||||||
players have extra gravity
|
players have extra gravity
|
||||||
might be from the short jump code
|
might be from the short jump code
|
||||||
add in a check every 7 seconds to try and fix it
|
add in a check every 7 seconds to try and fix it
|
||||||
this fix was added and it is working for some cases
|
this fix was added and it is working for some cases
|
||||||
maybe move the fix to once a second?
|
maybe move the fix to once a second?
|
||||||
|
bug fix - rewrite crouch to not translate the player height, but instead switch between 2 sensors
|
||||||
|
|
||||||
(intermittent, but almost every time) bug - capping the fps causes random slow downs, that can be fixed with pause
|
(intermittent, but almost every time) bug - capping the fps causes random slow downs, that can be fixed with pause
|
||||||
|
|
||||||
@@ -44,7 +40,39 @@ mod and mob are too similar
|
|||||||
|
|
||||||
******************************************************** TODO ********************************************************
|
******************************************************** TODO ********************************************************
|
||||||
|
|
||||||
make a reset hit box function as a way to fix crouch bug
|
mod: laser beams push like plasma torch pushes with directional force
|
||||||
|
|
||||||
|
mod: worm hole - you move through time instead of space. (field click to rewind)
|
||||||
|
add support for eating blocks, and damaging mobs that are nearby when you rewind
|
||||||
|
allow those mods
|
||||||
|
mod might not work as is because player needs to be able to pick up and move blocks sometimes
|
||||||
|
what about as a gun that uses energy not bullets?
|
||||||
|
|
||||||
|
mechanic: technological dead end - add mods to the mod pool with a dumb effect
|
||||||
|
don't show up in custom?
|
||||||
|
negative effect (one time effects are better to avoid code clutter)
|
||||||
|
make the player rainbow colors
|
||||||
|
mech.color = {
|
||||||
|
hue: 0,
|
||||||
|
sat: 100,
|
||||||
|
light: 50
|
||||||
|
}
|
||||||
|
setInterval(function(){
|
||||||
|
mech.color.hue++
|
||||||
|
mech.setFillColors()
|
||||||
|
}, 10);
|
||||||
|
remove all your energy
|
||||||
|
eject all your rerolls (not bad with dup)
|
||||||
|
teleport to the start of the level
|
||||||
|
remove your bots (requires you to have some bots)
|
||||||
|
your bots are changed to random bots
|
||||||
|
|
||||||
|
Mod: "High Risk": Spawn two bosses per level.
|
||||||
|
maybe limit to just the power up boss and spawn it at the exit every time to keep it simple
|
||||||
|
also weaken the player
|
||||||
|
remove a mod up?
|
||||||
|
lower harm reduction?
|
||||||
|
increase game difficulty by one level
|
||||||
|
|
||||||
mod that requires integrated armament
|
mod that requires integrated armament
|
||||||
|
|
||||||
@@ -75,15 +103,6 @@ make different move methods
|
|||||||
|
|
||||||
mod: when mobs are at full health you do 40% to them
|
mod: when mobs are at full health you do 40% to them
|
||||||
|
|
||||||
mechanic: failed technology - add mods to the mod pool with a dumb effect
|
|
||||||
don't show up in custom?
|
|
||||||
negative effect (one time effects are better to avoid code clutter)
|
|
||||||
remove all your energy
|
|
||||||
eject all your rerolls (not bad with dup)
|
|
||||||
teleport to the start of the level
|
|
||||||
remove your bots (requires you to have some bots)
|
|
||||||
your bots are changed to random bots
|
|
||||||
|
|
||||||
mod - move super fast, go intangible, drain energy very fast
|
mod - move super fast, go intangible, drain energy very fast
|
||||||
this is like a dodge roll
|
this is like a dodge roll
|
||||||
mod for standing wave?, cloaking?
|
mod for standing wave?, cloaking?
|
||||||
@@ -371,12 +390,16 @@ robot AI communication
|
|||||||
output to
|
output to
|
||||||
bottom left message
|
bottom left message
|
||||||
tab title?
|
tab title?
|
||||||
style
|
style
|
||||||
|
output console.log?
|
||||||
make it look like a computer terminal
|
make it look like a computer terminal
|
||||||
|
track multiple lines, like your vocoder program
|
||||||
|
messages about heal, ammo, mods, that just list internal computer code
|
||||||
|
example: a heal would be mech.health += 12
|
||||||
mono space font
|
mono space font
|
||||||
square edges
|
square edges
|
||||||
in baby talk?
|
black text on bottom right with no background?
|
||||||
with random ASCII gibberish letters
|
or white text, or yellow
|
||||||
end each message with a hexadecimal encryption code/hash
|
end each message with a hexadecimal encryption code/hash
|
||||||
message after selecting each new (mod / gun / field)
|
message after selecting each new (mod / gun / field)
|
||||||
put messages in (mod / gun / field) method
|
put messages in (mod / gun / field) method
|
||||||
@@ -385,6 +408,14 @@ robot AI communication
|
|||||||
you'd have to store an array of guns/fields/mod used last game
|
you'd have to store an array of guns/fields/mod used last game
|
||||||
n-gon escape simulation ${random seed}
|
n-gon escape simulation ${random seed}
|
||||||
say something about what mobs types are queued up, and level order
|
say something about what mobs types are queued up, and level order
|
||||||
|
**all communication should be from scientists watching the simulation; the robot shouldn't talk**
|
||||||
|
talking about the robot, watching
|
||||||
|
trying to communicate with the robot? but how
|
||||||
|
lines:
|
||||||
|
I think it's planing to escape
|
||||||
|
Why is it attacking those shapes?
|
||||||
|
Are those shapes supposed to be us?
|
||||||
|
|
||||||
|
|
||||||
add an ending to the game
|
add an ending to the game
|
||||||
maybe the game ending should ask you to open the console and type in some commands like in the end of doki doki
|
maybe the game ending should ask you to open the console and type in some commands like in the end of doki doki
|
||||||
|
|||||||
Reference in New Issue
Block a user