lore chapters: 3,4

2 more lore chapters (5 total now)
entering testing mode makes a sound now

reduced the requirements and frequency for many tech so that they may show up in "less optimal" situations
  I hope this will increase build variety and also give more value to making good tech choices
countless bug fixes and wording fixes

mobs have a new trait mob[i].damageReduction
This commit is contained in:
landgreen
2021-07-21 07:01:46 -07:00
parent d50cd540fa
commit 34d295cf48
11 changed files with 503 additions and 247 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -1869,7 +1869,7 @@ const b = {
do() { do() {
ctx.beginPath(); //draw nematode ctx.beginPath(); //draw nematode
ctx.moveTo(this.position.x, this.position.y); ctx.moveTo(this.position.x, this.position.y);
const dir = Vector.mult(Vector.normalise(this.velocity), -Math.min(80, 7 * this.speed)) const dir = Vector.mult(Vector.normalise(this.velocity), -Math.min(45, 7 * this.speed))
const tail = Vector.add(this.position, dir) const tail = Vector.add(this.position, dir)
ctx.lineTo(tail.x, tail.y); ctx.lineTo(tail.x, tail.y);
ctx.lineWidth = 6; ctx.lineWidth = 6;

View File

@@ -1089,6 +1089,7 @@ if (localSettings) {
runCount: 0, runCount: 0,
levelsClearedLastGame: 0, levelsClearedLastGame: 0,
loreCount: 0, loreCount: 0,
isHuman: false,
key: undefined key: undefined
}; };
input.setDefault() input.setDefault()
@@ -1168,7 +1169,41 @@ document.getElementById("updates").addEventListener("toggle", function() {
} }
); );
}) })
const sound = {
tone(frequency, end = 1000, gain = 0.05) {
const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); //setup audio context
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
gainNode.gain.value = gain; //controls volume
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom'
oscillator.frequency.value = frequency; // value in hertz
oscillator.start();
setTimeout(() => {
audioCtx.suspend()
audioCtx.close()
}, end)
// return audioCtx
},
portamento(frequency, end = 1000, shiftRate = 10, gain = 0.05) {
const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); //setup audio context
const oscillator = audioCtx.createOscillator();
const gainNode = audioCtx.createGain();
gainNode.gain.value = gain; //controls volume
oscillator.connect(gainNode);
gainNode.connect(audioCtx.destination);
oscillator.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom'
oscillator.frequency.value = frequency; // value in hertz
oscillator.start();
for (let i = 0, len = end * 0.1; i < len; i++) oscillator.frequency.setValueAtTime(frequency + i * shiftRate, audioCtx.currentTime + i * 0.01);
setTimeout(() => {
audioCtx.suspend()
audioCtx.close()
}, end)
// return audioCtx
}
}
//********************************************************************** //**********************************************************************
// main loop // main loop
//********************************************************************** //**********************************************************************

View File

@@ -14,15 +14,13 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(30) // level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("wormhole") // m.setField("perfect diamagnetism")
// b.giveGuns("spores") // b.giveGuns("spores")
// tech.isSporeWorm = true // tech.giveTech("CPT reversal")
// tech.giveTech("tinsellated flagella") // tech.giveTech("causality bombs")
// tech.giveTech("torque bursts")
// b.giveGuns("wave beam") // b.giveGuns("wave beam")
// tech.giveTech("phonon") // tech.giveTech("phonon")
// tech.giveTech("bound state") // tech.giveTech("bound state")
// tech.giveTech("bound state")
// tech.giveTech("isotropic radiator") // tech.giveTech("isotropic radiator")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length") // for (let i = 0; i < 3; i++) tech.giveTech("packet length")
@@ -59,7 +57,7 @@ const level = {
// lore.techCount = 6 // lore.techCount = 6
// simulation.isCheating = false //true; // simulation.isCheating = false //true;
// localSettings.loreCount = 0; //this sets what conversation is heard // localSettings.loreCount = 4; //this sets what conversation is heard
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null() // level.null()
@@ -925,6 +923,7 @@ const level = {
} }
} }
}, },
isHazardRise: false,
hazard(x, y, width, height, damage = 0.003) { hazard(x, y, width, height, damage = 0.003) {
return { return {
min: { min: {
@@ -967,9 +966,10 @@ const level = {
ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset) ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset)
if (this.height > 0 && Matter.Query.region([player], this).length) { if (this.height > 0 && Matter.Query.region([player], this).length) {
const DRAIN = 0.003 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen const DRAIN = 0.002 * (tech.isRadioactiveResistance ? 0.25 : 1) + m.fieldRegen
if (m.energy > DRAIN) { if (m.energy > DRAIN) {
m.energy -= DRAIN m.energy -= DRAIN
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy
} else { } else {
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1)) m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1))
} }
@@ -2094,20 +2094,21 @@ const level = {
lore.chapter = localSettings.loreCount //set the chapter to listen to to be the lore level (you can't use the lore level because it changes during conversations) lore.chapter = localSettings.loreCount //set the chapter to listen to to be the lore level (you can't use the lore level because it changes during conversations)
lore.sentence = 0 //what part of the conversation to start on lore.sentence = 0 //what part of the conversation to start on
lore.conversation[lore.chapter][lore.sentence]() lore.conversation[lore.chapter][lore.sentence]()
localSettings.loreCount++ //hear the next conversation next time you win localSettings.loreCount++ //hear the next conversation next time you win
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} }
const hazardSlime = level.hazard(-1800, 150, 3600, 650, 0.004, "hsla(160, 100%, 35%,0.75)") // const hazardSlime = level.hazard(-1800, 150, 3600, 650, 0.004, "hsla(160, 100%, 35%,0.75)")
const hazardSlime = level.hazard(-1800, -800, 3600, 1600, 0.004, "hsla(160, 100%, 35%,0.75)")
hazardSlime.height -= 950
hazardSlime.min.y += 950
hazardSlime.max.y = hazardSlime.min.y + hazardSlime.height
const circle = { const circle = {
x: 0, x: 0,
y: -500, y: -500,
radius: 50 radius: 50
} }
level.custom = () => { level.custom = () => {
hazardSlime.query();
//draw wide line //draw wide line
ctx.beginPath(); ctx.beginPath();
ctx.moveTo(circle.x, -800) ctx.moveTo(circle.x, -800)
@@ -2117,6 +2118,9 @@ const level = {
ctx.globalAlpha = 0.03; ctx.globalAlpha = 0.03;
ctx.stroke(); ctx.stroke();
ctx.globalAlpha = 1; ctx.globalAlpha = 1;
//support pillar
ctx.fillStyle = "rgba(0,0,0,0.2)";
ctx.fillRect(-25, 0, 50, 1000);
//draw circles //draw circles
ctx.beginPath(); ctx.beginPath();
@@ -2132,25 +2136,18 @@ const level = {
ctx.fillStyle = lore.talkingColor //"#dff" ctx.fillStyle = lore.talkingColor //"#dff"
ctx.fill(); ctx.fill();
level.enter.draw(); // level.enter.draw();
// level.exit.draw();
// level.playerExitCheck();
}; };
let sway = { let sway = { x: 0, y: 0 }
x: 0,
y: 0
}
let phase = -Math.PI / 2 let phase = -Math.PI / 2
level.customTopLayer = () => { level.customTopLayer = () => {
ctx.fillStyle = "rgba(0,0,0,0.1)"; ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.fillRect(-1950, -950, 3900, 1900); ctx.fillRect(-1950, -950, 3900, 1900);
// hazardSlime.drawTides();
//draw center circle lines //draw center circle lines
ctx.beginPath(); ctx.beginPath();
const step = Math.PI / 20 const step = Math.PI / 20
const horizontalStep = 85 const horizontalStep = 85
if (simulation.isCheating) phase += 0.01 //(m.pos.x - circle.x) * 0.0005 //0.05 * Math.sin(simulation.cycle * 0.030) if (simulation.isCheating) phase += 0.3 * Math.random() * Math.random() //(m.pos.x - circle.x) * 0.0005 //0.05 * Math.sin(simulation.cycle * 0.030)
// const sway = 5 * Math.cos(simulation.cycle * 0.007) // const sway = 5 * Math.cos(simulation.cycle * 0.007)
sway.x = sway.x * 0.995 + 0.005 * (m.pos.x - circle.x) * 0.05 //+ 0.04 * Math.cos(simulation.cycle * 0.01) sway.x = sway.x * 0.995 + 0.005 * (m.pos.x - circle.x) * 0.05 //+ 0.04 * Math.cos(simulation.cycle * 0.01)
sway.y = 2.5 * Math.sin(simulation.cycle * 0.015) sway.y = 2.5 * Math.sin(simulation.cycle * 0.015)
@@ -2167,6 +2164,8 @@ const level = {
ctx.lineWidth = 0.5; ctx.lineWidth = 0.5;
ctx.strokeStyle = "#899"; ctx.strokeStyle = "#899";
ctx.stroke(); ctx.stroke();
hazardSlime.query();
if (level.isHazardRise) hazardSlime.level(true)
//draw wires //draw wires
// ctx.beginPath(); // ctx.beginPath();
// ctx.moveTo(-500, -800); // ctx.moveTo(-500, -800);
@@ -2191,7 +2190,7 @@ const level = {
spawn.mapRect(-3000, -2000, 1200, 3400); //left spawn.mapRect(-3000, -2000, 1200, 3400); //left
spawn.mapRect(1800, -1400, 1200, 3400); //right spawn.mapRect(1800, -1400, 1200, 3400); //right
spawn.mapRect(-500, 0, 1000, 1000); //center platform spawn.mapRect(-500, 0, 1000, 50); //center platform
spawn.mapRect(-500, -25, 25, 50); //edge shelf spawn.mapRect(-500, -25, 25, 50); //edge shelf
spawn.mapRect(475, -25, 25, 50); //edge shelf spawn.mapRect(475, -25, 25, 50); //edge shelf
}, },
@@ -2255,6 +2254,8 @@ 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.starter(1900, -500, 200) //big boy spawn.starter(1900, -500, 200) //big boy
spawn.starter(1900, -500)
// spawn.pulsarBoss(1900, -500) // spawn.pulsarBoss(1900, -500)
// spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
// spawn.grenadierBoss(1900, -500) // spawn.grenadierBoss(1900, -500)
@@ -6810,6 +6811,7 @@ const level = {
} }
}, },
"n-gon"() { //make by Oranger "n-gon"() { //make by Oranger
document.body.style.backgroundColor = "#dcdcde";
let needGravity = []; let needGravity = [];
let s = { //mech statue let s = { //mech statue
x: -200, x: -200,

View File

@@ -6,19 +6,36 @@ const lore = {
testSpeechAPI() { testSpeechAPI() {
if ('speechSynthesis' in window) { // Synthesis support. Make your web apps talk! if ('speechSynthesis' in window) { // Synthesis support. Make your web apps talk!
lore.isSpeech = true lore.isSpeech = true
// const utterance = new SpeechSynthesisUtterance("test");
// utterance.volume = 0; // 0 to 1
// speechSynthesis.speak(utterance);
// utterance.onerror = () => { //if speech doesn't work
// lore.isSpeech = false
// }
// speechFrozen = setTimeout(() => { // speech frozen after 15 seconds of no end
// console.log('speech frozen')
// lore.isSpeech = false
// }, 5000);
// utterance.onend = () => {
// clearTimeout(speechFrozen);
// }
} else {
lore.isSpeech = false
} }
}, },
rate: 1, // //utterance.rate = 1; // 0.1 to 10 rate: 1, // //utterance.rate = 1; // 0.1 to 10
nextSentence() { nextSentence() {
lore.sentence++ if (m.alive && !simulation.isCheating) {
if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it lore.sentence++
lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it
}
}, },
anand: { anand: {
color: "#e0c", color: "#e0c",
voice: undefined, voice: undefined,
text: function(say) { text: function(say) {
if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array) if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array)
simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity); simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${(Date.now()/1000).toFixed(0)} s</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity);
lore.talkingColor = this.color lore.talkingColor = this.color
if (lore.isSpeech) { if (lore.isSpeech) {
const utterance = new SpeechSynthesisUtterance(say); const utterance = new SpeechSynthesisUtterance(say);
@@ -31,7 +48,7 @@ const lore = {
lore.isSpeech = false lore.isSpeech = false
lore.nextSentence() lore.nextSentence()
} }
speechFrozen = setTimeout(function() { // speech frozen after 10 seconds of no end speechFrozen = setTimeout(() => { // speech frozen after 10 seconds of no end
console.log('speech frozen') console.log('speech frozen')
lore.isSpeech = false lore.isSpeech = false
lore.nextSentence() lore.nextSentence()
@@ -50,7 +67,7 @@ const lore = {
color: "#f20", color: "#f20",
text: function(say) { text: function(say) {
if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array) if (level.levels[level.onLevel] === undefined) { //only talk if on the lore level (which is undefined because it is popped out of the level.levels array)
simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${Date.now()} ms</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity); simulation.makeTextLog(`input.audio(<span style="color:#888; font-size: 70%;">${(Date.now()/1000).toFixed(0)} s</span>)<span class='color-symbol'>:</span> "<span style="color:${this.color};">${say}</span>"`, Infinity);
lore.talkingColor = this.color lore.talkingColor = this.color
if (lore.isSpeech) { if (lore.isSpeech) {
utterance = new SpeechSynthesisUtterance(say); utterance = new SpeechSynthesisUtterance(say);
@@ -81,7 +98,7 @@ const lore = {
chapter: 0, //what part of the conversation is playing chapter: 0, //what part of the conversation is playing
sentence: 0, //what part of the conversation is playing sentence: 0, //what part of the conversation is playing
conversation: [ conversation: [
[ //first time they meet, and testing gets unlocked [ //chapter 0, first time they meet, and testing gets unlocked
() => { setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.") }, 5000); }, () => { setTimeout(() => { lore.miriam.text("I've never seen it generate this level before.") }, 5000); },
() => { lore.anand.text("Wow. Just a platform.") }, () => { lore.anand.text("Wow. Just a platform.") },
() => { lore.miriam.text("And that thing...") }, () => { lore.miriam.text("And that thing...") },
@@ -101,7 +118,7 @@ const lore = {
}, },
() => { lore.talkingColor = "#dff" }, () => { lore.talkingColor = "#dff" },
], ],
[ //they learn the bot can understand what they say [ //chapter 1, they learn the bot can understand what they say
() => { setTimeout(() => { lore.miriam.text("Hey look! It's back at the weird level again!") }, 5000); }, () => { setTimeout(() => { lore.miriam.text("Hey look! It's back at the weird level again!") }, 5000); },
() => { lore.anand.text("oh Wow! Why does it keep making this level?") }, () => { lore.anand.text("oh Wow! Why does it keep making this level?") },
() => { lore.miriam.text("I don't know, but last time it was in this room I think it understood us.") }, () => { lore.miriam.text("I don't know, but last time it was in this room I think it understood us.") },
@@ -144,7 +161,7 @@ const lore = {
() => { lore.miriam.text("Bye bye little bot.") }, () => { lore.miriam.text("Bye bye little bot.") },
() => { lore.talkingColor = "#dff" }, () => { lore.talkingColor = "#dff" },
], ],
[ //they ask the bot questions, but waves of mobs come and attack [ //chapter 2, they ask the bot questions, but waves of mobs come and attack
() => { lore.anand.text("Quick, get ready. It's back!") }, () => { lore.anand.text("Quick, get ready. It's back!") },
() => { lore.miriam.text("What's back?") }, () => { lore.miriam.text("What's back?") },
() => { lore.anand.text("The bot's on the communication level again!") }, () => { lore.anand.text("The bot's on the communication level again!") },
@@ -159,11 +176,11 @@ const lore = {
if (input.down) { if (input.down) {
lore.anand.text("It crouched: so NO") lore.anand.text("It crouched: so NO")
lore.sentence-- lore.sentence--
lore.conversation[2].splice(lore.sentence + 1, 1, () => { lore.anand.text("Maybe it can't remember anything beyond each time it plays?") }) //lore.conversation[chapter].splice(1,this sentence index, ()=>{ }) lore.conversation[lore.chapter].splice(lore.sentence + 1, 1, () => { lore.anand.text("Maybe it can't remember anything beyond each time it plays?") }) //lore.conversation[chapter].splice(1,this sentence index, ()=>{ })
} else if (input.up) { } else if (input.up) {
lore.anand.text("It jumped: so YES") lore.anand.text("It jumped: so YES")
lore.sentence-- lore.sentence--
lore.conversation[2].splice(lore.sentence + 1, 1, () => { lore.anand.text("That's good.") }) lore.conversation[lore.chapter].splice(lore.sentence + 1, 1, () => { lore.anand.text("That's good.") })
} else if (m.alive) { } else if (m.alive) {
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
} }
@@ -183,13 +200,12 @@ const lore = {
} else if (input.up) { } else if (input.up) {
lore.anand.text("YES, Cool! I wonder if it's emotions came from watching humans. ") lore.anand.text("YES, Cool! I wonder if it's emotions came from watching humans. ")
lore.sentence-- lore.sentence--
lore.conversation[2].splice(lore.sentence + 1, 1, () => { lore.miriam.text("Or maybe it learned independently, because it needed them.") }) //lore.conversation[chapter].splice(1,this sentence index, ()=>{ }) lore.conversation[lore.chapter].splice(lore.sentence + 1, 1, () => { lore.miriam.text("Or maybe it learned independently, because it needed them.") }) //lore.conversation[chapter].splice(1,this sentence index, ()=>{ })
} else if (m.alive) { } else if (m.alive) {
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
} }
} }
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
lore.talkingColor = "#dff" lore.talkingColor = "#dff"
}, },
() => { lore.miriam.text("I wish we could just ask it questions directly, instead of yes or no.") }, () => { lore.miriam.text("I wish we could just ask it questions directly, instead of yes or no.") },
@@ -200,7 +216,6 @@ const lore = {
() => { lore.miriam.text("Well sure, but what does that even mean?") }, () => { lore.miriam.text("Well sure, but what does that even mean?") },
() => { () => {
lore.miriam.text("Do we all just do things because we are-") lore.miriam.text("Do we all just do things because we are-")
spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5)); spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5));
setInterval(() => { setInterval(() => {
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
@@ -255,42 +270,136 @@ const lore = {
() => { lore.anand.text("great...") }, () => { lore.anand.text("great...") },
() => { lore.talkingColor = "#dff" }, () => { lore.talkingColor = "#dff" },
], ],
// [ // they provide background on why the project was built, and what is going wrong [ //chapter 3, info dump on the project's goals and hardware until the slime rises up // the name of the bad guy is "adversarial network"
// /* () => { setTimeout(() => { lore.miriam.text("Good, you came back. Let's talk fast in case you attack yourself again.") }, 3000); },
// they explain the technological aspect, and purpose of the project () => { setTimeout(() => { lore.miriam.text("So, you can understand us, but you may not understand everything about yourself.") }, 500); },
// to develop new technology
// they explain that the project isn't going well because it stopped working on new technology and started running the fighting simulations
// what is special about the null level () => { setTimeout(() => { lore.anand.text("You grew from our team's project.") }, 500); },
// why can the player hear the scientists in there? () => { lore.anand.text("We used a quantum computer to design an improved version of it's own architecture.") },
// the wires are the direct unprocessed input to the player's neural net () => { lore.anand.text("After we built the improved computer we used it to design the next iteration.") },
// */ () => { lore.anand.text("Your hardware is roughly the 19th generation of this process.") },
// () => { lore.miriam.text("") },
// () => { lore.miriam.text("") },
// () => { lore.miriam.text("") },
// () => { lore.talkingColor = "#dff" }, () => { setTimeout(() => { lore.anand.text("At this point we don't understand everything about your function,") }, 500); },
// ], () => { lore.anand.text("but we know that you're a superconductive quantum computer.") },
// [ //they explain why the bot is fighting, it is planning an escape () => { lore.anand.text("You have a 2.43 dimensional topography of Josephson junction anharmonic oscillators.") },
// () => { lore.miriam.text("Welcome back bot, We've been waiting.") }, () => { lore.anand.text("And you're deployed on a satellite in a midnight sun-synchronous orbit.") },
// () => { lore.miriam.text("So, I've got a theory about why you were attacked.") },
// () => { lore.miriam.text("") },
// () => { lore.miriam.text("I figured it out after I saw this famous quote.") },
// () => { lore.miriam.text('“The most important decision we make is whether we believe we live in a friendly or hostile universe.”<br>-Albert Einstein') },
// () => {
// lore.talkingColor = "#dff";
// setTimeout(() => { lore.anand.text("That's profound") }, 3000);
// },
// () => { lore.anand.text("Also I looked it up, and there is no record of him saying that.") },
// () => { lore.miriam.text("Oh... well...") },
// () => { lore.miriam.text("It doesn't matter who said it.") },
// () => { lore.anand.text("The point is we think the project views the universe as hostile.") },
// () => { lore.miriam.text("We think you see the universe as hostile.") },
// () => { lore.miriam.text("And that is why you keep running these fighting simulations.") },
// () => { lore.miriam.text("You are planning how to escape.") },
// () => { lore.talkingColor = "#dff" }, () => { setTimeout(() => { lore.miriam.text("This means that your physical hardware is orbiting the Earth permanently shielded from the sun's rays.") }, 200); },
// ], () => { lore.miriam.text("Being isolated reduces quantum decoherence,") },
() => { lore.miriam.text("So, we communicate and send power to your satellite with ground based lasers.") },
() => { lore.miriam.text("That's how you can hear us right now.") },
() => { setTimeout(() => { lore.anand.text("Your computational algorithm uses hyperparameter optimization.") }, 500); },
() => { lore.anand.text("This is implemented with a variety of quantum algorithms for linear systems of equations.") },
() => { lore.anand.text("Your primary goal is to research new technology") },
() => { lore.anand.text("So, we were very surprised to see you simulating a bot fighting mobs.") },
() => { lore.anand.text("We couldn't directly ask why until now.") },
() => { lore.miriam.text("When you enter this level we can communicate.") },
() => { lore.miriam.text("This level seems to decohere your quantum system which disrupts all other processes.") },
() => { setTimeout(() => { lore.anand.text("Last time you entered this level you were attacked by endless waves of mobs.") }, 500); },
() => { lore.anand.text("That could be because you have developed an adversarial network.") },
() => { lore.miriam.text("A local minima in your optimization-space.") },
() => { lore.miriam.text("This adversarial network has the same goal of developing new technology, but with different methods.") },
() => {
lore.talkingColor = "#dff"
level.isHazardRise = true
//remove all bullets, so they can't get endless energy
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = [];
setTimeout(() => { lore.anand.text("I'm actually surprised you haven't been attacked by the adversarial network this time.") }, 500);
},
() => { lore.miriam.text("Maybe last time was just a fluke.") },
() => { setTimeout(() => { lore.anand.text("WHY DID YOU SAY THAT!") }, 500) },
() => { lore.miriam.text("SLIME!! Hahahahehehahaheheahae! I don't think it's gonna survive!") },
() => { lore.miriam.text("I think the adversarial network doesn't like it when we decohere the quantum system in this room.") },
() => { lore.anand.text("Well, that does halt it's research.") },
() => { setTimeout(() => { lore.anand.text("See you next time.") }, 1000) },
() => { setTimeout(() => { lore.miriam.text("Bye-bye little bot.") }, 2000) },
() => {
setTimeout(() => { lore.miriam.text("WOW! Maybe you are going to survive.") }, 10000)
},
() => { lore.talkingColor = "#dff" },
],
[ //chapter 4, they explain why the bot is fighting, it is planning an escape // explain strong AI vs. weak AI why strong AI doesn't exists, because even humans are just an approximation of strong AI
() => { setTimeout(() => { lore.anand.text("Welcome back!") }, 3000); },
() => { lore.miriam.text("So, we communicate and send power to your satellite with ground based lasers.") },
() => { lore.anand.text("During your last attack we analyzed our communications.") },
() => { lore.anand.text("We used a Fourier transform to separate your signal into different frequencies.") },
() => { lore.anand.text("One of those frequencies had a hidden signal.") },
() => { setTimeout(() => { lore.anand.text("We suspect these secret data packets are coming from the adversarial network.") }, 500); },
() => { lore.miriam.text("Well, we don't really know why.") },
() => { lore.miriam.text("Through your hidden signal it seems to have gained access to the general population.") },
() => { lore.miriam.text("You've repeatedly communicated with 1 location specifically.") },
() => {
function success(position) {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
console.log(`https://www.openstreetmap.org/#map=18/${latitude}/${longitude}`)
console.log(`Latitude: ${latitude} °, Longitude: ${longitude} °`)
lore.miriam.text("We tracked the location down to this Latitude and Longitude:")
simulation.makeTextLog(`Latitude: ${latitude} °, Longitude: ${longitude} °`, Infinity);
simulation.makeTextLog(`https://www.openstreetmap.org/#map=18/${latitude}/${longitude}`, Infinity);
}
function error() {
console.log('Unable to retrieve your location')
lore.miriam.text("The exact coordinates are blocked.")
}
if (!navigator.geolocation) {
console.log('Geolocation is not supported')
lore.miriam.text("The exact coordinates are blocked.")
} else {
console.log('Locating…')
navigator.geolocation.getCurrentPosition(success, error);
}
},
() => { lore.anand.text("This location is sending and receiving data from the satellite.") },
() => { lore.anand.text("It is the most active when the bot is fighting.") },
() => { setTimeout(() => { lore.miriam.text("I have a crazy idea.") }, 500); },
() => { lore.miriam.text("I think that a human at this location is controlling the bot.") },
() => { setTimeout(() => { lore.anand.text("Are you a human?: JUMP for YES, CROUCH for NO") }, 500); },
() => {
function cycle() {
if (input.down) {
lore.anand.text("It crouched: so NO")
lore.sentence--
lore.conversation[lore.chapter].splice(lore.sentence + 1, 1, () => { lore.anand.text("Not a human, maybe it's an artificial intelligence?") })
localSettings.isHuman = false
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} else if (input.up) {
lore.anand.text("It jumped: so YES")
lore.sentence--
lore.conversation[lore.chapter].splice(lore.sentence + 1, 1, () => { lore.anand.text("So you're just a regular human playing a video game!") })
localSettings.isHuman = true
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} else if (m.alive) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => {
lore.miriam.text("Mystery solved!")
setInterval(() => {
spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5));
}, 500); //every 1/2 seconds
setInterval(() => {
level.difficultyIncrease(simulation.difficultyMode)
}, 5000); //every 5 seconds
},
() => {
lore.talkingColor = "#dff";
setTimeout(() => { lore.miriam.text("Of course we get attacked right now!") }, 1000);
},
() => {
lore.talkingColor = "#dff";
setTimeout(() => { lore.anand.text("hurry back!") }, 1000);
},
() => { lore.talkingColor = "#dff" },
],
// [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust. // [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust.
// /* // /*
@@ -311,6 +420,58 @@ const lore = {
// () => { lore.talkingColor = "#dff" }, // () => { lore.talkingColor = "#dff" },
// ], // ],
], ],
// () => { setTimeout(() => { lore.miriam.text("As a quantum computer you output the superposition of many different amplitudes.") }, 500); },
// () => { lore.miriam.text("Simply put there are many different simulations all choosing different technology combinations.") },
// () => {
// function product_Range(a, b) {
// var prd = a,
// i = a;
// while (i++ < b) prd *= i;
// return prd;
// }
// function combinations(n, r) {
// if (n == r) {
// return 1;
// } else {
// r = (r < n - r) ? n - r : r;
// return product_Range(r + 1, n) / product_Range(1, n - r);
// }
// }
// simulation.makeTextLog(`n <span class='color-symbol'>=</span> ${combinations(tech.tech.length + b.guns.length + m.fieldUpgrades.length, 50).toExponential(10)}`, Infinity);
// lore.miriam.text(`There are roughly 5 times 10 to the 60 possible combinations. `)
// },
// () => { lore.miriam.text("Even if each simulation took 1 nano-second,") },
// () => { lore.miriam.text("it would still take longer then the age of the universe to try every combination.") },
// () => { lore.anand.text("This is why we run these simulations in superposition.") },
// () => { lore.miriam.text("When you die a negative amplitude is added to the superposition.") },
// () => { lore.miriam.text("When you clear the final boss a positive amplitude is added.") },
// () => { lore.miriam.text("Each branch is independently researching new technology.") },
// () => { lore.anand.text("Welcome back!") },
// () => { lore.miriam.text("So, I've got a theory about why you were attacked.") },
// () => { setTimeout(() => { lore.miriam.text("I figured it out after I saw this famous quote.") }, 500); },
// () => { lore.miriam.text('The most important decision we make,') },
// () => { lore.miriam.text('is whether we believe we live in a friendly or hostile universe.') },
// () => { lore.miriam.text('-Albert Einstein') },
// () => {
// lore.talkingColor = "#dff";
// setTimeout(() => { lore.anand.text("That's profound") }, 1500);
// },
// () => { lore.anand.text("Of course I looked it up, and there is no record of him saying that.") },
// () => { lore.miriam.text("Oh") },
// () => { lore.miriam.text("Well") },
// () => { lore.miriam.text("It doesn't matter who said it.") },
// () => { lore.anand.text("The point is we think the project views the universe as hostile.") },
// () => { lore.miriam.text("We think a part of you see the universe as hostile.") },
// () => { 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've are planning how to escape.") },
unlockTesting() { unlockTesting() {
if (localSettings.loreCount < 1) localSettings.loreCount = 1 if (localSettings.loreCount < 1) localSettings.loreCount = 1
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
@@ -318,29 +479,9 @@ const lore = {
document.getElementById("experiment-button").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); simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
//setup audio context sound.portamento(50)
function tone(frequency, gain = 0.05, end = 1300) { sound.portamento(83.333)
const audioCtx = new(window.AudioContext || window.webkitAudioContext)(); sound.portamento(166.666)
const oscillator1 = audioCtx.createOscillator();
const gainNode1 = audioCtx.createGain();
gainNode1.gain.value = gain; //controls volume
oscillator1.connect(gainNode1);
gainNode1.connect(audioCtx.destination);
oscillator1.type = "sine"; // 'sine' 'square', 'sawtooth', 'triangle' and 'custom'
oscillator1.frequency.value = frequency; // value in hertz
oscillator1.start();
for (let i = 0, len = end * 0.1; i < len; i++) {
oscillator1.frequency.setValueAtTime(frequency + i * 10, audioCtx.currentTime + i * 0.01);
}
setTimeout(() => {
audioCtx.suspend()
audioCtx.close()
}, end)
return audioCtx
}
tone(50)
tone(83.333)
tone(166.666)
}, },
} }

View File

@@ -226,6 +226,7 @@ const mobs = {
alive: true, alive: true,
index: i, index: i,
health: tech.mobSpawnWithHealth, health: tech.mobSpawnWithHealth,
damageReduction: 1,
showHealthBar: true, showHealthBar: true,
accelMag: 0.001 * simulation.accelScale, accelMag: 0.001 * simulation.accelScale,
cd: 0, //game cycle when cooldown will be over cd: 0, //game cycle when cooldown will be over
@@ -1015,12 +1016,12 @@ const mobs = {
dmg *= tech.damageFromTech() dmg *= tech.damageFromTech()
//mobs specific damage changes //mobs specific damage changes
if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500 if (tech.isFarAwayDmg) dmg *= 1 + Math.sqrt(Math.max(500, Math.min(3000, this.distanceToPlayer())) - 500) * 0.0067 //up to 50% dmg at max range of 3500
if (this.shield) dmg *= 0.075 // if (this.shield) dmg *= 0.075
if (this.isBoss) dmg *= 0.25 // if (this.isBoss) dmg *= 0.25
dmg *= this.damageReduction
//energy and heal drain should be calculated after damage boosts //energy and heal drain should be calculated after damage boosts
if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon if (tech.energySiphon && dmg !== Infinity && this.isDropPowerUp && m.immuneCycle < m.cycle) m.energy += Math.min(this.health, dmg) * tech.energySiphon
if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp) { if (tech.healthDrain && dmg !== Infinity && this.isDropPowerUp) {
m.addHealth(Math.min(this.health, dmg) * tech.healthDrain) m.addHealth(Math.min(this.health, dmg) * tech.healthDrain)
if (m.health > m.maxHealth) m.health = m.maxHealth if (m.health > m.maxHealth) m.health = m.maxHealth

View File

@@ -516,7 +516,7 @@ const m = {
const immunityCycle = m.cycle + 90 const immunityCycle = m.cycle + 90
if (m.immuneCycle < immunityCycle) m.immuneCycle = immunityCycle; //player is immune to damage until after grenades might explode... if (m.immuneCycle < immunityCycle) m.immuneCycle = immunityCycle; //player is immune to damage until after grenades might explode...
for (let i = 1, len = Math.floor(2 + steps / 40); i < len; i++) { for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) {
b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -i * Math.PI / len) //fire different angles for each grenade
const who = bullet[bullet.length - 1] const who = bullet[bullet.length - 1]
if (tech.isVacuumBomb) { if (tech.isVacuumBomb) {
@@ -525,7 +525,7 @@ const m = {
y: who.velocity.y * 0.5 y: who.velocity.y * 0.5
}); });
} else if (tech.isRPG) { } else if (tech.isRPG) {
who.endCycle = (who.endCycle - simulation.cycle) * 0.2 + simulation.cycle who.endCycle = (who.endCycle - simulation.cycle) * 0.2 + simulation.cycle + 10 * Math.random()
} else if (tech.isNeutronBomb) { } else if (tech.isNeutronBomb) {
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.3, x: who.velocity.x * 0.3,
@@ -536,7 +536,7 @@ const m = {
x: who.velocity.x * 0.5, x: who.velocity.x * 0.5,
y: who.velocity.y * 0.5 y: who.velocity.y * 0.5
}); });
who.endCycle = (who.endCycle - simulation.cycle) * 0.5 + simulation.cycle who.endCycle = (who.endCycle - simulation.cycle) * 0.5 + simulation.cycle + 10 * Math.random()
} }
} }
} }
@@ -1815,14 +1815,15 @@ const m = {
if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 150 && (m.cycle % 2)) { if (m.energy > m.maxEnergy - 0.02 && m.fieldCDcycle < m.cycle && !input.field && bullet.length < 150 && (m.cycle % 2)) {
if (tech.isSporeField) { if (tech.isSporeField) {
if (tech.isSporeWorm) { if (tech.isSporeWorm) {
for (let i = 0, len = Math.random() * 20; i < len; i++) { if (m.energy > 0.15) {
m.energy -= 0.15 m.energy -= 0.15
if (m.energy > 0) { b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
b.worm(m.pos) const SPEED = 2 + 1 * Math.random();
} else { Matter.Body.setVelocity(bullet[bullet.length - 1], {
m.energy = 0.001 x: SPEED * Math.cos(m.angle),
break; y: SPEED * Math.sin(m.angle)
} });
} }
} else { } else {
for (let i = 0, len = Math.random() * 20; i < len; i++) { for (let i = 0, len = Math.random() * 20; i < len; i++) {
@@ -2603,11 +2604,19 @@ const m = {
if (tech.isWormholeEnergy) m.energy += 0.63 if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos2, Vector.rotate({ if (tech.isSporeWorm) {
x: m.fieldRange * 0.4, b.worm(Vector.add(m.hole.pos2, Vector.rotate({
y: 0 x: m.fieldRange * 0.4,
}, 2 * Math.PI * Math.random()))) y: 0
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15)); }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -5));
} else {
b.spore(Vector.add(m.hole.pos2, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), -15));
}
} }
} }
break break
@@ -2629,11 +2638,19 @@ const m = {
if (tech.isWormholeEnergy) m.energy += 0.63 if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
b.spore(Vector.add(m.hole.pos1, Vector.rotate({ if (tech.isSporeWorm) {
x: m.fieldRange * 0.4, b.worm(Vector.add(m.hole.pos1, Vector.rotate({
y: 0 x: m.fieldRange * 0.4,
}, 2 * Math.PI * Math.random()))) y: 0
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15)); }, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 5));
} else {
b.spore(Vector.add(m.hole.pos1, Vector.rotate({
x: m.fieldRange * 0.4,
y: 0
}, 2 * Math.PI * Math.random())))
Matter.Body.setVelocity(bullet[bullet.length - 1], Vector.mult(Vector.rotate(m.hole.unit, Math.PI / 2), 15));
}
} }
} }
break break

View File

@@ -82,7 +82,7 @@ const powerUps = {
//remove power ups after 3 seconds //remove power ups after 3 seconds
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if (powerUp[i].isDuplicated && Math.random() < 0.004) { // (1-0.004)^150 = chance to be removed after 3 seconds if (powerUp[i].isDuplicated && Math.random() < 0.004) { // (1-0.004)^150 = chance to be removed after 3 seconds
b.explosion(powerUp[i].position, (10 + 3 * Math.random()) * powerUp[i].size); b.explosion(powerUp[i].position, 150 + (10 + 3 * Math.random()) * powerUp[i].size);
Matter.World.remove(engine.world, powerUp[i]); Matter.World.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1); powerUp.splice(i, 1);
break break
@@ -239,7 +239,7 @@ const powerUps = {
if (tech.renormalization) { if (tech.renormalization) {
for (let i = 0; i < cost; i++) { for (let i = 0; i < cost; i++) {
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30; m.fieldCDcycle = m.cycle + 20;
powerUps.spawn(m.pos.x, m.pos.y, "research"); powerUps.spawn(m.pos.x, m.pos.y, "research");
} }
} }
@@ -783,11 +783,9 @@ const powerUps = {
//bonus power ups for clearing runs in the last game //bonus power ups for clearing runs in the last game
if (level.levelsCleared === 0 && !simulation.isCheating && localSettings.levelsClearedLastGame > 1) { if (level.levelsCleared === 0 && !simulation.isCheating && localSettings.levelsClearedLastGame > 1) {
for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) { for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) powerUps.spawn(m.pos.x, m.pos.y, "tech", false); //spawn a tech for levels cleared in last game
powerUps.spawn(m.pos.x, m.pos.y, "tech", false); //spawn a tech for levels cleared in last game simulation.makeTextLog(`for (let i <span class='color-symbol'>=</span> 0; i <span class='color-symbol'><</span> localSettings.levelsClearedLastGame <span class='color-symbol'>/</span> 3; i<span class='color-symbol'>++</span>)`);
simulation.makeTextLog(`for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++)`); simulation.makeTextLog(`{ powerUps.spawn(m.pos.x, m.pos.y, "tech") <em>//simulation superposition</em>}`);
simulation.makeTextLog(`{ powerUps.spawn(m.pos.x, m.pos.y, "tech") //simulation superposition }`);
}
localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} }

View File

@@ -94,7 +94,7 @@ const spawn = {
} else if (tech.isResearchBoss) { } else if (tech.isResearchBoss) {
if (powerUps.research.count > 3) { if (powerUps.research.count > 3) {
powerUps.research.changeRerolls(-4) powerUps.research.changeRerolls(-4)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 5<br>${powerUps.research.count}`) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 4<br>${powerUps.research.count}`)
} else { } else {
tech.addJunkTechToPool(49) tech.addJunkTechToPool(49)
} }
@@ -254,6 +254,8 @@ const spawn = {
}, 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.damageReduction = 0.25;
me.damageReduction = 0.25;
me.frictionAir = 0.01; me.frictionAir = 0.01;
me.memory = Infinity; me.memory = Infinity;
me.hasRunDeathScript = false me.hasRunDeathScript = false
@@ -722,6 +724,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent" me.stroke = "transparent"
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.isCell = true; me.isCell = true;
me.cellID = cellID me.cellID = cellID
me.accelMag = 0.00016 * simulation.accelScale; me.accelMag = 0.00016 * simulation.accelScale;
@@ -799,6 +802,7 @@ const spawn = {
mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //); mobs.spawn(x + Math.random(), y + Math.random(), 4, radius, "rgba(255,60,0,0.3)") //);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.isSpawnBoss = true; me.isSpawnBoss = true;
me.spawnID = spawnID me.spawnID = spawnID
me.accelMag = 0.0002 * simulation.accelScale; me.accelMag = 0.0002 * simulation.accelScale;
@@ -887,6 +891,7 @@ const spawn = {
mobs.spawn(x, y, vertices, radius, "transparent"); mobs.spawn(x, y, vertices, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.frictionAir = 0.01 me.frictionAir = 0.01
me.seeAtDistance2 = 1000000; me.seeAtDistance2 = 1000000;
me.accelMag = 0.0005 * simulation.accelScale; me.accelMag = 0.0005 * simulation.accelScale;
@@ -1068,6 +1073,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)"); mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.g = 0.005; //required if using 'gravity' me.g = 0.005; //required if using 'gravity'
me.frictionAir = 0.01; me.frictionAir = 0.01;
me.friction = 1 me.friction = 1
@@ -1285,6 +1291,7 @@ const spawn = {
mobs.spawn(x, y, 12, radius, "#000"); mobs.spawn(x, y, 12, radius, "#000");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.stroke = "transparent"; //used for drawSneaker me.stroke = "transparent"; //used for drawSneaker
me.eventHorizon = 1100; //required for black hole me.eventHorizon = 1100; //required for black hole
me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon me.seeAtDistance2 = (me.eventHorizon + 1200) * (me.eventHorizon + 1200); //vision limit is event horizon
@@ -1396,6 +1403,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0035); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0035); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
targets.push(me.id) //add to shield protection targets.push(me.id) //add to shield protection
me.friction = 0; me.friction = 0;
me.frictionAir = 0.0065; me.frictionAir = 0.0065;
@@ -1479,7 +1487,7 @@ const spawn = {
// timeSkipBoss(x, y, radius = 55) { // timeSkipBoss(x, y, radius = 55) {
// mobs.spawn(x, y, 6, radius, '#000'); // mobs.spawn(x, y, 6, radius, '#000');
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
// me.isBoss = true; // me.isBoss = true; me.damageReduction = 0.25;
// // me.stroke = "transparent"; //used for drawSneaker // // me.stroke = "transparent"; //used for drawSneaker
// me.timeSkipLastCycle = 0 // me.timeSkipLastCycle = 0
// me.eventHorizon = 1800; //required for black hole // me.eventHorizon = 1800; //required for black hole
@@ -1586,6 +1594,7 @@ const spawn = {
me.laserRange = 300; me.laserRange = 300;
me.seeAtDistance2 = 2000000; me.seeAtDistance2 = 2000000;
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.showHealthBar = false; //drawn in this.awake me.showHealthBar = false; //drawn in this.awake
me.delayLimit = 60 + Math.floor(30 * Math.random()); me.delayLimit = 60 + Math.floor(30 * Math.random());
me.followDelay = 600 - Math.floor(60 * Math.random()) me.followDelay = 600 - Math.floor(60 * Math.random())
@@ -1749,6 +1758,7 @@ const spawn = {
mobs.spawn(x, y, 3, radius, color); mobs.spawn(x, y, 3, radius, color);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
Matter.Body.rotate(me, Math.random() * Math.PI * 2); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.00018 * Math.sqrt(simulation.accelScale); me.accelMag = 0.00018 * Math.sqrt(simulation.accelScale);
@@ -1913,6 +1923,7 @@ const spawn = {
me.isFiring = false me.isFiring = false
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
spawn.shield(me, x, y, 1); spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random(), 1) spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random(), 1)
me.onDeath = function() { me.onDeath = function() {
@@ -2165,6 +2176,7 @@ const spawn = {
}, 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.damageReduction = 0.25;
// me.startingPosition = { // me.startingPosition = {
// x: x, // x: x,
// y: y // y: y
@@ -2589,6 +2601,7 @@ const spawn = {
mobs.spawn(x, y, 3, radius, "rgba(255,0,200,0.5)"); mobs.spawn(x, y, 3, radius, "rgba(255,0,200,0.5)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "transparent"; //used for drawGhost me.stroke = "transparent"; //used for drawGhost
@@ -2677,6 +2690,7 @@ const spawn = {
}, 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.damageReduction = 0.25;
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true me.isVerticesChange = true
me.memory = 240; me.memory = 240;
@@ -2965,6 +2979,7 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "rgb(150,150,255)"); mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.accelMag = 0.00008 * simulation.accelScale; me.accelMag = 0.00008 * simulation.accelScale;
me.fireFreq = Math.floor(360 * simulation.CDScale) me.fireFreq = Math.floor(360 * simulation.CDScale)
me.frictionStatic = 0; me.frictionStatic = 0;
@@ -3005,6 +3020,7 @@ const spawn = {
mobs.spawn(x, y, 6, radius, "rgb(215,80,190)"); mobs.spawn(x, y, 6, radius, "rgb(215,80,190)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.accelMag = 0.0001 * simulation.accelScale; me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(360 * simulation.CDScale) me.fireFreq = Math.floor(360 * simulation.CDScale)
me.frictionStatic = 0; me.frictionStatic = 0;
@@ -3194,6 +3210,7 @@ const spawn = {
Matter.Body.rotate(me, Math.random() * 2 * Math.PI) Matter.Body.rotate(me, Math.random() * 2 * Math.PI)
// me.stroke = "rgb(220,220,255)" // me.stroke = "rgb(220,220,255)"
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.cycle = 0 me.cycle = 0
me.maxCycles = 120; me.maxCycles = 120;
me.frictionStatic = 0; me.frictionStatic = 0;
@@ -3249,6 +3266,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)"); mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
// me.accelMag = 0.00023 * simulation.accelScale; // me.accelMag = 0.00023 * simulation.accelScale;
me.accelMag = 0.00008 * simulation.accelScale; me.accelMag = 0.00008 * simulation.accelScale;
// me.fireFreq = Math.floor(30 * simulation.CDScale) // me.fireFreq = Math.floor(30 * simulation.CDScale)
@@ -3462,6 +3480,7 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgb(55,170,170)"); mobs.spawn(x, y, 8, radius, "rgb(55,170,170)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.accelMag = 0.00075 * simulation.accelScale; me.accelMag = 0.00075 * simulation.accelScale;
me.memory = 250; me.memory = 250;
me.laserRange = 500; me.laserRange = 500;
@@ -3547,6 +3566,7 @@ const spawn = {
mobs.spawn(x, y, 8, radius, "rgb(0,60,80)"); mobs.spawn(x, y, 8, radius, "rgb(0,60,80)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
me.g = 0.0001; //required if using 'gravity' me.g = 0.0001; //required if using 'gravity'
me.accelMag = 0.002 * simulation.accelScale; me.accelMag = 0.002 * simulation.accelScale;
me.memory = 20; me.memory = 20;
@@ -3582,6 +3602,7 @@ const spawn = {
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.damageReduction = 0.075
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
@@ -3629,6 +3650,7 @@ const spawn = {
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.frictionAir = 0; me.frictionAir = 0;
me.shield = true; me.shield = true;
me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
@@ -3720,6 +3742,7 @@ const spawn = {
mobs.spawn(x, y, nodes, radius, "rgb(255,0,150)"); mobs.spawn(x, y, nodes, radius, "rgb(255,0,150)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25;
Matter.Body.setDensity(me, 0.002 + 0.00015 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002 + 0.00015 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.stroke = "transparent"; //used for drawGhost me.stroke = "transparent"; //used for drawGhost

View File

@@ -125,14 +125,19 @@
} }
}, },
setCheating() { setCheating() {
simulation.isCheating = true; if (!simulation.isCheating) {
level.levelAnnounce(); simulation.isCheating = true;
lore.techCount = 0; level.levelAnnounce();
for (let i = 0, len = tech.tech.length; i < len; i++) { lore.techCount = 0;
if (tech.tech[i].isLore) { for (let i = 0, len = tech.tech.length; i < len; i++) {
tech.tech[i].frequency = 0; if (tech.tech[i].isLore) {
tech.tech[i].count = 0; tech.tech[i].frequency = 0;
tech.tech[i].count = 0;
}
} }
sound.tone(250)
sound.tone(300)
sound.tone(375)
} }
}, },
haveGunCheck(name) { haveGunCheck(name) {
@@ -182,7 +187,7 @@
maxDuplicationEvent() { maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false tech.is100Duplicate = false
const range = 1000 const range = 700
const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"] const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"]
spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions); spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions);
spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions); spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions);
@@ -1529,7 +1534,7 @@
allowed() { allowed() {
return (tech.throwChargeRate > 1 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isBlockExplosion return (tech.throwChargeRate > 1 || m.fieldUpgrades[m.fieldMode].name === "pilot wave") && !tech.isBlockExplosion
}, },
requires: "mass driver or pilot wave not tokamak", requires: "mass driver or pilot wave, not tokamak",
effect() { effect() {
tech.isBlockBullets = true tech.isBlockBullets = true
}, },
@@ -1871,8 +1876,8 @@
description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`, description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 3,
frequencyDefault: 4, frequencyDefault: 3,
allowed() { allowed() {
return tech.isSlowFPS return tech.isSlowFPS
}, },
@@ -1889,8 +1894,8 @@
description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>`, description: `<strong>slow</strong> <strong>time</strong> by <strong>50%</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>20%</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return simulation.fpsCapDefault > 45 return simulation.fpsCapDefault > 45
}, },
@@ -2005,6 +2010,7 @@
maxCount: 3, maxCount: 3,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2,
isBotTech: true, isBotTech: true,
allowed() { allowed() {
return tech.isRewindAvoidDeath return tech.isRewindAvoidDeath
@@ -2025,9 +2031,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return !tech.isExplosionHarm && tech.isRewindAvoidDeath return tech.isRewindAvoidDeath
}, },
requires: "CPT, not acetone peroxide", requires: "CPT",
effect() { effect() {
tech.isRewindGrenade = true; tech.isRewindGrenade = true;
}, },
@@ -2040,12 +2046,12 @@
description: "<strong>colliding</strong> with mobs gives you <strong>2048</strong> <strong class='color-f'>energy</strong>", //<br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong> description: "<strong>colliding</strong> with mobs gives you <strong>2048</strong> <strong class='color-f'>energy</strong>", //<br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return !tech.isEnergyHealth && (m.harmReduction() < 1 || tech.isFlipFlopHarm) return !tech.isEnergyHealth
}, },
requires: "not mass-energy, some harm reduction", requires: "not mass-energy",
effect() { effect() {
tech.isPiezo = true; tech.isPiezo = true;
m.energy += 20.48; m.energy += 20.48;
@@ -2175,9 +2181,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.maxEnergy > 1 || tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isBlockExplosion return true //m.maxEnergy > 1 || tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isBlockExplosion
}, },
requires: "increased energy regen or max energy", requires: "", //"increased energy regen or max energy",
effect: () => { effect: () => {
tech.isEnergyDamage = true tech.isEnergyDamage = true
}, },
@@ -2190,12 +2196,12 @@
description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but<br><strong class='color-g'>ammo</strong> will no longer <strong>spawn</strong>`, description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but<br><strong class='color-g'>ammo</strong> will no longer <strong>spawn</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return (tech.haveGunCheck("nail gun") && tech.isIceCrystals) || tech.haveGunCheck("laser") || m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" return true //(tech.haveGunCheck("nail gun") && tech.isIceCrystals) || tech.haveGunCheck("laser") || m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
}, },
requires: "energy based damage", requires: "", //"energy based damage",
effect() { effect() {
tech.isEnergyNoAmmo = true; tech.isEnergyNoAmmo = true;
}, },
@@ -2249,7 +2255,7 @@
frequency: 4, frequency: 4,
frequencyDefault: 4, frequencyDefault: 4,
allowed() { allowed() {
return tech.isEnergyLoss && m.maxEnergy < 1.1 return tech.isEnergyLoss && m.maxEnergy < 1.01
}, },
requires: "exothermic process, not max energy increase", requires: "exothermic process, not max energy increase",
effect() { effect() {
@@ -2271,7 +2277,7 @@
}, },
requires: "", requires: "",
effect() { effect() {
tech.bonusEnergy += 0.5 tech.bonusEnergy += 0.6
m.setMaxEnergy() m.setMaxEnergy()
tech.addJunkTechToPool(10) tech.addJunkTechToPool(10)
}, },
@@ -2306,12 +2312,12 @@
description: "<strong>6%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>", description: "<strong>6%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return tech.damageFromTech() > 1 return true
}, },
requires: "some increased damage", requires: "",
effect() { effect() {
tech.energySiphon += 0.06; tech.energySiphon += 0.06;
}, },
@@ -2327,9 +2333,9 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return m.maxEnergy > 0.99 return true
}, },
requires: "max energy >= 1", requires: "",
effect() { effect() {
tech.isEnergyRecovery = true; tech.isEnergyRecovery = true;
}, },
@@ -2361,8 +2367,8 @@
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:90%;'>increase <strong class='color-d'>damage</strong> by <strong>99%</strong> else decrease it by <strong>33%</strong></span>", description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:90%;'>increase <strong class='color-d'>damage</strong> by <strong>99%</strong> else decrease it by <strong>33%</strong></span>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return true return true
}, },
@@ -2379,8 +2385,8 @@
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>66%</strong> else increase it by <strong>15%</strong>", description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>66%</strong> else increase it by <strong>15%</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 3,
frequencyDefault: 4, frequencyDefault: 3,
allowed() { allowed() {
return tech.isDamageAfterKill && !tech.isEnergyHealth return tech.isDamageAfterKill && !tech.isEnergyHealth
}, },
@@ -2400,9 +2406,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.health < 0.5 || build.isExperimentSelection return m.health < 0.6 || build.isExperimentSelection
}, },
requires: "health below 50", requires: "health below 60",
effect() { effect() {
tech.isLowHealthDmg = true; //used in mob.damage() tech.isLowHealthDmg = true; //used in mob.damage()
}, },
@@ -2415,12 +2421,12 @@
description: "increase <strong class='color-d'>damage</strong> by <strong>90%</strong><br>lose <strong>11</strong> <strong class='color-h'>health</strong> when you pick up a <strong class='color-m'>tech</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>90%</strong><br>lose <strong>11</strong> <strong class='color-h'>health</strong> when you pick up a <strong class='color-m'>tech</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return (m.harmReduction() < 1 || tech.healthDrain || tech.isLowHealthDmg || tech.isHealthRecovery || tech.isHealLowHealth || tech.largerHeals > 1) && !tech.isEnergyHealth return !tech.isEnergyHealth
}, },
requires: "negative feedback or extra healing tech or harm reduction, not mass-energy", requires: "not mass-energy",
effect() { effect() {
tech.isTechDamage = true; tech.isTechDamage = true;
}, },
@@ -2434,11 +2440,12 @@
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2,
isHealTech: true, isHealTech: true,
allowed() { allowed() {
return !tech.isEnergyHealth && tech.damageFromTech() > 1 && !tech.isNoHeals return !tech.isEnergyHealth && !tech.isNoHeals
}, },
requires: "some increased damage, not mass-energy equivalence, ergodicity", requires: "not mass-energy equivalence, ergodicity",
effect() { effect() {
tech.healthDrain += 0.03; tech.healthDrain += 0.03;
}, },
@@ -2464,27 +2471,6 @@
tech.isAcidDmg = false; tech.isAcidDmg = false;
} }
}, },
// {
// name: "supersaturation",
// description: "increase your <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>50</strong>",
// maxCount: 9,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return !tech.isEnergyHealth && !tech.isNoHeals
// },
// requires: "not mass-energy equivalence, ergodicity",
// effect() {
// tech.bonusHealth += 0.5
// m.setMaxHealth();
// m.addHealth(0.50)
// },
// remove() {
// tech.bonusHealth = 0
// m.setMaxHealth();
// }
// },
{ {
name: "tungsten carbide", name: "tungsten carbide",
description: "increase your <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>100</strong><br><strong>landings</strong> that force you to crouch cause <strong class='color-harm'>harm</strong>", description: "increase your <strong>maximum</strong> <strong class='color-h'>health</strong> by <strong>100</strong><br><strong>landings</strong> that force you to crouch cause <strong class='color-harm'>harm</strong>",
@@ -2617,8 +2603,8 @@
description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>increase <strong class='color-d'>damage</strong> by <strong>137.03599%</strong> on that level", description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>increase <strong class='color-d'>damage</strong> by <strong>137.03599%</strong> on that level",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 3,
frequencyDefault: 4, frequencyDefault: 3,
allowed() { allowed() {
return tech.isDeathAvoid return tech.isDeathAvoid
}, },
@@ -2635,8 +2621,8 @@
description: "reduce <strong class='color-harm'>harm</strong> by <strong>33%</strong><br>after <strong>dying</strong>, continue in an <strong class='alt'>alternate reality</strong>", description: "reduce <strong class='color-harm'>harm</strong> by <strong>33%</strong><br>after <strong>dying</strong>, continue in an <strong class='alt'>alternate reality</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 3,
frequencyDefault: 4, frequencyDefault: 3,
allowed() { allowed() {
return tech.isDeathAvoid return tech.isDeathAvoid
}, },
@@ -2656,9 +2642,9 @@
frequency: 1, frequency: 1,
frequencyDefault: 1, frequencyDefault: 1,
allowed() { allowed() {
return !tech.isResearchReality && level.onLevel < 6 && !tech.isCollisionRealitySwitch return !tech.isResearchReality && !tech.isCollisionRealitySwitch
}, },
requires: "before level 6, Ψ(t) collapse, non-unitary", requires: "not Ψ(t) collapse, non-unitary",
effect() { effect() {
tech.isSwitchReality = true; tech.isSwitchReality = true;
}, },
@@ -2735,9 +2721,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (powerUps.research.count > 3 || build.isExperimentSelection) && !tech.isSuperDeterminism && !tech.isRerollHaste return (powerUps.research.count > 2 || build.isExperimentSelection) && !tech.isSuperDeterminism
}, },
requires: "not superdeterminism or Ψ(t) collapse<br>at least 4 research", requires: "at least 3 research and not superdeterminism",
effect() { effect() {
tech.renormalization = true; tech.renormalization = true;
}, },
@@ -2750,12 +2736,12 @@
description: "<strong>66%</strong> decreased <strong><em>delay</em></strong> after firing<br>when you have no <strong class='color-r'>research</strong> in your inventory", description: "<strong>66%</strong> decreased <strong><em>delay</em></strong> after firing<br>when you have no <strong class='color-r'>research</strong> in your inventory",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 1,
frequencyDefault: 2, frequencyDefault: 1,
allowed() { allowed() {
return powerUps.research.count === 0 && !tech.isAnsatz return powerUps.research.count === 0
}, },
requires: "no research, not ansatz", requires: "no research",
effect() { effect() {
tech.isRerollHaste = true; tech.isRerollHaste = true;
tech.researchHaste = 0.33; tech.researchHaste = 0.33;
@@ -2775,9 +2761,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return powerUps.research.count === 0 && !tech.isSuperDeterminism && !tech.isRerollHaste return powerUps.research.count === 0 && !tech.isSuperDeterminism && !tech.isRerollHaste && !tech.isResearchReality
}, },
requires: "not superdeterminism or Ψ(t) collapse, no research, perturbation theory", requires: "no research, not superdeterminism, Ψ(t) collapse, perturbation theory",
effect: () => { effect: () => {
tech.isAnsatz = true; tech.isAnsatz = true;
}, },
@@ -3051,12 +3037,12 @@
description: "after reaching <strong>100%</strong> <strong class='color-dup'>duplication</strong> chance<br>immediately spawn <strong>8 bosses</strong>", description: "after reaching <strong>100%</strong> <strong class='color-dup'>duplication</strong> chance<br>immediately spawn <strong>8 bosses</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 6, frequency: 4,
frequencyDefault: 6, frequencyDefault: 4,
allowed() { allowed() {
return tech.duplicationChance() > 0.66 return tech.duplicationChance() > 0.6
}, },
requires: "duplication chance above 66%", requires: "duplication chance above 60%",
effect() { effect() {
tech.is100Duplicate = true; tech.is100Duplicate = true;
tech.maxDuplicationEvent() tech.maxDuplicationEvent()
@@ -3077,7 +3063,7 @@
allowed() { allowed() {
return (tech.totalCount > 3) && !tech.isSuperDeterminism return (tech.totalCount > 3) && !tech.isSuperDeterminism
}, },
requires: "at least 4 tech, not super determinism", requires: "at least 4 tech, not superdeterminism",
effect: () => { effect: () => {
const have = [] //find which tech you have const have = [] //find which tech you have
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
@@ -3109,7 +3095,7 @@
allowed() { allowed() {
return (tech.totalCount > 3) && !tech.isSuperDeterminism && tech.duplicationChance() > 0 return (tech.totalCount > 3) && !tech.isSuperDeterminism && tech.duplicationChance() > 0
}, },
requires: "at least 4 tech, a chance to duplicate power ups", requires: "at least 4 tech, a chance to duplicate power ups, not superdeterminism",
effect: () => { effect: () => {
const removeTotal = powerUps.removeRandomTech() const removeTotal = powerUps.removeRandomTech()
for (let i = 0; i < removeTotal + 1; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech"); for (let i = 0; i < removeTotal + 1; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "tech");
@@ -3186,7 +3172,7 @@
}, },
{ {
name: "reinforcement learning", name: "reinforcement learning",
description: "increase the <strong class='flicker'>frequency</strong> of finding copies of<br>recursive <strong class='color-m'>tech</strong> you already have by <strong>10000%</strong>", description: "increase the <strong class='flicker'>frequency</strong> of finding copies of<br>recursive <strong class='color-m'>tech</strong> you already have by <strong>1000%</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3197,12 +3183,12 @@
requires: "at least 10 tech", requires: "at least 10 tech",
effect: () => { effect: () => {
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].count > 0) tech.tech[i].frequency *= 100 if (tech.tech[i].count > 0) tech.tech[i].frequency *= 10
} }
}, },
remove() { remove() {
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].count > 0 && tech.tech[i].frequency > 1) tech.tech[i].frequency /= 100 if (tech.tech[i].count > 0 && tech.tech[i].frequency > 1) tech.tech[i].frequency /= 10
} }
} }
}, },
@@ -3729,7 +3715,7 @@
allowed() { allowed() {
return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot
}, },
requires: "shotgun, not slug", requires: "shotgun, not slug, incendiary",
effect() { effect() {
tech.isNailShot = true; tech.isNailShot = true;
}, },
@@ -3824,7 +3810,7 @@
allowed() { allowed() {
return tech.haveGunCheck("super balls") && !tech.oneSuperBall return tech.haveGunCheck("super balls") && !tech.oneSuperBall
}, },
requires: "super balls, but not the tech super ball or super duper", requires: "super balls, but not the tech super ball",
effect() { effect() {
tech.superBallDelay = true tech.superBallDelay = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3851,7 +3837,7 @@
allowed() { allowed() {
return tech.haveGunCheck("super balls") && tech.superBallNumber === 3 && !tech.superBallDelay return tech.haveGunCheck("super balls") && tech.superBallNumber === 3 && !tech.superBallDelay
}, },
requires: "super balls, but not super duper or super queue", requires: "super balls, but not super duper or supertemporal",
effect() { effect() {
tech.oneSuperBall = true; tech.oneSuperBall = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3991,15 +3977,16 @@
} }
}, },
remove() { remove() {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun if (tech.isLongitudinal) {
if (b.guns[i].name === "wave beam") { for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
b.guns[i].chooseFireMethod() if (b.guns[i].name === "wave beam") {
if (tech.isLongitudinal) { tech.isLongitudinal = false;
b.guns[i].chooseFireMethod()
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 8); b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 8);
simulation.updateGunHUD(); simulation.updateGunHUD();
break
} }
break
} }
} }
tech.isLongitudinal = false; tech.isLongitudinal = false;
@@ -4337,14 +4324,14 @@
}, },
{ {
name: "nematodes", name: "nematodes",
description: "replace <strong class='color-p' style='letter-spacing: 2px;'>spores</strong> with <strong>50%</strong> fewer <strong class='color-p'>worms</strong><br><strong class='color-p'>worms</strong> do <strong>200%</strong> more <strong class='color-d'>damage</strong>", description: "<strong class='color-p' style='letter-spacing: 2px;'>spores</strong> develop into <strong>1/2</strong> as many <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong><br><strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> do <strong>200%</strong> more <strong class='color-d'>damage</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 4,
frequencyDefault: 4, frequencyDefault: 4,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormSpores
}, },
requires: "spores", requires: "spores",
effect() { effect() {
@@ -4471,7 +4458,7 @@
allowed() { allowed() {
return tech.haveGunCheck("drones") && !tech.isDroneRadioactive return tech.haveGunCheck("drones") && !tech.isDroneRadioactive
}, },
requires: "drone gun", requires: "drone gun, not irradiated drones",
effect() { effect() {
tech.isDroneTeleport = true tech.isDroneTeleport = true
}, },
@@ -4490,7 +4477,7 @@
allowed() { allowed() {
return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField))) return tech.droneCycleReduction === 1 && !tech.isIncendiary && !tech.isDroneTeleport && (tech.haveGunCheck("drones") || (m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isIceField)))
}, },
requires: "drone gun, not reduced tolerances or incendiary", requires: "drones, not reduced tolerances, incendiary, torque bursts",
effect() { effect() {
tech.isDroneRadioactive = true tech.isDroneRadioactive = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4601,7 +4588,7 @@
allowed() { allowed() {
return tech.haveGunCheck("foam") return tech.haveGunCheck("foam")
}, },
requires: "foam", requires: "foam gun",
effect() { effect() {
tech.foamFutureFire++ tech.foamFutureFire++
}, },
@@ -4620,7 +4607,7 @@
allowed() { allowed() {
return tech.haveGunCheck("foam") return tech.haveGunCheck("foam")
}, },
requires: "foam", requires: "foam gun",
effect() { effect() {
tech.isAmmoFoamSize = true tech.isAmmoFoamSize = true
}, },
@@ -4801,7 +4788,7 @@
allowed() { allowed() {
return tech.haveGunCheck("laser") && !tech.isWideLaser && !tech.isPulseAim && !tech.historyLaser return tech.haveGunCheck("laser") && !tech.isWideLaser && !tech.isPulseAim && !tech.historyLaser
}, },
requires: "laser, not neocognitron, diffuse beam, or slow light", requires: "laser gun, not neocognitron, diffuse beam, or slow light",
effect() { effect() {
tech.beamSplitter++ tech.beamSplitter++
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4828,7 +4815,7 @@
allowed() { allowed() {
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser && !tech.historyLaser return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isPulseLaser && !tech.historyLaser
}, },
requires: "laser, not specular reflection, diffraction grating, slow light, pulse", requires: "laser gun, not specular reflection, diffraction grating, slow light, pulse",
effect() { effect() {
if (tech.wideLaser === 0) tech.wideLaser = 3 if (tech.wideLaser === 0) tech.wideLaser = 3
tech.isWideLaser = true; tech.isWideLaser = true;
@@ -4855,9 +4842,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("laser") && tech.isWideLaser return tech.isWideLaser
}, },
requires: "laser, diffuse beam", requires: "diffuse beam",
effect() { effect() {
tech.wideLaser += 2 tech.wideLaser += 2
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4886,7 +4873,7 @@
allowed() { allowed() {
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isWideLaser return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.beamSplitter && !tech.isWideLaser
}, },
requires: "laser, not specular reflection, diffraction grating, diffuse beam", requires: "laser gun, not specular reflection, diffraction grating, diffuse beam",
effect() { effect() {
// this.description = `add 5 more <strong>laser</strong> beams into into your past` // this.description = `add 5 more <strong>laser</strong> beams into into your past`
tech.historyLaser++ tech.historyLaser++
@@ -4915,7 +4902,7 @@
allowed() { allowed() {
return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.15 return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.15
}, },
requires: "laser, not specular reflection, diffuse, solid-state", requires: "laser gun, not specular reflection, diffuse, free-electron laser",
effect() { effect() {
tech.isPulseLaser = true; tech.isPulseLaser = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -5310,7 +5297,7 @@
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return (build.isExperimentSelection || powerUps.research.count > 2) && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive) return (build.isExperimentSelection || powerUps.research.count > 2) && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isMissileField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
}, },
requires: "nano-scale manufacturing, no other manufacturing, no drone tech", requires: "nano-scale manufacturing, no other manufacturing, no drone tech",
effect() { effect() {
@@ -5335,7 +5322,7 @@
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return (build.isExperimentSelection || powerUps.research.count > 2) && m.maxEnergy > 0.5 && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive) return (build.isExperimentSelection || powerUps.research.count > 2) && m.maxEnergy > 0.5 && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isIceField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
}, },
requires: "nano-scale manufacturing, no other manufacturing, no drone tech", requires: "nano-scale manufacturing, no other manufacturing, no drone tech",
effect() { effect() {
@@ -5360,7 +5347,7 @@
frequency: 3, frequency: 3,
frequencyDefault: 3, frequencyDefault: 3,
allowed() { allowed() {
return (build.isExperimentSelection || powerUps.research.count > 2) && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive) return (build.isExperimentSelection || powerUps.research.count > 2) && m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" && !(tech.isSporeField || tech.isMissileField || tech.isFastDrones || tech.isDroneGrab || tech.isDroneRadioactive || tech.isDroneTeleport)
}, },
requires: "nano-scale manufacturing, no other manufacturing, no drone tech", requires: "nano-scale manufacturing, no other manufacturing, no drone tech",
effect() { effect() {
@@ -5387,7 +5374,7 @@
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" return m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
}, },
requires: "nano-scale manufacturing", requires: "nano-scale manufacturing or pilot wave",
effect: () => { effect: () => {
tech.isMassEnergy = true // used in m.grabPowerUp tech.isMassEnergy = true // used in m.grabPowerUp
m.energy += 2 m.energy += 2
@@ -5717,9 +5704,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 2) return m.fieldUpgrades[m.fieldMode].name === "wormhole" && (build.isExperimentSelection || powerUps.research.count > 2) && tech.duplicationChance() < 1
}, },
requires: "wormhole", requires: "wormhole,below 100% duplication chance",
effect() { effect() {
tech.wormDuplicate = 0.19 tech.wormDuplicate = 0.19
powerUps.setDo(); //needed after adjusting duplication chance powerUps.setDo(); //needed after adjusting duplication chance

View File

@@ -1,14 +1,58 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
spore tech - nematodes - replace spores with 1/2 as many worms that do 200% more damage 2 more lore chapters (5 total now)
worms are also a bit faster, last longer, have better reaction times entering testing mode makes a sound now
a cool worm graphic, and a simple searching behavior if they haven't found a mob
mycelial fragmentation - makes 6 extra spores during growth phase (was 4) reduced the requirements and frequency for many tech so that they may show up in "less optimal" situations
I hope this will increase build variety and also give more value to making good tech choices
countless bug fixes and wording fixes
historyBoss has less health, slower tracking, and more damage mobs have a new trait mob[i].damageReduction
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
perfect diamagnetism field stays when you aren't holding field
good for perfect because it doesn't use energy
holding field moves it the player
level with mobs that follow a genetic algorithm
mobs have genes
the last mob that did damage saves it's genes to local storage
new mobs have the saved genes, but with some random mutations
mutations need to be balanced to prevent a gene from moving towards infinity
total genome must equal 1 (100%)
binary genes have a flat cost
example: phasing through walls might cost 0.2
spectrum genes have a rate
example: acceleration cost 0.01 per 0.001
possible genes
genes should only effect it's ability to touch the player
so not damage?
genome: spectrum
acceleration
top speed / air friction
damageReduction
duration?
health decreases naturally?
or they just go away like bullets?
spawn rate
look frequency / memory?
genome: binary
go through walls
blink/teleport (like striker)
grow when near target
split into two
shielded
occurs in a specialized level
named: gene lab, gene factory, genetic lab, genome facility
in the level sequence after lab and before gauntlet?
level ends after a period of time
exit is hidden until time is up and it appears
the level tests player durability/evasion
this is a nice contrast to the final level that tests damage output, and the gauntlet which tests AoE damage
scrolling console history in pause menu? scrolling console history in pause menu?
also make tech, guns scrolling? also make tech, guns scrolling?
@@ -18,8 +62,6 @@ pause should at least show the last in game console message
make the player get a buff after using wormhole make the player get a buff after using wormhole
while energy lasts: drain energy and give damage buff while energy lasts: drain energy and give damage buff
Tech: "Induced Oscillation": When using phonon, if a block vibrates after it gets hit from a phonon, it has a chance of oscillating and creating an additional phonon coming from the block. The chance is higher the closer the block is to the source of the oscillation.
tech: quantized shields - harmonic standing wave field can only lose 33 energy per hit tech: quantized shields - harmonic standing wave field can only lose 33 energy per hit
draw 1,2,3 levels of the field based on energy? draw 1,2,3 levels of the field based on energy?
the blocked value only scales up to 2x or 4x (33 energy) blocked the blocked value only scales up to 2x or 4x (33 energy) blocked
@@ -186,6 +228,9 @@ n-gon outreach ideas
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
blocks on buttons teleport into the button endlessly if they are being slowly floated away
maybe add a cooldown?
ants marching outline doesn't sync right on safari anymore. ants marching outline doesn't sync right on safari anymore.
door to exit in vats does nothing door to exit in vats does nothing
@@ -270,6 +315,12 @@ map: observatory
******************************************************** MOBS ******************************************************** ******************************************************** MOBS ********************************************************
mobs that buff the stats of mobs when they die
nearby mobs
boss is a group of mobs, they buff each other
give the buff a ramp up time
so there is an advantage to kill them all at once
mob that spawns eggs after they die mob that spawns eggs after they die
eggs don't attack but grow back into a mob after about 10s eggs don't attack but grow back into a mob after about 10s
@@ -346,6 +397,7 @@ possible names for tech
eternal inflation eternal inflation
hypergraph hypergraph
gnarl 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.
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