exciton-lattice
field: perfect diamagnetism is a bit larger can now grab power ups from far away mod: exciton-lattice - reduce harm by 80%, but after taking collision damage eject a random mod eject extra mods if you have recursive stacks power ups have a bit more air friction power ups must be in line of sight to be pulled by the player why mode now gets 100% chance for a second boss power up (up from 50%) this should let why mode reach more interesting build depth laser and pulse got a damage and energy use buff immune to harm for a second after exiting the power up selection menu
This commit is contained in:
10
js/bullet.js
10
js/bullet.js
@@ -670,7 +670,7 @@ const b = {
|
||||
},
|
||||
drone(speed = 1) {
|
||||
const me = bullet.length;
|
||||
const THRUST = mod.isFastDrones ? 0.0025 : 0.0015
|
||||
const THRUST = mod.isFastDrones ? 0.0023 : 0.0015
|
||||
// const FRICTION = mod.isFastDrones ? 0.008 : 0.0005
|
||||
const dir = mech.angle + 0.4 * (Math.random() - 0.5);
|
||||
const RADIUS = (4.5 + 3 * Math.random())
|
||||
@@ -2550,7 +2550,7 @@ const b = {
|
||||
name: "drones",
|
||||
description: "deploy drones that <strong>crash</strong> into mobs<br>crashes reduce their <strong>lifespan</strong> by 1 second",
|
||||
ammo: 0,
|
||||
ammoPack: 13,
|
||||
ammoPack: 14,
|
||||
have: false,
|
||||
fire() {
|
||||
b.drone(mech.crouch ? 45 : 1)
|
||||
@@ -3173,8 +3173,8 @@ const b = {
|
||||
};
|
||||
if (mod.isPulseAim) { //find mobs in line of sight
|
||||
let dist = 2200
|
||||
energy = 0.25 * Math.min(mech.energy, 1.75)
|
||||
explosionRange = 1100 * energy
|
||||
energy = 0.23 * Math.min(mech.energy, 1.75)
|
||||
explosionRange = 1300 * energy
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
|
||||
if (explosionRange < newDist &&
|
||||
@@ -3206,7 +3206,7 @@ const b = {
|
||||
} else {
|
||||
energy = 0.3 * Math.min(mech.energy, 1.75)
|
||||
mech.energy -= energy * mod.isLaserDiode
|
||||
explosionRange = 1100 * energy
|
||||
explosionRange = 1200 * energy
|
||||
if (best.who) b.explosion(path[1], explosionRange, true)
|
||||
mech.fireCDcycle = mech.cycle + Math.floor(50 * b.fireCD); // cool down
|
||||
}
|
||||
|
||||
15
js/engine.js
15
js/engine.js
@@ -162,6 +162,21 @@ function collisionChecks(event) {
|
||||
dmg *= 0.85
|
||||
}
|
||||
mech.damage(dmg);
|
||||
if (mod.isEjectMod) {
|
||||
const have = [] //find which mods you have
|
||||
for (let i = 0; i < mod.mods.length; i++) {
|
||||
if (mod.mods[i].count > 0) have.push(i)
|
||||
}
|
||||
const choose = have[Math.floor(Math.random() * have.length)]
|
||||
//message about what mod was lost
|
||||
game.makeTextLog(`<div class='circle mod'></div> <strong>${mod.mods[choose].name}</strong> ejected by exciton-lattice`, 300)
|
||||
|
||||
|
||||
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
|
||||
game.updateModHUD();
|
||||
}
|
||||
if (mob[k].onHit) mob[k].onHit(k);
|
||||
|
||||
//extra kick between player and mob //this section would be better with forces but they don't work...
|
||||
|
||||
79
js/game.js
79
js/game.js
@@ -43,6 +43,7 @@ const game = {
|
||||
// game.clip();
|
||||
ctx.restore();
|
||||
game.drawCursor();
|
||||
// game.pixelGraphics();
|
||||
},
|
||||
testingLoop() {
|
||||
game.gravity();
|
||||
@@ -153,6 +154,84 @@ const game = {
|
||||
// clip() {
|
||||
|
||||
// },
|
||||
pixelGraphics() {
|
||||
//copy current canvas pixel data
|
||||
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
let data = imgData.data;
|
||||
//change pixel data
|
||||
|
||||
|
||||
// const off = 4 * Math.floor(x) + 4 * canvas.width * Math.floor(y);
|
||||
// multiple windows
|
||||
for (let i = data.length / 2; i < data.length; i += 4) {
|
||||
index = i % (canvas.width * canvas.height * 2) // + canvas.width*4*canvas.height
|
||||
|
||||
data[i + 0] = data[index + 0]; // red
|
||||
data[i + 1] = data[index + 1]; // red
|
||||
data[i + 2] = data[index + 2]; // red
|
||||
data[i + 3] = data[index + 3]; // red
|
||||
}
|
||||
|
||||
for (let x = 0; x < len; x++) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
// const startX = 2 * canvas.width + 2 * canvas.width * canvas.height
|
||||
// const endX = 4 * canvas.width + 4 * canvas.width * canvas.height
|
||||
// const startY = 2 * canvas.width + 2 * canvas.width * canvas.height
|
||||
// const endY = 4 * canvas.width + 4 * canvas.width * canvas.height
|
||||
// for (let x = startX; x < endX; x++) {
|
||||
// for (let y = startY; y < endY; y++) {
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
//strange draw offset
|
||||
// const off = canvas.height * canvas.width * 4 / 2
|
||||
// for (let index = 0; index < data.length; index += 4) {
|
||||
// data[index + 0] = data[index + 0 + off]; // red
|
||||
// data[index + 1] = data[index + 1 + off]; // red
|
||||
// data[index + 2] = data[index + 2 + off]; // red
|
||||
// data[index + 3] = data[index + 3 + off]; // red
|
||||
// }
|
||||
|
||||
//change all pixels
|
||||
// for (let index = 0; index < data.length; index += 4) {
|
||||
// data[index + 0] = 255; // red
|
||||
// data[index + 1] = 255; // green
|
||||
// data[index + 2] = 255; // blue
|
||||
// data[index + 3] = 255; // alpha
|
||||
// }
|
||||
|
||||
//change random pixels
|
||||
// for (let i = 0, len = Math.floor(data.length / 10); i < len; ++i) {
|
||||
// const index = Math.floor((Math.random() * data.length) / 4) * 4;
|
||||
// data[index + 0] = 255; // red
|
||||
// data[index + 1] = 0; // green
|
||||
// data[index + 2] = 0; // blue
|
||||
// data[index + 3] = 255 //Math.floor(Math.random() * Math.random() * 255); // alpha
|
||||
// }
|
||||
|
||||
// //change random pixels
|
||||
// for (let i = 0, len = Math.floor(data.length / 1000); i < len; ++i) {
|
||||
// const index = Math.floor((Math.random() * data.length) / 4) * 4;
|
||||
// // data[index] = data[index] ^ 255; // Invert Red
|
||||
// // data[index + 1] = data[index + 1] ^ 255; // Invert Green
|
||||
// // data[index + 2] = data[index + 2] ^ 255; // Invert Blue
|
||||
// data[index + 0] = 0; // red
|
||||
// data[index + 1] = 0; // green
|
||||
// data[index + 2] = 0; // blue
|
||||
// // data[index + 3] = 255 //Math.floor(Math.random() * Math.random() * 255); // alpha
|
||||
// }
|
||||
|
||||
//draw new pixel data to canvas
|
||||
ctx.putImageData(imgData, 0, 0);
|
||||
},
|
||||
drawCursor() {
|
||||
const size = 10;
|
||||
ctx.beginPath();
|
||||
|
||||
@@ -16,9 +16,9 @@ const level = {
|
||||
// game.zoomScale = 1000;
|
||||
// game.setZoom();
|
||||
// mech.isStealth = true;
|
||||
// mech.setField("standing wave harmonics")
|
||||
// mech.setField("time dilation field")
|
||||
// b.giveGuns("rail gun")
|
||||
// mod.giveMod("capacitor bank");
|
||||
// mod.giveMod("quantum immortality");
|
||||
|
||||
level.intro(); //starting level
|
||||
// level.testing(); //not in rotation
|
||||
|
||||
47
js/mods.js
47
js/mods.js
@@ -86,7 +86,7 @@ const mod = {
|
||||
if (mod.isAcidDmg && mech.health > 1) dmg *= 1.4;
|
||||
if (mod.isRest && player.speed < 1) dmg *= 1.20;
|
||||
if (mod.isEnergyDamage) dmg *= 1 + mech.energy / 5.5;
|
||||
if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.004
|
||||
if (mod.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038
|
||||
if (mod.isRerollDamage) dmg *= 1 + 0.05 * powerUps.reroll.rerolls
|
||||
if (mod.isOneGun && b.inventory.length < 2) dmg *= 1.25
|
||||
return dmg * mod.slowFire
|
||||
@@ -713,6 +713,22 @@ const mod = {
|
||||
mod.isHarmArmor = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "exciton-lattice",
|
||||
description: `reduce <strong class='color-harm'>harm</strong> by <strong>80%</strong>, but<br>after a <strong>collision</strong>, <strong>eject</strong> one of your <strong class='color-m'>mods</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return !mod.isEnergyHealth && (mod.isBayesian || mod.isExtraChoice || mod.manyWorlds || mod.isImmortal || mod.isMineDrop || mod.renormalization)
|
||||
},
|
||||
requires: "Bayesian, cardinality, many worlds, immortality, renormalization, or mine synthesis",
|
||||
effect() {
|
||||
mod.isEjectMod = true;
|
||||
},
|
||||
remove() {
|
||||
mod.isEjectMod = false;
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "clock gating",
|
||||
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>`,
|
||||
@@ -1093,9 +1109,9 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return true
|
||||
return !mod.isBayesian
|
||||
},
|
||||
requires: "",
|
||||
requires: "not Bayesian inference",
|
||||
effect() {
|
||||
mod.isAmmoForGun = true;
|
||||
},
|
||||
@@ -1127,9 +1143,9 @@ const mod = {
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
allowed() {
|
||||
return !mod.isEnergyHealth
|
||||
return !mod.isEnergyHealth && !mod.isBayesian
|
||||
},
|
||||
requires: "not mass-energy equivalence",
|
||||
requires: "not mass-energy equivalence<br>not Bayesian inference",
|
||||
effect: () => {
|
||||
mod.isAmmoFromHealth = 0.023;
|
||||
},
|
||||
@@ -1288,7 +1304,7 @@ const mod = {
|
||||
},
|
||||
requires: "more than 6 mods",
|
||||
effect: () => {
|
||||
//remove bullets //to get rid of bots
|
||||
//remove active bullets //to get rid of bots
|
||||
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
|
||||
bullet = [];
|
||||
|
||||
@@ -1324,13 +1340,13 @@ const mod = {
|
||||
if (mod.mods[i].count > 0) have.push(i)
|
||||
}
|
||||
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)
|
||||
for (let i = 0; i < 2 * mod.mods[choose].count; i++) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
|
||||
}
|
||||
mod.mods[choose].remove(); // remove a random mod form the list of mods you have
|
||||
mod.mods[choose].count = 0;
|
||||
game.updateModHUD();
|
||||
|
||||
for (let i = 0; i < 2; i++) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
|
||||
}
|
||||
},
|
||||
remove() {}
|
||||
},
|
||||
@@ -2155,13 +2171,13 @@ const mod = {
|
||||
requires: "laser",
|
||||
effect() {
|
||||
mod.laserReflections++;
|
||||
mod.laserDamage += 0.05; //base is 0.1
|
||||
mod.laserFieldDrain += 0.001 //base is 0.002
|
||||
mod.laserDamage += 0.065; //base is 0.11
|
||||
mod.laserFieldDrain += 0.0009 //base is 0.002
|
||||
},
|
||||
remove() {
|
||||
mod.laserReflections = 2;
|
||||
mod.laserDamage = 0.1;
|
||||
mod.laserFieldDrain = 0.002;
|
||||
mod.laserDamage = 0.13;
|
||||
mod.laserFieldDrain = 0.0018;
|
||||
}
|
||||
},
|
||||
{
|
||||
@@ -2717,5 +2733,6 @@ const mod = {
|
||||
isBayesian: null,
|
||||
nailGun: null,
|
||||
nailInstantFireRate: null,
|
||||
isCapacitor: null
|
||||
isCapacitor: null,
|
||||
isEjectMod: null
|
||||
}
|
||||
74
js/player.js
74
js/player.js
@@ -359,9 +359,31 @@ const mech = {
|
||||
game.makeGunHUD(); //update gun HUD
|
||||
}
|
||||
|
||||
|
||||
function pixelWindows() {
|
||||
|
||||
//pixel graphics
|
||||
let imgData = ctx.getImageData(0, 0, canvas.width, canvas.height); //copy current canvas pixel data
|
||||
let data = imgData.data;
|
||||
//change random pixels
|
||||
//strange draw offset
|
||||
// const off = canvas.height * canvas.width * 4 / 16
|
||||
for (let i = 0; i < data.length; i += 4) {
|
||||
index = i % canvas.width
|
||||
data[index + 0] = data[index + 0]; // red
|
||||
data[index + 1] = data[index + 1]; // red
|
||||
data[index + 2] = data[index + 2]; // red
|
||||
data[index + 3] = data[index + 3]; // red
|
||||
}
|
||||
ctx.putImageData(imgData, 0, 0); //draw new pixel data to canvas
|
||||
|
||||
}
|
||||
|
||||
|
||||
game.wipe = function () { //set wipe to have trails
|
||||
ctx.fillStyle = "rgba(255,255,255,0)";
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// pixelWindows()
|
||||
}
|
||||
|
||||
function randomizeEverything() {
|
||||
@@ -387,6 +409,7 @@ const mech = {
|
||||
game.wipe = function () { //set wipe to have trails
|
||||
ctx.fillStyle = `rgba(255,255,255,${(i+1)*(i+1)*0.006})`;
|
||||
ctx.fillRect(0, 0, canvas.width, canvas.height);
|
||||
// pixelWindows()
|
||||
}
|
||||
}, (i + 1) * swapPeriod);
|
||||
}
|
||||
@@ -450,6 +473,7 @@ const mech = {
|
||||
let dmg = 1
|
||||
dmg *= mech.fieldHarmReduction
|
||||
dmg *= mod.isSlowFPS ? 0.85 : 1
|
||||
if (mod.isEjectMod) dmg *= 0.2
|
||||
if (mod.isHarmReduce && mech.fieldUpgrades[mech.fieldMode].name === "negative mass field" && mech.isFieldActive) dmg *= 0.6
|
||||
if (mod.isBotArmor) dmg *= 0.95 ** mod.totalBots()
|
||||
if (mod.isHarmArmor && mech.lastHarmCycle + 600 > mech.cycle) dmg *= 0.5;
|
||||
@@ -691,6 +715,7 @@ const mech = {
|
||||
holdingTarget: null,
|
||||
timeSkipLastCycle: 0,
|
||||
// these values are set on reset by setHoldDefaults()
|
||||
grabPowerUpRange2: 0,
|
||||
isFieldActive: false,
|
||||
fieldRange: 155,
|
||||
fieldShieldingScale: 1,
|
||||
@@ -713,6 +738,7 @@ const mech = {
|
||||
mech.fieldBlockCD = 10;
|
||||
game.isBodyDamage = true;
|
||||
mech.fieldHarmReduction = 1;
|
||||
mech.grabPowerUpRange2 = 156000;
|
||||
mech.fieldRange = 155;
|
||||
mech.fieldFire = false;
|
||||
mech.fieldCDcycle = 0;
|
||||
@@ -939,15 +965,18 @@ const mech = {
|
||||
ctx.stroke();
|
||||
},
|
||||
grabPowerUp() { //look for power ups to grab with field
|
||||
const grabPowerUpRange2 = 156000 //(mech.fieldRange + 220) * (mech.fieldRange + 220)
|
||||
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||
const dxP = mech.pos.x - powerUp[i].position.x;
|
||||
const dyP = mech.pos.y - powerUp[i].position.y;
|
||||
const dist2 = dxP * dxP + dyP * dyP;
|
||||
// float towards player if looking at and in range or if very close to player
|
||||
if (dist2 < grabPowerUpRange2 && (mech.lookingAt(powerUp[i]) || dist2 < 16000) && !(mech.health === mech.maxHealth && powerUp[i].name === "heal")) {
|
||||
powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass;
|
||||
powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
||||
if (dist2 < mech.grabPowerUpRange2 &&
|
||||
(mech.lookingAt(powerUp[i]) || dist2 < 16000) &&
|
||||
!(mech.health === mech.maxHealth && powerUp[i].name === "heal") &&
|
||||
Matter.Query.ray(map, powerUp[i].position, mech.pos).length === 0
|
||||
) {
|
||||
powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass;
|
||||
powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * game.g; //negate gravity
|
||||
//extra friction
|
||||
Matter.Body.setVelocity(powerUp[i], {
|
||||
x: powerUp[i].velocity.x * 0.11,
|
||||
@@ -1186,7 +1215,7 @@ const mech = {
|
||||
},
|
||||
fieldUpgrades: [{
|
||||
name: "field emitter",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>shield</strong> yourself from <strong class='color-harm'>harm</strong><br><strong>pick up</strong> and <strong>throw</strong> objects",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong>push</strong> mobs away<br><strong>throw</strong> blocks to <strong class='color-d'>damage</strong> mobs<br><strong>pick up</strong> power ups",
|
||||
effect: () => {
|
||||
game.replaceTextLog = true; //allow text over write
|
||||
mech.hold = function () {
|
||||
@@ -1212,9 +1241,9 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "standing wave harmonics",
|
||||
description: "three oscillating <strong>shields</strong> are permanently active<br>reduce <strong class='color-harm'>harm</strong> by <strong>30%</strong>",
|
||||
description: "three oscillating <strong>shields</strong> are permanently active<br><strong>blocking</strong> has no <strong>cool down</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>",
|
||||
effect: () => {
|
||||
mech.fieldHarmReduction = 0.70;
|
||||
mech.fieldHarmReduction = 0.20;
|
||||
mech.fieldBlockCD = 0;
|
||||
mech.hold = function () {
|
||||
if (mech.isHolding) {
|
||||
@@ -1231,8 +1260,8 @@ const mech = {
|
||||
}
|
||||
if (mech.energy > 0.1 && mech.fieldCDcycle < mech.cycle) {
|
||||
const fieldRange1 = (0.7 + 0.3 * Math.sin(mech.cycle / 23)) * mech.fieldRange
|
||||
const fieldRange2 = (0.6 + 0.4 * Math.sin(mech.cycle / 37)) * mech.fieldRange
|
||||
const fieldRange3 = (0.55 + 0.45 * Math.sin(mech.cycle / 47)) * mech.fieldRange
|
||||
const fieldRange2 = (0.63 + 0.37 * Math.sin(mech.cycle / 37)) * mech.fieldRange
|
||||
const fieldRange3 = (0.65 + 0.35 * Math.sin(mech.cycle / 47)) * mech.fieldRange
|
||||
const netfieldRange = Math.max(fieldRange1, fieldRange2, fieldRange3)
|
||||
ctx.fillStyle = "rgba(110,170,200," + (0.04 + mech.energy * (0.12 + 0.13 * Math.random())) + ")";
|
||||
ctx.beginPath();
|
||||
@@ -1254,16 +1283,18 @@ const mech = {
|
||||
{
|
||||
name: "perfect diamagnetism",
|
||||
// description: "gain <strong class='color-f'>energy</strong> when <strong>blocking</strong><br>no <strong>recoil</strong> when <strong>blocking</strong>",
|
||||
description: "<strong>blocking</strong> does not drain <strong class='color-f'>energy</strong><br><strong>blocking</strong> has no <strong>cool down</strong> and less <strong>recoil</strong>",
|
||||
description: "<strong>blocking</strong> does not drain <strong class='color-f'>energy</strong><br><strong>blocking</strong> has no <strong>cool down</strong> and less <strong>recoil</strong><br><strong>attract</strong> power ups from <strong>far away</strong>",
|
||||
effect: () => {
|
||||
mech.fieldShieldingScale = 0;
|
||||
mech.grabPowerUpRange2 = 4000000
|
||||
// mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping
|
||||
// mech.fieldMeterColor = "#0af"
|
||||
// mech.fieldArc = 0.3; //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
|
||||
// mech.calculateFieldThreshold();
|
||||
mech.hold = function () {
|
||||
const wave = Math.sin(mech.cycle * 0.022);
|
||||
mech.fieldRange = 165 + 12 * wave
|
||||
mech.fieldArc = 0.3 + 0.035 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
|
||||
mech.fieldRange = 170 + 12 * wave
|
||||
mech.fieldArc = 0.33 + 0.045 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
|
||||
mech.calculateFieldThreshold();
|
||||
if (mech.isHolding) {
|
||||
mech.drawHold(mech.holdingTarget);
|
||||
@@ -1317,13 +1348,13 @@ const mech = {
|
||||
if (mod.isSporeField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
|
||||
const len = Math.floor(6 + 4 * Math.random())
|
||||
mech.energy -= len * 0.074;
|
||||
mech.energy -= len * 0.07;
|
||||
for (let i = 0; i < len; i++) {
|
||||
b.spore(mech.pos)
|
||||
}
|
||||
} else if (mod.isMissileField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
|
||||
mech.energy -= 0.6;
|
||||
mech.energy -= 0.55;
|
||||
b.missile({
|
||||
x: mech.pos.x + 40 * Math.cos(mech.angle),
|
||||
y: mech.pos.y + 40 * Math.sin(mech.angle) - 3
|
||||
@@ -1333,11 +1364,11 @@ const mech = {
|
||||
1, mod.babyMissiles)
|
||||
} else if (mod.isIceField) {
|
||||
// mech.fieldCDcycle = mech.cycle + 17; // set cool down to prevent +energy from making huge numbers of drones
|
||||
mech.energy -= 0.045;
|
||||
mech.energy -= 0.04;
|
||||
b.iceIX(1)
|
||||
} else {
|
||||
// mech.fieldCDcycle = mech.cycle + 10; // set cool down to prevent +energy from making huge numbers of drones
|
||||
mech.energy -= 0.33;
|
||||
mech.energy -= 0.3;
|
||||
b.drone(1)
|
||||
}
|
||||
|
||||
@@ -1365,13 +1396,15 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "negative mass field",
|
||||
description: "use <strong class='color-f'>energy</strong> to nullify <strong style='letter-spacing: 12px;'>gravity</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>45%</strong>",
|
||||
description: "use <strong class='color-f'>energy</strong> to nullify <strong style='letter-spacing: 12px;'>gravity</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>45%</strong><br><strong>blocks</strong> held by the field have a lower <strong>mass</strong>",
|
||||
fieldDrawRadius: 0,
|
||||
effect: () => {
|
||||
mech.fieldFire = true;
|
||||
mech.holdingMassScale = 0.03; //can hold heavier blocks with lower cost to jumping
|
||||
mech.fieldMeterColor = "#000"
|
||||
mech.fieldHarmReduction = 0.55;
|
||||
mech.fieldDrawRadius = 0;
|
||||
|
||||
mech.hold = function () {
|
||||
mech.airSpeedLimit = 125 //5 * player.mass * player.mass
|
||||
mech.FxAir = 0.016
|
||||
@@ -1483,7 +1516,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "plasma torch",
|
||||
description: "use <strong class='color-f'>energy</strong> to emit short range plasma<br>plasma <strong class='color-d'>damages</strong> and <strong>pushes</strong> mobs",
|
||||
description: "use <strong class='color-f'>energy</strong> to emit short range plasma<br>plasma <strong class='color-d'>damages</strong> mobs<br>plasma <strong>pushes</strong> mobs and blocks away",
|
||||
effect() {
|
||||
mech.fieldMeterColor = "#f0f"
|
||||
mech.hold = function () {
|
||||
@@ -1638,7 +1671,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "time dilation field",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><em>you can move and fire while time is stopped</em>",
|
||||
description: "use <strong class='color-f'>energy</strong> to <strong style='letter-spacing: 1px;'>stop time</strong><br><strong>move</strong> and <strong>fire</strong> while time is stopped<br><strong>touching</strong> mobs still does <strong class='color-harm'>harm</strong>",
|
||||
effect: () => {
|
||||
// mech.fieldMeterColor = "#000"
|
||||
mech.fieldFire = true;
|
||||
@@ -1667,6 +1700,7 @@ const mech = {
|
||||
ctx.fillStyle = "#ccc";
|
||||
ctx.fillRect(-100000, -100000, 200000, 200000)
|
||||
ctx.globalCompositeOperation = "source-over"
|
||||
|
||||
//stop time
|
||||
mech.isBodiesAsleep = true;
|
||||
|
||||
@@ -1730,7 +1764,7 @@ const mech = {
|
||||
},
|
||||
{
|
||||
name: "phase decoherence field",
|
||||
description: "use <strong class='color-f'>energy</strong> to become <strong>intangible</strong><br><strong>firing</strong> and touching <strong>shields</strong> increases <strong>drain</strong>",
|
||||
description: "use <strong class='color-f'>energy</strong> to become <strong>intangible</strong><br><strong>firing</strong> and touching <strong>shields</strong> <strong>drains</strong> <strong class='color-f'>energy</strong><br>unable to <strong>see</strong> and be <strong>seen</strong> by mobs",
|
||||
effect: () => {
|
||||
mech.fieldFire = true;
|
||||
mech.fieldMeterColor = "#fff";
|
||||
|
||||
143
js/powerup.js
143
js/powerup.js
@@ -21,24 +21,30 @@ const powerUps = {
|
||||
}
|
||||
powerUps.endDraft();
|
||||
},
|
||||
endDraft() {
|
||||
if (mod.manyWorlds && powerUps.reroll.rerolls < 1) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
|
||||
}
|
||||
document.body.style.cursor = "none";
|
||||
document.getElementById("choose-grid").style.display = "none"
|
||||
document.getElementById("choose-background").style.display = "none"
|
||||
game.paused = false;
|
||||
game.isChoosing = false; //stops p from un pausing on key down
|
||||
requestAnimationFrame(cycle);
|
||||
},
|
||||
showDraft() {
|
||||
document.getElementById("choose-grid").style.display = "grid"
|
||||
document.getElementById("choose-background").style.display = "inline"
|
||||
document.body.style.cursor = "auto";
|
||||
if (mod.isExtraChoice) {
|
||||
document.body.style.overflowY = "scroll";
|
||||
document.body.style.overflowX = "hidden";
|
||||
}
|
||||
game.paused = true;
|
||||
game.isChoosing = true; //stops p from un pausing on key down
|
||||
},
|
||||
endDraft() {
|
||||
if (mod.manyWorlds && powerUps.reroll.rerolls < 1) {
|
||||
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll");
|
||||
}
|
||||
document.getElementById("choose-grid").style.display = "none"
|
||||
document.getElementById("choose-background").style.display = "none"
|
||||
document.body.style.cursor = "none";
|
||||
document.body.style.overflow = "hidden"
|
||||
game.paused = false;
|
||||
game.isChoosing = false; //stops p from un pausing on key down
|
||||
mech.immuneCycle = mech.cycle + 60; //player is immune to collision damage for 30 cycles
|
||||
requestAnimationFrame(cycle);
|
||||
},
|
||||
reroll: {
|
||||
rerolls: 0,
|
||||
name: "reroll",
|
||||
@@ -48,7 +54,7 @@ const powerUps = {
|
||||
},
|
||||
effect() {
|
||||
powerUps.reroll.changeRerolls(1)
|
||||
game.makeTextLog("<div class='circle reroll'></div> <span style='font-size:115%;'> <strong>+1 reroll</strong></span>", 300)
|
||||
game.makeTextLog(`<div class='circle reroll'></div> <span style='font-size:115%;'><strong>rerolls:</strong> ${powerUps.reroll.rerolls}</span>`, 300)
|
||||
},
|
||||
changeRerolls(amount) {
|
||||
powerUps.reroll.rerolls += amount
|
||||
@@ -262,66 +268,67 @@ const powerUps = {
|
||||
},
|
||||
choiceLog: [], //records all previous choice options
|
||||
effect() {
|
||||
|
||||
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
for (let i = 0; i < mod.mods.length; i++) {
|
||||
if (mod.mods[i].count < mod.mods[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && mod.mods[i].allowed()) {
|
||||
options.push(i);
|
||||
if (mech.alive) {
|
||||
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) {
|
||||
let options = [];
|
||||
for (let i = 0; i < mod.mods.length; i++) {
|
||||
if (mod.mods[i].count < mod.mods[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && mod.mods[i].allowed()) {
|
||||
options.push(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
//remove repeats from last selection
|
||||
const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2
|
||||
if (powerUps.mod.choiceLog.length > totalChoices || powerUps.mod.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
|
||||
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
|
||||
if (options.length > totalChoices) {
|
||||
for (let j = 0, len = options.length; j < len; j++) {
|
||||
if (powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i] === options[j]) {
|
||||
options.splice(j, 1) //remove previous choice from option pool
|
||||
break
|
||||
//remove repeats from last selection
|
||||
const totalChoices = mod.isDeterminism ? 1 : 3 + mod.isExtraChoice * 2
|
||||
if (powerUps.mod.choiceLog.length > totalChoices || powerUps.mod.choiceLog.length === totalChoices) { //make sure this isn't the first time getting a power up and there are previous choices to remove
|
||||
for (let i = 0; i < totalChoices; i++) { //repeat for each choice from the last selection
|
||||
if (options.length > totalChoices) {
|
||||
for (let j = 0, len = options.length; j < len; j++) {
|
||||
if (powerUps.mod.choiceLog[powerUps.mod.choiceLog.length - 1 - i] === options[j]) {
|
||||
options.splice(j, 1) //remove previous choice from option pool
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.length > 0) {
|
||||
const choose = options[Math.floor(Math.random() * options.length)]
|
||||
text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choose})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choose].name}</div> ${mod.mods[choose].description}</div>`
|
||||
return choose
|
||||
}
|
||||
if (options.length > 0) {
|
||||
const choose = options[Math.floor(Math.random() * options.length)]
|
||||
text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choose})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choose].name}</div> ${mod.mods[choose].description}</div>`
|
||||
return choose
|
||||
}
|
||||
|
||||
}
|
||||
let text = ""
|
||||
if (!mod.isDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft()'>✕</div>`
|
||||
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>choose a mod</h3>`
|
||||
let choice1 = pick()
|
||||
let choice2 = -1
|
||||
let choice3 = -1
|
||||
if (choice1 > -1) {
|
||||
if (!mod.isDeterminism) {
|
||||
choice2 = pick(choice1)
|
||||
// if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice2})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice2].name}</div> ${mod.mods[choice2].description}</div>`
|
||||
choice3 = pick(choice1, choice2)
|
||||
// if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice3})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice3].name}</div> ${mod.mods[choice3].description}</div>`
|
||||
}
|
||||
if (mod.isExtraChoice) {
|
||||
let choice4 = pick(choice1, choice2, choice3)
|
||||
// if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice4})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice4].name}</div> ${mod.mods[choice4].description}</div>`
|
||||
let choice5 = pick(choice1, choice2, choice3, choice4)
|
||||
// if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice5})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice5].name}</div> ${mod.mods[choice5].description}</div>`
|
||||
powerUps.mod.choiceLog.push(choice4)
|
||||
powerUps.mod.choiceLog.push(choice5)
|
||||
}
|
||||
powerUps.mod.choiceLog.push(choice1)
|
||||
powerUps.mod.choiceLog.push(choice2)
|
||||
powerUps.mod.choiceLog.push(choice3)
|
||||
if (powerUps.reroll.rerolls) text += `<div class="choose-grid-module" onclick="powerUps.reroll.use('mod')"><div class="grid-title"><div class="circle-grid reroll"></div> reroll <span class='dice'>${powerUps.reroll.diceText()}</span></div></div>`
|
||||
let text = ""
|
||||
if (!mod.isDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft()'>✕</div>`
|
||||
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>choose a mod</h3>`
|
||||
let choice1 = pick()
|
||||
let choice2 = -1
|
||||
let choice3 = -1
|
||||
if (choice1 > -1) {
|
||||
if (!mod.isDeterminism) {
|
||||
choice2 = pick(choice1)
|
||||
// if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice2})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice2].name}</div> ${mod.mods[choice2].description}</div>`
|
||||
choice3 = pick(choice1, choice2)
|
||||
// if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice3})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice3].name}</div> ${mod.mods[choice3].description}</div>`
|
||||
}
|
||||
if (mod.isExtraChoice) {
|
||||
let choice4 = pick(choice1, choice2, choice3)
|
||||
// if (choice4 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice4})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice4].name}</div> ${mod.mods[choice4].description}</div>`
|
||||
let choice5 = pick(choice1, choice2, choice3, choice4)
|
||||
// if (choice5 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('mod',${choice5})"><div class="grid-title"><div class="circle-grid mod"></div> ${mod.mods[choice5].name}</div> ${mod.mods[choice5].description}</div>`
|
||||
powerUps.mod.choiceLog.push(choice4)
|
||||
powerUps.mod.choiceLog.push(choice5)
|
||||
}
|
||||
powerUps.mod.choiceLog.push(choice1)
|
||||
powerUps.mod.choiceLog.push(choice2)
|
||||
powerUps.mod.choiceLog.push(choice3)
|
||||
if (powerUps.reroll.rerolls) text += `<div class="choose-grid-module" onclick="powerUps.reroll.use('mod')"><div class="grid-title"><div class="circle-grid reroll"></div> reroll <span class='dice'>${powerUps.reroll.diceText()}</span></div></div>`
|
||||
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
powerUps.showDraft();
|
||||
} else {
|
||||
powerUps.giveRandomAmmo()
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
powerUps.showDraft();
|
||||
} else {
|
||||
powerUps.giveRandomAmmo()
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -449,11 +456,7 @@ const powerUps = {
|
||||
randomPowerUpCounter: 0,
|
||||
spawnBossPowerUp(x, y) { //boss spawns field and gun mod upgrades
|
||||
powerUps.randomPowerUpCounter++;
|
||||
if (game.difficultyMode === 4 && Math.random() < 0.5) { //why mode gets a free power up chance
|
||||
powerUps.randomPowerUpCounter *= 0.5
|
||||
spawnPowerUps()
|
||||
}
|
||||
|
||||
if (game.difficultyMode === 4) spawnPowerUps() //why mode gets a free power up chance
|
||||
const chanceToFail = Math.max(level.levelsCleared, 10) * 0.1 //1 until level 10, then 1.1, 1.2, 1.3, ...
|
||||
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
|
||||
powerUps.randomPowerUpCounter = 0;
|
||||
@@ -528,8 +531,8 @@ const powerUps = {
|
||||
size = target.size();
|
||||
powerUp[index] = Matter.Bodies.polygon(x, y, 0, size, {
|
||||
density: 0.001,
|
||||
frictionAir: 0.01,
|
||||
restitution: 0.8,
|
||||
frictionAir: 0.03,
|
||||
restitution: 0.85,
|
||||
inertia: Infinity, //prevents rotation
|
||||
collisionFilter: {
|
||||
group: 0,
|
||||
|
||||
82
todo.txt
82
todo.txt
@@ -1,43 +1,46 @@
|
||||
rail gun mod: capacitor bank - no charge time, but smaller bullets
|
||||
field: perfect diamagnetism is a bit larger
|
||||
can now grab power ups from far away
|
||||
|
||||
stunned mobs now still display health bar
|
||||
when you hit a mob hard with a block they get stunned
|
||||
blocks do about 15% less collision damage
|
||||
stuns lasts longer for larger and faster blocks
|
||||
|
||||
mod: exciton-lattice - reduce harm by 80%, but after taking collision damage eject a random mod
|
||||
eject extra mods if you have recursive stacks
|
||||
|
||||
power ups have a bit more air friction
|
||||
power ups must be in line of sight to be pulled by the player
|
||||
why mode now gets 100% chance for a second boss power up (up from 50%)
|
||||
this should let why mode reach more interesting build depth
|
||||
laser and pulse got a damage and energy use buff
|
||||
immune to harm for a second after exiting the power up selection menu
|
||||
|
||||
************** TODO - n-gon **************
|
||||
|
||||
player goes intangible while immune after getting hit?
|
||||
getting stuck above a mob can immobilize player
|
||||
add a minimum knock from player mob collisions?
|
||||
new gun fire 3+ balls in arc
|
||||
name: something about energy
|
||||
does damage in area, like neutron bomb
|
||||
ends on contact with wall, doesn't stick or bounce
|
||||
hold fire to charge: increases the size of the balls
|
||||
mod: balls are attracted to mobs
|
||||
|
||||
when crouched make it harder for mobs to see player
|
||||
reduce arc size of mob vision cone
|
||||
reduce look range
|
||||
* (mech.crouch ? 0.7 : 1)
|
||||
fix: even with a scroll bar the top of the selection window is off screen for very short windows
|
||||
|
||||
rework perfect diamagnetism
|
||||
keep the zero energy cost
|
||||
add a very short blocking CD
|
||||
let the shield also do bremsstrahlung radiation
|
||||
mod: grab and launch mobs?
|
||||
|
||||
getting stuck above a mob can immobilize player
|
||||
seems to only occur with Pauli exclusion
|
||||
add a knock to player mob collisions even while player is immune to damage
|
||||
keep the knock very small
|
||||
|
||||
map element - player rotates a rotor that makes a platform go up or down
|
||||
|
||||
reduce damage by 80%, but lose ammo when you get hit
|
||||
|
||||
foam needs a new mod
|
||||
is the foam mod colloidal foam fun?
|
||||
increase foam bullet size?
|
||||
foam explodes when it runs out?
|
||||
|
||||
removing supersaturation sets total health to 1
|
||||
this cancels the health benefits from crystallized armor
|
||||
produce a method that calculates max health based on mods
|
||||
|
||||
use mac automator to speed up your n-gon -> git sync
|
||||
|
||||
considering removing the perfect diamagnetism field from the game
|
||||
or just rework perfect diamagnetism
|
||||
perfect diamagnetism be able to grab and launch mobs
|
||||
|
||||
Gun: Launch yourself at high speed to the enemy, gaining temporary invincibility while in the air and for 3 seconds after landing. Upon impact, trigger a large explosion.
|
||||
|
||||
fix door.isOpen actually meaning isClosed
|
||||
|
||||
mod - laser fires 3 beams
|
||||
@@ -45,27 +48,18 @@ mod - laser fires 3 beams
|
||||
after you die custom should be populated with your last build
|
||||
also you should be able to share while paused
|
||||
|
||||
use canvas pixel array effects for full screen graphics
|
||||
add some pixels after player gets hit?
|
||||
|
||||
give missiles a suck and delay explosion, like vacuum bomb
|
||||
|
||||
bot that does AOE damage while it rotates around player
|
||||
no physics / collisions
|
||||
cap 3 ?
|
||||
|
||||
|
||||
level Boss: fractal Sierpiński triangle
|
||||
https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle
|
||||
spawns a 1/2 size version of the boss, this version can also spawn a smaller version, but it is capped at some size level
|
||||
they spawn once at the start of the level
|
||||
if a version dies, one can be replaced every ten seconds by the largest version
|
||||
|
||||
performance issues with large numbers of spores
|
||||
consider limiting total bullets?
|
||||
300?
|
||||
|
||||
level element: a hanging chain of connected blocks
|
||||
level element: a zone with wind, anti-gravity, extra gravity
|
||||
control with button
|
||||
|
||||
@@ -123,15 +117,6 @@ new gun - deploy a turret that last for 20 seconds
|
||||
mod - mines become a turret that fires nails
|
||||
it could float to the mouse location on fire
|
||||
|
||||
minigun: high caliber - rework
|
||||
slow down the bullets even more and increase the size?
|
||||
remove and actually make a full gun like this?
|
||||
|
||||
portals:
|
||||
portal while holding block sometimes send player back to original portal
|
||||
only seems to happen with the bottom right block
|
||||
use buttons to turn on and off?
|
||||
|
||||
level boss: fires a line intersection in a random direction every few seconds.
|
||||
the last two intersections have a destructive laser between them.
|
||||
|
||||
@@ -144,8 +129,6 @@ map: prison
|
||||
doors linked to buttons
|
||||
mobs inside the doors?
|
||||
|
||||
map: airport
|
||||
|
||||
mod - do 50% more damage in close, but 50% less at a distance
|
||||
code it like mod.isFarAwayDmg
|
||||
have these mods disable each other
|
||||
@@ -153,9 +136,6 @@ mod - do 50% more damage in close, but 50% less at a distance
|
||||
phase field still isn't fun
|
||||
does phase field need the stealth flag?
|
||||
|
||||
mod: use the stealth flag from the phase decoherence field
|
||||
maybe trigger it along with the damage immunity CD
|
||||
|
||||
mod harmonic shield: slow everything in range around shield (temporal shield)
|
||||
set max speed?
|
||||
|
||||
@@ -166,10 +146,6 @@ mod: bot very slowly follows you and gives you a bonus when it's in range
|
||||
graphic idea: bezier curve that moves smoothly from mob to mob
|
||||
loops around player
|
||||
|
||||
graphic: give rail gun projectile a trail
|
||||
only draw above speed 5
|
||||
track previous positions?
|
||||
|
||||
movement fluidity
|
||||
let legs jump on mobs, but player will still take damage
|
||||
like: ori and the blind forest, celeste
|
||||
|
||||
Reference in New Issue
Block a user