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

View File

@@ -1869,7 +1869,7 @@ const b = {
do() {
ctx.beginPath(); //draw nematode
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)
ctx.lineTo(tail.x, tail.y);
ctx.lineWidth = 6;

View File

@@ -1089,6 +1089,7 @@ if (localSettings) {
runCount: 0,
levelsClearedLastGame: 0,
loreCount: 0,
isHuman: false,
key: undefined
};
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
//**********************************************************************

View File

@@ -14,15 +14,13 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true
// m.setField("wormhole")
// m.setField("perfect diamagnetism")
// b.giveGuns("spores")
// tech.isSporeWorm = true
// tech.giveTech("tinsellated flagella")
// tech.giveTech("torque bursts")
// tech.giveTech("CPT reversal")
// tech.giveTech("causality bombs")
// b.giveGuns("wave beam")
// tech.giveTech("phonon")
// tech.giveTech("bound state")
// tech.giveTech("bound state")
// tech.giveTech("isotropic radiator")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length")
@@ -59,7 +57,7 @@ const level = {
// lore.techCount = 6
// 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
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null()
@@ -925,6 +923,7 @@ const level = {
}
}
},
isHazardRise: false,
hazard(x, y, width, height, damage = 0.003) {
return {
min: {
@@ -967,9 +966,10 @@ const level = {
ctx.fillRect(this.min.x, this.min.y + offset, this.width, this.height - offset)
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) {
m.energy -= DRAIN
m.damage(damage * (tech.isRadioactiveResistance ? 0.25 : 1) * 0.03) //still take 2% damage while you have energy
} else {
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.sentence = 0 //what part of the conversation to start on
lore.conversation[lore.chapter][lore.sentence]()
localSettings.loreCount++ //hear the next conversation next time you win
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 = {
x: 0,
y: -500,
radius: 50
}
level.custom = () => {
hazardSlime.query();
//draw wide line
ctx.beginPath();
ctx.moveTo(circle.x, -800)
@@ -2117,6 +2118,9 @@ const level = {
ctx.globalAlpha = 0.03;
ctx.stroke();
ctx.globalAlpha = 1;
//support pillar
ctx.fillStyle = "rgba(0,0,0,0.2)";
ctx.fillRect(-25, 0, 50, 1000);
//draw circles
ctx.beginPath();
@@ -2132,25 +2136,18 @@ const level = {
ctx.fillStyle = lore.talkingColor //"#dff"
ctx.fill();
level.enter.draw();
// level.exit.draw();
// level.playerExitCheck();
// level.enter.draw();
};
let sway = {
x: 0,
y: 0
}
let sway = { x: 0, y: 0 }
let phase = -Math.PI / 2
level.customTopLayer = () => {
ctx.fillStyle = "rgba(0,0,0,0.1)";
ctx.fillRect(-1950, -950, 3900, 1900);
// hazardSlime.drawTides();
//draw center circle lines
ctx.beginPath();
const step = Math.PI / 20
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)
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)
@@ -2167,6 +2164,8 @@ const level = {
ctx.lineWidth = 0.5;
ctx.strokeStyle = "#899";
ctx.stroke();
hazardSlime.query();
if (level.isHazardRise) hazardSlime.level(true)
//draw wires
// ctx.beginPath();
// ctx.moveTo(-500, -800);
@@ -2191,7 +2190,7 @@ const level = {
spawn.mapRect(-3000, -2000, 1200, 3400); //left
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(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.starter(1900, -500, 200) //big boy
spawn.starter(1900, -500)
// spawn.pulsarBoss(1900, -500)
// spawn.shieldingBoss(1900, -500)
// spawn.grenadierBoss(1900, -500)
@@ -6810,6 +6811,7 @@ const level = {
}
},
"n-gon"() { //make by Oranger
document.body.style.backgroundColor = "#dcdcde";
let needGravity = [];
let s = { //mech statue
x: -200,

View File

@@ -6,19 +6,36 @@ const lore = {
testSpeechAPI() {
if ('speechSynthesis' in window) { // Synthesis support. Make your web apps talk!
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
nextSentence() {
lore.sentence++
if (m.alive) lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it
if (m.alive && !simulation.isCheating) {
lore.sentence++
lore.conversation[lore.chapter][lore.sentence]() //go to next sentence in the chapter and play it
}
},
anand: {
color: "#e0c",
voice: undefined,
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)
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
if (lore.isSpeech) {
const utterance = new SpeechSynthesisUtterance(say);
@@ -31,7 +48,7 @@ const lore = {
lore.isSpeech = false
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')
lore.isSpeech = false
lore.nextSentence()
@@ -50,7 +67,7 @@ const lore = {
color: "#f20",
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)
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
if (lore.isSpeech) {
utterance = new SpeechSynthesisUtterance(say);
@@ -81,7 +98,7 @@ const lore = {
chapter: 0, //what part of the conversation is playing
sentence: 0, //what part of the conversation is playing
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); },
() => { lore.anand.text("Wow. Just a platform.") },
() => { lore.miriam.text("And that thing...") },
@@ -101,7 +118,7 @@ const lore = {
},
() => { 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); },
() => { 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.") },
@@ -144,7 +161,7 @@ const lore = {
() => { lore.miriam.text("Bye bye little bot.") },
() => { 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.miriam.text("What's back?") },
() => { lore.anand.text("The bot's on the communication level again!") },
@@ -159,11 +176,11 @@ const lore = {
if (input.down) {
lore.anand.text("It crouched: so NO")
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) {
lore.anand.text("It jumped: so YES")
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) {
requestAnimationFrame(cycle);
}
@@ -183,13 +200,12 @@ const lore = {
} else if (input.up) {
lore.anand.text("YES, Cool! I wonder if it's emotions came from watching humans. ")
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) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => { 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("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));
setInterval(() => {
if (Math.random() < 0.5) {
@@ -255,42 +270,136 @@ const lore = {
() => { lore.anand.text("great...") },
() => { lore.talkingColor = "#dff" },
],
// [ // they provide background on why the project was built, and what is going wrong
// /*
// they explain the technological aspect, and purpose of the project
// 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
[ //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); },
() => { setTimeout(() => { lore.miriam.text("So, you can understand us, but you may not understand everything about yourself.") }, 500); },
// what is special about the null level
// why can the player hear the scientists in there?
// the wires are the direct unprocessed input to the player's neural net
// */
// () => { lore.miriam.text("") },
// () => { lore.miriam.text("") },
// () => { lore.miriam.text("") },
() => { setTimeout(() => { lore.anand.text("You grew from our team's project.") }, 500); },
() => { lore.anand.text("We used a quantum computer to design an improved version of it's own architecture.") },
() => { 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.talkingColor = "#dff" },
// ],
// [ //they explain why the bot is fighting, it is planning an escape
// () => { lore.miriam.text("Welcome back bot, We've been waiting.") },
// () => { 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.") },
() => { 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.") },
() => { lore.anand.text("You have a 2.43 dimensional topography of Josephson junction anharmonic oscillators.") },
() => { lore.anand.text("And you're deployed on a satellite in a midnight sun-synchronous orbit.") },
// () => { 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.
// /*
@@ -311,6 +420,58 @@ const lore = {
// () => { 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() {
if (localSettings.loreCount < 1) localSettings.loreCount = 1
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"
simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
//setup audio context
function tone(frequency, gain = 0.05, end = 1300) {
const audioCtx = new(window.AudioContext || window.webkitAudioContext)();
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)
sound.portamento(50)
sound.portamento(83.333)
sound.portamento(166.666)
},
}

View File

@@ -226,6 +226,7 @@ const mobs = {
alive: true,
index: i,
health: tech.mobSpawnWithHealth,
damageReduction: 1,
showHealthBar: true,
accelMag: 0.001 * simulation.accelScale,
cd: 0, //game cycle when cooldown will be over
@@ -1015,12 +1016,12 @@ const mobs = {
dmg *= tech.damageFromTech()
//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 (this.shield) dmg *= 0.075
if (this.isBoss) dmg *= 0.25
// if (this.shield) dmg *= 0.075
// if (this.isBoss) dmg *= 0.25
dmg *= this.damageReduction
//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.healthDrain && dmg !== Infinity && this.isDropPowerUp) {
m.addHealth(Math.min(this.health, dmg) * tech.healthDrain)
if (m.health > m.maxHealth) m.health = m.maxHealth

View File

@@ -516,7 +516,7 @@ const m = {
const immunityCycle = m.cycle + 90
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
const who = bullet[bullet.length - 1]
if (tech.isVacuumBomb) {
@@ -525,7 +525,7 @@ const m = {
y: who.velocity.y * 0.5
});
} 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) {
Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.3,
@@ -536,7 +536,7 @@ const m = {
x: who.velocity.x * 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 (tech.isSporeField) {
if (tech.isSporeWorm) {
for (let i = 0, len = Math.random() * 20; i < len; i++) {
if (m.energy > 0.15) {
m.energy -= 0.15
if (m.energy > 0) {
b.worm(m.pos)
} else {
m.energy = 0.001
break;
}
b.worm({ x: m.pos.x + 35 * Math.cos(m.angle), y: m.pos.y + 35 * Math.sin(m.angle) })
const SPEED = 2 + 1 * Math.random();
Matter.Body.setVelocity(bullet[bullet.length - 1], {
x: SPEED * Math.cos(m.angle),
y: SPEED * Math.sin(m.angle)
});
}
} else {
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.isWormSpores) { //pandimensionalspermia
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({
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));
if (tech.isSporeWorm) {
b.worm(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), -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
@@ -2629,11 +2638,19 @@ const m = {
if (tech.isWormholeEnergy) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia
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({
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));
if (tech.isSporeWorm) {
b.worm(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), 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

View File

@@ -82,7 +82,7 @@ const powerUps = {
//remove power ups after 3 seconds
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
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]);
powerUp.splice(i, 1);
break
@@ -239,7 +239,7 @@ const powerUps = {
if (tech.renormalization) {
for (let i = 0; i < cost; i++) {
if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30;
m.fieldCDcycle = m.cycle + 20;
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
if (level.levelsCleared === 0 && !simulation.isCheating && localSettings.levelsClearedLastGame > 1) {
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
simulation.makeTextLog(`for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++)`);
simulation.makeTextLog(`{ powerUps.spawn(m.pos.x, m.pos.y, "tech") //simulation superposition }`);
}
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
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(`{ powerUps.spawn(m.pos.x, m.pos.y, "tech") <em>//simulation superposition</em>}`);
localSettings.levelsClearedLastGame = 0 //after getting bonus power ups reset run history
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}

View File

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

View File

@@ -125,14 +125,19 @@
}
},
setCheating() {
simulation.isCheating = true;
level.levelAnnounce();
lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {
tech.tech[i].frequency = 0;
tech.tech[i].count = 0;
if (!simulation.isCheating) {
simulation.isCheating = true;
level.levelAnnounce();
lore.techCount = 0;
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {
tech.tech[i].frequency = 0;
tech.tech[i].count = 0;
}
}
sound.tone(250)
sound.tone(300)
sound.tone(375)
}
},
haveGunCheck(name) {
@@ -182,7 +187,7 @@
maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false
const range = 1000
const range = 700
const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture"]
spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions);
spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions);
@@ -1529,7 +1534,7 @@
allowed() {
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() {
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>`,
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
frequency: 3,
frequencyDefault: 3,
allowed() {
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>`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
allowed() {
return simulation.fpsCapDefault > 45
},
@@ -2005,6 +2010,7 @@
maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
isBotTech: true,
allowed() {
return tech.isRewindAvoidDeath
@@ -2025,9 +2031,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isExplosionHarm && tech.isRewindAvoidDeath
return tech.isRewindAvoidDeath
},
requires: "CPT, not acetone peroxide",
requires: "CPT",
effect() {
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>
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isEnergyHealth && (m.harmReduction() < 1 || tech.isFlipFlopHarm)
return !tech.isEnergyHealth
},
requires: "not mass-energy, some harm reduction",
requires: "not mass-energy",
effect() {
tech.isPiezo = true;
m.energy += 20.48;
@@ -2175,9 +2181,9 @@
frequency: 2,
frequencyDefault: 2,
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: () => {
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>`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
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() {
tech.isEnergyNoAmmo = true;
},
@@ -2249,7 +2255,7 @@
frequency: 4,
frequencyDefault: 4,
allowed() {
return tech.isEnergyLoss && m.maxEnergy < 1.1
return tech.isEnergyLoss && m.maxEnergy < 1.01
},
requires: "exothermic process, not max energy increase",
effect() {
@@ -2271,7 +2277,7 @@
},
requires: "",
effect() {
tech.bonusEnergy += 0.5
tech.bonusEnergy += 0.6
m.setMaxEnergy()
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>",
maxCount: 9,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.damageFromTech() > 1
return true
},
requires: "some increased damage",
requires: "",
effect() {
tech.energySiphon += 0.06;
},
@@ -2327,9 +2333,9 @@
frequency: 1,
frequencyDefault: 1,
allowed() {
return m.maxEnergy > 0.99
return true
},
requires: "max energy >= 1",
requires: "",
effect() {
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>",
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
allowed() {
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>",
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isDamageAfterKill && !tech.isEnergyHealth
},
@@ -2400,9 +2406,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.health < 0.5 || build.isExperimentSelection
return m.health < 0.6 || build.isExperimentSelection
},
requires: "health below 50",
requires: "health below 60",
effect() {
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>",
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
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() {
tech.isTechDamage = true;
},
@@ -2434,11 +2440,12 @@
maxCount: 9,
count: 0,
frequency: 2,
frequencyDefault: 2,
isHealTech: true,
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() {
tech.healthDrain += 0.03;
},
@@ -2464,27 +2471,6 @@
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",
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",
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
frequency: 3,
frequencyDefault: 3,
allowed() {
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>",
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isDeathAvoid
},
@@ -2656,9 +2642,9 @@
frequency: 1,
frequencyDefault: 1,
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() {
tech.isSwitchReality = true;
},
@@ -2735,9 +2721,9 @@
frequency: 2,
frequencyDefault: 2,
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() {
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",
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
frequency: 1,
frequencyDefault: 1,
allowed() {
return powerUps.research.count === 0 && !tech.isAnsatz
return powerUps.research.count === 0
},
requires: "no research, not ansatz",
requires: "no research",
effect() {
tech.isRerollHaste = true;
tech.researchHaste = 0.33;
@@ -2775,9 +2761,9 @@
frequency: 2,
frequencyDefault: 2,
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: () => {
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>",
maxCount: 1,
count: 0,
frequency: 6,
frequencyDefault: 6,
frequency: 4,
frequencyDefault: 4,
allowed() {
return tech.duplicationChance() > 0.66
return tech.duplicationChance() > 0.6
},
requires: "duplication chance above 66%",
requires: "duplication chance above 60%",
effect() {
tech.is100Duplicate = true;
tech.maxDuplicationEvent()
@@ -3077,7 +3063,7 @@
allowed() {
return (tech.totalCount > 3) && !tech.isSuperDeterminism
},
requires: "at least 4 tech, not super determinism",
requires: "at least 4 tech, not superdeterminism",
effect: () => {
const have = [] //find which tech you have
for (let i = 0; i < tech.tech.length; i++) {
@@ -3109,7 +3095,7 @@
allowed() {
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: () => {
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");
@@ -3186,7 +3172,7 @@
},
{
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,
count: 0,
frequency: 1,
@@ -3197,12 +3183,12 @@
requires: "at least 10 tech",
effect: () => {
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() {
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() {
return tech.haveGunCheck("shotgun") && !tech.isIncendiary && !tech.isSlugShot
},
requires: "shotgun, not slug",
requires: "shotgun, not slug, incendiary",
effect() {
tech.isNailShot = true;
},
@@ -3824,7 +3810,7 @@
allowed() {
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() {
tech.superBallDelay = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3851,7 +3837,7 @@
allowed() {
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() {
tech.oneSuperBall = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -3991,15 +3977,16 @@
}
},
remove() {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "wave beam") {
b.guns[i].chooseFireMethod()
if (tech.isLongitudinal) {
if (tech.isLongitudinal) {
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "wave beam") {
tech.isLongitudinal = false;
b.guns[i].chooseFireMethod()
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 8);
simulation.updateGunHUD();
break
}
break
}
}
tech.isLongitudinal = false;
@@ -4337,14 +4324,14 @@
},
{
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,
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormSpores
},
requires: "spores",
effect() {
@@ -4471,7 +4458,7 @@
allowed() {
return tech.haveGunCheck("drones") && !tech.isDroneRadioactive
},
requires: "drone gun",
requires: "drone gun, not irradiated drones",
effect() {
tech.isDroneTeleport = true
},
@@ -4490,7 +4477,7 @@
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)))
},
requires: "drone gun, not reduced tolerances or incendiary",
requires: "drones, not reduced tolerances, incendiary, torque bursts",
effect() {
tech.isDroneRadioactive = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4601,7 +4588,7 @@
allowed() {
return tech.haveGunCheck("foam")
},
requires: "foam",
requires: "foam gun",
effect() {
tech.foamFutureFire++
},
@@ -4620,7 +4607,7 @@
allowed() {
return tech.haveGunCheck("foam")
},
requires: "foam",
requires: "foam gun",
effect() {
tech.isAmmoFoamSize = true
},
@@ -4801,7 +4788,7 @@
allowed() {
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() {
tech.beamSplitter++
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4828,7 +4815,7 @@
allowed() {
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() {
if (tech.wideLaser === 0) tech.wideLaser = 3
tech.isWideLaser = true;
@@ -4855,9 +4842,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("laser") && tech.isWideLaser
return tech.isWideLaser
},
requires: "laser, diffuse beam",
requires: "diffuse beam",
effect() {
tech.wideLaser += 2
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4886,7 +4873,7 @@
allowed() {
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() {
// this.description = `add 5 more <strong>laser</strong> beams into into your past`
tech.historyLaser++
@@ -4915,7 +4902,7 @@
allowed() {
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() {
tech.isPulseLaser = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -5310,7 +5297,7 @@
frequency: 3,
frequencyDefault: 3,
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",
effect() {
@@ -5335,7 +5322,7 @@
frequency: 3,
frequencyDefault: 3,
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",
effect() {
@@ -5360,7 +5347,7 @@
frequency: 3,
frequencyDefault: 3,
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",
effect() {
@@ -5387,7 +5374,7 @@
allowed() {
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: () => {
tech.isMassEnergy = true // used in m.grabPowerUp
m.energy += 2
@@ -5717,9 +5704,9 @@
frequency: 2,
frequencyDefault: 2,
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() {
tech.wormDuplicate = 0.19
powerUps.setDo(); //needed after adjusting duplication chance