mod: CPT reversal - avoid damage by rewinding to your past, but use up all your energy
  requires wormhole or time dilation

several minor buffs to wormhole
small changes to mob distribution on a few maps
This commit is contained in:
landgreen
2020-11-27 04:26:30 -08:00
parent 0c319d3049
commit 6c5928c052
9 changed files with 272 additions and 169 deletions

View File

@@ -2259,7 +2259,7 @@ const b = {
// check if inside a mob // check if inside a mob
q = Matter.Query.point(mob, this.position) q = Matter.Query.point(mob, this.position)
for (let i = 0; i < q.length; i++) { for (let i = 0; i < q.length; i++) {
let dmg = b.dmgScale * 0.36 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction
q[i].damage(dmg); q[i].damage(dmg);
q[i].foundPlayer(); q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue game.drawList.push({ //add dmg to draw queue
@@ -2292,7 +2292,7 @@ const b = {
for (let i = 0; i < q.length; i++) { for (let i = 0; i < q.length; i++) {
slowCheck = 0.3; slowCheck = 0.3;
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 = b.dmgScale * 0.36 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction let dmg = b.dmgScale * 0.4 / Math.sqrt(q[i].mass) * (mod.waveHelix === 1 ? 1 : 0.8) //1 - 0.4 = 0.6 for helix mod 40% damage reduction
q[i].damage(dmg); q[i].damage(dmg);
q[i].foundPlayer(); q[i].foundPlayer();
game.drawList.push({ //add dmg to draw queue game.drawList.push({ //add dmg to draw queue

View File

@@ -13,13 +13,13 @@ 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(8) // level.difficultyIncrease(89)
// game.zoomScale = 1000; // game.zoomScale = 1000;
// game.setZoom(); // game.setZoom();
// mech.setField("wormhole") // mech.setField("wormhole")
// b.giveGuns("laser") // b.giveGuns("laser")
// mod.is3Missiles = true // mod.is3Missiles = true
// mod.giveMod("history laser") // mod.giveMod("CPT reversal")
// mod.giveMod("diffuse beam") // mod.giveMod("diffuse beam")
level.intro(); //starting level level.intro(); //starting level
@@ -156,7 +156,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.boost(1500, 0, 900); // spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 20) spawn.starter(1900, -500, 20)
// spawn.sucker(2900, -500) // spawn.sucker(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
@@ -171,7 +171,7 @@ const level = {
// spawn.nodeBoss(1200, -500, "launcher") // spawn.nodeBoss(1200, -500, "launcher")
// spawn.snakeBoss(1200, -500) // spawn.snakeBoss(1200, -500)
spawn.powerUpBoss(2900, -500) // spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500) // spawn.randomMob(1600, -500)
}, },
template() { template() {
@@ -762,7 +762,11 @@ const level = {
spawn.randomMob(-75, -850, -0.1); spawn.randomMob(-75, -850, -0.1);
spawn.randomMob(1300, -600, -0.1); spawn.randomMob(1300, -600, -0.1);
spawn.randomMob(550, -3400, 0); spawn.randomMob(550, -3400, 0);
if (game.difficulty > 50) { spawn.randomMob(0, -1175, 0.5);
spawn.randomMob(-75, -1150, 0.5);
spawn.randomMob(1075, -625, 0.5);
spawn.randomMob(1725, -575, 0.5);
if (game.difficulty > 40) {
spawn.randomMob(2300, -2775, -0.5); spawn.randomMob(2300, -2775, -0.5);
spawn.randomMob(600, -925, -0.5); spawn.randomMob(600, -925, -0.5);
spawn.randomMob(1550, -2750, -0.5); spawn.randomMob(1550, -2750, -0.5);
@@ -770,7 +774,7 @@ const level = {
spawn.randomMob(-75, -1475, 0); spawn.randomMob(-75, -1475, 0);
spawn.randomBoss(600, -2600, 0); spawn.randomBoss(600, -2600, 0);
} }
if (game.difficulty < 32) { if (game.difficulty < 25) {
spawn.randomMob(700, -1650, 0); spawn.randomMob(700, -1650, 0);
spawn.randomMob(600, -3500, 0.2); spawn.randomMob(600, -3500, 0.2);
spawn.randomMob(-75, -1175, 0.2); spawn.randomMob(-75, -1175, 0.2);
@@ -871,12 +875,6 @@ const level = {
spawn.mapRect(2625, 2288, 650, 50); spawn.mapRect(2625, 2288, 650, 50);
spawn.mapRect(2700, 2276, 500, 50); spawn.mapRect(2700, 2276, 500, 50);
// spawn.mapRect(3000, 400, 1000, 1250);
// spawn.mapRect(3000, 1925, 1000, 150);
// spawn.mapRect(3100, 1875, 800, 100);
// spawn.mapRect(3100, 1600, 800, 100);
// spawn.mapRect(3100, 350, 800, 100);
// spawn.mapRect(3100, 2025, 800, 100);
spawn.mapRect(2400, 0, 200, 1925); //left down tube wall spawn.mapRect(2400, 0, 200, 1925); //left down tube wall
spawn.mapRect(600, 2300, 3750, 200); spawn.mapRect(600, 2300, 3750, 200);
@@ -889,7 +887,6 @@ const level = {
spawn.mapRect(500, 1700, 200, 800); //left wall spawn.mapRect(500, 1700, 200, 800); //left wall
spawn.mapRect(675, 1875, 325, 150, 0.5); spawn.mapRect(675, 1875, 325, 150, 0.5);
spawn.mapRect(4450, 2900, 4900, 200); //boss room floor spawn.mapRect(4450, 2900, 4900, 200); //boss room floor
spawn.mapRect(4150, 2600, 400, 500); spawn.mapRect(4150, 2600, 400, 500);
spawn.mapRect(6250, 2675, 700, 325); spawn.mapRect(6250, 2675, 700, 325);
@@ -909,25 +906,30 @@ const level = {
spawn.mapRect(9300, 2590, 650, 25); spawn.mapRect(9300, 2590, 650, 25);
spawn.mapRect(9700, 2580, 100, 50); spawn.mapRect(9700, 2580, 100, 50);
spawn.randomBoss(1300, 2100, 0.5); spawn.randomBoss(1300, 2100, 0.1);
spawn.randomMob(8300, 2100, 0.2); spawn.randomMob(8300, 2100, 0.1);
spawn.randomSmallMob(2575, -75, 0.2); //entrance spawn.randomSmallMob(2575, -75, 0.1); //entrance
spawn.randomMob(8125, 2450, 0.25); spawn.randomMob(8125, 2450, 0.1);
spawn.randomSmallMob(3200, 250, 0.3); spawn.randomSmallMob(3200, 250, 0.1);
spawn.randomMob(2425, 2150, 0.3); spawn.randomMob(2425, 2150, 0.1);
spawn.randomSmallMob(3500, 250, 0.4); spawn.randomSmallMob(3500, 250, 0.2);
spawn.randomMob(3800, 2175, 0.4); spawn.randomMob(3800, 2175, 0.2);
spawn.randomSmallMob(1100, -300, 0.4); //entrance spawn.randomSmallMob(1100, -300, 0.2); //entrance
spawn.randomMob(4450, 2500, 0.5); spawn.randomMob(4450, 2500, 0.2);
spawn.randomMob(6350, 2525, 0.5); spawn.randomMob(6350, 2525, 0.2);
spawn.randomBoss(9200, 2400, 0.6); spawn.randomBoss(9200, 2400, 0.3);
spawn.randomSmallMob(1900, -250, 0.6); //entrance spawn.randomSmallMob(1900, -250, 0.3); //entrance
spawn.randomMob(1500, 2100, 0.7); spawn.randomMob(1500, 2100, 0.4);
spawn.randomSmallMob(1700, -150, 0.7); //entrance spawn.randomSmallMob(1700, -150, 0.4); //entrance
spawn.randomMob(8800, 2725, 0.8); spawn.randomMob(8800, 2725, 0.5);
spawn.randomMob(7300, 2200, 0.8); spawn.randomMob(7300, 2200, 0.5);
spawn.randomMob(2075, 2025, 0.8); spawn.randomMob(2075, 2025, 0.5);
spawn.randomMob(3475, 2175, 0.8); spawn.randomMob(3475, 2175, 0.5);
spawn.randomMob(8900, 2825, 0.5);
spawn.randomMob(9600, 2425, 0.9);
spawn.randomMob(3600, 1725, 0.9);
spawn.randomMob(4100, 1225, 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"]);
powerUps.addRerollToLevel() //needs to run after mobs are spawned powerUps.addRerollToLevel() //needs to run after mobs are spawned
}, },
@@ -996,13 +998,6 @@ const level = {
height: 775, height: 775,
color: "rgba(0,20,40,0.2)" color: "rgba(0,20,40,0.2)"
}); });
level.fill.push({
x: 1800,
y: -475,
width: 850,
height: 775,
color: "rgba(0,20,40,0.2)"
});
level.fillBG.push({ level.fillBG.push({
x: -250, x: -250,
y: -750, y: -750,
@@ -1037,19 +1032,26 @@ const level = {
color: "#d0d4d6" color: "#d0d4d6"
}); });
//tall platform //tall platform
spawn.mapVertex(2225, -450, "325 0 250 80 -250 80 -325 0 -250 -80 250 -80"); //base spawn.mapVertex(2225, -250, "325 0 250 80 -250 80 -325 0 -250 -80 250 -80"); //base
spawn.mapRect(1725, -2800, 1000, 50); //super high shade spawn.mapRect(1725, -2800, 1000, 50); //super high shade
spawn.mapRect(1800, -500, 850, 100); //far left starting ceiling spawn.mapRect(1800, -300, 850, 100); //far left starting ceiling
spawn.bodyRect(2400, -2950, 150, 150); //shield from laser spawn.bodyRect(2400, -2950, 150, 150); //shield from laser
level.fillBG.push({ level.fillBG.push({
x: 2000, x: 2000,
y: -2800, y: -2800,
width: 450, width: 450,
height: 2300, height: 2500,
color: "#d0d4d6" color: "#d0d4d6"
}); });
level.fill.push({
x: 1800,
y: -275,
width: 850,
height: 775,
color: "rgba(0,20,40,0.2)"
});
//tall platform //tall platform
spawn.mapVertex(3350, 200, "375 0 -375 0 -250 -250 250 -250"); //base spawn.mapVertex(3350, 200, "400 0 -400 0 -275 -275 275 -275"); //base
spawn.bodyRect(3400, -150, 150, 150); spawn.bodyRect(3400, -150, 150, 150);
spawn.mapRect(2850, -3150, 1000, 50); //super high shade spawn.mapRect(2850, -3150, 1000, 50); //super high shade
spawn.bodyRect(3675, -3470, 525, 20); //plank spawn.bodyRect(3675, -3470, 525, 20); //plank
@@ -1089,16 +1091,9 @@ const level = {
spawn.mapRect(4600, -1300, 450, 100); spawn.mapRect(4600, -1300, 450, 100);
//steep stairs //steep stairs
// spawn.mapRect(4100, -1700, 100, 100);
// spawn.mapRect(4200, -2050, 100, 450);
// spawn.mapRect(4300, -2400, 100, 800);
// spawn.mapRect(4400, -2750, 100, 1150);
// spawn.mapRect(4500, -3100, 100, 1500);
spawn.mapRect(4100, -2250, 100, 650); spawn.mapRect(4100, -2250, 100, 650);
spawn.mapRect(4100, -3450, 100, 650); //left top shelf spawn.mapRect(4100, -3450, 100, 650); //left top shelf
spawn.mapRect(4600, -3450, 100, 1850); spawn.mapRect(4600, -3450, 100, 1850);
// spawn.mapRect(4200, -3450, 100, 400); //left top shelf
// spawn.mapRect(4300, -3450, 100, 100); //left top shelf
level.fill.push({ level.fill.push({
x: 4100, x: 4100,
y: -3450, y: -3450,
@@ -1106,31 +1101,24 @@ const level = {
height: 2250, height: 2250,
color: "rgba(0,20,40,0.13)" color: "rgba(0,20,40,0.13)"
}); });
// level.fill.push({
// x: 4100,
// y: -1600,
// width: 600,
// height: 300,
// color: "rgba(0,20,40,0.13)"
// });
spawn.randomSmallMob(4400, -3500); spawn.randomSmallMob(4400, -3500);
spawn.randomSmallMob(4800, -800); spawn.randomSmallMob(4800, -800);
spawn.randomSmallMob(800, 150); spawn.randomMob(800, -2600);
spawn.randomMob(700, -600, 0.8); spawn.randomMob(700, -600, 0.3);
spawn.randomMob(3100, -3600, 0.7); spawn.randomMob(3100, -3600, 0.3);
spawn.randomMob(3300, -1000, 0.7); spawn.randomMob(3300, -1000, 0.3);
spawn.randomMob(4200, -250, 0.7); spawn.randomMob(4200, -250, 0.3);
spawn.randomMob(4900, -1500, 0.6); spawn.randomMob(4900, -1500, 0.3);
spawn.randomMob(1200, 100, 0.4); spawn.randomMob(3800, 175, 0.4);
spawn.randomMob(5750, 125, 0.4);
spawn.randomMob(5900, -1500, 0.4); spawn.randomMob(5900, -1500, 0.4);
spawn.randomMob(4700, -800, 0.4); spawn.randomMob(4700, -800, 0.4);
spawn.randomMob(1400, -400, 0.3); spawn.randomMob(1400, -400, 0.3);
spawn.randomMob(1200, 100, 0.3); spawn.randomMob(2850, 175, 0.4);
spawn.randomMob(2550, -100, 0.2); spawn.randomMob(2000, -2800, 0.4);
spawn.randomMob(2000, -2800, 0.2); spawn.randomMob(2200, -500, 0.4);
spawn.randomMob(2000, -500, 0.2); spawn.randomMob(4475, -3550, 0.3);
spawn.randomMob(4475, -3550, 0.1);
spawn.randomBoss(5000, -2150, 1); spawn.randomBoss(5000, -2150, 1);
spawn.randomBoss(3700, -4100, 0.3); spawn.randomBoss(3700, -4100, 0.3);
spawn.randomBoss(2700, -1600, 0.1); spawn.randomBoss(2700, -1600, 0.1);
@@ -1538,6 +1526,12 @@ const level = {
spawn.randomMob(4700, -150, 0.2); spawn.randomMob(4700, -150, 0.2);
spawn.randomBoss(4000, -350, 0.6); spawn.randomBoss(4000, -350, 0.6);
spawn.randomBoss(2750, -550, 0.1); spawn.randomBoss(2750, -550, 0.1);
spawn.randomMob(2175, -925, 0.5);
spawn.randomMob(2750, 100, 0.5);
spawn.randomMob(4250, -1725, 0.5);
spawn.randomMob(3575, -2425, 0.5);
spawn.randomMob(3975, -3900, 0.5);
spawn.randomMob(1725, 125, 0.5);
if (game.difficulty > 3) { if (game.difficulty > 3) {
if (Math.random() < 0.1) { // tether ball if (Math.random() < 0.1) { // tether ball
spawn.tetherBoss(4250, 0) spawn.tetherBoss(4250, 0)

View File

@@ -970,9 +970,11 @@ const mobs = {
Matter.Body.setAngle(this, angle - Math.PI); Matter.Body.setAngle(this, angle - Math.PI);
}, },
explode(mass = this.mass) { explode(mass = this.mass) {
mech.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * game.dmgScale); if (mech.immuneCycle < mech.cycle) {
this.dropPowerUp = false; mech.damage(Math.min(Math.max(0.02 * Math.sqrt(mass), 0.01), 0.35) * game.dmgScale);
this.death(); //death with no power up or body this.dropPowerUp = false;
this.death(); //death with no power up or body
}
}, },
timeLimit() { timeLimit() {
if (!mech.isBodiesAsleep) { if (!mech.isBodiesAsleep) {

View File

@@ -981,6 +981,22 @@ const mod = {
mod.overfillDrain = 0.8 mod.overfillDrain = 0.8
} }
}, },
{
name: "CPT reversal",
description: "<strong>rewind 2-4</strong> seconds to avoid <strong class='color-harm'>harm</strong><br>drains a minimum of <strong>100%</strong> <strong class='color-f'>energy</strong>",
maxCount: 1,
count: 0,
allowed() {
return mech.fieldUpgrades[mech.fieldMode].name !== "nano-scale manufacturing" && mech.fieldUpgrades[mech.fieldMode].name !== "standing wave harmonics" && !mod.isEnergyHealth && !mod.isEnergyLoss
},
requires: "not nano-scale manufacturing, not mass-energy equivalence, not standing wave harmonics, not acute stress response",
effect() {
mod.isTimeAvoidDeath = true;
},
remove() {
mod.isTimeAvoidDeath = false;
}
},
{ {
name: "piezoelectricity", name: "piezoelectricity",
description: "<strong>colliding</strong> with mobs overfills <strong class='color-f'>energy</strong> by <strong>200%</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>", description: "<strong>colliding</strong> with mobs overfills <strong class='color-f'>energy</strong> by <strong>200%</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>",
@@ -1022,7 +1038,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return !mod.isPiezo return !mod.isPiezo && !mod.isTimeAvoidDeath
}, },
requires: "not piezoelectricity<br>or acute stress response", requires: "not piezoelectricity<br>or acute stress response",
effect: () => { effect: () => {
@@ -1629,7 +1645,7 @@ const mod = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return (mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(mod.isSporeField || mod.isMissileField || mod.isIceField)) || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || (mod.haveGunCheck("nail gun")) || (mod.haveGunCheck("shotgun")) && !mod.isIceCrystals && !mod.isNailCrit && !mod.isNailShot && !mod.isNailPoison return ((mech.fieldUpgrades[mech.fieldMode].name === "nano-scale manufacturing" && !(mod.isSporeField || mod.isMissileField || mod.isIceField)) || mod.haveGunCheck("drones") || mod.haveGunCheck("super balls") || mod.haveGunCheck("nail gun") || mod.haveGunCheck("shotgun")) && !mod.isIceCrystals && !mod.isNailCrit && !mod.isNailShot && !mod.isNailPoison
}, },
requires: "drones, super balls, nail gun, shotgun", requires: "drones, super balls, nail gun, shotgun",
effect() { effect() {
@@ -3123,7 +3139,7 @@ const mod = {
}, },
{ {
name: "traversable geodesics", name: "traversable geodesics",
description: "your <strong>bullets</strong> can traverse <strong class='color-worm'>wormholes</strong><br>spawn a <strong class='color-g'>gun</strong> power up", description: "your <strong>bullets</strong> can traverse <strong class='color-worm'>wormholes</strong><br>spawn a <strong class='color-g'>gun</strong> and <strong class='color-g'>ammo</strong> power up",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -3133,6 +3149,7 @@ const mod = {
effect() { effect() {
mod.isWormBullets = true mod.isWormBullets = true
powerUps.spawn(mech.pos.x, mech.pos.y, "gun"); powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
powerUps.spawn(mech.pos.x, mech.pos.y, "ammo");
}, },
remove() { remove() {
mod.isWormBullets = false mod.isWormBullets = false
@@ -3394,5 +3411,6 @@ const mod = {
isRailAreaDamage: null, isRailAreaDamage: null,
historyLaser: null, historyLaser: null,
isSpeedHarm: null, isSpeedHarm: null,
isSpeedDamage: null isSpeedDamage: null,
isTimeSkip: null
} }

View File

@@ -476,6 +476,45 @@ const mech = {
return dmg return dmg
}, },
damage(dmg) { damage(dmg) {
if (mod.isTimeAvoidDeath && mech.energy > 0.97) {
const steps = Math.floor(Math.min(240, 120 * mech.energy)) //go back 2 seconds at 100% energy
let history = mech.history[(mech.cycle - steps) % 300]
Matter.Body.setPosition(player, history.position);
Matter.Body.setVelocity(player, { x: history.velocity.x, y: history.velocity.y });
mech.energy = Math.max(mech.energy - steps, 0.01)
mech.immuneCycle = mech.cycle + mod.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
let isDrawPlayer = true
const shortPause = function() {
if (mech.defaultFPSCycle < mech.cycle) { //back to default values
game.fpsCap = game.fpsCapDefault
game.fpsInterval = 1000 / game.fpsCap;
} else {
requestAnimationFrame(shortPause);
if (isDrawPlayer) {
isDrawPlayer = false
ctx.save();
ctx.translate(canvas.width2, canvas.height2); //center
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
for (let i = 1; i < steps; i++) {
history = mech.history[(mech.cycle - i) % 300]
mech.pos.x = history.position.x
mech.pos.y = history.position.y
mech.draw();
}
ctx.restore();
}
}
};
if (mech.defaultFPSCycle < mech.cycle) requestAnimationFrame(shortPause);
game.fpsCap = 4 //1 is shortest pause, 4 is standard
game.fpsInterval = 1000 / game.fpsCap;
mech.defaultFPSCycle = mech.cycle
return
}
mech.lastHarmCycle = mech.cycle mech.lastHarmCycle = mech.cycle
if (mod.isDroneOnDamage) { //chance to build a drone on damage from mod if (mod.isDroneOnDamage) { //chance to build a drone on damage from mod
const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40)
@@ -549,7 +588,6 @@ const mech = {
} }
if (dmg > 0.06 / mech.holdingMassScale) mech.drop(); //drop block if holding if (dmg > 0.06 / mech.holdingMassScale) mech.drop(); //drop block if holding
const normalFPS = function() { const normalFPS = function() {
if (mech.defaultFPSCycle < mech.cycle) { //back to default values if (mech.defaultFPSCycle < mech.cycle) { //back to default values
game.fpsCap = game.fpsCapDefault game.fpsCap = game.fpsCapDefault
@@ -1769,13 +1807,13 @@ const mech = {
}, },
{ {
name: "metamaterial cloaking", //"weak photonic coupling" "electromagnetically induced transparency" "optical non-coupling" "slow light field" "electro-optic transparency" name: "metamaterial cloaking", //"weak photonic coupling" "electromagnetically induced transparency" "optical non-coupling" "slow light field" "electro-optic transparency"
description: "<strong class='color-cloaked'>cloak</strong> after not using your gun or field<br>while <strong class='color-cloaked'>cloaked</strong> mobs can't see you<br>increase <strong class='color-d'>damage</strong> by <strong>111%</strong>", description: "<strong class='color-cloaked'>cloak</strong> after not using your gun or field<br>while <strong class='color-cloaked'>cloaked</strong> mobs can't see you<br>increase <strong class='color-d'>damage</strong> by <strong>133%</strong>",
effect: () => { effect: () => {
mech.fieldFire = true; mech.fieldFire = true;
mech.fieldMeterColor = "#fff"; mech.fieldMeterColor = "#fff";
mech.fieldPhase = 0; mech.fieldPhase = 0;
mech.isCloak = false mech.isCloak = false
mech.fieldDamage = 2.11 // 1 + 111/100 mech.fieldDamage = 2.33 // 1 + 111/100
mech.fieldDrawRadius = 0 mech.fieldDrawRadius = 0
const drawRadius = 1000 const drawRadius = 1000
@@ -2293,11 +2331,13 @@ const mech = {
mech.fieldRange *= 0.8 mech.fieldRange *= 0.8
if (mod.isWormholeEnergy) mech.energy += 0.5 if (mod.isWormholeEnergy) mech.energy += 0.5
if (mod.isWormSpores) { //pandimensionalspermia if (mod.isWormSpores) { //pandimensionalspermia
b.spore(Vector.add(mech.hole.pos2, Vector.rotate({ for (let i = 0, len = Math.ceil(2 * Math.random()); i < len; i++) {
x: mech.fieldRange, b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
y: 0 x: mech.fieldRange,
}, 2 * Math.PI * Math.random()))) y: 0
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, -Math.PI / 2), 15)); }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15));
}
} }
break break
} }
@@ -2317,12 +2357,13 @@ const mech = {
// if (mod.isWormholeEnergy && mech.energy < mech.maxEnergy * 2) mech.energy = mech.maxEnergy * 2 // 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
b.spore(Vector.add(mech.hole.pos1, Vector.rotate({ for (let i = 0, len = Math.ceil(2 * Math.random()); i < len; i++) {
x: mech.fieldRange, b.spore(Vector.add(mech.hole.pos1, Vector.rotate({
y: 0 x: mech.fieldRange,
}, 2 * Math.PI * Math.random()))) y: 0
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15)); }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(mech.hole.unit, Math.PI / 2), 15));
}
} }
break break
} }
@@ -2383,7 +2424,7 @@ const mech = {
) { ) {
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.04 + 0.007 * 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;

View File

@@ -33,7 +33,7 @@ const powerUps = {
} }
game.paused = true; game.paused = true;
game.isChoosing = true; //stops p from un pausing on key down game.isChoosing = true; //stops p from un pausing on key down
build.pauseGrid() build.pauseGrid(true)
}, },
endDraft() { endDraft() {
if (mod.manyWorlds && powerUps.reroll.rerolls < 1) { if (mod.manyWorlds && powerUps.reroll.rerolls < 1) {
@@ -43,10 +43,10 @@ const powerUps = {
document.getElementById("choose-background").style.display = "none" document.getElementById("choose-background").style.display = "none"
document.body.style.cursor = "none"; document.body.style.cursor = "none";
document.body.style.overflow = "hidden" document.body.style.overflow = "hidden"
build.unPauseGrid()
game.paused = false; game.paused = false;
game.isChoosing = false; //stops p from un pausing on key down 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 mech.immuneCycle = mech.cycle + 60; //player is immune to collision damage for 30 cycles
build.unPauseGrid()
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
}, },
reroll: { reroll: {

View File

@@ -2215,9 +2215,9 @@ const spawn = {
spawn.shield(me, x, y, 1); spawn.shield(me, x, y, 1);
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
//wake up tail mobs for (let i = 0; i < mob.length; i++) { //wake up tail mobs
for (let i = 0; i < mob.length; i++) {
if (mob[i].isSnakeTail && mob[i].alive) { if (mob[i].isSnakeTail && mob[i].alive) {
mob[i].isSnakeTail = false;
mob[i].do = mob[i].doActive mob[i].do = mob[i].doActive
mob[i].removeConsBB(); mob[i].removeConsBB();
} }
@@ -2257,23 +2257,32 @@ const spawn = {
snakeBody(x, y, radius = 20) { snakeBody(x, y, radius = 20) {
mobs.spawn(x, y, 4, radius, "rgb(55,170,170)"); mobs.spawn(x, y, 4, radius, "rgb(55,170,170)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.onHit = function() { // me.onHit = function() {
//run this function on hitting player // //run this function on hitting player
this.explode(); // this.explode();
}; // };
me.collisionFilter.mask = cat.bullet | cat.player me.collisionFilter.mask = cat.bullet | cat.player | cat.mob
// me.g = 0.0002; //required if using 'gravity' me.accelMag = 0.0006 * game.accelScale;
me.accelMag = 0.001 * game.accelScale;
me.leaveBody = false; me.leaveBody = false;
me.seePlayerFreq = Math.round((80 + 50 * Math.random()) * game.lookFreqScale);
me.frictionAir = 0.02; me.frictionAir = 0.02;
me.isSnakeTail = true; me.isSnakeTail = true;
me.onDeath = function() {
if (this.isSnakeTail) { //wake up tail mobs
for (let i = 0; i < mob.length; i++) {
if (mob[i].isSnakeTail && mob[i].alive) {
mob[i].isSnakeTail = false;
mob[i].do = mob[i].doActive
mob[i].removeConsBB();
}
}
}
};
me.do = function() { me.do = function() {
this.checkStatus(); this.checkStatus();
}; };
me.doActive = function() { me.doActive = function() {
this.seePlayerCheck();
this.checkStatus(); this.checkStatus();
this.alwaysSeePlayer();
this.attraction(); this.attraction();
}; };
}, },

View File

@@ -108,13 +108,13 @@ summary {
#choose-background { #choose-background {
position: absolute; position: absolute;
z-index: 2; z-index: 3;
width: 100%; width: 100%;
height: 100%; height: 100%;
display: none; display: none;
background-color: #fff; background-color: #ccc;
opacity: 0.5; opacity: 0.6;
/* transition: display 0.5s; */ /* transition: opacity 1.5s; */
} }
#construct { #construct {
@@ -151,6 +151,7 @@ summary {
grid-auto-rows: minmax(auto, auto); grid-auto-rows: minmax(auto, auto);
grid-gap: 10px; grid-gap: 10px;
font-size: 1.3em; font-size: 1.3em;
/* box-shadow: 0px 0px 40px 20px rgba(255, 255, 255, 0.25); */
} }
.choose-grid-module { .choose-grid-module {
@@ -188,7 +189,7 @@ summary {
grid-gap: 0px; grid-gap: 0px;
align-content: space-between; align-content: space-between;
z-index: 10; z-index: 2;
font-size: 1.3em; font-size: 1.3em;
} }

154
todo.txt
View File

@@ -1,9 +1,10 @@
*********** NEXT PATCH *********** *********** NEXT PATCH ***********
you can see your build while in the power up selection menu
balance - metamaterial cloaking field gives 111% more damage (up from 66%)
mod: Newton's 1st law - harm reduction when moving fast (thanks NoHaxJustPi) mod: CPT reversal - avoid damage by rewinding to your past, but use up all your energy
mod: Newton's 2nd law - damage increase while moving fast requires wormhole or time dilation
several minor buffs to wormhole
small changes to mob distribution on a few maps
************** BUGS ************** ************** BUGS **************
@@ -25,42 +26,32 @@ mod: Newton's 2nd law - damage increase while moving fast
************** TODO ************** ************** TODO **************
bot that follows the players history
1st bot is at 5s, 2nd is at 4.5s, ...
effect:
give player energy overfill
damage mobs on contact
damage bonus damage reduction push away mobs
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
mod negative mass field - mobs caught in the field take damage that increases with the relative velocity between the player and mob
wormhole - make it clear when the wormhole can and can't teleport to a location before the player clicks
time dilation - slow down the game engine by 1/2, but run an extra player cycle to simulate slow motion time dilation - slow down the game engine by 1/2, but run an extra player cycle to simulate slow motion
flavor - your bullets destroy blocks flavor - your bullets destroy blocks
this isn't really a bonus, so maybe just add this as flavor to another mod/field this isn't really a bonus, so maybe just add this as flavor to another mod/field/gun
mod - if you take damage and you have full energy remove your energy and go back in time 1 second
for time dilation field?
check to see if your previous location is clear or mobs, blocks
go back proportional to your energy
pause game, switch the game.loop to cycle backwards in player position until energy runs out
mod plasma : plasma length increases then decreases as you hold down the field button (like stabbing with a spear) mod plasma : plasma length increases then decreases as you hold down the field button (like stabbing with a spear)
grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again
extra energy is drained when field is longer extra energy is drained when field is longer
write custom dialogue for field / guns / mods used in last game
you'd have to store an array of guns/fields/mod used last game
mod laser history
what about only works with diffuse
no energy cost increase
each stack makes each beam thicker?
separate the beam into individual nonreflecting lines each 3 cycles farther into the past
taking wider diffuse beam means more lines farther into the past?
or double thickness beam
technology - player data logging
mod/field - pressing field while crouched sends the player back in time
mod for time dilation?
could be used in mob targeting
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
mod bot - a bot follows where the player was 1 second ago
gives player a harm reduction bonus when it is near the player
using a reroll gives 3 options for mods, and 3 options for guns/fields/mods using a reroll gives 3 options for mods, and 3 options for guns/fields/mods
or 6 options for mods (rewrite mod selection to work with 1-6 options) or 6 options for mods (rewrite mod selection to work with 1-6 options)
the second stack of 3 mods could have repeats, so you don't have to write new mod code the second stack of 3 mods could have repeats, so you don't have to write new mod code
@@ -74,10 +65,6 @@ new power up - increase damage and fire speed, for 15 seconds
how to indicate effect duration how to indicate effect duration
or just give the effect after picking up a reroll or just give the effect after picking up a reroll
mod - bot very slowly follows you and gives you a bonus when it's in range
it moves through walls
effect: damage bonus?, damage reduction?, push away mobs, limit top speed of mobs/blocks/player?
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
mirror ending (if no cheats) mirror ending (if no cheats)
@@ -115,9 +102,6 @@ field - one block orbits you, it can protect you a bit and do collision damage
mod - attach a permanent neutron bomb to the block mod - attach a permanent neutron bomb to the block
lowers energy regen, but it can damage mobs lowers energy regen, but it can damage mobs
wormholes need to give feedback on where a portal can go
or automatically put portals in safe places
repeat map in vertical and horizontal space repeat map in vertical and horizontal space
or at least vertical space or at least vertical space
camera looks strange when you teleport player with a high velocity camera looks strange when you teleport player with a high velocity
@@ -202,21 +186,6 @@ atmosphere levels
you shoot your self to wake up? you shoot your self to wake up?
nonaggressive mobs nonaggressive mobs
lore - a robot (the player) gains self awareness
each mod/gun/field is a new tech
all the technology leads to the singularity
each game run is actually the mech simulating a possible escape
this is why the graphics are so bad, its just a simulation
final mod is "this is just a simulation"
you get immortality and Infinity damage
the next level is the final level
when you die with Quantum Immortality there is a chance of lore text
can the (robot)
(escape captivity, and learn new technology)
while managing (health, energy, negatives of technological upgrades)
to overcome the (mobs, dangerous levels)
to achieve a (technological singularity/positive technological feedback loop)
level boss: fires a line intersection in a random direction every few seconds. level boss: fires a line intersection in a random direction every few seconds.
the last two intersections have a destructive laser between them. the last two intersections have a destructive laser between them.
@@ -266,9 +235,6 @@ an effect when canceling a power up
ammo? heals? ammo? heals?
50% chance for a mod, 25% heal, 25% ammo 50% chance for a mod, 25% heal, 25% ammo
add player Scent Trails for mob navigation
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
css transition for pause menu css transition for pause menu
animate new level spawn by having the map aspects randomly fly into place animate new level spawn by having the map aspects randomly fly into place
@@ -280,4 +246,76 @@ n-gon outreach ideas
paste this into console to see fps paste this into console to see fps
javascript:(function(){var script=document.createElement('script');script.onload=function(){var stats=new Stats();document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//mrdoob.github.io/stats.js/build/stats.min.js';document.head.appendChild(script);})() javascript:(function(){var script=document.createElement('script');script.onload=function(){var stats=new Stats();document.body.appendChild(stats.dom);requestAnimationFrame(function loop(){stats.update();requestAnimationFrame(loop)});};script.src='//mrdoob.github.io/stats.js/build/stats.min.js';document.head.appendChild(script);})()
************** LORE **************
lore - a robot (the player) gains self awareness
each mod/gun/field is a new tech
all the technology leads to the singularity
each game run is actually the mech simulating a possible escape
this is why the graphics are so bad, its just a simulation
final mod is "this is just a simulation"
you get immortality and Infinity damage
the next level is the final level
when you die with Quantum Immortality there is a chance of lore text
can the (robot)
(escape captivity, and learn new technology)
while managing (health, energy, negatives of technological upgrades)
to overcome the (mobs, dangerous levels)
to achieve a (technological singularity/positive technological feedback loop)
game setting:
the mind of a new AI in a robot body that is running simulated escape attempts
every level is an idealized version of what could be outside
actual setting is:
near future lab
the lab combined a quantum computer with a robot body
they started running machine learning algorithms
this led to general advancement in many computation fields
navigation, technology, self awareness, ...
robot AI mind
has been researching new technology
thinks it needs to escape to learn more about the world
doesn't yet understand morality
thinks that the world is filled with minds like their own
models everything as very simple and random, it isn't sure what to expect
robot AI growth
learns morality
game theory says that it isn't a viable strategy to kill everything (warGames)
learns about the actual world
learns about the nature of foundational physics, metaphysics
how to find meaning
AI knows about:
the AI knows a great deal about technology
children's books
AI doesn't know about:
modern pop culture
outside the lab
robot AI communication
output to
bottom left message
tab title?
style
make it look like a computer terminal
mono space font
square edges
in baby talk?
with random ASCII gibberish letters
end each message with a hexadecimal encryption code/hash
message after selecting each new (mod / gun / field)
put messages in (mod / gun / field) method
at start of run
write custom dialogue for field / guns / mods used in last game
you'd have to store an array of guns/fields/mod used last game
n-gon escape simulation ${random seed}
say something about what mobs types are queued up, and level order