laser mod
mod: stimulated emission - 8% chance to duplicate power ups laser mod: diffuse beam - laser is wide but doesn't reflect, 150% damage and energy drain
This commit is contained in:
335
js/bullet.js
335
js/bullet.js
@@ -376,6 +376,164 @@ const b = {
|
||||
}
|
||||
}
|
||||
},
|
||||
laser(where = {
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 20 * Math.sin(mech.angle)
|
||||
}, angle = mech.angle, dmg = mod.laserDamage, reflections = mod.laserReflections, isThickBeam = false) {
|
||||
const reflectivity = 1 - 1 / (reflections * 1.5)
|
||||
let damage = b.dmgScale * dmg
|
||||
let best = {
|
||||
x: null,
|
||||
y: null,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
};
|
||||
const color = "#f00";
|
||||
const range = 3000;
|
||||
const path = [{
|
||||
x: where.x,
|
||||
y: where.y
|
||||
},
|
||||
{
|
||||
x: where.x + range * Math.cos(angle),
|
||||
y: where.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]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkForCollisions = function () {
|
||||
best = {
|
||||
x: null,
|
||||
y: null,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
};
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], mob);
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], map);
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], body);
|
||||
};
|
||||
const laserHitMob = function () {
|
||||
if (best.who.alive) {
|
||||
best.who.damage(damage);
|
||||
best.who.locatePlayer();
|
||||
ctx.fillStyle = color; //draw mob damage circle
|
||||
ctx.beginPath();
|
||||
ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(damage) * 100, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
};
|
||||
const reflection = function () { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
|
||||
const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
|
||||
const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
|
||||
const nn = Vector.mult(n, 2 * Vector.dot(d, n));
|
||||
const r = Vector.normalise(Vector.sub(d, nn));
|
||||
path[path.length] = Vector.add(Vector.mult(r, range), path[path.length - 1]);
|
||||
};
|
||||
|
||||
checkForCollisions();
|
||||
let lastBestOdd
|
||||
let lastBestEven = best.who //used in hack below
|
||||
if (best.dist2 !== Infinity) { //if hitting something
|
||||
path[path.length - 1] = {
|
||||
x: best.x,
|
||||
y: best.y
|
||||
};
|
||||
laserHitMob();
|
||||
for (let i = 0; i < reflections; i++) {
|
||||
reflection();
|
||||
checkForCollisions();
|
||||
if (best.dist2 !== Infinity) { //if hitting something
|
||||
lastReflection = best
|
||||
|
||||
path[path.length - 1] = {
|
||||
x: best.x,
|
||||
y: best.y
|
||||
};
|
||||
damage *= reflectivity
|
||||
laserHitMob();
|
||||
//I'm not clear on how this works, but it gets ride of a bug where the laser reflects inside a block, often vertically.
|
||||
//I think it checks to see if the laser is reflecting off a different part of the same block, if it is "inside" a block
|
||||
if (i % 2) {
|
||||
if (lastBestOdd === best.who) break
|
||||
} else {
|
||||
lastBestOdd = best.who
|
||||
if (lastBestEven === best.who) break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if (isThickBeam) {
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 8
|
||||
ctx.globalAlpha = 0.5;
|
||||
for (let i = 1, len = path.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path[i - 1].x, path[i - 1].y);
|
||||
ctx.lineTo(path[i].x, path[i].y);
|
||||
ctx.stroke();
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
} else {
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2
|
||||
ctx.lineDashOffset = 300 * Math.random()
|
||||
ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
|
||||
for (let i = 1, len = path.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path[i - 1].x, path[i - 1].y);
|
||||
ctx.lineTo(path[i].x, path[i].y);
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha *= reflectivity; //reflections are less intense
|
||||
}
|
||||
ctx.setLineDash([0, 0]);
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
},
|
||||
mine(where, velocity, angle = 0, isAmmoBack = false) {
|
||||
const bIndex = bullet.length;
|
||||
bullet[bIndex] = Bodies.rectangle(where.x, where.y, 45, 16, {
|
||||
@@ -1544,11 +1702,9 @@ const b = {
|
||||
do() {
|
||||
//check for damage
|
||||
if (!mech.isCloak && !mech.isBodiesAsleep) { //if time dilation isn't active
|
||||
|
||||
|
||||
// q = Matter.Query.point(mob, this.position)
|
||||
// q = Matter.Query.collides(this, mob)
|
||||
const size = 30
|
||||
const size = 33
|
||||
q = Matter.Query.region(mob, {
|
||||
min: {
|
||||
x: this.position.x - size,
|
||||
@@ -1560,8 +1716,8 @@ const b = {
|
||||
}
|
||||
})
|
||||
for (let i = 0; i < q.length; i++) {
|
||||
mobs.statusStun(q[i], this.isUpgraded ? 240 : 120)
|
||||
const dmg = 1 * b.dmgScale * (this.isUpgraded ? 2.25 : 1)
|
||||
mobs.statusStun(q[i], 180)
|
||||
const dmg = 0.5 * b.dmgScale * (this.isUpgraded ? 2.25 : 1) * (mod.isCrit ? 4 : 1)
|
||||
q[i].damage(dmg);
|
||||
q[i].foundPlayer();
|
||||
game.drawList.push({ //add dmg to draw queue
|
||||
@@ -3066,159 +3222,40 @@ const b = {
|
||||
ammoPack: Infinity,
|
||||
have: false,
|
||||
nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
|
||||
holdDamage: 1,
|
||||
holdCount: 0,
|
||||
healthLost: 0,
|
||||
fire() {
|
||||
mech.fireCDcycle = mech.cycle
|
||||
|
||||
const reflectivity = 1 - 1 / (mod.laserReflections * 1.5)
|
||||
let damage = b.dmgScale * mod.laserDamage * this.holdDamage
|
||||
if (mech.energy < mod.laserFieldDrain) {
|
||||
mech.fireCDcycle = mech.cycle + 100; // cool down if out of energy
|
||||
} else {
|
||||
mech.fireCDcycle = mech.cycle
|
||||
mech.energy -= mech.fieldRegen + mod.laserFieldDrain * mod.isLaserDiode
|
||||
let best = {
|
||||
x: null,
|
||||
y: null,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
};
|
||||
const color = "#f00";
|
||||
const range = 3000;
|
||||
const path = [{
|
||||
if (mod.isWideLaser) {
|
||||
const off = 8
|
||||
const dmg = 0.6 * mod.laserDamage // 5 * 0.4 = 200% more damage
|
||||
// ctx.lineCap = 'butt';
|
||||
b.laser({
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 20 * Math.sin(mech.angle)
|
||||
},
|
||||
{
|
||||
x: mech.pos.x + range * Math.cos(mech.angle),
|
||||
y: mech.pos.y + range * Math.sin(mech.angle)
|
||||
}
|
||||
];
|
||||
const vertexCollision = function (v1, v1End, domain) {
|
||||
for (let i = 0; i < domain.length; ++i) {
|
||||
let vertices = domain[i].vertices;
|
||||
const len = vertices.length - 1;
|
||||
for (let j = 0; j < len; j++) {
|
||||
results = game.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
||||
best = {
|
||||
x: results.x,
|
||||
y: results.y,
|
||||
dist2: dist2,
|
||||
who: domain[i],
|
||||
v1: vertices[j],
|
||||
v2: vertices[j + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
results = game.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
||||
best = {
|
||||
x: results.x,
|
||||
y: results.y,
|
||||
dist2: dist2,
|
||||
who: domain[i],
|
||||
v1: vertices[0],
|
||||
v2: vertices[len]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const checkForCollisions = function () {
|
||||
best = {
|
||||
x: null,
|
||||
y: null,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
};
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], mob);
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], map);
|
||||
vertexCollision(path[path.length - 2], path[path.length - 1], body);
|
||||
};
|
||||
const laserHitMob = function () {
|
||||
if (best.who.alive) {
|
||||
best.who.damage(damage);
|
||||
best.who.locatePlayer();
|
||||
ctx.fillStyle = color; //draw mob damage circle
|
||||
ctx.beginPath();
|
||||
ctx.arc(path[path.length - 1].x, path[path.length - 1].y, Math.sqrt(damage) * 100, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
};
|
||||
const reflection = function () { // https://math.stackexchange.com/questions/13261/how-to-get-a-reflection-vector
|
||||
const n = Vector.perp(Vector.normalise(Vector.sub(best.v1, best.v2)));
|
||||
const d = Vector.sub(path[path.length - 1], path[path.length - 2]);
|
||||
const nn = Vector.mult(n, 2 * Vector.dot(d, n));
|
||||
const r = Vector.normalise(Vector.sub(d, nn));
|
||||
path[path.length] = Vector.add(Vector.mult(r, range), path[path.length - 1]);
|
||||
};
|
||||
|
||||
checkForCollisions();
|
||||
let lastBestOdd
|
||||
let lastBestEven = best.who //used in hack below
|
||||
if (best.dist2 !== Infinity) {
|
||||
//if hitting something
|
||||
path[path.length - 1] = {
|
||||
x: best.x,
|
||||
y: best.y
|
||||
};
|
||||
laserHitMob();
|
||||
for (let i = 0; i < mod.laserReflections; i++) {
|
||||
reflection();
|
||||
checkForCollisions();
|
||||
if (best.dist2 !== Infinity) { //if hitting something
|
||||
lastReflection = best
|
||||
|
||||
path[path.length - 1] = {
|
||||
x: best.x,
|
||||
y: best.y
|
||||
};
|
||||
damage *= reflectivity
|
||||
laserHitMob();
|
||||
//I'm not clear on how this works, but it gets ride of a bug where the laser reflects inside a block, often vertically.
|
||||
//I think it checks to see if the laser is reflecting off a different part of the same block, if it is "inside" a block
|
||||
if (i % 2) {
|
||||
if (lastBestOdd === best.who) break
|
||||
} else {
|
||||
lastBestOdd = best.who
|
||||
if (lastBestEven === best.who) break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}, mech.angle, dmg, 0, true)
|
||||
for (let i = 1; i < 3; i++) {
|
||||
b.laser(Vector.add({
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 20 * Math.sin(mech.angle)
|
||||
}, {
|
||||
x: i * off * Math.cos(mech.angle + Math.PI / 2),
|
||||
y: i * off * Math.sin(mech.angle + Math.PI / 2)
|
||||
}), mech.angle, dmg, 0, true)
|
||||
b.laser(Vector.add({
|
||||
x: mech.pos.x + 20 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 20 * Math.sin(mech.angle)
|
||||
}, {
|
||||
x: i * off * Math.cos(mech.angle - Math.PI / 2),
|
||||
y: i * off * Math.sin(mech.angle - Math.PI / 2)
|
||||
}), mech.angle, dmg, 0, true)
|
||||
}
|
||||
// ctx.lineCap = 'round';
|
||||
} else {
|
||||
b.laser()
|
||||
}
|
||||
|
||||
ctx.fillStyle = color;
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2 * this.holdDamage;
|
||||
ctx.lineDashOffset = 300 * Math.random()
|
||||
ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
|
||||
for (let i = 1, len = path.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path[i - 1].x, path[i - 1].y);
|
||||
ctx.lineTo(path[i].x, path[i].y);
|
||||
ctx.stroke();
|
||||
ctx.globalAlpha *= reflectivity; //reflections are less intense
|
||||
}
|
||||
ctx.setLineDash([0, 0]);
|
||||
ctx.globalAlpha = 1;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -153,8 +153,8 @@ function collisionChecks(event) {
|
||||
const choose = have[Math.floor(Math.random() * have.length)]
|
||||
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> ejected by Bayesian statistics`, 600) //message about what mod was lost
|
||||
for (let i = 0; i < mod.mods[choose].count; i++) powerUps.spawn(mech.pos.x, mech.pos.y, "mod");
|
||||
mod.mods[choose].count = 0;
|
||||
mod.mods[choose].remove(); // remove a random mod form the list of mods you have
|
||||
mod.mods[choose].count = 0;
|
||||
mod.mods[choose].isLost = true;
|
||||
game.updateModHUD();
|
||||
mech.fieldCDcycle = mech.cycle + 30; //disable field so you can't pick up the ejected mod
|
||||
|
||||
37
js/game.js
37
js/game.js
@@ -978,6 +978,43 @@ const game = {
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
},
|
||||
powerUpBonus() { //draws crackle effect for bonus power ups
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
ctx.globalAlpha = 0.4 * Math.sin(mech.cycle * 0.15) + 0.6;
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = powerUp[i].color;
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
|
||||
if (powerUp[i].isBonus && Math.random() < 0.1) {
|
||||
//draw electricity
|
||||
const mag = 5 + powerUp[i].size / 5
|
||||
let unit = Vector.rotate({
|
||||
x: mag,
|
||||
y: mag
|
||||
}, 2 * Math.PI * Math.random())
|
||||
let path = {
|
||||
x: powerUp[i].position.x + unit.x,
|
||||
y: powerUp[i].position.y + unit.y
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path.x, path.y);
|
||||
for (let i = 0; i < 6; i++) {
|
||||
unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
|
||||
path = Vector.add(path, unit)
|
||||
ctx.lineTo(path.x, path.y);
|
||||
}
|
||||
ctx.lineWidth = 0.5 + 2 * Math.random();
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
// ctx.globalAlpha = 1;
|
||||
},
|
||||
|
||||
// map: function() {
|
||||
// ctx.beginPath();
|
||||
// for (let i = 0, len = map.length; i < len; ++i) {
|
||||
|
||||
@@ -62,6 +62,7 @@ window.addEventListener('load', (event) => {
|
||||
for (const property in set) {
|
||||
// console.log(set[property], property);
|
||||
set[property] = set[property].replace(/%20/g, " ")
|
||||
set[property] = set[property].replace(/%CE%A8/g, "Ψ")
|
||||
|
||||
if (property === "field") {
|
||||
let found = false
|
||||
|
||||
33
js/level.js
33
js/level.js
@@ -17,9 +17,9 @@ const level = {
|
||||
// mech.isCloak = true;
|
||||
// mech.setField("metamaterial cloaking")
|
||||
// b.giveGuns("laser")
|
||||
for (let i = 0; i < 1; i++) {
|
||||
mod.giveMod("orbital-bot");
|
||||
}
|
||||
// for (let i = 0; i < 1; i++) {
|
||||
// mod.giveMod("diffuse beam");
|
||||
// }
|
||||
// mod.giveMod("orbit-bot upgrade")
|
||||
|
||||
|
||||
@@ -80,7 +80,10 @@ const level = {
|
||||
//******************************************************************************************************************
|
||||
//******************************************************************************************************************
|
||||
testing() {
|
||||
const button = level.button(200, -700)
|
||||
level.custom = () => {
|
||||
button.query();
|
||||
button.draw();
|
||||
level.playerExitCheck();
|
||||
};
|
||||
level.customTopLayer = () => {};
|
||||
@@ -147,7 +150,7 @@ const level = {
|
||||
// spawn.sniper(1800, -120)
|
||||
// spawn.sniper(2200, -120)
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
spawn.starter(1600, -500, 60)
|
||||
spawn.starter(1600, -500, 160)
|
||||
// spawn.powerUpBoss(1600, -500)
|
||||
// spawn.shield(mob[mob.length - 1], 1200, -500, 1);
|
||||
|
||||
@@ -4206,18 +4209,24 @@ const level = {
|
||||
width: width,
|
||||
height: 20,
|
||||
query() {
|
||||
// if (Matter.Query.collides(buttonSensor, body).length === 0 && Matter.Query.collides(buttonSensor, [player]).length === 0) {
|
||||
if (Matter.Query.region(body, this).length === 0 && Matter.Query.region([player], this).length === 0) {
|
||||
this.isUp = true;
|
||||
} else {
|
||||
this.isUp = false;
|
||||
// const list = Matter.Query.collides(buttonSensor, body)
|
||||
// if (list.length > 0) {
|
||||
// Matter.Body.setVelocity(list[0].bodyB, {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// });
|
||||
// if (this.isUp === true) {
|
||||
// const list = Matter.Query.region(body, this)
|
||||
// console.log(list)
|
||||
// if (list.length > 0) {
|
||||
// Matter.Body.setPosition(list[0], {
|
||||
// x: this.min.x + width / 2,
|
||||
// y: list[0].position.y
|
||||
// })
|
||||
// Matter.Body.setVelocity(list[0], {
|
||||
// x: 0,
|
||||
// y: 0
|
||||
// });
|
||||
// }
|
||||
// }
|
||||
this.isUp = false;
|
||||
}
|
||||
},
|
||||
draw() {
|
||||
|
||||
116
js/mods.js
116
js/mods.js
@@ -261,7 +261,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "Ψ(t) collapse",
|
||||
description: "<strong>50%</strong> decreased <strong>delay</strong> after firing<br>if you have no <strong class='color-r'>rerolls</strong>",
|
||||
description: "<strong>60%</strong> decreased <strong>delay</strong> after firing<br>if you have no <strong class='color-r'>rerolls</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -270,7 +270,7 @@ const mod = {
|
||||
requires: "no rerolls",
|
||||
effect() {
|
||||
mod.isRerollHaste = true;
|
||||
mod.rerollHaste = 0.5;
|
||||
mod.rerollHaste = 0.4;
|
||||
b.setFireCD();
|
||||
},
|
||||
remove() {
|
||||
@@ -298,7 +298,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "auto-loading heuristics",
|
||||
description: "<strong>25%</strong> decreased <strong>delay</strong> after firing",
|
||||
description: "<strong>30%</strong> decreased <strong>delay</strong> after firing",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -306,7 +306,7 @@ const mod = {
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
mod.fireRate *= 0.75
|
||||
mod.fireRate *= 0.7
|
||||
b.setFireCD();
|
||||
},
|
||||
remove() {
|
||||
@@ -642,7 +642,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "orbital-bot",
|
||||
description: "a bot is locked in <strong>orbit</strong> around you<br><strong class='color-d'>damages</strong> and <strong>stuns</strong> mobs on <strong>contact</strong>",
|
||||
description: "a bot is locked in <strong>orbit</strong> around you<br><strong>stuns</strong> and <strong class='color-d'>damages</strong> mobs on <strong>contact</strong>",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -659,7 +659,7 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "orbital-bot upgrade",
|
||||
description: "<strong>125%</strong> increased <strong class='color-d'>damage</strong> and <strong>stun</strong> duration<br><em>applies to all current and future orbit-bots</em>",
|
||||
description: "<strong>125%</strong> increased <strong class='color-d'>damage</strong><br><em>applies to all current and future orbit-bots</em>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
@@ -897,7 +897,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.isStunField || mod.isPulseStun || mod.isNeutronStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun
|
||||
return mod.isStunField || mod.isPulseStun || mod.isNeutronStun || mod.oneSuperBall || mod.isHarmFreeze || mod.isIceField || mod.isIceCrystals || mod.isSporeFreeze || mod.isAoESlow || mod.isFreezeMobs || mod.isPilotFreeze || mod.haveGunCheck("ice IX") || mod.isCloakStun || mod.orbitBotCount > 1
|
||||
},
|
||||
requires: "a freezing or stunning effect",
|
||||
effect() {
|
||||
@@ -1201,48 +1201,37 @@ const mod = {
|
||||
requires: "",
|
||||
effect: () => {
|
||||
mod.isBayesian = true
|
||||
//change power up draw
|
||||
game.draw.powerUp = function () {
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
ctx.globalAlpha = 0.4 * Math.sin(mech.cycle * 0.15) + 0.6;
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
ctx.beginPath();
|
||||
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = powerUp[i].color;
|
||||
ctx.fill();
|
||||
}
|
||||
ctx.globalAlpha = 1;
|
||||
|
||||
if (powerUp[i].isBayesian && Math.random() < 0.1) {
|
||||
//draw electricity
|
||||
const mag = 5 + powerUp[i].size / 5
|
||||
let unit = Vector.rotate({
|
||||
x: mag,
|
||||
y: mag
|
||||
}, 2 * Math.PI * Math.random())
|
||||
let path = {
|
||||
x: powerUp[i].position.x + unit.x,
|
||||
y: powerUp[i].position.y + unit.y
|
||||
}
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(path.x, path.y);
|
||||
for (let i = 0; i < 6; i++) {
|
||||
unit = Vector.rotate(unit, 3 * (Math.random() - 0.5))
|
||||
path = Vector.add(path, unit)
|
||||
ctx.lineTo(path.x, path.y);
|
||||
}
|
||||
ctx.lineWidth = 0.5 + 2 * Math.random();
|
||||
ctx.strokeStyle = "#000"
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
// ctx.globalAlpha = 1;
|
||||
}
|
||||
mod.duplicateChance += 0.17
|
||||
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
||||
|
||||
},
|
||||
remove() {
|
||||
if (mod.isBayesian) {
|
||||
mod.duplicateChance -= 0.17
|
||||
if (mod.duplicateChance < 0) mod.duplicateChance = 0
|
||||
}
|
||||
mod.isBayesian = false
|
||||
game.draw.powerUp = game.draw.powerUpNormal
|
||||
if (mod.duplicateChance)
|
||||
if (!mod.duplicateChance) game.draw.powerUp = game.draw.powerUpNormal
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "stimulated emission",
|
||||
description: "<strong>8%</strong> chance to <strong>duplicate</strong> spawned <strong>power ups</strong>",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect: () => {
|
||||
mod.duplicateChance += 0.08
|
||||
game.draw.powerUp = game.draw.powerUpBonus //change power up draw
|
||||
|
||||
},
|
||||
remove() {
|
||||
mod.duplicateChance -= 0.08 * this.count
|
||||
if (!mod.duplicateChance) game.draw.powerUp = game.draw.powerUpNormal
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2345,22 +2334,40 @@ const mod = {
|
||||
},
|
||||
{
|
||||
name: "specular reflection",
|
||||
description: "<strong>laser</strong> beams gain <strong>1</strong> reflection<br><strong>50%</strong> laser <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain",
|
||||
description: "<strong>laser</strong> beams gain <strong>1</strong> reflection<br>increase <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain by <strong>50%</strong>",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("laser")
|
||||
return mod.haveGunCheck("laser") && !mod.isWideLaser
|
||||
},
|
||||
requires: "laser",
|
||||
requires: "laser, not wide beam",
|
||||
effect() {
|
||||
mod.laserReflections++;
|
||||
mod.laserDamage += 0.06; //base is 0.12
|
||||
mod.laserFieldDrain += 0.0008 //base is 0.002
|
||||
mod.laserDamage += 0.08; //base is 0.12
|
||||
mod.laserFieldDrain += 0.0006 //base is 0.002
|
||||
},
|
||||
remove() {
|
||||
mod.laserReflections = 2;
|
||||
mod.laserDamage = 0.12;
|
||||
mod.laserFieldDrain = 0.0016;
|
||||
mod.laserDamage = 0.16;
|
||||
mod.laserFieldDrain = 0.0012;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "diffuse beam",
|
||||
description: "<strong>laser</strong> beam is <strong>wider</strong> but doesn't <strong>reflect</strong><br>increase <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain by <strong>150%</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.haveGunCheck("laser") && mod.laserReflections < 3
|
||||
},
|
||||
requires: "laser, not specular reflection",
|
||||
effect() {
|
||||
mod.isWideLaser = true
|
||||
mod.laserFieldDrain = 0.0012 * 2.5 //base is 0.002
|
||||
},
|
||||
remove() {
|
||||
mod.isWideLaser = false
|
||||
mod.laserFieldDrain = 0.0012;
|
||||
}
|
||||
},
|
||||
// {
|
||||
@@ -2438,7 +2445,7 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return mod.isStunField || mod.oneSuperBall || mod.isCloakStun
|
||||
return mod.isStunField || mod.oneSuperBall || mod.isCloakStun || mod.orbitBotCount > 1
|
||||
},
|
||||
requires: "flux pinning or super ball<br>or flashbang",
|
||||
effect() {
|
||||
@@ -2965,5 +2972,6 @@ const mod = {
|
||||
healMaxEnergyBonus: null,
|
||||
aimDamage: null,
|
||||
isNoFireDefense: null,
|
||||
isNoFireDamage: null
|
||||
isNoFireDamage: null,
|
||||
duplicateChance: null
|
||||
}
|
||||
@@ -577,9 +577,9 @@ const powerUps = {
|
||||
!(mod.isEnergyNoAmmo && target === 'ammo')
|
||||
) {
|
||||
powerUps.directSpawn(x, y, target, moving, mode, size)
|
||||
if (mod.isBayesian && Math.random() < 0.17) {
|
||||
if (mod.duplicateChance && Math.random() < mod.duplicateChance) {
|
||||
powerUps.directSpawn(x, y, target, moving, mode)
|
||||
powerUp[powerUp.length - 1].isBayesian = true
|
||||
powerUp[powerUp.length - 1].isBonus = true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user