training maps

first 4 levels of the training maps are live
  this is very much a work in progress, but I'm putting it up for feedback

stunned and frozen mobs do no harm by default
  removed tech: osmoprotectant - stunned and frozen mobs do no harm

tech: annelids - randomly increase worm size and damage up to 100%

weak anthropic principle gives 45->50% duplication chance after almost dieing
complex spin-statistics immune to harm for 1.5->1.8 s every 7 s
exciton gives 60->66% damage
electronegativity gives 1% dmg for every 11->10 stored energy
arsenal gives 14->12% more damage per gun
pair production is now also a standing wave field tech
mass-energy takes 10% less damage
JUNK tech black hole cluster spawns mobs farther away, so you have a better chance to survive
undefinded tech no longer shows up on your first couple times playing, since it's a distraction for new players
This commit is contained in:
landgreen committed 2021-12-20 12:03:38 -08:00
1 parent 1a5a395992
commit 9dc5c8d456
13 files changed
+859 -429

No files matched your search

Vendored
BIN
View File
Binary file not shown.
+5
View File
@@ -93,6 +93,11 @@
<text x="10" y="33">experiment</text> <text x="10" y="33">experiment</text>
</g> </g>
</svg> </svg>
<svg class="SVG-button" id="training-button" width="120" height="45" style="border: 2px #333 solid;" onclick="simulation.startGame(false, true)">
<g stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Arial, sans-serif">
<text x="10" y="33">training</text>
</g>
</svg>
<div id='info'> <div id='info'>
<div id="settings"> <div id="settings">
<details> <details>
+7 -5
View File
@@ -2361,9 +2361,9 @@ const b = {
}, },
worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death() worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
const bIndex = bullet.length; const bIndex = bullet.length;
const size = 3 const wormSize = 6 + tech.wormSize * 7.2 * Math.random()
if (bIndex < 500) { //can't make over 500 spores if (bIndex < 500) { //can't make over 500 spores
bullet[bIndex] = Bodies.polygon(where.x, where.y, size, size, { bullet[bIndex] = Bodies.polygon(where.x, where.y, 3, 3, {
inertia: Infinity, inertia: Infinity,
isFreeze: isFreeze, isFreeze: isFreeze,
restitution: 0.5, restitution: 0.5,
@@ -2371,7 +2371,9 @@ const b = {
friction: 0, friction: 0,
frictionAir: 0.025, frictionAir: 0.025,
thrust: (tech.isFastSpores ? 0.001 : 0.0005) * (1 + 0.5 * (Math.random() - 0.5)), thrust: (tech.isFastSpores ? 0.001 : 0.0005) * (1 + 0.5 * (Math.random() - 0.5)),
dmg: (tech.isMutualism ? 16.8 : 7) * 2.5, //bonus damage from tech.isMutualism //2.5 is extra damage as worm wormSize: wormSize,
wormTail: 1 + wormSize,
dmg: (tech.isMutualism ? 7 : 2.9) * wormSize, //bonus damage from tech.isMutualism //2.5 is extra damage as worm
lookFrequency: 100 + Math.floor(37 * Math.random()), lookFrequency: 100 + Math.floor(37 * Math.random()),
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -2408,10 +2410,10 @@ const b = {
do() { do() {
ctx.beginPath(); //draw nematode ctx.beginPath(); //draw nematode
ctx.moveTo(this.position.x, this.position.y); ctx.moveTo(this.position.x, this.position.y);
const dir = Vector.mult(Vector.normalise(this.velocity), -Math.min(45, 7 * this.speed)) const dir = Vector.mult(Vector.normalise(this.velocity), -Math.min(100, this.wormTail * this.speed))
const tail = Vector.add(this.position, dir) const tail = Vector.add(this.position, dir)
ctx.lineTo(tail.x, tail.y); ctx.lineTo(tail.x, tail.y);
ctx.lineWidth = 6; ctx.lineWidth = this.wormSize;
ctx.strokeStyle = "#000"; ctx.strokeStyle = "#000";
ctx.stroke(); ctx.stroke();
+1 -1
View File
@@ -103,7 +103,7 @@ function collisionChecks(event) {
if ( if (
m.immuneCycle < m.cycle && m.immuneCycle < m.cycle &&
(obj === playerBody || obj === playerHead) && (obj === playerBody || obj === playerHead) &&
!(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned)) !mob[k].isSlowed && !mob[k].isStunned
) { ) {
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
if (m.isCloak) dmg *= 0.5 if (m.isCloak) dmg *= 0.5
+1 -11
View File
@@ -622,6 +622,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
function openExperimentMenu() { function openExperimentMenu() {
document.getElementById("experiment-button").style.display = "none"; document.getElementById("experiment-button").style.display = "none";
document.getElementById("training-button").style.display = "none";
const el = document.getElementById("experiment-grid") const el = document.getElementById("experiment-grid")
el.style.display = "grid" el.style.display = "grid"
document.body.style.overflowY = "scroll"; document.body.style.overflowY = "scroll";
@@ -1295,16 +1296,5 @@ function cycle() {
level.start(); level.start();
} }
simulation.loop(); simulation.loop();
// if (isNaN(m.health) || isNaN(m.energy)) {
// console.log(`m.health = ${m.health}`)
// simulation.paused = true;
// build.pauseGrid()
// document.body.style.cursor = "auto";
// alert("health is NaN, please report this bug to the discord \n https://discordapp.com/invite/2eC9pgJ")
// }
// for (let i = 0, len = loop.length; i < len; i++) {
// loop[i]()
// }
} }
} }
// simulation.introPlayer()
+372 -32
View File
@@ -8,6 +8,7 @@ const level = {
onLevel: -1, onLevel: -1,
levelsCleared: 0, levelsCleared: 0,
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"], playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"],
trainingLevels: ["trainingHold", "trainingThrow", "trainingCrouch", "trainingJump"],
levels: [], levels: [],
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
@@ -17,19 +18,23 @@ const level = {
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("plasma torch") // m.setField("plasma torch")
// b.giveGuns("drones") // b.giveGuns("spores")
// b.giveGuns("nail gun") // b.giveGuns("nail gun")
// b.giveGuns("harpoon") // b.giveGuns("harpoon")
// tech.giveTech("brainstorming") // tech.giveTech("nematodes")
// tech.giveTech("nanowires") // for (let i = 0; i < 9; i++) tech.giveTech("annelids")
// tech.giveTech("relativistic momentum") // tech.giveTech("tinsellated flagella")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal") // for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience") // tech.giveTech("antiscience")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum") // for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot") // for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.tech[297].frequency = 100 // tech.tech[297].frequency = 100
// level.trainingThrow();
level.intro(); //starting level if (simulation.isTraining) {
level.trainingHold();
} else {
level.intro(); //starting level
}
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
// level.template(); //not in rotation, blank start new map development // level.template(); //not in rotation, blank start new map development
// level.final() //final boss level // level.final() //final boss level
@@ -68,13 +73,13 @@ const level = {
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"]
level[level.levels[level.onLevel]](); //picks the current map from the the levels array level[level.levels[level.onLevel]](); //picks the current map from the the levels array
if (!simulation.isCheating && !build.isExperimentRun) { if (!simulation.isCheating && !build.isExperimentRun && !simulation.isTraining) {
localSettings.runCount += level.levelsCleared //track the number of total runs locally localSettings.runCount += level.levelsCleared //track the number of total runs locally
localSettings.levelsClearedLastGame = level.levelsCleared localSettings.levelsClearedLastGame = level.levelsCleared
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} }
} }
level.levelAnnounce(); if (!simulation.isTraining) level.levelAnnounce();
simulation.noCameraScroll(); simulation.noCameraScroll();
simulation.setZoom(); simulation.setZoom();
level.addToWorld(); //add bodies to game engine level.addToWorld(); //add bodies to game engine
@@ -131,6 +136,337 @@ const level = {
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "tech", false); //start // for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "tech", false); //start
} }
}, },
trainingJump() { //learn to crouch
m.addHealth(Infinity)
document.getElementById("health").style.display = "none" //hide your health bar
document.getElementById("health-bg").style.display = "none"
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1400 //1400 is normal
level.defaultZoom = 1400
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#e1e1e1";
simulation.lastLogTime = 0; //clear previous messages
let instruction = 0
simulation.makeTextLog(`hold down <strong>${input.key.up}</strong> longer to jump higher`, Infinity)
level.custom = () => {
if (instruction === 0 && m.pos.x > 300) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>hold down <strong>${input.key.up}</strong> longer to jump higher</s>`, Infinity)
}
m.health = 1 //can't die
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(1600, -400, 400, 400)
level.exit.draw();
level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
//dark
ctx.fillStyle = "rgba(0,0,0,0.2)"
ctx.fillRect(1000, 0, 450, 1800)
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(2000, -2800, 2600, 4600); //right wall
spawn.mapRect(275, -350, 200, 375);
spawn.mapRect(-250, 0, 1250, 1800);
spawn.mapRect(1450, 0, 1075, 1800);
spawn.mapRect(-250, -2800, 3500, 2200); //roof
spawn.mapRect(1600, -1200, 500, 850); //exit roof
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
trainingCrouch() { //learn to crouch
m.addHealth(Infinity)
//hide your health bar
document.getElementById("health").style.display = "none"
document.getElementById("health-bg").style.display = "none"
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1400 //1400 is normal
level.defaultZoom = 1400
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#e1e1e1";
simulation.lastLogTime = 0; //clear previous messages
let instruction = 0
simulation.makeTextLog(`press <strong>${input.key.down}</strong> to crouch`, Infinity)
level.custom = () => {
if (instruction === 0 && input.down) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>press <strong>${input.key.down}</strong> to crouch</s>`, Infinity)
}
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(1650, -400, 400, 400)
level.exit.draw();
level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1650, -400, 400, 400)
//dark
ctx.fillStyle = "rgba(0,0,0,0.2)"
ctx.fillRect(625, -100, 1025, 175)
};
// spawn.mapRect(1025, -675, 300, 623); //crouch wall
spawn.mapRect(625, -650, 1025, 550);
spawn.mapRect(-200, -650, 875, 300);
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(2000, -2800, 2600, 4600); //right wall
spawn.mapRect(-250, 50, 3500, 1750); //floor
spawn.mapRect(-200, 0, 950, 100);
spawn.mapRect(1575, 0, 500, 100);
spawn.mapRect(-250, -2800, 3500, 2200); //roof
spawn.mapRect(725, 12, 50, 25);
spawn.mapRect(725, 25, 75, 25);
spawn.mapRect(750, 38, 75, 25);
spawn.mapRect(1525, 25, 75, 50);
spawn.mapRect(1500, 38, 50, 25);
spawn.mapRect(1550, 12, 50, 25);
spawn.mapRect(1600, -1200, 500, 850); //exit roof
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
trainingThrow() { //throw a block on button to open door
m.addHealth(Infinity)
//hide your health bar
document.getElementById("health").style.display = "none"
document.getElementById("health-bg").style.display = "none"
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1400 //1400 is normal
level.defaultZoom = 1400
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#e1e1e1";
spawn.bodyRect(1025, -75, 50, 50); //block to go on button
const buttonDoor = level.button(1635, -400)
const door = level.door(1612.5, -175, 25, 190, 185, 3)
simulation.lastLogTime = 0; //clear previous messages
let instruction = 0
simulation.makeTextLog(`activate your <strong class='color-f'>field</strong> with <strong>space</strong> or <strong>right mouse</strong>
<br>pick up the <strong class='color-block'>block</strong> with your <strong class='color-f'>field</strong>`, Infinity)
level.custom = () => {
console.log(m.throwCharge)
if (instruction === 0 && m.isHolding) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>pick up the <strong class='color-block'>block</strong> with your <strong class='color-f'>field</strong></s>
<br>hold your <strong class='color-f'>field</strong> down to charge up then release to throw a <strong class='color-block'>block</strong>`, Infinity)
} else if (instruction === 1 && m.throwCharge > 2) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>pick up the <strong class='color-block'>block</strong> with your <strong class='color-f'>field</strong>
<br>hold your <strong class='color-f'>field</strong> down to charge up then release to throw a <strong class='color-block'>block</strong></s>
<br>throw the <strong class='color-block'>block</strong> onto the button`, Infinity)
// the <strong class='color-block'>block</strong> at the button
} else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>pick up the <strong class='color-block'>block</strong> with your <strong class='color-f'>field</strong>
<br>hold your <strong class='color-f'>field</strong> down to charge up then release to throw a <strong class='color-block'>block</strong>
<br>throw the <strong class='color-block'>block</strong> onto the button</s>`, Infinity)
}
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(1600, -400, 400, 400)
level.exit.draw();
level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
buttonDoor.query();
buttonDoor.draw();
if (buttonDoor.isUp) {
door.isOpen = true
} else {
door.isOpen = false
}
door.openClose();
door.draw();
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(2000, -2800, 2600, 4600); //right wall
spawn.mapRect(-250, 50, 3500, 1750); //floor
spawn.mapRect(-200, 0, 950, 100);
spawn.mapRect(1575, 0, 500, 100);
spawn.mapRect(-250, -2800, 3500, 2200); //roof
spawn.mapRect(725, 12, 50, 25);
spawn.mapRect(725, 25, 75, 25);
spawn.mapRect(750, 38, 75, 25);
spawn.mapRect(1525, 25, 75, 50);
spawn.mapRect(1500, 38, 50, 25);
spawn.mapRect(1550, 12, 50, 25);
// spawn.mapRect(1600, -1200, 500, 850); //exit roof
spawn.mapRect(1790, -600, 250, 225); //button left wall
spawn.mapRect(1625, -400, 400, 50);
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
trainingHold() { //put block on button to open door
m.addHealth(Infinity)
//hide your health bar
document.getElementById("health").style.display = "none"
document.getElementById("health-bg").style.display = "none"
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1400 //1400 is normal
level.defaultZoom = 1400
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#e1e1e1";
spawn.bodyRect(1025, -75, 50, 50); //block to go on button
const buttonDoor = level.button(500, 0)
const door = level.door(1612.5, -175, 25, 190, 185, 3)
simulation.lastLogTime = 0; //clear previous messages
let instruction = 0
simulation.makeTextLog(`activate your <strong class='color-f'>field</strong> with <strong>space</strong> or <strong>right mouse</strong>`, Infinity)
level.custom = () => {
if (instruction === 0 && input.field) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>activate your <strong class='color-f'>field</strong> with <strong>space</strong> or <strong>right mouse</strong></s><br>release your <strong class='color-f'>field</strong> on a <strong class='color-block'>block</strong> to pick it up`, Infinity)
} else if (instruction === 1 && m.isHolding) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>activate your <strong class='color-f'>field</strong> with <strong>space</strong> or <strong>right mouse</strong><br>release your <strong class='color-f'>field</strong> on a <strong class='color-block'>block</strong> to pick it up</s><br>drop the <strong class='color-block'>block</strong> on the red button to open the door`, Infinity)
} else if (instruction === 2 && !buttonDoor.isUp && Vector.magnitudeSquared(Vector.sub(body[0].position, buttonDoor.min)) < 10000) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>activate your <strong class='color-f'>field</strong> with <strong>space</strong> or <strong>right mouse</strong><br>release your <strong class='color-f'>field</strong> on a <strong class='color-block'>block</strong> to pick it up<br>drop the <strong class='color-block'>block</strong> on the red button to open the door</s>`, Infinity)
}
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(1600, -400, 400, 400)
level.exit.draw();
level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
buttonDoor.query();
buttonDoor.draw();
if (buttonDoor.isUp) {
door.isOpen = true
} else {
door.isOpen = false
}
door.openClose();
door.draw();
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(2000, -2800, 2600, 4600); //right wall
spawn.mapRect(-250, 50, 3500, 1750); //floor
spawn.mapRect(-200, 0, 950, 100);
spawn.mapRect(1575, 0, 500, 100);
spawn.mapRect(-250, -2800, 3500, 2200); //roof
spawn.mapRect(725, 12, 50, 25);
spawn.mapRect(725, 25, 75, 25);
spawn.mapRect(750, 38, 75, 25);
spawn.mapRect(1525, 25, 75, 50);
spawn.mapRect(1500, 38, 50, 25);
spawn.mapRect(1550, 12, 50, 25);
spawn.mapRect(1600, -1200, 500, 850); //exit roof
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
trainingTemplate() { //learn to crouch
m.addHealth(Infinity)
document.getElementById("health").style.display = "none" //hide your health bar
document.getElementById("health-bg").style.display = "none"
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 100); //exit bump
simulation.zoomScale = 1400 //1400 is normal
level.defaultZoom = 1400
simulation.zoomTransition(level.defaultZoom, 1)
document.body.style.backgroundColor = "#e1e1e1";
simulation.lastLogTime = 0; //clear previous messages
let instruction = 0
simulation.makeTextLog(`press <strong>${input.key.down}</strong> to crouch`, Infinity)
level.custom = () => {
if (instruction === 0 && input.down) {
instruction++
simulation.lastLogTime = 0; //clear previous messages
simulation.makeTextLog(`<s>press <strong>${input.key.down}</strong> to crouch</s>`, Infinity)
}
//exit room
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(1600, -400, 400, 400)
level.exit.draw();
level.enter.draw();
level.playerExitCheck();
};
level.customTopLayer = () => {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
spawn.mapRect(2000, -2800, 2600, 4600); //right wall
spawn.mapRect(-250, 50, 3500, 1750); //floor
spawn.mapRect(-200, 0, 950, 100);
spawn.mapRect(1575, 0, 500, 100);
spawn.mapRect(-250, -2800, 3500, 2200); //roof
spawn.mapRect(725, 12, 50, 25);
spawn.mapRect(725, 25, 75, 25);
spawn.mapRect(750, 38, 75, 25);
spawn.mapRect(1525, 25, 75, 50);
spawn.mapRect(1500, 38, 50, 25);
spawn.mapRect(1550, 12, 50, 25);
spawn.mapRect(1600, -1200, 500, 850); //exit roof
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
custom() {}, custom() {},
customTopLayer() {}, customTopLayer() {},
setDifficulty() { setDifficulty() {
@@ -214,27 +550,31 @@ const level = {
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
}, },
populateLevels() { populateLevels() {
simulation.isHorizontalFlipped = (Math.random() < 0.5) ? true : false //if true, some maps are flipped horizontally if (simulation.isTraining) {
level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment level.levels = level.trainingLevels.slice(0) //copy array, not by just by assignment
if (simulation.isCommunityMaps) {
level.levels.push("stronghold");
level.levels.push("basement");
level.levels.push("crossfire");
level.levels.push("vats")
level.levels.push("n-gon")
level.levels.push("house");
level.levels.push("perplex");
level.levels.push("coliseum");
level.levels.push("tunnel");
level.levels = shuffle(level.levels); //shuffles order of maps
level.levels.splice(0, 9); //remove some random levels to make up for adding the community levels
} else { } else {
level.levels = shuffle(level.levels); //shuffles order of maps simulation.isHorizontalFlipped = (Math.random() < 0.5) ? true : false //if true, some maps are flipped horizontally
} level.levels = level.playableLevels.slice(0) //copy array, not by just by assignment
if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech if (simulation.isCommunityMaps) {
level.levels.unshift("intro"); //add level to the start of the randomized levels list level.levels.push("stronghold");
level.levels.push("gauntlet"); //add level to the end of the randomized levels list level.levels.push("basement");
level.levels.push("final"); //add level to the end of the randomized levels list level.levels.push("crossfire");
level.levels.push("vats")
level.levels.push("n-gon")
level.levels.push("house");
level.levels.push("perplex");
level.levels.push("coliseum");
level.levels.push("tunnel");
level.levels = shuffle(level.levels); //shuffles order of maps
level.levels.splice(0, 9); //remove some random levels to make up for adding the community levels
} else {
level.levels = shuffle(level.levels); //shuffles order of maps
}
if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech
level.levels.unshift("intro"); //add level to the start of the randomized levels list
level.levels.push("gauntlet"); //add level to the end of the randomized levels list
level.levels.push("final"); //add level to the end of the randomized levels list
}
} }
}, },
flipHorizontal() { flipHorizontal() {
@@ -723,7 +1063,7 @@ const level = {
} }
} }
}, },
door(x, y, width, height, distance) { door(x, y, width, height, distance, speed = 1) {
x = x + width / 2 x = x + width / 2
y = y + height / 2 y = y + height / 2
const doorBlock = body[body.length] = Bodies.rectangle(x, y, width, height, { const doorBlock = body[body.length] = Bodies.rectangle(x, y, width, height, {
@@ -743,7 +1083,7 @@ const level = {
if (this.position.y > y - distance) { //try to open if (this.position.y > y - distance) { //try to open
const position = { const position = {
x: this.position.x, x: this.position.x,
y: this.position.y - 1 y: this.position.y - speed
} }
Matter.Body.setPosition(this, position) Matter.Body.setPosition(this, position)
} }
@@ -756,7 +1096,7 @@ const level = {
) { ) {
const position = { const position = {
x: this.position.x, x: this.position.x,
y: this.position.y + 1 y: this.position.y + speed
} }
Matter.Body.setPosition(this, position) Matter.Body.setPosition(this, position)
} }
@@ -1228,7 +1568,7 @@ const level = {
spawn.randomMob(x + 1175, y - 725, mobSpawnChance); spawn.randomMob(x + 1175, y - 725, mobSpawnChance);
spawn.randomMob(x + 1450, y - 725, mobSpawnChance); spawn.randomMob(x + 1450, y - 725, mobSpawnChance);
spawn.randomMob(x + 425, y - 100, mobSpawnChance); spawn.randomMob(x + 425, y - 100, mobSpawnChance);
spawn.randomMob(x + 1200, y - 125, mobSpawnChance); spawn.randomMob(x + 1700, y - 300, mobSpawnChance);
spawn.randomMob(x + 1300, y - 375, mobSpawnChance); spawn.randomMob(x + 1300, y - 375, mobSpawnChance);
} }
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
+1 -1
View File
@@ -45,7 +45,7 @@ const lore = {
if (localSettings.loreCount < 1) localSettings.loreCount = 1 if (localSettings.loreCount < 1) localSettings.loreCount = 1
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" // document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity); simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
sound.portamento(50) sound.portamento(50)
+2 -5
View File
@@ -647,7 +647,7 @@ const m = {
} }
if (tech.isEnergyHealth) { if (tech.isEnergyHealth) {
m.energy -= dmg * 1.1; m.energy -= dmg
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) { if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
tech.isDeathAvoidedThisLevel = true tech.isDeathAvoidedThisLevel = true
@@ -1248,7 +1248,6 @@ const m = {
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, range, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false); ctx.arc(m.pos.x, m.pos.y, range, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
ctx.lineWidth = 2; ctx.lineWidth = 2;
ctx.lineCap = "butt"
ctx.stroke(); ctx.stroke();
let eye = 13; let eye = 13;
let aMag = 0.75 * Math.PI * m.fieldArc let aMag = 0.75 * Math.PI * m.fieldArc
@@ -1741,7 +1740,6 @@ const m = {
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false); ctx.arc(m.pos.x, m.pos.y, m.fieldRange, m.angle - Math.PI * m.fieldArc, m.angle + Math.PI * m.fieldArc, false);
ctx.lineWidth = 2.5 - 1.5 * wave; ctx.lineWidth = 2.5 - 1.5 * wave;
ctx.lineCap = "butt"
ctx.stroke(); ctx.stroke();
const curve = 0.57 + 0.04 * wave const curve = 0.57 + 0.04 * wave
const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
@@ -1766,7 +1764,6 @@ const m = {
ctx.beginPath(); ctx.beginPath();
ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false); ctx.arc(m.fieldPosition.x, m.fieldPosition.y, m.fieldRange, m.fieldAngle - Math.PI * m.fieldArc, m.fieldAngle + Math.PI * m.fieldArc, false);
ctx.lineWidth = 2.5 - 1.5 * wave; ctx.lineWidth = 2.5 - 1.5 * wave;
ctx.lineCap = "butt"
ctx.stroke(); ctx.stroke();
const curve = 0.8 + 0.06 * wave const curve = 0.8 + 0.06 * wave
const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
@@ -3564,7 +3561,7 @@ const m = {
m.immuneCycle < m.cycle && m.immuneCycle < m.cycle &&
// (obj === playerBody || obj === playerHead) && // (obj === playerBody || obj === playerHead) &&
(obj === player) && (obj === player) &&
!(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned)) !mob[k].isSlowed && !mob[k].isStunned
) { ) {
mob[k].foundPlayer(); mob[k].foundPlayer();
let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0 let dmg = Math.min(Math.max(0.025 * Math.sqrt(mob[k].mass), 0.05), 0.3) * simulation.dmgScale; //player damage is capped at 0.3*dmgScale of 1.0
+10 -2
View File
@@ -110,6 +110,7 @@ const simulation = {
g: 0.0024, // applies to player, bodies, and power ups (not mobs) g: 0.0024, // applies to player, bodies, and power ups (not mobs)
onTitlePage: true, onTitlePage: true,
isCheating: false, isCheating: false,
isTraining: false,
paused: false, paused: false,
isChoosing: false, isChoosing: false,
testing: false, //testing mode: shows wire frame and some variables testing: false, //testing mode: shows wire frame and some variables
@@ -530,6 +531,8 @@ const simulation = {
document.getElementById("info").style.opacity = "0"; document.getElementById("info").style.opacity = "0";
document.getElementById("experiment-button").style.display = "inline" document.getElementById("experiment-button").style.display = "inline"
document.getElementById("experiment-button").style.opacity = "0"; document.getElementById("experiment-button").style.opacity = "0";
document.getElementById("training-button").style.display = "inline"
document.getElementById("training-button").style.opacity = "0";
document.getElementById("experiment-grid").style.display = "none" document.getElementById("experiment-grid").style.display = "none"
document.getElementById("pause-grid-left").style.display = "none" document.getElementById("pause-grid-left").style.display = "none"
document.getElementById("pause-grid-right").style.display = "none" document.getElementById("pause-grid-right").style.display = "none"
@@ -540,6 +543,7 @@ const simulation = {
document.body.style.cursor = "auto"; document.body.style.cursor = "auto";
setTimeout(() => { setTimeout(() => {
document.getElementById("experiment-button").style.opacity = "1"; document.getElementById("experiment-button").style.opacity = "1";
document.getElementById("training-button").style.opacity = "1";
document.getElementById("info").style.opacity = "1"; document.getElementById("info").style.opacity = "1";
document.getElementById("splash").style.opacity = "1"; document.getElementById("splash").style.opacity = "1";
}, 200); }, 200);
@@ -588,7 +592,7 @@ const simulation = {
requestAnimationFrame(cycle) requestAnimationFrame(cycle)
}, 1000); }, 1000);
}, },
startGame(isBuildRun = false) { startGame(isBuildRun = false, isTrainingRun = false) {
simulation.clearMap() simulation.clearMap()
if (!isBuildRun) { //if a build run logic flow returns to "experiment-button").addEventListener if (!isBuildRun) { //if a build run logic flow returns to "experiment-button").addEventListener
document.body.style.cursor = "none"; document.body.style.cursor = "none";
@@ -601,6 +605,7 @@ const simulation = {
document.getElementById("experiment-grid").style.display = "none" document.getElementById("experiment-grid").style.display = "none"
document.getElementById("info").style.display = "none"; document.getElementById("info").style.display = "none";
document.getElementById("experiment-button").style.display = "none"; document.getElementById("experiment-button").style.display = "none";
document.getElementById("training-button").style.display = "none";
// document.getElementById("experiment-button").style.opacity = "0"; // document.getElementById("experiment-button").style.opacity = "0";
document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once document.getElementById("splash").onclick = null; //removes the onclick effect so the function only runs once
document.getElementById("splash").style.display = "none"; //hides the element that spawned the function document.getElementById("splash").style.display = "none"; //hides the element that spawned the function
@@ -616,7 +621,7 @@ const simulation = {
} else { } else {
Composite.add(engine.world, [player]) Composite.add(engine.world, [player])
} }
if (isTrainingRun) simulation.isTraining = true
level.populateLevels() level.populateLevels()
input.endKeySensing(); input.endKeySensing();
@@ -694,6 +699,7 @@ const simulation = {
tech.healMaxEnergyBonus = 0 tech.healMaxEnergyBonus = 0
m.setMaxEnergy(); m.setMaxEnergy();
m.energy = 0 m.energy = 0
m.immuneCycle = 0;
// simulation.makeTextLog(`${simulation.SVGrightMouse}<strong style='font-size:30px;'> ${m.fieldUpgrades[m.fieldMode].name}</strong><br><span class='faded'></span><br>${m.fieldUpgrades[m.fieldMode].description}`, 600); // simulation.makeTextLog(`${simulation.SVGrightMouse}<strong style='font-size:30px;'> ${m.fieldUpgrades[m.fieldMode].name}</strong><br><span class='faded'></span><br>${m.fieldUpgrades[m.fieldMode].description}`, 600);
// simulation.makeTextLog(` // simulation.makeTextLog(`
// input.key.up <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"] // input.key.up <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]
@@ -751,6 +757,7 @@ const simulation = {
if (b.guns[i].name === "mine") { if (b.guns[i].name === "mine") {
if (tech.isCrouchAmmo) count = Math.ceil(count / 2) if (tech.isCrouchAmmo) count = Math.ceil(count / 2)
b.guns[i].ammo += count b.guns[i].ammo += count
if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo)
simulation.updateGunHUD(); simulation.updateGunHUD();
break; break;
} }
@@ -779,6 +786,7 @@ const simulation = {
} }
} }
} }
simulation.lastLogTime = 0; //clear previous messages
powerUps.totalPowerUps = powerUp.length powerUps.totalPowerUps = powerUp.length
let holdTarget = (m.holdingTarget) ? m.holdingTarget : undefined //if player is holding something this remembers it before it gets deleted let holdTarget = (m.holdingTarget) ? m.holdingTarget : undefined //if player is holding something this remembers it before it gets deleted
tech.deathSpawnsFromBoss = 0; tech.deathSpawnsFromBoss = 0;
+3 -1
View File
@@ -140,7 +140,9 @@ const spawn = {
me.chaseSpeed = 3.3 me.chaseSpeed = 3.3
me.isMACHO = true; me.isMACHO = true;
me.frictionAir = 0.006 me.frictionAir = 0.006
me.onDeath = function() {
tech.isHarmMACHO = false;
}
me.do = function() { me.do = function() {
const sine = Math.sin(simulation.cycle * 0.015) const sine = Math.sin(simulation.cycle * 0.015)
this.radius = 370 * (1 + 0.1 * sine) this.radius = 370 * (1 + 0.1 * sine)
+397 -365
View File
@@ -13,8 +13,10 @@ const tech = {
tech.tech[i].frequency = 2 tech.tech[i].frequency = 2
} }
} }
//remove lore if it's your first time playing since it's confusing
//also remove lore if cheating
lore.techCount = 0; lore.techCount = 0;
if (simulation.isCheating) { //simulation.isCommunityMaps || if (simulation.isCheating || localSettings.runCount > 1) { //simulation.isCommunityMaps ||
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) { if (tech.tech[i].isLore) {
tech.tech[i].frequency = 0; tech.tech[i].frequency = 0;
@@ -219,14 +221,14 @@ const tech = {
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy)
if (tech.isMaxEnergyTech) dmg *= 1.5 if (tech.isMaxEnergyTech) dmg *= 1.5
if (tech.isEnergyNoAmmo) dmg *= 1.6 if (tech.isEnergyNoAmmo) dmg *= 1.66
if (tech.isDamageForGuns) dmg *= 1 + 0.14 * b.inventory.length if (tech.isDamageForGuns) dmg *= 1 + 0.12 * b.inventory.length
if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5 if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5
if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
if (tech.isEnergyLoss) dmg *= 1.55; if (tech.isEnergyLoss) dmg *= 1.55;
if (tech.isAcidDmg && m.health > 1) dmg *= 1.35; if (tech.isAcidDmg && m.health > 1) dmg *= 1.35;
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isEnergyDamage) dmg *= 1 + m.energy / 11; if (tech.isEnergyDamage) dmg *= 1 + m.energy * 0.1;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007 if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
if (tech.isRerollDamage) dmg *= 1 + 0.037 * powerUps.research.count if (tech.isRerollDamage) dmg *= 1 + 0.037 * powerUps.research.count
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25 if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25
@@ -237,7 +239,7 @@ const tech = {
return dmg * tech.slowFire * tech.aimDamage return dmg * tech.slowFire * tech.aimDamage
}, },
duplicationChance() { duplicationChance() {
return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.042 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.45 : 0)) return Math.max(0, (tech.isPowerUpsVanish ? 0.12 : 0) + (tech.isStimulatedEmission ? 0.15 : 0) + tech.cancelCount * 0.042 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0))
}, },
isScaleMobsWithDuplication: false, isScaleMobsWithDuplication: false,
maxDuplicationEvent() { maxDuplicationEvent() {
@@ -457,7 +459,7 @@ const tech = {
// descriptionFunction() { // descriptionFunction() {
// return `increase <strong class='color-d'>damage</strong> by <strong>${14 * b.inventory.length}%</strong><br><strong>14%</strong> for each <strong class='color-g'>gun</strong> in your inventory` // return `increase <strong class='color-d'>damage</strong> by <strong>${14 * b.inventory.length}%</strong><br><strong>14%</strong> for each <strong class='color-g'>gun</strong> in your inventory`
// }, // },
description: "increase <strong class='color-d'>damage</strong> by <strong>14%</strong><br>for each <strong class='color-g'>gun</strong> in your inventory", description: "increase <strong class='color-d'>damage</strong> by <strong>12%</strong><br>for each <strong class='color-g'>gun</strong> in your inventory",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -493,24 +495,6 @@ const tech = {
b.setFireCD(); b.setFireCD();
} }
}, },
{
name: "logistics",
description: `${powerUps.orb.ammo()} give <strong>80%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>it's only added to your current <strong class='color-g'>gun</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isEnergyNoAmmo
},
requires: "not exciton",
effect() {
tech.isAmmoForGun = true;
},
remove() {
tech.isAmmoForGun = false;
}
},
{ {
name: "supply chain", name: "supply chain",
junk: 0.05, junk: 0.05,
@@ -542,10 +526,31 @@ const tech = {
} }
} }
}, },
{
name: "logistics",
description: `${powerUps.orb.ammo()} give <strong>80%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>it's only added to your current <strong class='color-g'>gun</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isEnergyNoAmmo
},
requires: "not exciton",
effect() {
tech.isAmmoForGun = true;
},
remove() {
tech.isAmmoForGun = false;
}
},
{ {
name: "cache", name: "cache",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`,
description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`, description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
// ammo powerups always max out your gun,
// but the maximum ammo ti limited
// description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -580,6 +585,24 @@ const tech = {
tech.isAmmoFromHealth = false; tech.isAmmoFromHealth = false;
} }
}, },
{
name: "exciton",
description: `increase <strong class='color-d'>damage</strong> by <strong>66%</strong>, but<br>${powerUps.orb.ammo()} will no longer <strong>spawn</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isAmmoFromHealth
},
requires: "not catabolism",
effect() {
tech.isEnergyNoAmmo = true;
},
remove() {
tech.isEnergyNoAmmo = false;
}
},
{ {
name: "desublimated ammunition", name: "desublimated ammunition",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Deposition_(phase_transition)' class="link">desublimated ammunition</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Deposition_(phase_transition)' class="link">desublimated ammunition</a>`,
@@ -743,7 +766,23 @@ const tech = {
tech.isLessDamageReduction = false tech.isLessDamageReduction = false
} }
}, },
{
name: "microstates",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Microstate_(statistical_mechanics)' class="link">microstates</a>`,
description: "increase <strong class='color-d'>damage</strong> by <strong>7%</strong><br>for every <strong>10</strong> active <strong>projectiles</strong>",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isDamageFromBulletCount = true
},
remove() {
tech.isDamageFromBulletCount = false
}
},
{ {
name: "simulated annealing", name: "simulated annealing",
description: "increase <strong class='color-d'>damage</strong> by <strong>20%</strong><br><strong>20%</strong> increased <strong><em>delay</em></strong> after firing", description: "increase <strong class='color-d'>damage</strong> by <strong>20%</strong><br><strong>20%</strong> increased <strong><em>delay</em></strong> after firing",
@@ -798,23 +837,6 @@ const tech = {
tech.isCrit = false; tech.isCrit = false;
} }
}, },
{
name: "microstates",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Microstate_(statistical_mechanics)' class="link">microstates</a>`,
description: "increase <strong class='color-d'>damage</strong> by <strong>7%</strong><br>for every <strong>10</strong> active <strong>projectiles</strong>",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isDamageFromBulletCount = true
},
remove() {
tech.isDamageFromBulletCount = false
}
},
{ {
name: "thermal runaway", name: "thermal runaway",
description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong>", description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong>",
@@ -1620,7 +1642,7 @@ const tech = {
}, },
{ {
name: "complex spin-statistics", name: "complex spin-statistics",
description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.5</strong> seconds<br>once every <strong>7</strong> seconds`, description: `become <strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1.8</strong> seconds<br>once every <strong>7</strong> seconds`,
maxCount: 3, maxCount: 3,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1630,7 +1652,7 @@ const tech = {
}, },
requires: "", requires: "",
effect() { effect() {
tech.cyclicImmunity += 90; tech.cyclicImmunity += 108;
}, },
remove() { remove() {
tech.cyclicImmunity = 0; tech.cyclicImmunity = 0;
@@ -1857,24 +1879,24 @@ const tech = {
tech.isAoESlow = false tech.isAoESlow = false
} }
}, },
{ // {
name: "osmoprotectant", // name: "osmoprotectant",
description: `collisions with <strong>stunned</strong> or <strong class='color-s'>frozen</strong> mobs<br>cause you <strong>no</strong> <strong class='color-harm'>harm</strong>`, // description: `collisions with <strong>stunned</strong> or <strong class='color-s'>frozen</strong> mobs<br>cause you <strong>no</strong> <strong class='color-harm'>harm</strong>`,
maxCount: 1, // maxCount: 1,
count: 0, // count: 0,
frequency: 2, // frequency: 2,
frequencyDefault: 2, // frequencyDefault: 2,
allowed() { // allowed() {
return tech.isStunField || tech.isExplosionStun || tech.isMineStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isNeedleIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot // return tech.isStunField || tech.isExplosionStun || tech.isMineStun || tech.oneSuperBall || tech.isHarmFreeze || tech.isIceField || tech.relayIce || tech.isNeedleIce || tech.isIceCrystals || tech.isSporeFreeze || tech.isAoESlow || tech.isFreezeMobs || tech.isCloakStun || tech.orbitBotCount > 1 || tech.isWormholeDamage || tech.blockingIce > 1 || tech.iceIXOnDeath || tech.isIceShot
}, // },
requires: "a freezing or stunning effect", // requires: "a freezing or stunning effect",
effect() { // effect() {
tech.isFreezeHarmImmune = true; // tech.isFreezeHarmImmune = true;
}, // },
remove() { // remove() {
tech.isFreezeHarmImmune = false; // tech.isFreezeHarmImmune = false;
} // }
}, // },
{ {
name: "liquid cooling", name: "liquid cooling",
description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`, description: `<strong class='color-s'>freeze</strong> all mobs for <strong>7</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong>`,
@@ -1911,22 +1933,6 @@ const tech = {
tech.isSlowFPS = false; tech.isSlowFPS = false;
} }
}, },
{
name: "quantum immortality",
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: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isImmortal = true;
},
remove() {
tech.isImmortal = false;
}
},
{ {
name: "MACHO", name: "MACHO",
description: "a massive but compact object slowly <strong>follows</strong> you<br>take <strong>66%</strong> less <strong class='color-harm'>harm</strong> inside it's <strong>halo</strong>", description: "a massive but compact object slowly <strong>follows</strong> you<br>take <strong>66%</strong> less <strong class='color-harm'>harm</strong> inside it's <strong>halo</strong>",
@@ -1944,6 +1950,7 @@ const tech = {
}, },
remove() { remove() {
tech.isMACHO = false; tech.isMACHO = false;
tech.isHarmMACHO = false;
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isMACHO) mob[i].alive = false; if (mob[i].isMACHO) mob[i].alive = false;
} }
@@ -2218,7 +2225,7 @@ const tech = {
}, },
{ {
name: "electronegativity", name: "electronegativity",
description: "increase <strong class='color-d'>damage</strong> by <strong>1%</strong><br>for every <strong>11</strong> stored <strong class='color-f'>energy</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>1%</strong><br>for every <strong>10</strong> stored <strong class='color-f'>energy</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2232,22 +2239,6 @@ const tech = {
tech.isEnergyDamage = false; tech.isEnergyDamage = false;
} }
}, },
{
name: "exciton",
description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but<br>${powerUps.orb.ammo()} will no longer <strong>spawn</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isEnergyNoAmmo = true;
},
remove() {
tech.isEnergyNoAmmo = false;
}
},
{ {
name: "exothermic process", name: "exothermic process",
description: "increase <strong class='color-d'>damage</strong> by <strong>50%</strong><br>if a mob <strong>dies</strong> drain <strong class='color-f'>energy</strong> by <strong>25%</strong>", description: "increase <strong class='color-d'>damage</strong> by <strong>50%</strong><br>if a mob <strong>dies</strong> drain <strong class='color-f'>energy</strong> by <strong>25%</strong>",
@@ -2426,7 +2417,7 @@ const tech = {
}, },
{ {
name: "predator", name: "predator",
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><span style = 'font-size:91%;'>increase <strong class='color-d'>damage</strong> <strong>50%</strong> and inhibit <strong class='color-f'>energy</strong> regen", description: "<span style = 'font-size:91%;'>if a mob has <strong>died</strong> in the last <strong>5 seconds</strong> inhibit<br>passive <strong class='color-f'>energy</strong> regen and increase <strong class='color-d'>damage</strong> <strong>50%</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2686,7 +2677,7 @@ const tech = {
}, },
{ {
name: "weak anthropic principle", name: "weak anthropic principle",
description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>add <strong>45%</strong> <strong class='color-dup'>duplication</strong> chance for that level", description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>add <strong>50%</strong> <strong class='color-dup'>duplication</strong> chance for that level",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
@@ -2722,6 +2713,22 @@ const tech = {
tech.isAnthropicDamage = false tech.isAnthropicDamage = false
} }
}, },
{
name: "quantum immortality",
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: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isImmortal = true;
},
remove() {
tech.isImmortal = false;
}
},
{ {
name: "non-unitary operator", name: "non-unitary operator",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unitary_operator' class="link">non-unitary operator</a>`, link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Unitary_operator' class="link">non-unitary operator</a>`,
@@ -2903,7 +2910,7 @@ const tech = {
}, },
{ {
name: "brainstorming", name: "brainstorming",
description: "the <strong class='color-m'>tech</strong> choice menu <strong>randomizes</strong><br>every <strong>2</strong> seconds for <strong>10</strong> seconds", description: "<strong class='color-m'>tech</strong> choices <strong>randomize</strong><br>every <strong>2</strong> seconds for <strong>10</strong> seconds",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2922,144 +2929,6 @@ const tech = {
tech.isBrainstormActive = false tech.isBrainstormActive = false
} }
}, },
{
name: "Born rule",
description: "<strong>remove</strong> all current <strong class='color-m'>tech</strong><br>spawn new <strong class='color-m'>tech</strong> to replace them",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return (tech.totalCount > 6)
},
requires: "NOT EXPERIMENT MODE, more than 6 tech",
effect: () => {
//remove active bullets //to get rid of bots
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
bullet = [];
let count = 1 //count tech
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (!tech.tech[i].isNonRefundable) count += tech.tech[i].count
}
if (tech.isDeterminism) count -= 4 //remove the bonus tech
if (tech.isSuperDeterminism) count -= 4 //remove the bonus tech
tech.setupAllTech(); // remove all tech
if (simulation.isCheating) tech.setCheating();
lore.techCount = 0;
// tech.addLoreTechToPool();
for (let i = 0; i < count; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "tech"); // spawn new tech power ups
//have state is checked in m.death()
},
remove() {}
},
{
name: "Occam's razor",
descriptionFunction() {
return `randomly remove <strong>${this.removePercent * 100}%</strong> of your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return (tech.totalCount > 6)
},
requires: "NOT EXPERIMENT MODE, more than 6 tech",
removePercent: 0.5,
damagePerRemoved: 0.5,
effect() {
let pool = []
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (tech.tech[i].count && !tech.tech[i].isNonRefundable) pool.push(i)
}
pool = shuffle(pool); //shuffles order of maps
let removeCount = 0
for (let i = 0, len = pool.length * this.removePercent; i < len; i++) removeCount += tech.removeTech(pool[i])
tech.OccamDamage = 1 + this.damagePerRemoved * removeCount
// tech.OccamDamage = Math.pow(1.25, removeCount)
},
remove() {
tech.OccamDamage = 0;
}
},
{
name: "abiogenesis",
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 3) && !tech.isDuplicateBoss
},
requires: "at least 4 research and not parthenogenesis",
effect() {
tech.isResearchBoss = true; //abiogenesis
},
remove() {
tech.isResearchBoss = false;
}
},
{
name: "bubble fusion",
description: `after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isShieldAmmo = true;
},
remove() {
tech.isShieldAmmo = false;
}
},
{
name: "meta-analysis",
description: `if you choose a <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> you instead get a<br>random normal <strong class='color-m'>tech</strong> and ${powerUps.orb.research(3)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isMetaAnalysis = true
},
remove() {
tech.isMetaAnalysis = false
}
},
{
name: "unified field theory",
description: `spawn ${powerUps.orb.research(6)}and when <strong>paused</strong><br><strong>clicking</strong> the <strong class='color-f'>field</strong> box switches your <strong class='color-f'>field</strong>`,
// description: `in the <strong>pause</strong> menu, change your <strong class='color-f'>field</strong><br>by <strong>clicking</strong> on your <strong class='color-f'>field's</strong> box`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return true
},
requires: "not superdeterminism",
effect() {
tech.isPauseSwitchField = true;
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
},
remove() {
if (tech.isPauseSwitchField) {
tech.isPauseSwitchField = false;
powerUps.research.changeRerolls(-6)
}
}
},
{ {
name: "cross disciplinary", name: "cross disciplinary",
description: "<strong class='color-m'>tech</strong> have an extra <strong class='color-f'>field</strong> or <strong class='color-g'>gun</strong> <strong>choice</strong>", description: "<strong class='color-m'>tech</strong> have an extra <strong class='color-f'>field</strong> or <strong class='color-g'>gun</strong> <strong>choice</strong>",
@@ -3117,7 +2986,7 @@ const tech = {
allowed() { allowed() {
return !tech.isExtraChoice && !tech.isExtraGunField return !tech.isExtraChoice && !tech.isExtraGunField
}, },
requires: "not emergence, cross disciplinary", requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary",
effect: () => { effect: () => {
tech.isDeterminism = true; tech.isDeterminism = true;
//if you change the number spawned also change it in Born rule //if you change the number spawned also change it in Born rule
@@ -3154,7 +3023,7 @@ const tech = {
allowed() { allowed() {
return tech.isDeterminism && !tech.isAnsatz return tech.isDeterminism && !tech.isAnsatz
}, },
requires: "determinism, not ansatz", requires: "NOT EXPERIMENT MODE, determinism, not ansatz",
effect: () => { effect: () => {
tech.isSuperDeterminism = true; tech.isSuperDeterminism = true;
//if you change the number spawned also change it in Born rule //if you change the number spawned also change it in Born rule
@@ -3168,6 +3037,174 @@ const tech = {
// } // }
} }
}, },
{
name: "unified field theory",
description: `spawn ${powerUps.orb.research(6)}and when <strong>paused</strong><br><strong>clicking</strong> the <strong class='color-f'>field</strong> box switches your <strong class='color-f'>field</strong>`,
// description: `in the <strong>pause</strong> menu, change your <strong class='color-f'>field</strong><br>by <strong>clicking</strong> on your <strong class='color-f'>field's</strong> box`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return true
},
requires: "not superdeterminism",
effect() {
tech.isPauseSwitchField = true;
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
},
remove() {
if (tech.isPauseSwitchField) {
tech.isPauseSwitchField = false;
powerUps.research.changeRerolls(-6)
}
}
},
{
name: "abiogenesis",
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 3) && !tech.isDuplicateBoss
},
requires: "at least 4 research and not parthenogenesis",
effect() {
tech.isResearchBoss = true; //abiogenesis
},
remove() {
tech.isResearchBoss = false;
}
},
{
name: "meta-analysis",
description: `if you choose a <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> you instead get a<br>random normal <strong class='color-m'>tech</strong> and ${powerUps.orb.research(3)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isMetaAnalysis = true
},
remove() {
tech.isMetaAnalysis = false
}
},
{
name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel < 8 && level.onLevel > 0
},
requires: "on levels 1 through 7",
effect() {
level.difficultyDecrease(simulation.difficultyMode)
// simulation.difficulty<span class='color-symbol'>-=</span>
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`)
this.refundAmount += tech.addJunkTechToPool(0.31)
// for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i])
},
refundAmount: 0,
remove() {
if (this.count > 0) {
if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
level.difficultyIncrease(simulation.difficultyMode)
}
}
},
{
name: "ergodicity",
description: `reduce combat <strong>difficulty</strong> by <strong>2 levels</strong><br>${powerUps.orb.heal()} have <strong>no</strong> effect`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel > 1 && !tech.isEnergyHealth
},
requires: "past levels 1, not mass-energy",
effect() {
tech.isNoHeals = true;
level.difficultyDecrease(simulation.difficultyMode * 2)
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode <span class='color-symbol'>*</span> 2)`)
powerUps.heal.color = "#abb"
for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live
if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color
}
},
remove() {
if (tech.isNoHeals) {
powerUps.heal.color = "#0eb"
for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live
if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color
}
}
tech.isNoHeals = false;
if (this.count > 0) level.difficultyIncrease(simulation.difficultyMode * 2)
}
},
{
name: "bubble fusion",
description: `after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() { return true },
requires: "",
effect() {
tech.isShieldAmmo = true;
},
remove() {
tech.isShieldAmmo = false;
}
},
{
name: "commodities exchange",
description: `clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>5-10</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isSuperDeterminism
},
requires: "not superdeterminism",
effect() {
tech.isCancelRerolls = true
},
remove() {
tech.isCancelRerolls = false
}
},
{
name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to <strong>cancel</strong> a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.2%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.duplicationChance() < 1 && !tech.isSuperDeterminism
},
requires: "below 100% duplication chance, not superdeterminism",
effect() {
tech.isCancelDuplication = true //search for tech.cancelCount to balance
powerUps.setDupChance(); //needed after adjusting duplication chance
},
remove() {
tech.isCancelDuplication = false
powerUps.setDupChance(); //needed after adjusting duplication chance
}
},
{ {
name: "replication", name: "replication",
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+40%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool", description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+40%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
@@ -3237,44 +3274,6 @@ const tech = {
powerUps.setDupChance(); //needed after adjusting duplication chance powerUps.setDupChance(); //needed after adjusting duplication chance
} }
}, },
{
name: "futures exchange",
description: "clicking <strong style = 'font-size:150%;'>×</strong> to <strong>cancel</strong> a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>adds <strong>4.2%</strong> power up <strong class='color-dup'>duplication</strong> chance",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.duplicationChance() < 1 && !tech.isSuperDeterminism
},
requires: "below 100% duplication chance, not superdeterminism",
effect() {
tech.isCancelDuplication = true //search for tech.cancelCount to balance
powerUps.setDupChance(); //needed after adjusting duplication chance
},
remove() {
tech.isCancelDuplication = false
powerUps.setDupChance(); //needed after adjusting duplication chance
}
},
{
name: "commodities exchange",
description: `clicking <strong style = 'font-size:150%;'>×</strong> to cancel a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>5-10</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isSuperDeterminism
},
requires: "not superdeterminism",
effect() {
tech.isCancelRerolls = true
},
remove() {
tech.isCancelRerolls = false
}
},
{ {
name: "correlated damage", name: "correlated damage",
description: "your chance to <strong class='color-dup'>duplicate</strong> power ups<br>increases your <strong class='color-d'>damage</strong> by the same percent", description: "your chance to <strong class='color-dup'>duplicate</strong> power ups<br>increases your <strong class='color-d'>damage</strong> by the same percent",
@@ -3331,9 +3330,77 @@ const tech = {
tech.is111Duplicate = false; tech.is111Duplicate = false;
} }
}, },
{
name: "Born rule",
description: "<strong>remove</strong> all current <strong class='color-m'>tech</strong><br>spawn new <strong class='color-m'>tech</strong> to replace them",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return (tech.totalCount > 6)
},
requires: "NOT EXPERIMENT MODE, more than 6 tech",
effect: () => {
//remove active bullets //to get rid of bots
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
bullet = [];
let count = 1 //count tech
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (!tech.tech[i].isNonRefundable) count += tech.tech[i].count
}
if (tech.isDeterminism) count -= 4 //remove the bonus tech
if (tech.isSuperDeterminism) count -= 4 //remove the bonus tech
tech.setupAllTech(); // remove all tech
if (simulation.isCheating) tech.setCheating();
lore.techCount = 0;
// tech.addLoreTechToPool();
for (let i = 0; i < count; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "tech"); // spawn new tech power ups
//have state is checked in m.death()
},
remove() {}
},
{
name: "Occam's razor",
// descriptionFunction() {
// return `randomly remove <strong>${this.removePercent * 100}%</strong> of your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong>`
// },
descriptionFunction() {
return `randomly remove <strong>half</strong> your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong> <em>(~${this.damagePerRemoved * 50 * tech.totalCount}%)</em>`
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 100,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return (tech.totalCount > 6)
},
requires: "NOT EXPERIMENT MODE, more than 6 tech",
removePercent: 0.5,
damagePerRemoved: 0.5,
effect() {
let pool = []
for (let i = 0, len = tech.tech.length; i < len; i++) { // spawn new tech power ups
if (tech.tech[i].count && !tech.tech[i].isNonRefundable) pool.push(i)
}
pool = shuffle(pool); //shuffles order of maps
let removeCount = 0
for (let i = 0, len = pool.length * this.removePercent; i < len; i++) removeCount += tech.removeTech(pool[i])
tech.OccamDamage = 1 + this.damagePerRemoved * removeCount
// tech.OccamDamage = Math.pow(1.25, removeCount)
},
remove() {
tech.OccamDamage = 0;
}
},
{ {
name: "exchange symmetry", name: "exchange symmetry",
description: "convert <strong>1</strong> random <strong class='color-m'>tech</strong> into <strong>2</strong> new <strong class='color-g'>guns</strong><br><em>recursive tech lose all stacks</em>", description: "remove <strong>1</strong> random <strong class='color-m'>tech</strong><br>spawn <strong>2</strong> new <strong class='color-g'>guns</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3365,7 +3432,7 @@ const tech = {
}, },
{ {
name: "monte carlo experiment", name: "monte carlo experiment",
description: "spawn <strong>2</strong> <strong class='color-m'>tech</strong><br>remove <strong>1</strong> random <strong class='color-m'>tech</strong>", description: "remove <strong>1</strong> random <strong class='color-m'>tech</strong><br>spawn <strong>2</strong> <strong class='color-m'>tech</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3496,63 +3563,6 @@ const tech = {
// }, // },
// remove() {} // remove() {}
// }, // },
{
name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel < 8 && level.onLevel > 0
},
requires: "on levels 1 through 7",
effect() {
level.difficultyDecrease(simulation.difficultyMode)
// simulation.difficulty<span class='color-symbol'>-=</span>
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`)
this.refundAmount += tech.addJunkTechToPool(0.31)
// for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i])
},
refundAmount: 0,
remove() {
if (this.count > 0) {
if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
level.difficultyIncrease(simulation.difficultyMode)
}
}
},
{
name: "ergodicity",
description: `reduce combat <strong>difficulty</strong> by <strong>2 levels</strong><br>${powerUps.orb.heal()} have <strong>no</strong> effect`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel > 1 && !tech.isEnergyHealth
},
requires: "past levels 1, not mass-energy",
effect() {
tech.isNoHeals = true;
level.difficultyDecrease(simulation.difficultyMode * 2)
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode <span class='color-symbol'>*</span> 2)`)
powerUps.heal.color = "#abb"
for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live
if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color
}
},
remove() {
if (tech.isNoHeals) {
powerUps.heal.color = "#0eb"
for (let i = 0; i < powerUp.length; i++) { //find active heal power ups and adjust color live
if (powerUp[i].name === "heal") powerUp[i].color = powerUps.heal.color
}
}
tech.isNoHeals = false;
if (this.count > 0) level.difficultyIncrease(simulation.difficultyMode * 2)
}
},
//************************************************** //**************************************************
//************************************************** gun //************************************************** gun
//************************************************** tech //************************************************** tech
@@ -4985,8 +4995,8 @@ const tech = {
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 4, frequency: 3,
frequencyDefault: 4, frequencyDefault: 3,
allowed() { allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormholeSpores return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormholeSpores
}, },
@@ -4998,6 +5008,25 @@ const tech = {
tech.isSporeWorm = false tech.isSporeWorm = false
} }
}, },
{
name: "annelids",
description: "increase <strong class='color-p' style='letter-spacing: -0.8px;'>worm</strong> size and <strong class='color-d'>damage</strong><br>between <strong>10%</strong> and <strong>120%</strong>",
isGunTech: true,
maxCount: 9,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isSporeWorm || tech.isWormShot
},
requires: "spore gun, shotgun, worms",
effect() {
tech.wormSize++
},
remove() {
tech.wormSize = 0
}
},
{ {
name: "necrophage", name: "necrophage",
description: "if <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>they reset their <strong>lifespan</strong>", description: "if <strong class='color-p' style='letter-spacing: -0.8px;'>worms</strong> <strong>kill</strong> their target<br>they reset their <strong>lifespan</strong>",
@@ -5009,7 +5038,7 @@ const tech = {
allowed() { allowed() {
return tech.isSporeWorm || tech.isWormShot return tech.isSporeWorm || tech.isWormShot
}, },
requires: "spore gun, worms", requires: "spore gun, shotgun, worms",
effect() { effect() {
tech.wormSurviveDmg = true tech.wormSurviveDmg = true
}, },
@@ -5447,7 +5476,7 @@ const tech = {
{ {
name: "unaaq", name: "unaaq",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Harpoon#/media/File:Harpon_Unaaq_MHNT_ETH_AC_198.jpg' class="link">unaaq</a>`, //https://en.wikipedia.org/wiki/Weapon link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Harpoon#/media/File:Harpon_Unaaq_MHNT_ETH_AC_198.jpg' class="link">unaaq</a>`, //https://en.wikipedia.org/wiki/Weapon
description: "increase the <strong>size</strong> of your <strong>harpoon</strong><br>by <strong>10%</strong> of the square root of its <strong class='color-ammo'>ammo</strong>", description: "increase the <strong>size</strong> of your <strong>harpoon</strong><br>by <strong>10%</strong> of the square root of harpoon <strong class='color-ammo'>ammo</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5881,7 +5910,7 @@ const tech = {
}, },
{ {
name: "expansion", name: "expansion",
description: "using <strong>standing wave</strong> field temporarily<br><strong>expands</strong> its <strong>radius</strong>", description: "using <strong>standing wave</strong> field<br>temporarily <strong>expands</strong> its <strong>radius</strong>",
// description: "use <strong class='color-f'>energy</strong> to <strong>expand</strong> <strong>standing wave</strong><br>the field slowly <strong>contracts</strong> when not used", // description: "use <strong class='color-f'>energy</strong> to <strong>expand</strong> <strong>standing wave</strong><br>the field slowly <strong>contracts</strong> when not used",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
@@ -6104,6 +6133,26 @@ const tech = {
tech.isFreezeMobs = false tech.isFreezeMobs = false
} }
}, },
{
name: "pair production",
description: "picking up a <strong>power up</strong> gives you <strong>200</strong> <strong class='color-f'>energy</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "standing wave" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
},
requires: "molecular assembler or pilot wave",
effect: () => {
tech.isMassEnergy = true // used in m.grabPowerUp
m.energy += 2
},
remove() {
tech.isMassEnergy = false;
}
},
{ {
name: "bot manufacturing", name: "bot manufacturing",
description: `use <strong>molecular assembler</strong> and ${powerUps.orb.research(2)}<br>to build <strong>3</strong> random <strong class='color-bot'>bots</strong>`, description: `use <strong>molecular assembler</strong> and ${powerUps.orb.research(2)}<br>to build <strong>3</strong> random <strong class='color-bot'>bots</strong>`,
@@ -6288,26 +6337,6 @@ const tech = {
if (this.count > 0) powerUps.research.changeRerolls(1) if (this.count > 0) powerUps.research.changeRerolls(1)
} }
}, },
{
name: "pair production",
description: "picking up a <strong>power up</strong> gives you <strong>200</strong> <strong class='color-f'>energy</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return m.fieldUpgrades[m.fieldMode].name === "molecular assembler" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
},
requires: "molecular assembler or pilot wave",
effect: () => {
tech.isMassEnergy = true // used in m.grabPowerUp
m.energy += 2
},
remove() {
tech.isMassEnergy = false;
}
},
// { // {
// name: "thermal reservoir", // name: "thermal reservoir",
// description: "increase your <strong class='color-plasma'>plasma</strong> <strong class='color-d'>damage</strong> by <strong>100%</strong><br><strong class='color-plasma'>plasma</strong> temporarily lowers health not <strong class='color-f'>energy</strong>", // description: "increase your <strong class='color-plasma'>plasma</strong> <strong class='color-d'>damage</strong> by <strong>100%</strong><br><strong class='color-plasma'>plasma</strong> temporarily lowers health not <strong class='color-f'>energy</strong>",
@@ -8790,9 +8819,11 @@ const tech = {
effect() { effect() {
const unit = { x: 1, y: 0 } const unit = { x: 1, y: 0 }
for (let i = 0; i < 30; i++) { for (let i = 0; i < 30; i++) {
const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 600 + 200 * Math.random())) const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 1200 * Math.random()))
spawn.sucker(where.x, where.y, 250) spawn.sucker(where.x, where.y, 200)
mob[mob.length - 1].damageReduction = 0.2 const who = mob[mob.length - 1]
who.locatePlayer()
// who.damageReduction = 0.2
} }
}, },
remove() {} remove() {}
@@ -8993,7 +9024,7 @@ const tech = {
nailInstantFireRate: null, nailInstantFireRate: null,
isCapacitor: null, isCapacitor: null,
isEnergyNoAmmo: null, isEnergyNoAmmo: null,
isFreezeHarmImmune: null, // isFreezeHarmImmune: null,
isSmallExplosion: null, isSmallExplosion: null,
isExplosionHarm: null, isExplosionHarm: null,
extraMaxHealth: null, extraMaxHealth: null,
@@ -9163,5 +9194,6 @@ const tech = {
needleTunnel: null, needleTunnel: null,
isBrainstorm: null, isBrainstorm: null,
isBrainstormActive: null, isBrainstormActive: null,
brainStormDelay: null brainStormDelay: null,
wormSize: null
} }
+8
View File
@@ -129,6 +129,14 @@ summary {
transition: opacity 5s ease-in; transition: opacity 5s ease-in;
} }
#training-button {
position: absolute;
bottom: 58px;
right: 4px;
z-index: 12;
transition: opacity 5s ease-in;
}
#construct { #construct {
display: none; display: none;
position: absolute; position: absolute;
+52 -6
View File
@@ -1,20 +1,67 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
powerUpBoss no longer gets invulnerability after death first 4 levels of the training maps are live
but powerUpBossBaby still has it this is very much a work in progress, but I'm putting it up for feedback
tech: brainstorming - randomize your tech choice menu every 2s for 10s stunned and frozen mobs do no harm by default
JUNK tech: brainstorm - randomize your tech choice menu every 0.5s for 10s removed tech: osmoprotectant - stunned and frozen mobs do no harm
tech: annelids - randomly increase worm size and damage up to 100%
weak anthropic principle gives 45->50% duplication chance after almost dieing
complex spin-statistics immune to harm for 1.5->1.8 s every 7 s
exciton gives 60->66% damage
electronegativity gives 1% dmg for every 11->10 stored energy
arsenal gives 14->12% more damage per gun
pair production is now also a standing wave field tech
mass-energy takes 10% less damage
JUNK tech black hole cluster spawns mobs farther away, so you have a better chance to survive
undefinded tech no longer shows up on your first couple times playing, since it's a distraction for new players
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
door.openClose(); is flipped T/F
balance time dilation with bose einstein (you can freeze everything and take no damage)
training
button takes you to a series of levels that teach simple game mechanics
make the button more obvious if the account has only played 1-2 times
at high levels has some puzzle aspects?
uses the lore voice/text code?
save training level progress as local variable
rooms:
jump over wall and gap
crouch through tunnel
push block onto button to open door
pick up a block an drop onto a button to open door
fire block at button to open door
fire block at mob to open door
pick up power ups with field to open door
use gun to kill a mob and use it's block body to activate a button to open a door
use field to deflect a mob that is stationary, but blocking a passage
set health to very low
final room, takes you back to the menu, like when winning the game
puzzle or combat rooms?
boss gauntlet, spawn with nothing but a few power ups and fight 10 bosses
tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health) tech: basic research - heal power ups spawn as research power ups instead, and using research heals you (needs to be pretty low, like 3% health)
tech: maintenance - heals no longer spawn, but using research heals you 100% tech: maintenance - heals no longer spawn, but using research heals you 100%
tech reversed regression - mobs take less damage after each time you hit them, but you get +100% damage
maybe a gun tech only?
what gun?
tech extend fracture analysis to give bonus damage to frozen also, but reduce the 400%->300%?
pulsar mobs retarget too easily pulsar mobs retarget too easily
also they drift around too much also they drift around too much
convert blocked mobs into bullets
only for the very small bullets that move fast after being blocked
delete bulletmob and spawn a nail-like bullet with the same properties as the bulletmob
electric motors: increases movement speed and jump height, but jumping and moving costs energy electric motors: increases movement speed and jump height, but jumping and moving costs energy
overwrite the key event listeners? overwrite the key event listeners?
JUNK tech? JUNK tech?
@@ -81,8 +128,7 @@ animate going to next level?
Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement. Plasma Burner: upgrade for plasma torch, basically just a jet engine. does high damage, but short range, mostly for player movement.
maybe reduce gravity to really low then apply a vector away from mouse direction maybe reduce gravity to really low then apply a vector away from mouse direction
game idea - auto battler with n-gon mob AI and tech auto-gon - auto battler with n-gon mob AI and tech
name: auto-gon
you build a group of mobs and bosses from n-gon you build a group of mobs and bosses from n-gon
they fight other mobs and bosses they fight other mobs and bosses
similar research and tech system to n-gon similar research and tech system to n-gon