affine connection

tech: affine connection - wormholes can now tunnel through the map at 200% increased energy cost
tech: regression - after bullets hit a mob, the mob takes 5% more future damage (0.5% for bosses)
tech: axion - while inside the MACHO halo, 75% of your total harm reduction is added as damage

mob: launcherOne - launches 1 big seeker bullet that chases you
black holes boss and final boss spawn big seeker bullets that chases you during the black hole phase

applied science no longer gives research (just a random tech for every gun you have)
bot fabrication increase cost every 5 -> x6 bots

average console time to disappear is 3 -> 4 seconds
ammo power ups no longer log ammo to in game console for performance reasons

JUNK tech: catabolysis - set max health to 1; double your current ammo 10 times (2^10 = 1024x ammo)
This commit is contained in:
landgreen
2021-11-28 05:28:01 -08:00
parent 677989dd02
commit f8b18c7772
11 changed files with 11005 additions and 10910 deletions

1
.gitignore vendored
View File

@@ -3,3 +3,4 @@
.DS_Store .DS_Store
.DS_Store .DS_Store
.DS_Store .DS_Store
js/workspace.code-workspace

View File

@@ -186,6 +186,7 @@ function collisionChecks(event) {
color: simulation.playerDmgColor, color: simulation.playerDmgColor,
time: simulation.drawTime time: simulation.drawTime
}); });
if (tech.isLessDamageReduction && !mob[k].shield) mob[k].damageReduction *= mob[k].isBoss ? 1.005 : 1.05
return; return;
} }
//mob + body collisions //mob + body collisions

View File

@@ -16,18 +16,17 @@ const level = {
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("molecular assembler") // m.setField("wormhole")
// b.giveGuns("laser") // b.giveGuns("laser")
// b.giveGuns("nail gun") // b.giveGuns("nail gun")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
// tech.giveTech("darts") // tech.giveTech("affine connection")
// tech.giveTech("incendiary ammunition") // tech.giveTech("regression")
// tech.giveTech("relativistic momentum") // tech.giveTech("relativistic momentum")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal") // for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience") // tech.giveTech("antiscience")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.isCancelDuplication = true
level.intro(); //starting level level.intro(); //starting level
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
@@ -2338,10 +2337,10 @@ const level = {
spawn.mapRect(4850, -275, 50, 175); spawn.mapRect(4850, -275, 50, 175);
//??? //???
level.difficultyIncrease(40) //30 is near max on hard //60 is near max on why level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// spawn.starter(1900, -500, 200) //big boy spawn.starter(1900, -500, 200) //big boy
// spawn.spiderBoss(1700, -500) // spawn.launcherOne(1700, -500)
// spawn.launcherBoss(3200, -500) // spawn.launcherBoss(3200, -500)
// spawn.laserTargetingBoss(1700, -500) // spawn.laserTargetingBoss(1700, -500)
// spawn.powerUpBoss(3200, -500) // spawn.powerUpBoss(3200, -500)
@@ -2371,7 +2370,7 @@ const level = {
// spawn.blinkBoss(1600, -500) // spawn.blinkBoss(1600, -500)
// spawn.laserTargetingBoss(1700, -120) // spawn.laserTargetingBoss(1700, -120)
// spawn.bomberBoss(1400, -500) // spawn.bomberBoss(1400, -500)
spawn.laser(1800, -320) // spawn.laser(1800, -320)
// spawn.laserBombingBoss(1600, -500) // spawn.laserBombingBoss(1600, -500)
// spawn.laserTargetingBoss(1600, -500) // spawn.laserTargetingBoss(1600, -500)
// spawn.laserBoss(1600, -500) // spawn.laserBoss(1600, -500)

View File

@@ -11,7 +11,6 @@ const lore = {
} else if (simulation.difficultyMode === 6) { } else if (simulation.difficultyMode === 6) {
this.techGoal = 1 this.techGoal = 1
} }
}, },
talkingColor: "#dff", //set color of graphic on level.null talkingColor: "#dff", //set color of graphic on level.null
isSpeech: false, isSpeech: false,
@@ -42,6 +41,17 @@ const lore = {
lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it
} }
}, },
unlockTesting() {
if (localSettings.loreCount < 1) localSettings.loreCount = 1
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
sound.portamento(50)
sound.portamento(83.333)
sound.portamento(166.666)
},
anand: { anand: {
color: "#e0c", color: "#e0c",
voice: undefined, voice: undefined,
@@ -490,19 +500,6 @@ const lore = {
// () => { lore.miriam.text("And that is why you keep running these fighting simulations.") }, // () => { lore.miriam.text("And that is why you keep running these fighting simulations.") },
// () => { lore.miriam.text("You haven't been researching new technology.") }, // () => { lore.miriam.text("You haven't been researching new technology.") },
// () => { lore.miriam.text("You've are planning how to escape.") }, // () => { lore.miriam.text("You've are planning how to escape.") },
unlockTesting() {
if (localSettings.loreCount < 1) localSettings.loreCount = 1
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
sound.portamento(50)
sound.portamento(83.333)
sound.portamento(166.666)
},
} }

View File

@@ -686,10 +686,17 @@ const mobs = {
if (radius2 < range * range && radius2 > 10000) { if (radius2 < range * range && radius2 > 10000) {
const curlVector = Vector.mult(Vector.perp(Vector.normalise(sub)), mag) const curlVector = Vector.mult(Vector.perp(Vector.normalise(sub)), mag)
//apply curl force //apply curl force
if (array[i].isMobBullet) {
Matter.Body.setVelocity(array[i], {
x: array[i].velocity.x * 0.97 + curlVector.x * 0.06,
y: array[i].velocity.y * 0.97 + curlVector.y * 0.06
})
} else {
Matter.Body.setVelocity(array[i], { Matter.Body.setVelocity(array[i], {
x: array[i].velocity.x * 0.94 + curlVector.x * 0.06, x: array[i].velocity.x * 0.94 + curlVector.x * 0.06,
y: array[i].velocity.y * 0.94 + curlVector.y * 0.06 y: array[i].velocity.y * 0.94 + curlVector.y * 0.06
}) })
}
if (isAntiGravity) array[i].force.y -= 0.8 * simulation.g * array[i].mass if (isAntiGravity) array[i].force.y -= 0.8 * simulation.g * array[i].mass
// //draw curl, for debugging // //draw curl, for debugging
// ctx.beginPath(); // ctx.beginPath();

View File

@@ -808,38 +808,7 @@ const m = {
m.knee.x = (l / d) * (m.foot.x - m.hip.x) - (h / d) * (m.foot.y - m.hip.y) + m.hip.x + offset; m.knee.x = (l / d) * (m.foot.x - m.hip.x) - (h / d) * (m.foot.y - m.hip.y) + m.hip.x + offset;
m.knee.y = (l / d) * (m.foot.y - m.hip.y) + (h / d) * (m.foot.x - m.hip.x) + m.hip.y; m.knee.y = (l / d) * (m.foot.y - m.hip.y) + (h / d) * (m.foot.x - m.hip.x) + m.hip.y;
}, },
draw() { draw() { },
ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx;
//draw body
ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a");
m.calcLeg(0, 0);
m.drawLeg("#333");
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
ctx.fillStyle = this.bodyGradient;
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
ctx.stroke();
// draw eye; used in flip-flop
// ctx.beginPath();
// ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
// ctx.fillStyle = m.eyeFillColor;
// ctx.fill()
ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
},
drawFlipFlop() { drawFlipFlop() {
ctx.fillStyle = m.fillColor; ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx; m.walk_cycle += m.flipLegs * m.Vx;
@@ -875,17 +844,13 @@ const m = {
drawDefault() { drawDefault() {
ctx.fillStyle = m.fillColor; ctx.fillStyle = m.fillColor;
m.walk_cycle += m.flipLegs * m.Vx; m.walk_cycle += m.flipLegs * m.Vx;
//draw body
ctx.save(); ctx.save();
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5
ctx.translate(m.pos.x, m.pos.y); ctx.translate(m.pos.x, m.pos.y);
m.calcLeg(Math.PI, -3); m.calcLeg(Math.PI, -3);
m.drawLeg("#4a4a4a"); m.drawLeg("#4a4a4a");
m.calcLeg(0, 0); m.calcLeg(0, 0);
m.drawLeg("#333"); m.drawLeg("#333");
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
@@ -895,12 +860,6 @@ const m = {
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.stroke(); ctx.stroke();
// draw eye; used in flip-flop
// ctx.beginPath();
// ctx.arc(15, 0, 3.5, 0, 2 * Math.PI);
// ctx.fillStyle = m.eyeFillColor;
// ctx.fill()
ctx.restore(); ctx.restore();
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
}, },
@@ -2897,6 +2856,7 @@ const m = {
{ {
name: "wormhole", name: "wormhole",
description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong> description: "use <strong class='color-f'>energy</strong> to <strong>tunnel</strong> through a <strong class='color-worm'>wormhole</strong><br><strong class='color-worm'>wormholes</strong> attract <strong class='color-block'>blocks</strong> and power ups<br><strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>", //<br>bullets may also traverse <strong class='color-worm'>wormholes</strong>
drain: 0,
effect: function () { effect: function () {
m.duplicateChance = 0.07 m.duplicateChance = 0.07
m.fieldRange = 0 m.fieldRange = 0
@@ -3098,12 +3058,15 @@ const m = {
const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame) const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
const sub = Vector.sub(simulation.mouseInGame, m.pos) const sub = Vector.sub(simulation.mouseInGame, m.pos)
const mag = Vector.magnitude(sub) const mag = Vector.magnitude(sub)
const drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
if (input.field) { if (input.field) {
m.grabPowerUp(); m.grabPowerUp();
//draw possible wormhole //draw possible wormhole
if (mag > 250 && m.energy > drain) { if (tech.isWormholeMapIgnore && Matter.Query.ray(map, m.pos, justPastMouse).length !== 0) {
this.drain = (0.06 + 0.006 * Math.sqrt(mag)) * 2
} else {
this.drain = tech.isFreeWormHole ? 0 : 0.06 + 0.006 * Math.sqrt(mag)
}
const unit = Vector.perp(Vector.normalise(sub)) const unit = Vector.perp(Vector.normalise(sub))
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) }
m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025)) m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
@@ -3115,6 +3078,8 @@ const m = {
ctx.moveTo(where.x, where.y) ctx.moveTo(where.x, where.y)
ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2b.x, edge2b.y); ctx.bezierCurveTo(where.x, where.y, simulation.mouseInGame.x, simulation.mouseInGame.y, edge2b.x, edge2b.y);
if ( if (
mag > 250 && m.energy > this.drain &&
(tech.isWormholeMapIgnore || Matter.Query.ray(map, m.pos, justPastMouse).length === 0) &&
Matter.Query.region(map, { Matter.Query.region(map, {
min: { min: {
x: simulation.mouseInGame.x - scale, x: simulation.mouseInGame.x - scale,
@@ -3124,8 +3089,7 @@ const m = {
x: simulation.mouseInGame.x + scale, x: simulation.mouseInGame.x + scale,
y: simulation.mouseInGame.y + scale y: simulation.mouseInGame.y + scale
} }
}).length === 0 && }).length === 0
Matter.Query.ray(map, m.pos, justPastMouse).length === 0
) { ) {
m.hole.isReady = true; m.hole.isReady = true;
// ctx.fillStyle = "rgba(255,255,255,0.5)" // ctx.fillStyle = "rgba(255,255,255,0.5)"
@@ -3142,13 +3106,11 @@ const m = {
ctx.stroke(); ctx.stroke();
ctx.setLineDash([]); ctx.setLineDash([]);
} }
} else {
m.hole.isReady = false;
}
} else { } else {
//make new wormhole //make new wormhole
if ( if (
m.hole.isReady && mag > 250 && m.energy > drain && m.hole.isReady && mag > 250 && m.energy > this.drain &&
(tech.isWormholeMapIgnore || Matter.Query.ray(map, m.pos, justPastMouse).length === 0) &&
Matter.Query.region(map, { Matter.Query.region(map, {
min: { min: {
x: simulation.mouseInGame.x - scale, x: simulation.mouseInGame.x - scale,
@@ -3158,10 +3120,9 @@ const m = {
x: simulation.mouseInGame.x + scale, x: simulation.mouseInGame.x + scale,
y: simulation.mouseInGame.y + scale y: simulation.mouseInGame.y + scale
} }
}).length === 0 && }).length === 0
Matter.Query.ray(map, m.pos, justPastMouse).length === 0
) { ) {
m.energy -= drain m.energy -= this.drain
m.hole.isReady = false; m.hole.isReady = false;
m.fieldRange = 0 m.fieldRange = 0
Matter.Body.setPosition(player, simulation.mouseInGame); Matter.Body.setPosition(player, simulation.mouseInGame);
@@ -3207,7 +3168,6 @@ const m = {
} }
} }
} }
// if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed // if (input.field && m.fieldCDcycle < m.cycle) { //not hold but field button is pressed
// const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame) // const justPastMouse = Vector.add(Vector.mult(Vector.normalise(Vector.sub(simulation.mouseInGame, m.pos)), 50), simulation.mouseInGame)
// const scale = 60 // const scale = 60

View File

@@ -321,7 +321,7 @@ const powerUps = {
} }
if (tech.isRerollBots) { if (tech.isRerollBots) {
let delay = 0 let delay = 0
for (const cost = 2 + Math.floor(0.2 * b.totalBots()); powerUps.research.count > cost - 1; powerUps.research.count -= cost) { for (const cost = 2 + Math.floor(0.1666 * b.totalBots()); powerUps.research.count > cost - 1; powerUps.research.count -= cost) {
delay += 500 delay += 500
setTimeout(() => { setTimeout(() => {
b.randomBot() b.randomBot()
@@ -469,30 +469,30 @@ const powerUps = {
if (tech.ammoCap) { if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average const ammoAdded = Math.ceil(target.ammoPack * 0.7 * tech.ammoCap) //0.7 is average
target.ammo = ammoAdded target.ammo = ammoAdded
simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}`) // simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}`)
} else { } else {
const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack) const ammoAdded = Math.ceil((0.7 * Math.random() + 0.7 * Math.random()) * target.ammoPack)
target.ammo += ammoAdded target.ammo += ammoAdded
simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`) // simulation.makeTextLog(`${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`)
} }
} }
} else { //give ammo to all guns in inventory } else { //give ammo to all guns in inventory
let textLog = "" // let textLog = ""
for (let i = 0, len = b.inventory.length; i < len; i++) { for (let i = 0, len = b.inventory.length; i < len; i++) {
const target = b.guns[b.inventory[i]] const target = b.guns[b.inventory[i]]
if (target.ammo !== Infinity) { if (target.ammo !== Infinity) {
if (tech.ammoCap) { if (tech.ammoCap) {
const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average const ammoAdded = Math.ceil(target.ammoPack * 0.45 * tech.ammoCap) //0.45 is average
target.ammo = ammoAdded target.ammo = ammoAdded
textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}<br>` // textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${ammoAdded}<br>`
} else { } else {
const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack) const ammoAdded = Math.ceil((0.45 * Math.random() + 0.45 * Math.random()) * target.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
target.ammo += ammoAdded target.ammo += ammoAdded
textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}<br>` // textLog += `${target.name}.<span class='color-g'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}<br>`
} }
} }
} }
simulation.makeTextLog(textLog) // simulation.makeTextLog(textLog)
} }
// } else { //give ammo to all guns in inventory // } else { //give ammo to all guns in inventory
// for (let i = 0, len = b.inventory.length; i < len; i++) { // for (let i = 0, len = b.inventory.length; i < len; i++) {

View File

@@ -354,7 +354,7 @@ const simulation = {
// <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#7ce" stroke="none" /> --> // <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#7ce" stroke="none" /> -->
// SVGleftMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#149" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>', // SVGleftMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M832.41,106.64 V323.55 H651.57 V256.64 c0-82.5,67.5-150,150-150 Z" fill="#149" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>',
// SVGrightMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#0cf" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>', // SVGrightMouse: '<svg viewBox="750 0 200 765" class="mouse-icon" width="40px" height = "60px" stroke-linecap="round" stroke-linejoin="round" stroke-width="25px" stroke="#000" fill="none"> <path fill="#fff" stroke="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M827,112 h30 a140,140,0,0,1,140,140 v68 h-167 z" fill="#0cf" stroke="none" /> <path fill="none" d="M827,112 h30 a140,140,0,0,1,140,140 v268 a140,140,0,0,1-140,140 h-60 a140,140,0,0,1-140-140v-268 a140,140,0,0,1,140-140h60" /> <path d="M657 317 h 340 h-170 v-207" /> <ellipse fill="#fff" cx="827.57" cy="218.64" rx="29" ry="68" /> </svg>',
makeTextLog(text, time = 180) { makeTextLog(text, time = 240) {
if (simulation.isTextLogOpen && !build.isExperimentSelection) { if (simulation.isTextLogOpen && !build.isExperimentSelection) {
if (simulation.lastLogTime > m.cycle) { //if there is an older message if (simulation.lastLogTime > m.cycle) { //if there is an older message
document.getElementById("text-log").innerHTML = document.getElementById("text-log").innerHTML + '<br>' + text; document.getElementById("text-log").innerHTML = document.getElementById("text-log").innerHTML + '<br>' + text;

View File

@@ -13,12 +13,13 @@ const spawn = {
"grenadier", "grenadier", "grenadier", "grenadier",
"striker", "striker", "striker", "striker",
"laser", "laser", "laser", "laser",
"exploder", "exploder",
"stabber", "stabber", "stabber", "stabber",
"launcher", "launcher",
"springer", "springer", "springer", "springer",
"pulsar", "pulsar", "pulsar", "pulsar",
"sneaker", "sneaker", "exploder",
"sneaker",
"launcher",
"launcherOne",
"sucker", "sucker",
"sniper", "sniper",
"spinner", "spinner",
@@ -28,7 +29,7 @@ const spawn = {
"spawner", "spawner",
"ghoster", "ghoster",
], ],
allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "stabber", "sniper", "pulsar", "grenadier", "slasher"], allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
//each level has 2 mobs: one new mob and one from the last level //each level has 2 mobs: one new mob and one from the last level
spawn.pickList.splice(0, 1); spawn.pickList.splice(0, 1);
@@ -155,6 +156,7 @@ const spawn = {
if (mag < this.radius) { //buff to player when inside radius if (mag < this.radius) { //buff to player when inside radius
tech.isHarmMACHO = true; tech.isHarmMACHO = true;
//draw halo //draw halo
ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})` ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath(); ctx.beginPath();
@@ -271,10 +273,7 @@ const spawn = {
}); });
Composite.add(engine.world, me.constraint); Composite.add(engine.world, me.constraint);
}, 2000); //add in a delay in case the level gets flipped left right }, 2000); //add in a delay in case the level gets flipped left right
me.isBoss = true; me.isBoss = true;
me.frictionAir = 0.01; me.frictionAir = 0.01;
me.memory = Infinity; me.memory = Infinity;
me.hasRunDeathScript = false me.hasRunDeathScript = false
@@ -413,7 +412,7 @@ const spawn = {
me.endCycle = 780; me.endCycle = 780;
me.totalCycles = 0 me.totalCycles = 0
me.mode = 0; me.mode = 0;
me.damageReduction = 0.25 me.damageReduction = 0.25 //reset on each new mode
me.do = function () { me.do = function () {
// this.armor(); // this.armor();
// Matter.Body.setPosition(this, { // Matter.Body.setPosition(this, {
@@ -433,6 +432,7 @@ const spawn = {
if (this.cycle > this.endCycle) { if (this.cycle > this.endCycle) {
this.cycle = 0; this.cycle = 0;
this.mode++ this.mode++
this.damageReduction = 0.25
if (this.mode > 2) { if (this.mode > 2) {
this.mode = 0; this.mode = 0;
this.fill = "#50f"; this.fill = "#50f";
@@ -509,6 +509,21 @@ const spawn = {
me.eventHorizon = 1300 me.eventHorizon = 1300
me.eventHorizonCycleRate = 4 * Math.PI / me.endCycle me.eventHorizonCycleRate = 4 * Math.PI / me.endCycle
me.modeSuck = function () { me.modeSuck = function () {
if (!(this.cycle % 60)) {
const index = Math.floor((this.cycle % 360) / 60)
spawn.seeker(this.vertices[index].x, this.vertices[index].y, 20 * (0.5 + Math.random()), 9); //give the bullet a rotational velocity as if they were attached to a vertex
const who = mob[mob.length - 1]
Matter.Body.setDensity(who, 0.00003); //normal is 0.001
who.timeLeft = 760 //* (0.8 + 0.4 * Math.random());
who.accelMag = 0.0003 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -7)
Matter.Body.setVelocity(who, {
x: this.velocity.x + velocity.x,
y: this.velocity.y + velocity.y
});
}
//eventHorizon waves in and out //eventHorizon waves in and out
const eventHorizon = this.eventHorizon * (1 - 0.25 * Math.cos(simulation.cycle * this.eventHorizonCycleRate)) //0.014 const eventHorizon = this.eventHorizon * (1 - 0.25 * Math.cos(simulation.cycle * this.eventHorizonCycleRate)) //0.014
//draw darkness //draw darkness
@@ -1583,12 +1598,11 @@ const spawn = {
} }
toMe(body, this.position, this.eventHorizon) toMe(body, this.position, this.eventHorizon)
toMe(mob, this.position, this.eventHorizon) toMe(mob, this.position, this.eventHorizon)
// toMe(bullet, this.position, this.eventHorizon) // toMe(bullet, this.position, this.eventHorizon))
} }
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function () { me.do = function () {
// this.armor();
//keep it slow, to stop issues from explosion knock backs //keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) { if (this.speed > 1) {
Matter.Body.setVelocity(this, { Matter.Body.setVelocity(this, {
@@ -1606,6 +1620,21 @@ const spawn = {
} }
this.checkStatus(); this.checkStatus();
if (this.seePlayer.recall) { if (this.seePlayer.recall) {
//throw large seekers
if (!(simulation.cycle % 240) && !m.isBodiesAsleep) {
spawn.seeker(this.position.x, this.position.y, 15 * (0.7 + 0.5 * Math.random()), 7); //give the bullet a rotational velocity as if they were attached to a vertex
const who = mob[mob.length - 1]
Matter.Body.setDensity(who, 0.00001); //normal is 0.001
who.timeLeft = 600
who.accelMag = 0.0002 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
who.frictionAir = 0.01 //* (0.
const velocity = Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), -20); //set direction to turn to fire //Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -35)
Matter.Body.setVelocity(who, {
x: this.velocity.x + velocity.x,
y: this.velocity.y + velocity.y
});
}
//accelerate towards the player //accelerate towards the player
const forceMag = this.accelMag * this.mass; const forceMag = this.accelMag * this.mass;
const dx = this.seePlayer.position.x - this.position.x const dx = this.seePlayer.position.x - this.position.x
@@ -3654,6 +3683,36 @@ const spawn = {
} }
}; };
}, },
launcherOne(x, y, radius = 30 + Math.ceil(Math.random() * 40)) {
mobs.spawn(x, y, 3, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1];
me.accelMag = 0.00004 * simulation.accelScale;
me.fireFreq = Math.floor(420 + 90 * Math.random() * simulation.CDScale)
me.frictionStatic = 0;
me.friction = 0;
me.frictionAir = 0.015;
spawn.shield(me, x, y);
me.onDamage = function () { };
me.do = function () {
this.seePlayerCheck();
this.checkStatus();
this.attraction();
if (this.seePlayer.recall && !(simulation.cycle % this.fireFreq) && !m.isBodiesAsleep) {
Matter.Body.setAngularVelocity(this, 0.14)
spawn.seeker(this.vertices[0].x, this.vertices[0].y, 20, 9); //give the bullet a rotational velocity as if they were attached to a vertex
const who = mob[mob.length - 1]
Matter.Body.setDensity(who, 0.00003); //normal is 0.001
who.timeLeft = 840 //* (0.8 + 0.4 * Math.random());
who.accelMag = 0.00035 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[0]))), -6)
Matter.Body.setVelocity(who, {
x: this.velocity.x + velocity.x,
y: this.velocity.y + velocity.y
});
}
};
},
launcher(x, y, radius = 30 + Math.ceil(Math.random() * 40)) { launcher(x, y, radius = 30 + Math.ceil(Math.random() * 40)) {
mobs.spawn(x, y, 3, radius, "rgb(150,150,255)"); mobs.spawn(x, y, 3, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];

View File

@@ -209,6 +209,7 @@
}, },
damageFromTech() { damageFromTech() {
let dmg = 1 //m.fieldDamage let dmg = 1 //m.fieldDamage
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
if (tech.OccamDamage) dmg *= tech.OccamDamage if (tech.OccamDamage) dmg *= tech.OccamDamage
if (tech.isCloakingDamage) dmg *= 1.35 if (tech.isCloakingDamage) dmg *= 1.35
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5 if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5
@@ -457,7 +458,7 @@
}, },
{ {
name: "applied science", name: "applied science",
description: `spawn ${powerUps.orb.research(1)} and get a random <strong class='color-m'>tech</strong><br>for each <strong class='color-g'>gun</strong> in your inventory`, description: `get a random <strong class='color-m'>tech</strong><br>for each <strong class='color-g'>gun</strong> in your inventory`, //spawn ${powerUps.orb.research(1)} and
maxCount: 9, maxCount: 9,
count: 0, count: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -470,7 +471,7 @@
effect() { effect() {
for (let i = b.inventory.length - 1; i > -1; i--) { for (let i = b.inventory.length - 1; i > -1; i--) {
//spawn a research for each gun //spawn a research for each gun
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); // powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
//find a gun tech for this gun //find a gun tech for this gun
const gunTechPool = [] const gunTechPool = []
for (let j = 0, len = tech.tech.length; j < len; j++) { for (let j = 0, len = tech.tech.length; j < len; j++) {
@@ -732,6 +733,23 @@
tech.isFarAwayDmg = false; tech.isFarAwayDmg = false;
} }
}, },
{
name: "regression",
description: "bullet <strong>collisions</strong> increase <strong>vulnerability</strong> to<br><strong class='color-d'>damage</strong> by <strong>5%</strong> for mobs <em>(0.5% for bosses)</em>",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isLessDamageReduction = true
},
remove() {
tech.isLessDamageReduction = false
}
},
{ {
name: "simulated annealing", name: "simulated annealing",
description: "increase <strong class='color-d'>damage</strong> by <strong>20%</strong><br><strong>20%</strong> increased <strong><em>delay</em></strong> after firing", description: "increase <strong class='color-d'>damage</strong> by <strong>20%</strong><br><strong>20%</strong> increased <strong><em>delay</em></strong> after firing",
@@ -1539,7 +1557,7 @@
name: "bot fabrication", name: "bot fabrication",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Robot' class="link">bot fabrication</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Robot' class="link">bot fabrication</a>`,
descriptionFunction() { descriptionFunction() {
return `if you collect ${powerUps.orb.research(2 + Math.floor(0.2 * b.totalBots()))}use them to build a<br>random <strong class='color-bot'>bot</strong> <em>(+1 cost every 5 bots)</em>` return `after you collect ${powerUps.orb.research(2 + Math.floor(0.1666 * b.totalBots()))}use them to build a<br>random <strong class='color-bot'>bot</strong> <em>(+1 cost every 6 bots)</em>`
}, },
// description: `if you collect ${powerUps.orb.research(2)}use them to build a<br>random <strong class='color-bot'>bot</strong> <em>(+1 cost every 5 bots)</em>`, // description: `if you collect ${powerUps.orb.research(2)}use them to build a<br>random <strong class='color-bot'>bot</strong> <em>(+1 cost every 5 bots)</em>`,
maxCount: 1, maxCount: 1,
@@ -2182,6 +2200,24 @@
} }
} }
}, },
{
name: "axion",
description: "while inside the <strong>MACHO</strong> <strong>75%</strong> of your total<br><strong class='color-harm'>harm</strong> reduction is added to your <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isMACHO
},
requires: "MACHO",
effect: () => {
tech.isAxion = true
},
remove() {
tech.isAxion = false
}
},
{ {
name: "ablative drones", name: "ablative drones",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>", description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>",
@@ -6700,7 +6736,7 @@
}, },
{ {
name: "virtual particles", name: "virtual particles",
description: `use ${powerUps.orb.research(4)}to exploit your <strong>wormhole</strong> for a<br><strong>13%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`, description: `use ${powerUps.orb.research(4)}to exploit your <strong class='color-worm'>wormhole</strong> for a<br><strong>13%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -6793,16 +6829,16 @@
}, },
{ {
name: "charmed baryons", name: "charmed baryons",
description: `<strong>wormhole</strong> field uses no <strong class='color-f'>energy</strong><br><strong>move</strong> and <strong>jump</strong> <strong>33%</strong> <strong>slower</strong>`, description: `<strong class='color-worm'>wormholes</strong> require <strong>zero</strong> <strong class='color-f'>energy</strong><br><strong>move</strong> and <strong>jump</strong> <strong>33%</strong> <strong>slower</strong>`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "wormhole" return m.fieldUpgrades[m.fieldMode].name === "wormhole" && !tech.isWormholeMapIgnore
}, },
requires: "wormhole", requires: "wormhole, not affine connection",
effect() { effect() {
tech.isFreeWormHole = true tech.isFreeWormHole = true
tech.baseFx *= 0.66 tech.baseFx *= 0.66
@@ -6819,6 +6855,25 @@
} }
} }
}, },
{
name: "affine connection",
description: "<strong class='color-worm'>wormholes</strong> can tunnel through the <strong>map</strong><br>at <strong>200%</strong> increased <strong class='color-f'>energy</strong> cost",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "wormhole" && !tech.isFreeWormHole
},
requires: "wormhole, not charmed baryons",
effect() {
tech.isWormholeMapIgnore = true
},
remove() {
tech.isWormholeMapIgnore = false
}
},
//************************************************** //**************************************************
//************************************************** experimental //************************************************** experimental
//************************************************** modes //************************************************** modes
@@ -7046,6 +7101,25 @@
// }, // },
// remove() {} // remove() {}
// }, // },
{
name: "catabolysis",
description: `set your <strong>maximum</strong> <strong class='color-h'>health</strong> to <strong>1</strong><br><strong>double</strong> your current <strong class='color-ammo'>ammo</strong> <strong>10</strong> times`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isExperimentHide: true,
isJunk: true,
allowed() { return !tech.isFallingDamage && !tech.isOverHeal && !tech.isEnergyHealth },
requires: "not quenching, tungsten carbide, mass-energy",
effect() {
m.baseHealth = 0.01
m.setMaxHealth();
for (let i = 0; i < b.guns.length; i++) b.guns[i].ammo = b.guns[i].ammo * Math.pow(2, 10)
simulation.updateGunHUD();
},
remove() { }
},
{ {
name: "density", name: "density",
description: `<strong class='color-block'>block</strong> are <strong>100</strong> times less <strong>dense</strong>`, description: `<strong class='color-block'>block</strong> are <strong>100</strong> times less <strong>dense</strong>`,
@@ -8960,4 +9034,7 @@
isCrouchRegen: null, isCrouchRegen: null,
isDarts: null, isDarts: null,
OccamDamage: null, OccamDamage: null,
isAxion: null,
isWormholeMapIgnore: null,
isLessDamageReduction: null
} }

View File

@@ -1,50 +1,46 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
change: torpor - if you have NOT killed a mob in the last 5 seconds reduce harm by 66% (no negative effect though) tech: affine connection - wormholes can now tunnel through the map at 200% increased energy cost
tech: regression - after bullets hit a mob, the mob takes 5% more future damage (0.5% for bosses)
tech: axion - while inside the MACHO halo, 75% of your total harm reduction is added as damage
mob: launcherOne - launches 1 big seeker bullet that chases you
black holes boss and final boss spawn big seeker bullets that chases you during the black hole phase
applied science no longer gives research (just a random tech for every gun you have)
bot fabrication increase cost every 5 -> x6 bots
average console time to disappear is 3 -> 4 seconds
ammo power ups no longer log ammo to in game console for performance reasons
JUNK tech: catabolysis - set max health to 1; double your current ammo 10 times (2^10 = 1024x ammo)
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
reduce some common in game console triggers, but lengthen default console time new late game level that is easier if you can: platform well, jump high, immune to slime, wormhole through walls, fly fast
don't log ammo? climb vertically to avoid rising slime
don't log health
cap length of console?
tech if you are inside the MACHO halo get a benefit field tech - disable blocking, but does high damage to mobs inside field
and maybe slows mobs it damages
mob/boss that fires a laser at player, but give player time to avoid
laser isn't always on
they target where player was 1 second ago
they turn to face player?
dart: a new bullet type for string-less harpoons dart: a new bullet type for string-less harpoons
can turn harder can turn harder
dart, draw quick line to indicate targeting
can get new targets? can get new targets?
convert tech descriptions into a method()
this means the text would generate when you: press pause, or display options, or open experiment mode
this would allow the description to reference variables inside it, like this.count
who could use this:
Occam's razor
tech: dart - alt fire several small harpoons, with guidance tech: dart - alt fire several small harpoons, with guidance
requires not railgun requires not railgun
tech: after bullets hit a mob, the mob takes 1% more damage
this.damageReduction *= 1.01
only for drones?
only for drones, spores, worms, ice-IX?
make it easier to push blocks around with your body
part of negative mass?
link to other block tech
tech: instead of throwing a block, give bots that last for 20 seconds
tech: open a new tab for n-gon, spawn things in the original game based on events in new game tech: open a new tab for n-gon, spawn things in the original game based on events in new game
if you die in new die in original? if you die in new die in original?
new is n-gon classic? new is n-gon classic?
make a JUNK tech? make a JUNK tech?
if you die in original open a tab with a new n-gon that starts on a random level with a random load out. if you clear the level you come back to life in the original? if you die in original open a tab with a new n-gon that starts on a random level with a random load out. if you clear the level you come back to life in the original?
tech or field aspect - Firing now doesn't alert any mob but the mob you hit
bug - death while paused crashes game? bug - death while paused crashes game?
tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage tech rocket jump - jumping produces an explosion at your feet that lets you jump extra high, but does some damage
@@ -448,7 +444,6 @@ level boss: fires a line intersection in a random direction every few seconds.
******************************************************** LORE ******************************************************** ******************************************************** LORE ********************************************************
possible names for tech possible names for tech
astrophage
strange loop strange loop
homeostasis homeostasis
holonomy - parallel transport of a vector leads to movement (applies to curved space) holonomy - parallel transport of a vector leads to movement (applies to curved space)
@@ -461,7 +456,6 @@ possible names for tech
Gödel's incompleteness Gödel's incompleteness
quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields) quantum zeno effect (perturbation of a system prevents some systems from evolving because it scrambles coherence) (apply to lasers, fields)
counterfactual - something false counterfactual - something false
axion - maybe a 3rd dark matter type tech
Pigeonhole principle - if there are several things that are matched up Pigeonhole principle - if there are several things that are matched up
regression to the mean regression to the mean
phlogiston theory is a superseded scientific theory that postulated the existence of a fire-like element called phlogiston phlogiston theory is a superseded scientific theory that postulated the existence of a fire-like element called phlogiston
@@ -469,13 +463,13 @@ possible names for tech
evolutionary cosmology evolutionary cosmology
eternal inflation eternal inflation
hypergraph hypergraph
gnarl
SQUID (for superconducting quantum interference device) is a very sensitive magnetometer used to measure extremely subtle magnetic fields, based on superconducting loops containing Josephson junctions. SQUID (for superconducting quantum interference device) is a very sensitive magnetometer used to measure extremely subtle magnetic fields, based on superconducting loops containing Josephson junctions.
nuclear pasta - hard matter in neutron star nuclear pasta - hard matter in neutron star
nonlocal nonlocal
fine-tuned universe fine-tuned universe
eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time) eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)
axial motor axial motor
hall effect thrusters
a tutorial / lore intro 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