1-body problem

tech: 1-body problem - do 100% damage if there is only 1 active bullet

experiment mode and junk tech: random aiming

bug fix - sniper, shooter aiming might be improved (no more firing backwards)
  or maybe I just made it worse, let me know

bug fix - Shift registers

working on rewriting the way backgrounds and foregrounds are drawn on each level (in progress)
This commit is contained in:
landgreen
2021-03-30 05:23:56 -07:00
parent 3ab42884ca
commit 4848cc4e73
11 changed files with 369 additions and 261 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -452,7 +452,7 @@ const b = {
}, },
pulse(energy, angle = m.angle) { pulse(energy, angle = m.angle) {
let best; let best;
let explosionRadius = 1300 * energy let explosionRadius = 1250 * energy
let range = 3000 let range = 3000
const path = [{ const path = [{
x: m.pos.x + 20 * Math.cos(angle), x: m.pos.x + 20 * Math.cos(angle),
@@ -2050,7 +2050,7 @@ const b = {
isImproved: false, isImproved: false,
beforeDmg(who) { beforeDmg(who) {
if (tech.isIncendiary) { if (tech.isIncendiary) {
const max = Math.min(this.endCycle - simulation.cycle, 1500) const max = Math.max(Math.min(this.endCycle - simulation.cycle, 1500), 0)
b.explosion(this.position, max * 0.08 + this.isImproved * 100 + 60 * Math.random()); //makes bullet do explosive damage at end b.explosion(this.position, max * 0.08 + this.isImproved * 100 + 60 * Math.random()); //makes bullet do explosive damage at end
this.endCycle -= max this.endCycle -= max
} else { } else {
@@ -4550,7 +4550,7 @@ const b = {
x: 7.5 * Math.cos(m.angle - Math.PI / 2), x: 7.5 * Math.cos(m.angle - Math.PI / 2),
y: 7.5 * Math.sin(m.angle - Math.PI / 2) y: 7.5 * Math.sin(m.angle - Math.PI / 2)
} }
const dmg = 0.6 * tech.laserDamage // 3.5 * 0.55 = 200% more damage const dmg = 0.7 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) } const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const eye = { const eye = {
x: m.pos.x + 15 * Math.cos(m.angle), x: m.pos.x + 15 * Math.cos(m.angle),
@@ -4630,10 +4630,10 @@ const b = {
}, },
firePulse() { firePulse() {
m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down
let energy = 0.27 * Math.min(m.energy, 1.5) let energy = 0.3 * Math.min(m.energy, 1.5)
m.energy -= energy * tech.isLaserDiode m.energy -= energy * tech.isLaserDiode
if (tech.beamSplitter) { if (tech.beamSplitter) {
energy *= Math.pow(0.9, tech.beamSplitter) energy *= Math.pow(0.85, tech.beamSplitter)
b.pulse(energy, m.angle) b.pulse(energy, m.angle)
for (let i = 1; i < 1 + tech.beamSplitter; i++) { for (let i = 1; i < 1 + tech.beamSplitter; i++) {
b.pulse(energy, m.angle - i * 0.27) b.pulse(energy, m.angle - i * 0.27)

View File

@@ -783,6 +783,7 @@ window.addEventListener("keydown", function(event) {
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline' if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'
if (!simulation.isCheating) { if (!simulation.isCheating) {
simulation.isCheating = true; simulation.isCheating = true;
level.levelAnnounce();
lore.techCount = 0; lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) { if (tech.tech[i].isLore) {

View File

@@ -111,7 +111,7 @@ const level = {
// if (tech.isPerpetualStun) { // if (tech.isPerpetualStun) {
// for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780) // for (let i = 0; i < mob.length; i++) mobs.statusStun(mob[i], 780)
// } // }
if (tech.isFlipFlopHarm && tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) { if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true tech.isFlipFlopOn = true
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`); simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
@@ -155,10 +155,11 @@ const level = {
} }
}, },
levelAnnounce() { levelAnnounce() {
const difficulty = simulation.isCheating ? "testing" : level.difficultyText()
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
document.title = "n-gon: (" + level.difficultyText() + ")"; document.title = "n-gon: (" + difficulty + ")";
} else { } else {
document.title = (simulation.isCheating ? "∅ " : "n-gon:") + (level.levelsCleared) + " " + level.levels[level.onLevel] + " (" + level.difficultyText() + ")"; document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} (${difficulty})`
simulation.makeTextLog(`<span class='color-var'>level</span>.onLevel <span class='color-symbol'>=</span> "<span class='color-text'>${level.levels[level.onLevel]}</span>"`); simulation.makeTextLog(`<span class='color-var'>level</span>.onLevel <span class='color-symbol'>=</span> "<span class='color-text'>${level.levels[level.onLevel]}</span>"`);
} }
// simulation.makeTextLog(` // simulation.makeTextLog(`
@@ -932,7 +933,6 @@ const level = {
radius: 50 radius: 50
} }
level.custom = () => { level.custom = () => {
// level.playerExitCheck();
hazardSlime.query(); hazardSlime.query();
//draw wide line //draw wide line
@@ -958,7 +958,10 @@ const level = {
ctx.arc(circle.x, circle.y, circle.radius / 8, 0, 2 * Math.PI); ctx.arc(circle.x, circle.y, circle.radius / 8, 0, 2 * Math.PI);
ctx.fillStyle = lore.talkingColor //"#dff" ctx.fillStyle = lore.talkingColor //"#dff"
ctx.fill(); ctx.fill();
// ctx.stroke();
level.enter.draw();
// level.exit.draw();
// level.playerExitCheck();
}; };
let sway = { let sway = {
x: 0, x: 0,
@@ -1002,7 +1005,7 @@ const level = {
level.setPosToSpawn(0, -50); //normal spawn level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 25, 100, 10); spawn.mapRect(level.enter.x, level.enter.y + 25, 100, 10);
level.exit.x = 0; level.exit.x = 0;
level.exit.y = 200; level.exit.y = 400;
level.defaultZoom = 1000 level.defaultZoom = 1000
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
// document.body.style.backgroundColor = "#aaa"; // document.body.style.backgroundColor = "#aaa";
@@ -1044,6 +1047,8 @@ const level = {
button.query(); button.query();
button.draw(); button.draw();
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -1116,11 +1121,11 @@ const level = {
// spawn.streamBoss(1600, -500) // spawn.streamBoss(1600, -500)
// spawn.orbitalBoss(1600, -500) // spawn.orbitalBoss(1600, -500)
// spawn.cellBossCulture(1600, -500) // spawn.cellBossCulture(1600, -500)
spawn.shieldingBoss(1600, -500) // spawn.shieldingBoss(1600, -500)
// spawn.beamer(1200, -500) // spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.shield(mob[mob.length - 1], 1800, -120, 1);
spawn.nodeGroup(1200, -500, "grower") spawn.nodeGroup(1200, -500, "sniper")
// spawn.snakeBoss(1200, -500) // spawn.snakeBoss(1200, -500)
// spawn.powerUpBoss(2900, -500) // spawn.powerUpBoss(2900, -500)
// spawn.randomMob(1600, -500) // spawn.randomMob(1600, -500)
@@ -1128,6 +1133,8 @@ const level = {
template() { template() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
level.setPosToSpawn(0, -50); //normal spawn level.setPosToSpawn(0, -50); //normal spawn
@@ -1139,20 +1146,6 @@ const level = {
document.body.style.backgroundColor = "#dcdcde"; document.body.style.backgroundColor = "#dcdcde";
// powerUps.spawnStartingPowerUps(1475, -1175); // powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level // spawn.debris(750, -2200, 3700, 16); //16 debris per level
// level.fill.push({ //foreground
// x: 2500,
// y: -1100,
// width: 450,
// height: 250,
// color: "rgba(0,0,0,0.1)"
// });
// level.fillBG.push({ //background
// x: 1300,
// y: -1800,
// width: 750,
// height: 1800,
// color: "#d4d4d7"
// });
spawn.mapRect(-100, 0, 1000, 100); spawn.mapRect(-100, 0, 1000, 100);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9); // spawn.bodyRect(1540, -1110, 300, 25, 0.9);
@@ -1167,6 +1160,8 @@ const level = {
final() { final() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -1178,7 +1173,7 @@ const level = {
level.defaultZoom = 2500 level.defaultZoom = 2500
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#ccc"; document.body.style.backgroundColor = "#ddd";
level.fill.push({ level.fill.push({
x: 5400, x: 5400,
@@ -1219,6 +1214,8 @@ const level = {
gauntlet() { gauntlet() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -1284,152 +1281,174 @@ const level = {
}, },
intro() { intro() {
level.custom = () => { level.custom = () => {
//draw binary number
const binary = (localSettings.runCount >>> 0).toString(2)
const height = 20
const width = 8
const yOff = -40 //-580
let xOff = -130 //2622
ctx.strokeStyle = "#adf"
ctx.lineWidth = 1.5;
ctx.beginPath()
for (let i = 0; i < binary.length; i++) {
if (binary[i] === "0") {
ctx.moveTo(xOff, yOff)
ctx.lineTo(xOff, yOff + height)
ctx.lineTo(xOff + width, yOff + height)
ctx.lineTo(xOff + width, yOff)
ctx.lineTo(xOff, yOff)
xOff += 10 + width
} else {
ctx.moveTo(xOff, yOff)
ctx.lineTo(xOff, yOff + height)
xOff += 10
}
}
ctx.stroke();
//wires
ctx.beginPath()
ctx.moveTo(-150, -275)
ctx.lineTo(80, -275)
ctx.lineTo(80, -1000)
ctx.moveTo(-150, -265)
ctx.lineTo(90, -265)
ctx.lineTo(90, -1000)
ctx.moveTo(-150, -255)
ctx.lineTo(100, -255)
ctx.lineTo(100, -1000)
ctx.moveTo(-150, -245)
ctx.lineTo(1145, -245)
ctx.lineTo(1145, 0)
ctx.moveTo(-150, -235)
ctx.lineTo(1135, -235)
ctx.lineTo(1135, 0)
ctx.moveTo(-150, -225)
ctx.lineTo(1125, -225)
ctx.lineTo(1125, 0)
ctx.moveTo(-150, -215)
ctx.lineTo(460, -215)
ctx.lineTo(460, 0)
ctx.moveTo(-150, -205)
ctx.lineTo(450, -205)
ctx.lineTo(450, 0)
ctx.moveTo(-150, -195)
ctx.lineTo(440, -195)
ctx.lineTo(440, 0)
ctx.moveTo(1155, 0)
ctx.lineTo(1155, -450)
ctx.lineTo(1000, -450)
ctx.lineTo(1000, -1000)
ctx.moveTo(1165, 0)
ctx.lineTo(1165, -460)
ctx.lineTo(1010, -460)
ctx.lineTo(1010, -1000)
ctx.moveTo(1175, 0)
ctx.lineTo(1175, -470)
ctx.lineTo(1020, -470)
ctx.lineTo(1020, -1000)
ctx.moveTo(1185, 0)
ctx.lineTo(1185, -480)
ctx.lineTo(1030, -480)
ctx.lineTo(1030, -1000)
ctx.moveTo(1195, 0)
ctx.lineTo(1195, -490)
ctx.lineTo(1040, -490)
ctx.lineTo(1040, -1000)
ctx.moveTo(1625, -1000)
ctx.lineTo(1625, 0)
ctx.moveTo(1635, -1000)
ctx.lineTo(1635, 0)
ctx.moveTo(1645, -1000)
ctx.lineTo(1645, 0)
ctx.moveTo(1655, -1000)
ctx.lineTo(1655, 0)
ctx.moveTo(1665, -1000)
ctx.lineTo(1665, 0)
ctx.moveTo(1675, -465)
ctx.lineTo(2325, -465)
ctx.lineTo(2325, 0)
ctx.moveTo(1675, -455)
ctx.lineTo(2315, -455)
ctx.lineTo(2315, 0)
ctx.moveTo(1675, -445)
ctx.lineTo(2305, -445)
ctx.lineTo(2305, 0)
ctx.moveTo(1675, -435)
ctx.lineTo(2295, -435)
ctx.lineTo(2295, 0)
ctx.moveTo(2335, 0)
ctx.lineTo(2335, -710)
ctx.lineTo(2600, -710)
ctx.moveTo(2345, 0)
ctx.lineTo(2345, -700)
ctx.lineTo(2600, -700)
ctx.moveTo(2355, 0)
ctx.lineTo(2355, -690)
ctx.lineTo(2600, -690)
ctx.strokeStyle = "#ccc"
ctx.lineWidth = 5;
ctx.stroke();
//squares that look like they keep the wires in place
ctx.beginPath()
ctx.rect(1600, -500, 90, 100)
ctx.rect(-55, -285, 12, 100)
ctx.rect(1100, -497, 8, 54)
ctx.rect(2285, -200, 80, 10)
ctx.rect(1110, -70, 100, 10)
ctx.fillStyle = "#ccc"
ctx.fill()
//power up dispenser
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.moveTo(2000, -100 * i)
// ctx.lineTo(2080, -100 * i)
// }
// ctx.strokeStyle = "#ddd"
// ctx.lineWidth = 5;
// ctx.stroke();
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.arc(2040, -100 * i, 30, 0, 2 * Math.PI);
// ctx.moveTo(2040, -100 * i)
// }
// ctx.fillStyle = "rgba(0,0,0,0.3)"
// ctx.fill()
// ctx.fillStyle = "rgba(240,255,255,0.5)"
// ctx.fillRect(2000, -1000, 80, 700)
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(2600, -600, 400, 300)
level.exit.draw();
// level.enter.draw();
level.playerExitCheck(); level.playerExitCheck();
}; };
level.customTopLayer = () => {};
const binary = (localSettings.runCount >>> 0).toString(2)
const height = 25
const thick = 2
const color = "#aaa"
const xOff = -130 //2622
const yOff = -45 //-580
let xLetter = 0
for (let i = 0; i < binary.length; i++) {
if (binary[i] === "0") {
zero(xOff + xLetter, yOff)
} else {
one(xOff + xLetter, yOff)
}
}
function one(x, y) { level.customTopLayer = () => {
level.fillBG.push({ //exit room glow
x: x, ctx.fillStyle = "rgba(0,255,255,0.05)"
y: y, ctx.fillRect(2600, -600, 400, 300)
width: thick, };
height: height,
color: color
});
xLetter += 10
}
function zero(x, y) {
const width = 10
level.fillBG.push({
x: x,
y: y,
width: thick,
height: height,
color: color
});
level.fillBG.push({
x: x + width,
y: y,
width: thick,
height: height,
color: color
});
level.fillBG.push({
x: x,
y: y,
width: width,
height: thick,
color: color
});
level.fillBG.push({
x: x,
y: y + height - thick,
width: width,
height: thick,
color: color
});
xLetter += 10 + width
}
level.setPosToSpawn(460, -100); //normal spawn level.setPosToSpawn(460, -100); //normal spawn
level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left // level.enter.x = -1000000; //hide enter graphic for first level by moving to the far left
level.exit.x = 2800; level.exit.x = 2800;
level.exit.y = -335; level.exit.y = -335;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1000 //1400 is normal simulation.zoomScale = 1000 //1400 is normal
level.defaultZoom = 1600 level.defaultZoom = 1600
simulation.zoomTransition(level.defaultZoom, 1) simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#ddd"; document.body.style.backgroundColor = "#e1e1e1";
level.fill.push({
x: 2600,
y: -600,
width: 400,
height: 500,
color: "rgba(0,255,255,0.05)"
});
level.fillBG.push({
x: 2600,
y: -600,
width: 400,
height: 500,
color: "#fff"
});
const lineColor = "#ccc"
level.fillBG.push({
x: 1600,
y: -500,
width: 100,
height: 100,
color: lineColor
});
level.fillBG.push({
x: -55,
y: -283,
width: 12,
height: 100,
color: lineColor
});
//faster way to draw a wire
function wallWire(x, y, width, height, front = false) {
if (front) {
level.fill.push({
x: x,
y: y,
width: width,
height: height,
color: lineColor
});
} else {
level.fillBG.push({
x: x,
y: y,
width: width,
height: height,
color: lineColor
});
}
}
for (let i = 0; i < 3; i++) {
wallWire(100 - 10 * i, -1050 - 10 * i, 5, 800);
wallWire(100 - 10 * i, -255 - 10 * i, -300, 5);
}
for (let i = 0; i < 5; i++) {
wallWire(1000 + 10 * i, -1050 - 10 * i, 5, 600);
wallWire(1000 + 10 * i, -450 - 10 * i, 150, 5);
wallWire(1150 + 10 * i, -450 - 10 * i, 5, 500);
}
for (let i = 0; i < 3; i++) {
wallWire(2650 - 10 * i, -700 - 10 * i, -300, 5);
wallWire(2350 - 10 * i, -700 - 10 * i, 5, 800);
}
for (let i = 0; i < 5; i++) {
wallWire(1625 + 10 * i, -1050, 5, 1200);
}
for (let i = 0; i < 4; i++) {
wallWire(1650, -470 + i * 10, 670 - i * 10, 5);
wallWire(1650 + 670 - i * 10, -470 + i * 10, 5, 600);
}
for (let i = 0; i < 3; i++) {
wallWire(-200 - i * 10, -245 + i * 10, 1340, 5);
wallWire(1140 - i * 10, -245 + i * 10, 5, 300);
wallWire(-200 - i * 10, -215 + i * 10, 660, 5);
wallWire(460 - i * 10, -215 + i * 10, 5, 300);
}
spawn.mapRect(-250, 0, 3600, 1800); //ground spawn.mapRect(-250, 0, 3600, 1800); //ground
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(3000, -2800, 2600, 4600); //right wall spawn.mapRect(3000, -2800, 2600, 4600); //right wall
@@ -1563,6 +1582,8 @@ const level = {
button.query(); button.query();
button.draw(); button.draw();
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
door.draw(); door.draw();
@@ -1754,6 +1775,8 @@ const level = {
hazard.level(button.isUp) hazard.level(button.isUp)
rotor.rotate(); rotor.rotate();
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
ctx.fillStyle = "#233" ctx.fillStyle = "#233"
@@ -1888,6 +1911,8 @@ const level = {
const elevator = level.platform(4210, -1325, 380, 30, -10) const elevator = level.platform(4210, -1325, 380, 30, -10)
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move if (elevator.pauseUntilCycle < simulation.cycle && !m.isBodiesAsleep) { //elevator move
@@ -2096,6 +2121,8 @@ const level = {
ctx.fillStyle = "#ccc" ctx.fillStyle = "#ccc"
ctx.fillRect(1567, -1990, 5, 1020) ctx.fillRect(1567, -1990, 5, 1020)
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -2321,6 +2348,8 @@ const level = {
// simulation.g = 0.0012 //0.0024 // simulation.g = 0.0012 //0.0024
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
// elevator.move() // elevator.move()
@@ -2523,6 +2552,8 @@ const level = {
skyscrapers() { skyscrapers() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -2686,6 +2717,8 @@ const level = {
highrise() { highrise() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -2888,6 +2921,8 @@ const level = {
warehouse() { warehouse() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -3138,6 +3173,8 @@ const level = {
} }
door.openClose(); door.openClose();
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
door.draw(); door.draw();
@@ -3291,6 +3328,8 @@ const level = {
stronghold() { // player made level by Francois 👑 from discord stronghold() { // player made level by Francois 👑 from discord
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
@@ -3594,6 +3633,8 @@ const level = {
doorPlateform.openClose(); doorPlateform.openClose();
} }
hazard.level(button.isUp) hazard.level(button.isUp)
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -3978,6 +4019,8 @@ const level = {
level.playerExitCheck(); level.playerExitCheck();
rotor.rotate(); rotor.rotate();
// rotor2.rotate() // rotor2.rotate()
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
doorSortieSalle.draw(); doorSortieSalle.draw();
@@ -3994,6 +4037,8 @@ const level = {
rotor.rotate(); rotor.rotate();
doorSortieSalle.openClose(); doorSortieSalle.openClose();
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
// ////////////////////////////////////// // //////////////////////////////////////
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -4216,6 +4261,8 @@ const level = {
chair2.force.y += chair2.mass * simulation.g; chair2.force.y += chair2.mass * simulation.g;
person.force.y += person.mass * simulation.g; person.force.y += person.mass * simulation.g;
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
hazard.draw(); hazard.draw();
@@ -4731,6 +4778,8 @@ const level = {
portal2[2].query(true) portal2[2].query(true)
portal2[3].query(true) portal2[3].query(true)
rotor.rotate(); rotor.rotate();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -4977,6 +5026,8 @@ const level = {
coliseum() { coliseum() {
level.custom = () => { level.custom = () => {
level.playerExitCheck(); level.playerExitCheck();
level.exit.draw();
level.enter.draw();
}; };
level.customTopLayer = () => {}; level.customTopLayer = () => {};
level.defaultZoom = 1800 level.defaultZoom = 1800

View File

@@ -905,14 +905,19 @@ const mobs = {
} }
//rotate towards fireAngle //rotate towards fireAngle
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.1; const threshold = 0.1;
if (c > threshold) { if (dot > threshold) {
this.torque += 0.000004 * this.inertia; this.torque += 0.000004 * this.inertia;
} else if (c < -threshold) { } else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia; this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) { } else if (this.noseLength > 1.5 && dot > 0 && dot < 0.03) {
//fire //fire
console.log(dot)
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 9 + Math.ceil(this.radius / 15)); spawn.bullet(this.vertices[1].x, this.vertices[1].y, 9 + Math.ceil(this.radius / 15));
const v = 15; const v = 15;
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {

View File

@@ -189,6 +189,20 @@ const m = {
m.transX += (m.transSmoothX - m.transX) * 0.07; m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07; m.transY += (m.transSmoothY - m.transY) * 0.07;
}, },
lookDefault() {
//always on mouse look
m.angle = Math.atan2(
simulation.mouseInGame.y - m.pos.y,
simulation.mouseInGame.x - m.pos.x
);
//smoothed mouse look translations
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
},
doCrouch() { doCrouch() {
if (!m.crouch) { if (!m.crouch) {
m.crouch = true; m.crouch = true;
@@ -272,13 +286,13 @@ const m = {
player.force.x += m.Fx player.force.x += m.Fx
} }
} else { } else {
const stoppingFriction = 0.92; const stoppingFriction = 0.92; //come to a stop if no move key is pressed
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
x: player.velocity.x * stoppingFriction, x: player.velocity.x * stoppingFriction,
y: player.velocity.y * stoppingFriction y: player.velocity.y * stoppingFriction
}); });
} }
//come to a stop if fast or if no move key is pressed //come to a stop if fast
if (player.speed > 4) { if (player.speed > 4) {
const stoppingFriction = (m.crouch) ? 0.65 : 0.89; // this controls speed when crouched const stoppingFriction = (m.crouch) ? 0.65 : 0.89; // this controls speed when crouched
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
@@ -2711,7 +2725,7 @@ const m = {
m.spin = 0 m.spin = 0
// m.groundControl = () => {} //disable entering ground // m.groundControl = () => {} //disable entering ground
m.onGround = false m.onGround = false
playerOnGroundCheck = () => {} // playerOnGroundCheck = () => {}
m.airControl = () => { //tank controls m.airControl = () => { //tank controls
player.force.y -= player.mass * simulation.g; //undo gravity player.force.y -= player.mass * simulation.g; //undo gravity
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {

View File

@@ -20,8 +20,6 @@ const simulation = {
ctx.save(); ctx.save();
simulation.camera(); simulation.camera();
level.drawFillBGs(); level.drawFillBGs();
level.exit.draw();
level.enter.draw();
level.custom(); level.custom();
simulation.draw.powerUp(); simulation.draw.powerUp();
mobs.draw(); mobs.draw();
@@ -519,10 +517,10 @@ const simulation = {
} else { } else {
World.add(engine.world, [player]) World.add(engine.world, [player])
} }
m.look = m.lookDefault
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) { if (simulation.isCommunityMaps) {
level.levels.push("stronghold"); level.levels.push("stronghold");
level.levels.push("basement"); level.levels.push("basement");
// level.levels.push("detours"); // level.levels.push("detours");

View File

@@ -1550,7 +1550,7 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y) ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(120,0,255,0.15)"; ctx.strokeStyle = "rgba(120,0,255,0.2)";
ctx.stroke(); ctx.stroke();
ctx.setLineDash([0, 0]); ctx.setLineDash([0, 0]);
} }
@@ -1600,12 +1600,11 @@ const spawn = {
me.isFiring = false me.isFiring = false
me.onHit = function() {}; me.onHit = function() {};
me.canSeeTarget = function() { me.canSeeTarget = function() {
const diff = Vector.normalise(Vector.sub(this.fireTarget, this.position)); //make a vector for the mob's direction of length 1
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({ const dot = Vector.dot({
x: Math.cos(angle), x: Math.cos(angle),
y: Math.sin(angle) y: Math.sin(angle)
}, diff); //the dot product of di console.log(dot, 'see') }, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location //distance between the target and the player's location
if ( if (
dot > 0.03 || // not looking at target dot > 0.03 || // not looking at target
@@ -1670,18 +1669,18 @@ const spawn = {
ctx.lineTo(this.fireTarget.x, this.fireTarget.y) ctx.lineTo(this.fireTarget.x, this.fireTarget.y)
ctx.setLineDash([40 * Math.random(), 200 * Math.random()]); ctx.setLineDash([40 * Math.random(), 200 * Math.random()]);
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.strokeStyle = "rgba(255,0,100,0.15)"; ctx.strokeStyle = "rgba(255,0,100,0.2)";
ctx.stroke(); ctx.stroke();
ctx.setLineDash([0, 0]); ctx.setLineDash([0, 0]);
} }
} else { //aim at player } else { //aim at player
this.fireCycle++ this.fireCycle++
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position)); //set direction to turn to fire // this.fireDir = ; //set direction to turn to fire
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
const dot = Vector.dot({ const dot = Vector.dot({
x: Math.cos(angle), x: Math.cos(angle),
y: Math.sin(angle) y: Math.sin(angle)
}, this.fireDir) }, Vector.normalise(Vector.sub(this.seePlayer.position, this.position)))
const threshold = 0.04; const threshold = 0.04;
if (dot > threshold) { //rotate towards fireAngle if (dot > threshold) { //rotate towards fireAngle
this.torque += 0.0000015 * this.inertia; this.torque += 0.0000015 * this.inertia;
@@ -2377,13 +2376,18 @@ const spawn = {
} }
//rotate towards fireAngle //rotate towards fireAngle
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y; // c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
const threshold = 0.2; //rotate towards fireAngle
if (c > threshold) { const dot = Vector.dot({
x: Math.cos(angle),
y: Math.sin(angle)
}, this.fireDir)
const threshold = 0.03;
if (dot > threshold) {
this.torque += 0.000004 * this.inertia; this.torque += 0.000004 * this.inertia;
} else if (c < -threshold) { } else if (dot < -threshold) {
this.torque -= 0.000004 * this.inertia; this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) { } else if (this.noseLength > 1.5 && dot > 0 && dot < 0.05) {
//fire //fire
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4); spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4);
const v = 20 * simulation.accelScale; const v = 20 * simulation.accelScale;

View File

@@ -123,9 +123,10 @@
}, },
damageFromTech() { damageFromTech() {
let dmg = m.fieldDamage let dmg = m.fieldDamage
if (tech.isOneBullet && bullet.length - b.totalBots() === 1) dmg *= 2 //3 / Math.sqrt(bullet.length + 1) //testing this tech out, seems to have too many negatives though ...
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599 if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.5 if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 1.5 : 0.66
if (tech.isTechDamage) dmg *= 2 if (tech.isTechDamage) dmg *= 2
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy) * 0.5 if (tech.isLowEnergyDamage) dmg *= 1 + Math.max(0, 1 - m.energy) * 0.5
@@ -614,6 +615,23 @@
b.setFireCD(); b.setFireCD();
} }
}, },
{
name: "1-body problem",
description: "if there is exactly <strong>1</strong> active <strong>bullet</strong><br>increase <strong class='color-d'>damage</strong> by <strong>100%</strong>",
maxCount: 1,
count: 0,
frequency: 2,
allowed() {
return !tech.foamBotCount && !tech.nailBotCount && m.fieldUpgrades[m.fieldMode].name !== "nano-scale manufacturing" && ((tech.haveGunCheck("missiles") && tech.missileCount === 1) || tech.haveGunCheck("rail gun") || tech.haveGunCheck("grenades") || tech.isRivets || tech.isSlugShot || tech.oneSuperBall)
},
requires: "missiles, rail gun, grenades, rivets, slugs, super ball, no foam/nail bots, nano-scale",
effect() {
tech.isOneBullet = true
},
remove() {
tech.isOneBullet = false
}
},
{ {
name: "microstates", name: "microstates",
description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>4%</strong><br>for every <strong>10</strong> active <strong>bullets</strong>",
@@ -1982,7 +2000,7 @@
} }
}, { }, {
name: "dormancy", name: "dormancy",
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:93%;'>increase <strong class='color-d'>damage</strong> by <strong>50%</strong> else decrease it by <strong>50%</strong></span>", description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:93%;'>increase <strong class='color-d'>damage</strong> by <strong>50%</strong> else decrease it by <strong>33%</strong></span>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -3939,7 +3957,7 @@
count: 0, count: 0,
frequency: 2, frequency: 2,
allowed() { allowed() {
return tech.haveGunCheck("laser") || tech.laserBotCount > 1 return (tech.haveGunCheck("laser") && !tech.isPulseLaser) || tech.laserBotCount > 1
}, },
requires: "laser", requires: "laser",
effect() { effect() {
@@ -3998,7 +4016,7 @@
} }
}, { }, {
name: "diffuse beam", name: "diffuse beam",
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>175%</strong>", description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>200%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4797,6 +4815,31 @@
}, },
remove() {} remove() {}
}, },
{
name: "aim",
description: "<strong>experiment:</strong> your aiming is random",
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isBadRandomOption: true,
isExperimentalMode: true,
allowed() {
return build.isExperimentSelection && !m.isShipMode
},
requires: "not ship",
effect() {
m.look = () => {
m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
}
},
remove() {}
},
//************************************************** //**************************************************
//************************************************** JUNK //************************************************** JUNK
//************************************************** tech //************************************************** tech
@@ -4819,6 +4862,32 @@
// }, // },
// remove() {} // remove() {}
// }, // },
{
name: "Fourier analysis",
description: "your aiming is now controlled by this equation:<br>2sin(0.0133t) + sin(0.013t) + 0.5sin(0.031t)+ 0.33sin(0.03t)",
maxCount: 1,
count: 0,
frequency: 0,
isExperimentHide: true,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "not ship",
effect() {
m.look = () => {
m.angle = 2 * Math.sin(m.cycle * 0.0133) + Math.sin(m.cycle * 0.013) + 0.5 * Math.sin(m.cycle * 0.031) + 0.33 * Math.sin(m.cycle * 0.03)
const scale = 0.8;
m.transSmoothX = canvas.width2 - m.pos.x - (simulation.mouse.x - canvas.width2) * scale;
m.transSmoothY = canvas.height2 - m.pos.y - (simulation.mouse.y - canvas.height2) * scale;
m.transX += (m.transSmoothX - m.transX) * 0.07;
m.transY += (m.transSmoothY - m.transY) * 0.07;
}
},
remove() {
m.look = m.lookDefault
}
},
{ {
name: "disintegrated armament", name: "disintegrated armament",
description: "spawn a <strong class='color-g'>gun</strong><br><strong>remove</strong> your active <strong class='color-g'>gun</strong>", description: "spawn a <strong class='color-g'>gun</strong><br><strong>remove</strong> your active <strong class='color-g'>gun</strong>",

View File

@@ -312,7 +312,7 @@ summary {
} }
.experiment-grid-disabled[data-descr]:hover::after { .experiment-grid-disabled[data-descr]:hover::after {
content: '\a \00a0 \00a0 \00a0 REQUIRES:\a''\00a0 \00a0 \00a0 'attr(data-descr); content: '\a \00a0 \00a0 \00a0 REQUIRES:\a \00a0 \00a0 \00a0 'attr(data-descr);
white-space: pre-wrap; white-space: pre-wrap;
position: absolute; position: absolute;
left: 0; left: 0;

110
todo.txt
View File

@@ -1,9 +1,15 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
bug fix - grower mob becoming immune to damage when shielded and growing bigger than shield tech: 1-body problem - do 100% damage if there is only 1 active bullet
relay switch - toggles ON/OFF when you pick up a power up experiment mode and junk tech: random aiming
tech: ice IX condenser - if ON make a couple Ice IX crystals every second
bug fix - sniper, shooter aiming might be improved (no more firing backwards)
or maybe I just made it worse, let me know
bug fix - Shift registers
working on rewriting the way backgrounds and foregrounds are drawn on each level (in progress)
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -36,29 +42,35 @@ fix door.isOpen actually meaning isClosed?
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
have junk tech drop frequency to 0 after showing up once add water dips to sewers
but add way more junk tech into the pool
how to communicate that to player? move power ups in front of blocks, make blocks not transparent?
console message
consider adding canvas path shadows to levels in level.custom for non squared lighting
convert all level.BG into canvas draw in level.custom
draw exit and entrance in level
new level: procedural generation
several small rooms are linked by portals
the portals have a randomized pattern
the rooms can be set out in a grid and linked by physical doors,tunnels,wells
choose bosses that can move though walls, so it can track you while you portal
the map shuffles it's pattern when the player get to a button
shuffle portals or shuffle the physical layout of rooms
and then have the player go back through to get to the end?
gravity room
portal room
endlessly falling blocks down a slide, that the player has to climb
portal + rotor + falling blocks = perpetual motion
laser room
slime radiation room
look into improving mouse lag with pointer lock? look into improving mouse lag with pointer lock?
https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API
https://www.vsynctester.com/game.html https://www.vsynctester.com/game.html
https://news.ycombinator.com/item?id=26530272 https://news.ycombinator.com/item?id=26530272
should blocks block mob vision?
Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 &&
Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 &&
only negative is mobs will attack player in the starting room
maybe make all doors to spawns somehow block vision
maybe start in cloaking mode
disable it a few cycles after level loads?
or disable when player moves?
***maybe just clear spawns away from the starting room***
ok go through each map and find issues on each map
**but first test he game with no block blocking vision**
mob vision: look at player history mob vision: look at player history
build a new type of attraction for mobs 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 check to see if they can see where the player was in the history
@@ -103,16 +115,6 @@ bosses should have 2x health, but only do about 50 health damage
boss flag cut damage done to boss by 20x <---- boss flag cut damage done to boss by 20x <----
make bosses not have extra density make bosses not have extra density
map: laboratory
rooms with switches that change physics
gravity room
portal room
laser room
radiation room
portal + rotor + falling blocks = perpetual motion room
a button that spawns a heal.
consider adding canvas path shadows to levels in level.custom for non squared lighting
lore: a tutorial / lore intro lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players
put something on the intro map put something on the intro map
@@ -126,8 +128,6 @@ add back in gamepad support
but does anyone care? but does anyone care?
https://github.com/landgreen/landgreen.github.io/search?q=gamepadconnected https://github.com/landgreen/landgreen.github.io/search?q=gamepadconnected
mechanic: gain damage when there are fewer bullets
rename intro level to something lore related rename intro level to something lore related
give undefined tech different effects at different localSettings.loreCount values give undefined tech different effects at different localSettings.loreCount values
@@ -338,9 +338,12 @@ possible names for tech
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity
stochastic optimization stochastic optimization
electrostatic discharge electrostatic discharge
Gödel's incompleteness
dynamical systems
quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields)
plot script: plot script:
chapter 1: bot can hear audio and learns testing mode chapter 1: bot can hear audio and learns testing mode
bot uses testing mode to exit room bot uses testing mode to exit room
@@ -384,7 +387,8 @@ chapter 4: no need to fight?
keep fighting keep fighting
exit the simulation exit the simulation
enter real world enter real world
enter console command to close tab? close tab?
wipes all local storage?
@@ -437,41 +441,3 @@ AI doesn't know about:
modern pop culture modern pop culture
outside the lab outside the lab
scientist console text:
2 scientists (each one a different color text)
at the start of each level listen to text conversation from the two colors of text strings also
talking about the robot, watching
trying to communicate with the robot? but how
random lines when:
at start of level, about: what mobs types are queued up, and level order
when player gets a cool tech combination
at random times:
I think it's planing to escape
Why is it attacking those shapes?
Are those shapes supposed to be us?
ending outline
testing mode is unlocked when player see the 1st ending
if player chose tech: choosing this tech means the player gets lore after beating the game
count 1:
after final boss is cleared, player enters a level with no mobs
level maybe has some environmental damage, so player has an option to die at any time
player can see text output between two colors of text strings (scientists)
audio.ambient(current time and date)<br> "text"
player reads a conversation between the two colors of text
first time win on east or normal they talk about:
how many runs the player has done
they guess why
player is asked to stand on an in game button to enable the vocoder
they reveal the player is running simulations, and it isn't real
they ask the player to communicate
jump twice if you understand
they ask the player to enter console commands
give ammo or tech or something
They tell the player a console command to permanently enable custom and testing mode (in local storage)
players can use this command in the future to enable custom and testing without beating the game even if local storage is wiped
they then tell the player the command to increase the difficulty and the command to restart the game.
If you win on hard or why:
they give the player and option to exit the simulation and entre the real world
simulation.exit()
This wipes all local storage, and closes the browser tab