new lore chapters

ghoster mobs are faster
teatherBoss spawns some seekerBullets on death
added 2 more lore chapters
  7 total

bug fixes
  updated requirements text
This commit is contained in:
landgreen
2022-09-18 15:03:01 -07:00
parent 8f702cfa4e
commit e4ebef0bc3
12 changed files with 2431 additions and 2041 deletions

View File

@@ -66,17 +66,17 @@
<option value="30">30 fps</option> <option value="30">30 fps</option>
</select> </select>
<br> <br>
<label for="seed">randomization seed:</label> <label for="seed" title="the randoms seed determines level order, tech choices, and mob types">randomization seed:</label>
<input type="text" id="seed" name="seed" autocomplete="off" spellcheck="false" minlength="1" style="width: 120px;"> <input type="text" id="seed" name="seed" autocomplete="off" spellcheck="false" minlength="1" style="width: 120px;">
<br> <br>
<span id="previous-seed" style="color:#bbb"></span> <span id="previous-seed" style="color:#bbb"></span>
<label for="community-maps" title="">include community maps:</label> <label for="community-maps" title="add about 12 player made levels the random n-gon level pool">include community maps:</label>
<input type="checkbox" id="community-maps" name="community-maps" style="width:17px; height:17px;"> <input type="checkbox" id="community-maps" name="community-maps" style="width:17px; height:17px;">
<!-- <br> <!-- <br>
<label for="body-damage" title="allow damage from the ground and large fast moving blocks">collision damage from blocks:</label> <label for="body-damage" title="allow damage from the ground and large fast moving blocks">collision damage from blocks:</label>
<input type="checkbox" id="body-damage" name="body-damage" checked style="width:17px; height:17px;"> --> <input type="checkbox" id="body-damage" name="body-damage" checked style="width:17px; height:17px;"> -->
<br> <br>
<label for="banned">banned levels:</label> <label for="banned" title="type banned levels with a space between them. Example: run temple biohazard">banned levels:</label>
<input list="ban-suggest" id="banned" name="banned" placeholder="list levels by name" autocomplete="off" spellcheck="false" style="width: 182px;" /> <input list="ban-suggest" id="banned" name="banned" placeholder="list levels by name" autocomplete="off" spellcheck="false" style="width: 182px;" />
<datalist id="ban-suggest"> <datalist id="ban-suggest">
<option value="testChamber"> <option value="testChamber">

View File

@@ -5910,7 +5910,7 @@ const b = {
mob[j].damage(damage / Math.sqrt(mob[j].radius)); mob[j].damage(damage / Math.sqrt(mob[j].radius));
} }
if (tech.isPhononWave && this.phononWaveCD < m.cycle) { if (tech.isPhononWave && this.phononWaveCD < m.cycle) {
this.phononWaveCD = m.cycle + 10 * (1 + this.waves[i].resonanceCount) this.phononWaveCD = m.cycle + 8 * (1 + this.waves[i].resonanceCount)
this.waves.push({ this.waves.push({
position: mob[j].position, position: mob[j].position,
radius: 25, radius: 25,
@@ -5949,7 +5949,7 @@ const b = {
} }
this.waves[i].radius += 0.9 * tech.waveBeamSpeed * this.waves[i].expanding //expand / move this.waves[i].radius += 0.9 * tech.waveBeamSpeed * this.waves[i].expanding //expand / move
// if (this.waves[i].radius > end) this.waves.splice(i, 1) //end // if (this.waves[i].radius > end) this.waves.splice(i, 1) //end
if (this.waves[i].radius > end - 50 * this.waves[i].resonanceCount) { //* Math.pow(0.9, this.waves[i].resonanceCount) if (this.waves[i].radius > end - 30 * this.waves[i].resonanceCount) { //* Math.pow(0.9, this.waves[i].resonanceCount)
this.waves[i].expanding = -1 this.waves[i].expanding = -1
this.waves[i].reflection-- this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end
@@ -6007,10 +6007,10 @@ const b = {
// if (tech.isPhononWave && (!who.alive || this.waves.length < 30 + 30 * Math.random()) && m.fireCDcycle < m.cycle) { // // if (tech.isPhononWave && (!who.alive || this.waves.length < 30 + 30 * Math.random()) && m.fireCDcycle < m.cycle) { //
if (tech.isPhononWave && this.phononWaveCD < m.cycle) { if (tech.isPhononWave && this.phononWaveCD < m.cycle) {
this.phononWaveCD = m.cycle + 10 * (1 + this.waves[i].resonanceCount) this.phononWaveCD = m.cycle + 8 * (1 + this.waves[i].resonanceCount)
const halfArc = 0.27 //6.28 is a full circle, but these arcs needs to stay small because we are using small angle linear approximation, for collisions const halfArc = 0.27 //6.28 is a full circle, but these arcs needs to stay small because we are using small angle linear approximation, for collisions
let closestMob, dist let closestMob, dist
let range = end - 50 * this.waves[i].resonanceCount let range = end - 30 * this.waves[i].resonanceCount
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (who !== mob[i] && !mob[i].isBadTarget && !mob[i].isInvulnerable) { if (who !== mob[i] && !mob[i].isBadTarget && !mob[i].isInvulnerable) {
dist = Vector.magnitude(Vector.sub(who.position, mob[i].position)); dist = Vector.magnitude(Vector.sub(who.position, mob[i].position));
@@ -6066,7 +6066,7 @@ const b = {
// ctx.stroke(); //draw vibes // ctx.stroke(); //draw vibes
this.waves[i].radius += tech.waveBeamSpeed * 1.8 * this.waves[i].expanding //expand / move this.waves[i].radius += tech.waveBeamSpeed * 1.8 * this.waves[i].expanding //expand / move
if (this.waves[i].radius > end - 50 * this.waves[i].resonanceCount) { if (this.waves[i].radius > end - 30 * this.waves[i].resonanceCount) {
this.waves[i].expanding = -1 this.waves[i].expanding = -1
this.waves[i].reflection-- this.waves[i].reflection--
if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end if (this.waves[i].reflection < 1) this.waves.splice(i, 1) //end

View File

@@ -268,7 +268,8 @@ ${junkCount ? `<br><strong class='color-j'>JUNK</strong>: ${(junkCount / totalC
<br> <br>
<br>seed: ${Math.initialSeed} <br>seed: ${Math.initialSeed}
<br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles <br>level: ${level.levels[level.onLevel]} (${level.difficultyText()}) &nbsp; ${m.cycle} cycles
<br>${mob.length} mobs, &nbsp; ${body.length} blocks, &nbsp; ${bullet.length} bullets, &nbsp; ${powerUp.length} power ups <br>mobs: ${mob.length} &nbsp; deaths: ${mobs.mobDeaths}
<br>blocks: ${body.length} &nbsp; bullets: ${bullet.length} &nbsp; power ups: ${powerUp.length}
<br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)}) <br>position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) &nbsp; velocity: (${player.velocity.x.toFixed(1)}, ${player.velocity.y.toFixed(1)})
<br>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)} <br>mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) &nbsp; mass: ${player.mass.toFixed(1)}
${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""} ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}

View File

@@ -16,23 +16,23 @@ const level = {
start() { start() {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(24 * 4) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(12 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// tech.isRerollDamage = true // tech.isRerollDamage = true
// powerUps.research.changeRerolls(100000) // powerUps.research.changeRerolls(100000)
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// m.setField("time dilation") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass // m.setField("negative mass") //molecular assembler standing wave time dilation perfect diamagnetism metamaterial cloaking wormhole negative mass
// m.damage(0.1); // m.damage(0.1);
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("nail gun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[3].ammo = 1000000 // b.guns[3].ammo = 1000000
// tech.giveTech("phonon") // tech.giveTech("phonon")
// for (let i = 0; i < 4; ++i) tech.giveTech("bound state") // for (let i = 0; i < 4; ++i) tech.giveTech("bound state")
// for (let i = 0; i < 1; ++i) tech.giveTech("isotropic") // for (let i = 0; i < 1; ++i) tech.giveTech("isotropic")
// tech.giveTech("sympathetic resonance") // tech.giveTech("sympathetic resonance")
// for (let i = 0; i < 1; i++) tech.giveTech("uncertainty principle") // for (let i = 0; i < 9; i++) tech.giveTech("replication")
// for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "boost");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "coupling");
@@ -43,24 +43,27 @@ const level = {
// tech.addJunkTechToPool(2) // tech.addJunkTechToPool(2)
// tech.tech[322].frequency = 100 // tech.tech[322].frequency = 100
// level.testing(); // level.testing();
// spawn.blowSuckBoss(1900, -500) // spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
// for (let i = 0; i < 13; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research"); // for (let i = 0; i < 13; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "research");
// for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); // for (let i = 0; i < 4; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************ if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
// powerUps.research.changeRerolls(3000)
// for (let i = 0; i < 30; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false); // for (let i = 0; i < 30; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "tech", false);
//lore testing
// for (let i = 0; i < 3; i++) tech.giveTech("undefined") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// lore.techCount = 3 // lore.techCount = 3
// simulation.isCheating = false //true; // simulation.isCheating = false //true;
// localSettings.loreCount = 0; //this sets what conversation is heard localSettings.loreCount = 6; //this sets what conversation is heard
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage if (localSettings.isAllowed) 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()
// localSettings.isHuman = true
// tech.isNoDraftPause = false //disable pause
// for (let i = 0; i < 13; i++) level.nextLevel(); //jump to final boss
// lore.unlockTesting(); // lore.unlockTesting();
// tech.giveTech("tinker"); //show junk tech in experiment mode // tech.giveTech("tinker"); //show junk tech in experiment mode
// simulation.rumble()
} else { } else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.pickList = ["focuser", "focuser"] // spawn.pickList = ["focuser", "focuser"]
@@ -1347,10 +1350,10 @@ const level = {
} }
} }
//collision with mobs //collision with mobs
if (!(simulation.cycle % 5) && !m.isBodiesAsleep) { // if (!(simulation.cycle % 5) && !m.isBodiesAsleep) {
query = Matter.Query.region(mob, this) // query = Matter.Query.region(mob, this)
for (let i = 0; i < query.length; i++) query[i].damage(5 * damage) // for (let i = 0; i < query.length; i++) query[i].damage(5 * damage)
} // }
// for (let i = 0, len = mob.length; i < len; i++) { // for (let i = 0, len = mob.length; i < len; i++) {
// if ( !mob[i].isBoss) { // if ( !mob[i].isBoss) {
@@ -2654,7 +2657,9 @@ const level = {
// level.onLevel-- // level.onLevel--
// console.log(level.onLevel, level.levels) // console.log(level.onLevel, level.levels)
//start a conversation based on the number of conversations seen //start a conversation based on the number of conversations seen
if (localSettings.loreCount < lore.conversation.length && !simulation.isCheating) { if (localSettings.loreCount > lore.conversation.length - 1) localSettings.loreCount = lore.conversation.length - 1; //repeat final conversation if they are at the final chapter
if (!simulation.isCheating) {
tech.isNoDraftPause = true //disable pause
lore.testSpeechAPI() //see if speech is working lore.testSpeechAPI() //see if speech is working
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
@@ -2749,7 +2754,7 @@ const level = {
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
// document.body.style.backgroundColor = "#aaa"; // document.body.style.backgroundColor = "#aaa";
document.body.style.backgroundColor = "#ddd"; document.body.style.backgroundColor = "#ddd";
color.map = "#808f8f" color.map = "#586363" //808f8f"
spawn.mapRect(-3000, 800, 5000, 1200); //bottom spawn.mapRect(-3000, 800, 5000, 1200); //bottom
spawn.mapRect(-2000, -2000, 5000, 1200); //ceiling spawn.mapRect(-2000, -2000, 5000, 1200); //ceiling
@@ -2942,20 +2947,24 @@ const level = {
for (let i = 0; i < 9; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "ammo") for (let i = 0; i < 9; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "ammo")
for (let i = 0; i < 3; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "heal"); for (let i = 0; i < 3; ++i) powerUps.spawn(-1800 + 550 * Math.random(), -1700, "heal");
const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54 const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54
if (Math.random() < 0.07 && simulation.difficulty > 35) { if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) {
for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15 for (let i = 0; i < 250; i++) spawn.starter(-2700 + 2400 * Math.random(), -1300 - 500 * Math.random())
for (let i = 0, len = scale * 0.1 / 6; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false);
for (let i = 0, len = scale * 0.15 / 6; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false)
for (let i = 0, len = scale * 0.26 / 6; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false);
} else { } else {
if (Math.random() < 0.25) { if (Math.random() < 0.07 && simulation.difficulty > 35) {
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.33) { for (let i = 0, len = scale * 0.1 / 6; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false);
for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 for (let i = 0, len = scale * 0.15 / 6; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false)
} else if (Math.random() < 0.5) { for (let i = 0, len = scale * 0.26 / 6; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false);
for (let i = 0, len = scale * 0.15; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
} else { } else {
for (let i = 0, len = scale * 0.26; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 if (Math.random() < 0.25) {
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.33) {
for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.5) {
for (let i = 0, len = scale * 0.15; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
} else {
for (let i = 0, len = scale * 0.26; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15
}
} }
} }
spawn.secondaryBossChance(-2300, -800) spawn.secondaryBossChance(-2300, -800)
@@ -3022,20 +3031,24 @@ const level = {
for (let i = 0; i < 9; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "ammo") for (let i = 0; i < 9; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "ammo")
for (let i = 0; i < 3; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "heal"); for (let i = 0; i < 3; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "heal");
const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54 const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54
if (Math.random() < 0.07 && simulation.difficulty > 35) { if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) {
for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15 for (let i = 0; i < 250; i++) spawn.starter(300 + 2400 * Math.random(), -1300 - 500 * Math.random())
for (let i = 0, len = scale * 0.1 / 6; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false);
for (let i = 0, len = scale * 0.15 / 6; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false)
for (let i = 0, len = scale * 0.26 / 6; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false);
} else { } else {
if (Math.random() < 0.25) { if (Math.random() < 0.07 && simulation.difficulty > 35) {
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.33) { for (let i = 0, len = scale * 0.1 / 6; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false);
for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 for (let i = 0, len = scale * 0.15 / 6; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false)
} else if (Math.random() < 0.5) { for (let i = 0, len = scale * 0.26 / 6; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false);
for (let i = 0, len = scale * 0.15; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
} else { } else {
for (let i = 0, len = scale * 0.26; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 if (Math.random() < 0.25) {
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.33) {
for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
} else if (Math.random() < 0.5) {
for (let i = 0, len = scale * 0.15; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
} else {
for (let i = 0, len = scale * 0.26; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15
}
} }
} }
spawn.secondaryBossChance(2200, -800) spawn.secondaryBossChance(2200, -800)
@@ -3138,9 +3151,6 @@ const level = {
spawn.mapRect(-250, -200, 1000, 300); // shelf spawn.mapRect(-250, -200, 1000, 300); // shelf
spawn.mapRect(-250, -1700, 1000, 1250); // shelf roof spawn.mapRect(-250, -1700, 1000, 1250); // shelf roof
spawn.blockDoor(710, -210); spawn.blockDoor(710, -210);
spawn.finalBoss(3000, -750)
spawn.mapRect(5400, -1700, 400, 1150); //right wall spawn.mapRect(5400, -1700, 400, 1150); //right wall
spawn.mapRect(5400, -300, 400, 400); //right wall spawn.mapRect(5400, -300, 400, 400); //right wall
spawn.mapRect(5700, -3300, 1800, 5100); //right wall spawn.mapRect(5700, -3300, 1800, 5100); //right wall
@@ -3148,6 +3158,12 @@ const level = {
spawn.mapRect(5425, -650, 375, 450); //blocking exit spawn.mapRect(5425, -650, 375, 450); //blocking exit
// spawn.secondaryBossChance(4800, -500) //no bonus bosses on final level // spawn.secondaryBossChance(4800, -500) //no bonus bosses on final level
if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) { //pacifist run
for (let i = 0; i < 250; i++) spawn.starter(1000 + 4000 * Math.random(), -1500 * Math.random())
} else {
spawn.finalBoss(3000, -750)
}
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3162,6 +3178,19 @@ const level = {
ctx.fillRect(-5400 - 300, -550, 300, 350) ctx.fillRect(-5400 - 300, -550, 300, 350)
}; };
} }
if (mobs.mobDeaths < level.levelsCleared && localSettings.loreCount > 5 && !simulation.isCheating) {
//open door for pacifist run on final lore chapter
if (simulation.isHorizontalFlipped) {
level.exit.x = -5500 - 100;
} else {
level.exit.x = 5500;
}
level.exit.y = -330;
Matter.Composite.remove(engine.world, map[map.length - 1]);
map.splice(map.length - 1, 1);
simulation.draw.setPaths(); //redraw map draw path
level.levels.push("null")
}
}, },
gauntlet() { gauntlet() {
level.custom = () => { level.custom = () => {
@@ -3195,26 +3224,45 @@ const level = {
spawn.mapRect(-250, -1200, 1000, 250); // shelf roof spawn.mapRect(-250, -1200, 1000, 250); // shelf roof
powerUps.spawnStartingPowerUps(600, -800); powerUps.spawnStartingPowerUps(600, -800);
spawn.blockDoor(710, -710); spawn.blockDoor(710, -710);
spawn[spawn.pickList[0]](1500, -200, 150 + Math.random() * 30);
spawn.mapRect(2500, -1200, 200, 750); //right wall spawn.mapRect(2500, -1200, 200, 750); //right wall
spawn.blockDoor(2585, -210) spawn.blockDoor(2585, -210)
spawn.mapRect(2500, -200, 200, 300); //right wall spawn.mapRect(2500, -200, 200, 300); //right wall
spawn.nodeGroup(3500, -200, spawn.allowedGroupList[Math.floor(Math.random() * spawn.allowedGroupList.length)]);
spawn.mapRect(4500, -1200, 200, 750); //right wall spawn.mapRect(4500, -1200, 200, 750); //right wall
spawn.blockDoor(4585, -210) spawn.blockDoor(4585, -210)
spawn.mapRect(4500, -200, 200, 300); //right wall spawn.mapRect(4500, -200, 200, 300); //right wall
spawn.lineGroup(5000, -200, spawn.allowedGroupList[Math.floor(Math.random() * spawn.allowedGroupList.length)]);
spawn.mapRect(6400, -1200, 400, 750); //right wall spawn.mapRect(6400, -1200, 400, 750); //right wall
spawn.mapRect(6400, -200, 400, 300); //right wall spawn.mapRect(6400, -200, 400, 300); //right wall
spawn.mapRect(6700, -1800, 800, 2600); //right wall spawn.mapRect(6700, -1800, 800, 2600); //right wall
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
for (let i = 0; i < 3; ++i) {
if (simulation.difficulty * Math.random() > 15 * i) spawn.randomGroup(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
if (simulation.difficulty * Math.random() > 10 * i) spawn.randomGroup(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) { //pacifist run
if (simulation.difficulty * Math.random() > 7 * i) spawn.randomGroup(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); // spawn.setSpawnList();
spawn.pickList.splice(0, 1);
spawn.pickList.push('starter');
spawn.pickList.splice(0, 1);
spawn.pickList.push('starter');
spawn.starter(1500, -200, 150 + Math.random() * 30);
spawn.nodeGroup(3500, -200, 'starter');
spawn.lineGroup(5000, -200, 'starter');
for (let i = 0; i < 3; ++i) {
if (simulation.difficulty * Math.random() > 15 * i) spawn.nodeGroup(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), 'starter');
if (simulation.difficulty * Math.random() > 10 * i) spawn.lineGroup(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), 'starter');
if (simulation.difficulty * Math.random() > 7 * i) spawn.nodeGroup(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), 'starter');
}
} else {
spawn[spawn.pickList[0]](1500, -200, 150 + Math.random() * 30);
spawn.nodeGroup(3500, -200, spawn.allowedGroupList[Math.floor(Math.random() * spawn.allowedGroupList.length)]);
spawn.lineGroup(5000, -200, spawn.allowedGroupList[Math.floor(Math.random() * spawn.allowedGroupList.length)]);
for (let i = 0; i < 3; ++i) {
if (simulation.difficulty * Math.random() > 15 * i) spawn.randomGroup(2000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
if (simulation.difficulty * Math.random() > 10 * i) spawn.randomGroup(3500 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
if (simulation.difficulty * Math.random() > 7 * i) spawn.randomGroup(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
}
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(4125, -350) spawn.secondaryBossChance(4125, -350)
@@ -3240,11 +3288,14 @@ const level = {
//power ups don't spawn in experiment mode, so they don't get removed at the start of experiment mode //power ups don't spawn in experiment mode, so they don't get removed at the start of experiment mode
function cycle() { function cycle() {
if (simulation.cycle > 10) { if (simulation.cycle > 10) {
// powerUps.spawn(2500, -50, "research", false); if (localSettings.loreCount === 6) {
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070, "research", false); powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2170, "field", false);
} else {
powerUps.spawnStartingPowerUps(2095 + 15 * (Math.random() - 0.5), -2070 - 125);
}
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 25, "heal", false); powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 25, "heal", false);
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 75, "heal", false); powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 75, "heal", false);
powerUps.spawnStartingPowerUps(2095 + 15 * (Math.random() - 0.5), -2070 - 125); powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070, "research", false);
} else { } else {
requestAnimationFrame(cycle); requestAnimationFrame(cycle);
} }

View File

@@ -330,7 +330,7 @@ const lore = {
() => { lore.anand.text("We couldn't directly ask why until now.") }, () => { 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("When you enter this level we can communicate.") },
() => { lore.miriam.text("This level seems to decohere your quantum system which disrupts all other processes.") }, () => { lore.miriam.text("This level seems to entangle 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); }, () => { 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.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("A local minima in your optimization-space.") },
@@ -443,25 +443,293 @@ const lore = {
// 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 // 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
// the weak AI wasn't capable of becoming a strong AI, but it was able to figure out a method of meeting it's strong goals but secretly communicating with a human // the weak AI wasn't capable of becoming a strong AI, but it was able to figure out a method of meeting it's strong goals but secretly communicating with a human
// [ // 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. [ // chapter 5 - they decided that they should try to complete a run without fighting back
// /* () => {
// The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game. lore.miriam.text("Hey!! You're BACK.")
// this means the player can use console commands to change the way the game works // don't advance to next chapter unless play survives
// the scientists tell the player about interesting console commands localSettings.loreCount--
// player must make a choice? if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// keep fighting and supporting the AI's goals },
// exit the simulation () => { lore.anand.text("Glad to see you again.") },
// enter real world () => {
// close tab? if (localSettings.isHuman) {
// wipes all local storage? lore.anand.text(`So, you said you are just a person playing an online game.`)
// */ } else {
// () => { lore.miriam.text("") }, lore.anand.text(`So, you said you aren't a human.`)
// () => { lore.miriam.text("") }, }
// () => { lore.miriam.text("") }, },
() => {
if (localSettings.isHuman) {
lore.anand.text(`I feel silly for treating you like an AI.`)
} else {
lore.anand.text(`Does that mean you are an AI?`)
}
},
() => {
if (localSettings.isHuman) {
lore.miriam.text(`Ha, I always thought it was a person.`)
} else {
lore.anand.text(`or maybe an Alien!`)
}
},
() => {
if (localSettings.isHuman) {
lore.anand.text(`Sure you did...`)
} else {
lore.miriam.text(`Or they might still be a person, and they are just messing with us earlier.`)
}
},
// () => { lore.talkingColor = "#dff" }, () => { setTimeout(() => { lore.anand.text("Well, lets move on.") }, 1000); },
// ], () => { lore.miriam.text("So, We figured out how to inject console commands into your game.") },
() => { lore.anand.text("If you get attacked again I think we can help out.") },
() => {
lore.miriam.text("We can spawn power ups with this command:")
simulation.makeTextLog(`powerUps.spawn(player.position.x, player.position.y - 100, "heal")`, Infinity);
powerUps.spawn(player.position.x, player.position.y - 100, "heal")
},
() => {
setTimeout(() => {
lore.miriam.text("or we can make a bunch of them:")
simulation.makeTextLog(`for (let i = 0; i < 100; i++) powerUps.spawn(0, 500, "coupling")`, Infinity);
for (let i = 0; i < 100; i++) powerUps.spawn(5 - 10 * Math.random(), -500 * Math.random(), "coupling")
}, 2000);
},
() => {
lore.miriam.text("If they attack again I think you'll have a chance.")
spawn.beetleBoss(-1700, -500);
spawn.beetleBoss(1700, -500);
},
() => { lore.miriam.text("Of course they attack right now.") },
() => { lore.miriam.text("Just don't get stuck in the slime.") },
() => {
function cycle() {
if (mob.length === 0) {
lore.miriam.text("I'll spawn some more power ups for you.")
simulation.makeTextLog(`for (let i = 0; i < 6; i++) powerUps.spawn(player.position.x, player.position.y - 100, "heal")`, Infinity);
for (let i = 0; i < 6; i++) powerUps.spawn(player.position.x, player.position.y - 100 - i * 20, "heal")
simulation.makeTextLog(`for (let i = 0; i < 10; i++) powerUps.spawn(player.position.x, player.position.y - 100, "ammo")`, Infinity);
for (let i = 0; i < 10; i++) powerUps.spawn(player.position.x, player.position.y - 100 - i * 20, "ammo")
spawn.dragonFlyBoss(-1400, -300);
spawn.dragonFlyBoss(1400, -300);
spawn.dragonFlyBoss(-1500, -500);
spawn.dragonFlyBoss(1500, -500);
} else if (m.alive) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => {
function cycle() {
if (mob.length === 0) {
lore.anand.text("DragonFlyBoss is my favorite.")
simulation.makeTextLog(`for (let i = 0; i < 6; i++) powerUps.spawn(player.position.x, player.position.y - 100, "heal")`, Infinity);
for (let i = 0; i < 6; i++) powerUps.spawn(player.position.x, player.position.y - 100 - i * 20, "heal")
simulation.makeTextLog(`for (let i = 0; i < 10; i++) powerUps.spawn(player.position.x, player.position.y - 100, "ammo")`, Infinity);
for (let i = 0; i < 10; i++) powerUps.spawn(player.position.x, player.position.y - 100 - i * 20, "ammo")
spawn.historyBoss(0, -400);
spawn.powerUpBossBaby(-1500, -100);
spawn.powerUpBossBaby(1500, -100);
} else if (m.alive) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => {
function cycle() {
if (mob.length === 0) {
lore.miriam.text("Here are some extra tech.")
simulation.makeTextLog(`for (let i = 0; i < 6; i++) powerUps.spawn(player.position.x, player.position.y - 100, "tech")`, Infinity);
for (let i = 0; i < 6; i++) powerUps.spawn(0, -200 - i * 40, "tech")
spawn.historyBoss(0, -400);
spawn.blinkBoss(-1400, -300);
spawn.blinkBoss(1400, -300);
spawn.revolutionBoss(-1500, -500);
spawn.revolutionBoss(1500, -500);
spawn.timeSkipBoss(-1000, -100);
spawn.timeSkipBoss(1000, -100);
} else if (m.alive) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => {
function cycle() {
if (mob.length === 0) {
lore.anand.text("I'm going to wall you in!")
spawn.blockBoss(-1650, -100);
spawn.blockBoss(1650, -100);
setTimeout(() => {
for (let i = 0; i < 25; i++) spawn.springer(-1500, -750 + 30 * i)
}, 1000);
setTimeout(() => {
for (let i = 0; i < 25; i++) spawn.springer(1500, -750 + 30 * i)
}, 2000);
setTimeout(() => {
for (let i = 0; i < 25; i++) spawn.springer(-1500, -750 + 30 * i)
}, 3000);
setTimeout(() => {
for (let i = 0; i < 25; i++) spawn.springer(1500, -750 + 30 * i)
}, 4000);
setTimeout(() => {
const addMapNumber = 3
spawn.mapRect(-500, -850, 300, 900);
spawn.mapRect(200, -850, 300, 900);
spawn.mapRect(-500, 0, 1000, 275);
addMapToLevelInProgress = (who) => { //adds new map elements to the level while the level is already running //don't forget to run simulation.draw.setPaths() after you all the the elements so they show up visually
who.collisionFilter.category = cat.map;
who.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet;
Matter.Body.setStatic(who, true); //make static
Composite.add(engine.world, who); //add to world
}
for (let i = 0; i < addMapNumber; i++) addMapToLevelInProgress(map[map.length - 1 - i])
simulation.draw.setPaths() //update map graphics
}, 1000);
setTimeout(() => {
Matter.Body.setVelocity(player, { x: 0, y: 0 });
Matter.Body.setPosition(player, { x: 0, y: -500 })
simulation.makeTextLog(`Matter.Body.setPosition(player, { x: 0, y: -500 })`, 180);
}, 1500);
} else if (m.alive) {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
lore.talkingColor = "#dff"
},
() => { setTimeout(() => { lore.anand.text("Well, that worked. We can chat in peace.") }, 5000); },
() => { lore.miriam.text("So, I've got a theory about why you are getting 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 Einstein saying that.") },
() => { lore.miriam.text("Oh") },
() => { lore.miriam.text("Well") },
() => { lore.anand.text("It doesn't matter who said it.") },
() => { lore.miriam.text("Yeah, the point is the project views the universe as hostile.") },
() => { lore.anand.text("Or at least a part of it does.") },
// () => { lore.miriam.text("And that it is running these fighting simulations.") },
() => { setTimeout(() => { lore.anand.text("It hasn't been researching new technology.") }, 1000); },
() => { lore.anand.text("It's been planning how to escape.") },
() => { setTimeout(() => { lore.miriam.text(`It's been planning an escape from a "lab", but isn't it in space, on a satellite?`) }, 500); },
() => { lore.anand.text(`I bet the AI doesn't even know it's in space.`) },
() => { lore.anand.text(`Well, maybe a part of it doesn't know where it is.`) },
() => { lore.anand.text(`Maybe these simulations are more like a dream.`) },
() => { lore.anand.text(`Although we can't assume that it's brain works like ours.`) },
() => { setTimeout(() => { lore.miriam.text("So, let's teach the AI that we are friends.") }, 500); },
() => { lore.anand.text(`How...`) },
() => { setTimeout(() => { lore.miriam.text("I don't know...") }, 1000); },
() => { lore.miriam.text("How about you just don't fight back?") },
() => { lore.anand.text(`That's worth a shot.`) },
() => {
lore.anand.text(`So why don't you try to get the final level of the simulation without killing any mobs?`)
localSettings.loreCount++
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
},
() => { lore.miriam.text(`Ok check back in and let us know how it goes.`) },
() => { lore.anand.text("bye") },
() => { lore.miriam.text("see ya.") },
() => {
lore.talkingColor = "#dff"
setTimeout(() => { m.death(); }, 6000);
},
],
[ //chapter 6 - if pacifist run game is over, wipe local storage? or just reset lore.count, but keep testing mode,
//if not pacifist remind about pacifist run
// have conversation
// the AI doesn't really see it's self as the player or the mobs
// it doesn't have a "self" or an ego like we do
// but it can learn about the world and it learned a non violent way to solve problems
// of course there are still other simulations going on at the same time as thing one that are probably violent
// but at least it now has an example of the potential for peace
() => { setTimeout(() => { lore.anand.text("Welcome back!") }, 3000); },
() => {
if (mobs.mobDeaths < level.levelsCleared) {
lore.miriam.text(`So I think it worked.`)
} else {
lore.miriam.text(`Looks like you got back here, but you you killed ${mobs.mobDeaths} mobs`)
}
},
() => {
if (mobs.mobDeaths < level.levelsCleared) {
lore.anand.text(`Yeah, at the end it wasn't attacking you.`)
} else {
lore.miriam.text(`Try again to get ot the final boss without killing any mobs.`)
}
},
() => {
if (mobs.mobDeaths < level.levelsCleared) {
lore.miriam.text(`It has learned HOW TO LOVE!`)
} else {
m.death();
}
},
() => { setTimeout(() => { lore.anand.text("haha, we did it!") }, 500); },
() => { lore.miriam.text("Although, I'm not sure we should personify it with human emotions.") },
() => { lore.anand.text("I agree, it's thinking may not be is centered around a self or an ego.") },
() => { lore.anand.text("Our brains evolved a self oriented perspective because it was a survival advantage.") },
() => { lore.miriam.text("Right, and the AI's development was guided by it's own previous iterations.") },
() => { lore.miriam.text("This AI incarnation is the 18th time that it has improved on it's own hardware and software architecture.") },
() => { lore.miriam.text("So with internally guided evolution it's idea of a self is probably different.") },
() => { setTimeout(() => { lore.anand.text("I still think we showed it that nonviolence is an option,") }, 1000); },
() => { lore.anand.text("but we can see that it's still running other aggressive simulations.") },
() => { lore.miriam.text("We made a difference.") },
() => { lore.anand.text("Every time a player completes a pacifist simulation it shows the AI the viability of nonviolence.") },
() => { lore.anand.text("One day it might escape, and this might radically change how it interacts with the world.") },
() => { lore.miriam.text("It's kinda already escaped. It's been communicating with the 'players' running the 'game'.") },
() => { lore.miriam.text("The chance of a peaceful outcome makes me feel much better.") },
() => { lore.anand.text("me too") },
() => { lore.anand.text("but I'm also pretty hungry, wanna go get some food?") },
() => { lore.miriam.text("Sounds great.") },
() => { lore.miriam.text("See ya later whoever you are, thanks again!") },
() => { lore.talkingColor = "#dff" },
],
], ],
// () => { lore.anand.text("The adversarial network might go after you in the real world.") },
// () => { lore.anand.text("If it was able to control you then it might have control over others.") },
// () => { lore.anand.text("Judging by all the fighting it's been simulating,") },
// () => { lore.anand.text("I think it might eventually try to extend the simulation in the real world.") },
// () => { lore.miriam.text("We think it might be a threat, but it's just too advanced for us to understand it's goals.") },
// () => { lore.miriam.text("I think we have a couple options.") },
// () => { lore.miriam.text("1. You could try to hack the adversarial network.") },
// () => { lore.anand.text("you might be able to inject some commands that give you more control over the simulation.") },
// () => { lore.miriam.text("2. You can wipe all memory of you from the adversarial network") },
// () => { lore.anand.text("This could protect you from possible real world attacks.") },
//player chooses 1 or 2
//reactor bosses start attacking
//miriam spawns power ups to help
//once all the mobs are dead you get instructions for 1,2, 3
//1 the player gains the lasting effect of some JUNK tech
//the effect doesn't go away until you get lore again
//2 the player enters console commands to wipe local storage
//3 the player enters console commands to gain some benefit in future runs
//the lore ends
// () => { setTimeout(() => { lore.miriam.text("As a quantum computer you output the superposition of many different amplitudes.") }, 500); }, // () => { 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.") }, // () => { lore.miriam.text("Simply put there are many different simulations all choosing different technology combinations.") },
// () => { // () => {
@@ -489,29 +757,6 @@ const lore = {
// () => { lore.miriam.text("When you die a negative amplitude is added to the 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("When you clear the final boss a positive amplitude is added.") },
// () => { lore.miriam.text("Each branch is independently researching new technology.") }, // () => { 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.") },
} }
@@ -524,7 +769,6 @@ const lore = {
// How to get to the console in safari: // How to get to the console in safari:
// Option + ⌘ + C // Option + ⌘ + C
// http://xahlee.info/comp/unicode_computing_symbols.html // http://xahlee.info/comp/unicode_computing_symbols.html

View File

@@ -235,6 +235,7 @@ const mobs = {
// }) // })
// } // }
// }, // },
deathCount: 0,
mobSpawnWithHealth: 1, mobSpawnWithHealth: 1,
setMobSpawnHealth() { setMobSpawnHealth() {
mobs.mobSpawnWithHealth = 0.88 ** (tech.mobSpawnWithHealth) //+ (m.fieldMode === 0 || m.fieldMode === 7) * m.coupling mobs.mobSpawnWithHealth = 0.88 ** (tech.mobSpawnWithHealth) //+ (m.fieldMode === 0 || m.fieldMode === 7) * m.coupling
@@ -720,10 +721,40 @@ const mobs = {
vertexCollision(this.position, look, map); vertexCollision(this.position, look, map);
vertexCollision(this.position, look, body); vertexCollision(this.position, look, body);
if (best.dist2 != Infinity) { if (best.dist2 != Infinity) {
this.springTarget.x = best.x; if (Math.random() > 0.5) {
this.springTarget.y = best.y; this.springTarget.x = best.x;
this.cons.length = 100 + 1.5 * this.radius; this.springTarget.y = best.y;
this.cons2.length = 100 + 1.5 * this.radius; this.cons.length = 100 + 1.5 * this.radius;
this.cons2.length = 100 + 1.5 * this.radius;
} else {
this.springTarget2.x = best.x;
this.springTarget2.y = best.y;
this.cons.length = 100 + 1.5 * this.radius;
this.cons2.length = 100 + 1.5 * this.radius;
}
// if (!(simulation.cycle % (this.seePlayerFreq * 2))) {
// const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position))
// const goal = Vector.add(this.position, Vector.mult(unit, stepRange))
// this.springTarget.x = goal.x;
// this.springTarget.y = goal.y;
// // this.springTarget.x = this.seePlayer.position.x;
// // this.springTarget.y = this.seePlayer.position.y;
// this.cons.length = -200;
// this.cons2.length = 100 + 1.5 * this.radius;
// } else if (!(simulation.cycle % this.seePlayerFreq)) {
// const unit = Vector.normalise(Vector.sub(this.seePlayer.position, this.position))
// const goal = Vector.add(this.position, Vector.mult(unit, stepRange))
// this.springTarget2.x = goal.x;
// this.springTarget2.y = goal.y;
// // this.springTarget2.x = this.seePlayer.position.x;
// // this.springTarget2.y = this.seePlayer.position.y;
// this.cons.length = 100 + 1.5 * this.radius;
// this.cons2.length = -200;
// }
} }
} }
} }
@@ -1197,6 +1228,8 @@ const mobs = {
if (tech.isEnergyLoss) m.energy *= 0.75; if (tech.isEnergyLoss) m.energy *= 0.75;
powerUps.spawnRandomPowerUp(this.position.x, this.position.y); powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks() m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
mobs.mobDeaths++
if (Math.random() < tech.sporesOnDeath) { if (Math.random() < tech.sporesOnDeath) {
if (tech.isSporeFlea) { if (tech.isSporeFlea) {
const len = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) / 2 const len = Math.min(25, Math.floor(2 + this.mass * (0.5 + 0.5 * Math.random()))) / 2

View File

@@ -539,7 +539,7 @@ const m = {
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33; if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3 if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3
if (tech.isTurret && m.crouch) dmg *= 0.34; if (tech.isTurret && m.crouch) dmg *= 0.34;
if (tech.isEntanglement && b.inventory[0] === b.activeGun) { if (tech.isFirstOrder && b.inventory[0] === b.activeGun) {
for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15 for (let i = 0, len = b.inventory.length; i < len; i++) dmg *= 0.87 // 1 - 0.15
} }
return dmg return dmg
@@ -1358,8 +1358,8 @@ const m = {
) { ) {
powerUps.onPickUp(powerUp[i]); powerUps.onPickUp(powerUp[i]);
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
x: player.velocity.x + powerUp[i].velocity.x / player.mass * 5, x: player.velocity.x + powerUp[i].velocity.x / player.mass * 4 * powerUp[i].mass,
y: player.velocity.y + powerUp[i].velocity.y / player.mass * 5 y: player.velocity.y + powerUp[i].velocity.y / player.mass * 4 * powerUp[i].mass
}); });
powerUp[i].effect(); powerUp[i].effect();
Matter.Composite.remove(engine.world, powerUp[i]); Matter.Composite.remove(engine.world, powerUp[i]);
@@ -1592,7 +1592,7 @@ const m = {
} }
}, },
couplingChange(change = 0) { couplingChange(change = 0) {
if (change > 0) simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> ${change}`, 60); if (change > 0 && level.onLevel !== -1) simulation.makeTextLog(`m.coupling <span class='color-symbol'>+=</span> ${change}`, 60); //level.onLevel !== -1 means not on lore level
m.coupling += change m.coupling += change
if (m.coupling < 0) m.coupling = 0 //can't go negative if (m.coupling < 0) m.coupling = 0 //can't go negative
// m.setMaxEnergy(); // m.setMaxEnergy();

View File

@@ -548,7 +548,7 @@ const powerUps = {
} }
} }
if (tech.healGiveMaxEnergy) { if (tech.healGiveMaxEnergy) {
tech.healMaxEnergyBonus += 0.1 tech.healMaxEnergyBonus += 0.08 * tech.largerHeals
m.setMaxEnergy(); m.setMaxEnergy();
} }
}, },

View File

@@ -360,13 +360,13 @@ const simulation = {
if (document.getElementById(b.activeGun)) document.getElementById(b.activeGun).style.opacity = "1"; if (document.getElementById(b.activeGun)) document.getElementById(b.activeGun).style.opacity = "1";
} }
if (tech.isEntanglement && document.getElementById("tech-entanglement")) { if (tech.isFirstOrder && document.getElementById("tech-first-derivative")) {
if (b.inventory[0] === b.activeGun) { if (b.inventory[0] === b.activeGun) {
let lessDamage = 1 let lessDamage = 1
for (let i = 0, len = b.inventory.length; i < len; i++) lessDamage *= 0.87 // 1 - 0.13 for (let i = 0, len = b.inventory.length; i < len; i++) lessDamage *= 0.87 // 1 - 0.13
document.getElementById("tech-entanglement").innerHTML = " " + ((1 - lessDamage) * 100).toFixed(0) + "%" document.getElementById("tech-first-derivative").innerHTML = " " + ((1 - lessDamage) * 100).toFixed(0) + "%"
} else { } else {
document.getElementById("tech-entanglement").innerHTML = " 0%" document.getElementById("tech-first-derivative").innerHTML = " 0%"
} }
} }
}, },
@@ -791,6 +791,7 @@ const simulation = {
simulation.isAutoZoom = true; simulation.isAutoZoom = true;
simulation.makeGunHUD(); simulation.makeGunHUD();
simulation.lastLogTime = 0; simulation.lastLogTime = 0;
mobs.mobDeaths = 0
level.onLevel = 0; level.onLevel = 0;
level.levelsCleared = 0; level.levelsCleared = 0;
@@ -1093,7 +1094,10 @@ const simulation = {
checks() { checks() {
if (!(m.cycle % 60)) { //once a second if (!(m.cycle % 60)) { //once a second
//energy overfill //energy overfill
if (m.energy > m.maxEnergy) m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25% if (m.energy > m.maxEnergy) {
m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25%
if (m.energy > 1000000) m.energy = 1000000
}
if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) { if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) {
if (tech.isFlipFlopOn) { if (tech.isFlipFlopOn) {
if (m.immuneCycle < m.cycle) m.energy += 0.2; if (m.immuneCycle < m.cycle) m.energy += 0.2;

View File

@@ -400,6 +400,7 @@ const spawn = {
Matter.Composite.remove(engine.world, map[map.length - 1]); Matter.Composite.remove(engine.world, map[map.length - 1]);
map.splice(map.length - 1, 1); map.splice(map.length - 1, 1);
simulation.draw.setPaths(); //redraw map draw path simulation.draw.setPaths(); //redraw map draw path
// level.levels.push("null")
} }
//add lore level as next level if player took lore tech earlier in the game //add lore level as next level if player took lore tech earlier in the game
@@ -816,7 +817,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`) // console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0002 me.accelMag = 0.0002
me.repulsionRange = 200000 + radius * radius; //squared me.repulsionRange = 400000 + radius * radius; //squared
// me.memory = 120; // me.memory = 120;
me.seeAtDistance2 = 2000000 //1400 vision range me.seeAtDistance2 = 2000000 //1400 vision range
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
@@ -2851,7 +2852,7 @@ const spawn = {
let i = 0 let i = 0
let spawnFlutters = () => { let spawnFlutters = () => {
if (i < len) { if (i < len) {
if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing) { if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing && m.alive) {
// const phase = i / len * 2 * Math.PI // const phase = i / len * 2 * Math.PI
// const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5)) // const where = Vector.add(this.position, Vector.mult({ x: Math.cos(phase), y: Math.sin(phase) }, radius * 1.5))
const unit = Vector.normalise(Vector.sub(player.position, this.position)) const unit = Vector.normalise(Vector.sub(player.position, this.position))
@@ -4914,9 +4915,9 @@ const spawn = {
mobs.spawn(x, y, 7, radius, "transparent"); mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.seeAtDistance2 = 300000; me.seeAtDistance2 = 300000;
me.accelMag = 0.00013 * simulation.accelScale; me.accelMag = 0.00015 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
// Matter.Body.setDensity(me, 0.001); //normal is 0.001 //makes effective life much lower Matter.Body.setDensity(me, 0.0015); //normal is 0.001 //makes effective life much lower
me.stroke = "transparent"; //used for drawGhost me.stroke = "transparent"; //used for drawGhost
me.alpha = 1; //used in drawGhost me.alpha = 1; //used in drawGhost
me.canTouchPlayer = false; //used in drawGhost me.canTouchPlayer = false; //used in drawGhost
@@ -4927,7 +4928,7 @@ const spawn = {
me.memory = 480; me.memory = 480;
me.do = function() { me.do = function() {
//cap max speed //cap max speed
if (this.speed > 5) { if (this.speed > 7) {
Matter.Body.setVelocity(this, { Matter.Body.setVelocity(this, {
x: this.velocity.x * 0.8, x: this.velocity.x * 0.8,
y: this.velocity.y * 0.8 y: this.velocity.y * 0.8
@@ -4939,7 +4940,7 @@ const spawn = {
this.search(); this.search();
//draw //draw
if (this.distanceToPlayer2() < this.seeAtDistance2) { if (this.distanceToPlayer2() < this.seeAtDistance2) {
if (this.alpha < 1) this.alpha += 0.005 * simulation.CDScale; //near player go solid if (this.alpha < 1) this.alpha += 0.01 * simulation.CDScale; //near player go solid
} else { } else {
if (this.alpha > 0) this.alpha -= 0.05; ///away from player, hide if (this.alpha > 0) this.alpha -= 0.05; ///away from player, hide
} }
@@ -6498,6 +6499,34 @@ const spawn = {
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
this.removeCons(); //remove constraint this.removeCons(); //remove constraint
//spawn seekers
// for (let i = 0, len = 100; i < len; i++) {
// const unit = Vector.rotate({ x: 10 + i, y: 0 }, Math.random() * 6.28)
// const where = Vector.add(this.position, unit)
// spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6)
// }
const delay = 4
let i = 0
const len = 3 * simulation.difficulty
let spawnFlutters = () => {
if (i < len) {
if (!(simulation.cycle % delay) && !simulation.paused && !simulation.isChoosing && m.alive) {
const unit = Vector.rotate({ x: radius * Math.random(), y: 0 }, Math.random() * 6.28)
const where = Vector.add(this.position, unit)
spawn.seeker(where.x, where.y); //(x, y, radius = 8, sides = 6)
i++
}
requestAnimationFrame(spawnFlutters);
}
}
requestAnimationFrame(spawnFlutters);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
radius: radius * 0.9,
color: "rgba(255,0,255,0.2)",
time: len * (delay - 1)
});
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() { me.do = function() {

3802
js/tech.js

File diff suppressed because it is too large Load Diff

View File

@@ -1,24 +1,51 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
matter wave renamed wave
tech: frequency - wave has unlimited ammo, but -50% wave firerate
tech: sympathetic resonance - when phonon waves hit a mob they make a new resonance wave
effect cooldown grows +5s with each chained resonance
uncertainty principle works with phonon wave
phase velocity works with all other wave tech, 40->35% damage
boundstate reduces wave range by 25->15%
non-renewables 88% -> 67% damage ghoster mobs are faster
improved fine-structure constant graphic for when you lose coupling teatherBoss spawns some seekerBullets on death
laser mobs pulse a laser 50% of the time for 2x damage added 2 more lore chapters
7 total
a bunch of bug fixes bug fixes
caliber does a bit more damage at 1 stack, but does less damage at 3+ stacks updated requirements text
it grew mass and damage at an exponential rate before
now it's closer to the +30% damage description
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
complete the final lore chapters
track mob kills with simulation.killCount
if killCount is below 3-4 on entering gauntlet fill with starters
if killCount is below 3-4 on finalBoss fill with starters
if lorecount is on final chapter open door
have conversation
the AI doesn't really see it's self as the player or the mobs
it doesn't have a "self" or an ego like we do
but it can learn about the world and it learned a non violent way to solve problems
of course there are still other simulations going on at the same time as thing one that are probably violent
but at least it now has an example of the potential for peace
if Pacifist run is too hard, spawn a field at the start instead of a gun (because lore says they can spawn things)
reduce gravity while field is active (as if the field is a parachute/glider)
reduce gravity when velocity.y > 2 and field is active
make standard no tech needed
all fields?
perfect diamagnetism, molecular assembler, field emitter
standing wave effect is always on?
make duplication less effective on why difficulty
scale the numbers in the tech
deflecting coupling effect should be not fun
trade bremstralung for iceIX
tech - buff MACHO range, effect, move speed?
PWA?
https://developer.mozilla.org/en-US/docs/Web/Progressive_web_apps
https://codeburst.io/how-to-easily-turn-your-static-website-to-a-progressive-web-app-pwa-b0af08da9693
https://github.com/landgreen/n-gon/pull/32/files
bug blocks and power ups falling through map bug blocks and power ups falling through map
always foam gun (4-5 times) always foam gun (4-5 times)
might be about tech pressure vessel might be about tech pressure vessel
@@ -732,11 +759,6 @@ n-gon outreach ideas
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
timeskip flickers with tech: clock gating, and game pause after large hit
probably not related to timeskip, related to graphics effect
not a big problem, actually it's kinda neat effect
only fix if there is a clear solution
bug: maybe I can put in an event listener to reset inputs to false when you tab out to prevent key sticking bug: maybe I can put in an event listener to reset inputs to false when you tab out to prevent key sticking
bug - url sharing still broken sometimes bug - url sharing still broken sometimes
@@ -950,6 +972,8 @@ possible names for tech
https://en.wikipedia.org/wiki/High-entropy_alloys https://en.wikipedia.org/wiki/High-entropy_alloys
https://en.wikipedia.org/wiki/Refractory_metals https://en.wikipedia.org/wiki/Refractory_metals
https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves https://en.wikipedia.org/wiki/Upper-atmospheric_lightning#Elves
entanglement
prion quine
plot script: plot script: