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
+860 -430

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>
</g>
</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="settings">
<details>
+7 -5
View File
@@ -2361,9 +2361,9 @@ const b = {
},
worm(where, isFreeze = tech.isSporeFreeze) { //used with the tech upgrade in mob.death()
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
bullet[bIndex] = Bodies.polygon(where.x, where.y, size, size, {
bullet[bIndex] = Bodies.polygon(where.x, where.y, 3, 3, {
inertia: Infinity,
isFreeze: isFreeze,
restitution: 0.5,
@@ -2371,7 +2371,9 @@ const b = {
friction: 0,
frictionAir: 0.025,
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()),
classType: "bullet",
collisionFilter: {
@@ -2408,10 +2410,10 @@ const b = {
do() {
ctx.beginPath(); //draw nematode
ctx.moveTo(this.position.x, this.position.y);
const dir = Vector.mult(Vector.normalise(this.velocity), -Math.min(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)
ctx.lineTo(tail.x, tail.y);
ctx.lineWidth = 6;
ctx.lineWidth = this.wormSize;
ctx.strokeStyle = "#000";
ctx.stroke();
+1 -1
View File
@@ -103,7 +103,7 @@ function collisionChecks(event) {
if (
m.immuneCycle < m.cycle &&
(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
if (m.isCloak) dmg *= 0.5
+2 -12
View File
@@ -622,6 +622,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
function openExperimentMenu() {
document.getElementById("experiment-button").style.display = "none";
document.getElementById("training-button").style.display = "none";
const el = document.getElementById("experiment-grid")
el.style.display = "grid"
document.body.style.overflowY = "scroll";
@@ -1295,16 +1296,5 @@ function cycle() {
level.start();
}
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,
levelsCleared: 0,
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"],
trainingLevels: ["trainingHold", "trainingThrow", "trainingCrouch", "trainingJump"],
levels: [],
start() {
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
// simulation.isHorizontalFlipped = true
// m.setField("plasma torch")
// b.giveGuns("drones")
// b.giveGuns("spores")
// b.giveGuns("nail gun")
// b.giveGuns("harpoon")
// tech.giveTech("brainstorming")
// tech.giveTech("nanowires")
// tech.giveTech("relativistic momentum")
// tech.giveTech("nematodes")
// for (let i = 0; i < 9; i++) tech.giveTech("annelids")
// tech.giveTech("tinsellated flagella")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("antiscience")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.tech[297].frequency = 100
level.intro(); //starting level
// level.trainingThrow();
if (simulation.isTraining) {
level.trainingHold();
} else {
level.intro(); //starting level
}
// level.testing(); //not in rotation, used for testing
// level.template(); //not in rotation, blank start new map development
// 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.pickList = ["focuser", "focuser"]
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.levelsClearedLastGame = level.levelsCleared
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
}
level.levelAnnounce();
if (!simulation.isTraining) level.levelAnnounce();
simulation.noCameraScroll();
simulation.setZoom();
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
}
},
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() {},
customTopLayer() {},
setDifficulty() {
@@ -214,27 +550,31 @@ const level = {
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
},
populateLevels() {
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 (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
if (simulation.isTraining) {
level.levels = level.trainingLevels.slice(0) //copy array, not by just by assignment
} 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
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 (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 {
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() {
@@ -723,7 +1063,7 @@ const level = {
}
}
},
door(x, y, width, height, distance) {
door(x, y, width, height, distance, speed = 1) {
x = x + width / 2
y = y + height / 2
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
const position = {
x: this.position.x,
y: this.position.y - 1
y: this.position.y - speed
}
Matter.Body.setPosition(this, position)
}
@@ -756,7 +1096,7 @@ const level = {
) {
const position = {
x: this.position.x,
y: this.position.y + 1
y: this.position.y + speed
}
Matter.Body.setPosition(this, position)
}
@@ -1228,7 +1568,7 @@ const level = {
spawn.randomMob(x + 1175, y - 725, mobSpawnChance);
spawn.randomMob(x + 1450, y - 725, 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);
}
ctx.fillStyle = "#d4f4f4"
+1 -1
View File
@@ -45,7 +45,7 @@ const lore = {
if (localSettings.loreCount < 1) localSettings.loreCount = 1
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
// document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
simulation.makeTextLog(`<span class='color-var'>lore</span>.unlockTesting()`, Infinity);
sound.portamento(50)
+2 -5
View File
@@ -647,7 +647,7 @@ const m = {
}
if (tech.isEnergyHealth) {
m.energy -= dmg * 1.1;
m.energy -= dmg
if (m.energy < 0 || isNaN(m.energy)) { //taking deadly damage
if (tech.isDeathAvoid && powerUps.research.count && !tech.isDeathAvoidedThisLevel) {
tech.isDeathAvoidedThisLevel = true
@@ -1248,7 +1248,6 @@ const m = {
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.lineWidth = 2;
ctx.lineCap = "butt"
ctx.stroke();
let eye = 13;
let aMag = 0.75 * Math.PI * m.fieldArc
@@ -1741,7 +1740,6 @@ const m = {
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.lineWidth = 2.5 - 1.5 * wave;
ctx.lineCap = "butt"
ctx.stroke();
const curve = 0.57 + 0.04 * wave
const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
@@ -1766,7 +1764,6 @@ const m = {
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.lineWidth = 2.5 - 1.5 * wave;
ctx.lineCap = "butt"
ctx.stroke();
const curve = 0.8 + 0.06 * wave
const aMag = (1 - curve * 1.2) * Math.PI * m.fieldArc
@@ -3564,7 +3561,7 @@ const m = {
m.immuneCycle < m.cycle &&
// (obj === playerBody || obj === playerHead) &&
(obj === player) &&
!(tech.isFreezeHarmImmune && (mob[k].isSlowed || mob[k].isStunned))
!mob[k].isSlowed && !mob[k].isStunned
) {
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
+10 -2
View File
@@ -110,6 +110,7 @@ const simulation = {
g: 0.0024, // applies to player, bodies, and power ups (not mobs)
onTitlePage: true,
isCheating: false,
isTraining: false,
paused: false,
isChoosing: false,
testing: false, //testing mode: shows wire frame and some variables
@@ -530,6 +531,8 @@ const simulation = {
document.getElementById("info").style.opacity = "0";
document.getElementById("experiment-button").style.display = "inline"
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("pause-grid-left").style.display = "none"
document.getElementById("pause-grid-right").style.display = "none"
@@ -540,6 +543,7 @@ const simulation = {
document.body.style.cursor = "auto";
setTimeout(() => {
document.getElementById("experiment-button").style.opacity = "1";
document.getElementById("training-button").style.opacity = "1";
document.getElementById("info").style.opacity = "1";
document.getElementById("splash").style.opacity = "1";
}, 200);
@@ -588,7 +592,7 @@ const simulation = {
requestAnimationFrame(cycle)
}, 1000);
},
startGame(isBuildRun = false) {
startGame(isBuildRun = false, isTrainingRun = false) {
simulation.clearMap()
if (!isBuildRun) { //if a build run logic flow returns to "experiment-button").addEventListener
document.body.style.cursor = "none";
@@ -601,6 +605,7 @@ const simulation = {
document.getElementById("experiment-grid").style.display = "none"
document.getElementById("info").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("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
@@ -616,7 +621,7 @@ const simulation = {
} else {
Composite.add(engine.world, [player])
}
if (isTrainingRun) simulation.isTraining = true
level.populateLevels()
input.endKeySensing();
@@ -694,6 +699,7 @@ const simulation = {
tech.healMaxEnergyBonus = 0
m.setMaxEnergy();
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(`
// 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 (tech.isCrouchAmmo) count = Math.ceil(count / 2)
b.guns[i].ammo += count
if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo)
simulation.updateGunHUD();
break;
}
@@ -779,6 +786,7 @@ const simulation = {
}
}
}
simulation.lastLogTime = 0; //clear previous messages
powerUps.totalPowerUps = powerUp.length
let holdTarget = (m.holdingTarget) ? m.holdingTarget : undefined //if player is holding something this remembers it before it gets deleted
tech.deathSpawnsFromBoss = 0;
+3 -1
View File
@@ -140,7 +140,9 @@ const spawn = {
me.chaseSpeed = 3.3
me.isMACHO = true;
me.frictionAir = 0.006
me.onDeath = function() {
tech.isHarmMACHO = false;
}
me.do = function() {
const sine = Math.sin(simulation.cycle * 0.015)
this.radius = 370 * (1 + 0.1 * sine)
+397 -365
View File
@@ -13,8 +13,10 @@ const tech = {
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;
if (simulation.isCheating) { //simulation.isCommunityMaps ||
if (simulation.isCheating || localSettings.runCount > 1) { //simulation.isCommunityMaps ||
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].isLore) {
tech.tech[i].frequency = 0;
@@ -219,14 +221,14 @@ const tech = {
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.isMaxEnergyTech) dmg *= 1.5
if (tech.isEnergyNoAmmo) dmg *= 1.6
if (tech.isDamageForGuns) dmg *= 1 + 0.14 * b.inventory.length
if (tech.isEnergyNoAmmo) dmg *= 1.66
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.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3;
if (tech.isEnergyLoss) dmg *= 1.55;
if (tech.isAcidDmg && m.health > 1) dmg *= 1.35;
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.isRerollDamage) dmg *= 1 + 0.037 * powerUps.research.count
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.25
@@ -237,7 +239,7 @@ const tech = {
return dmg * tech.slowFire * tech.aimDamage
},
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,
maxDuplicationEvent() {
@@ -457,7 +459,7 @@ const tech = {
// 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`
// },
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,
count: 0,
frequency: 1,
@@ -493,24 +495,6 @@ const tech = {
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",
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",
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`,
// 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,
count: 0,
frequency: 1,
@@ -580,6 +585,24 @@ const tech = {
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",
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
}
},
{
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",
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;
}
},
{
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",
description: "mobs <strong class='color-e'>explode</strong> when they <strong>die</strong>",
@@ -1620,7 +1642,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -1630,7 +1652,7 @@ const tech = {
},
requires: "",
effect() {
tech.cyclicImmunity += 90;
tech.cyclicImmunity += 108;
},
remove() {
tech.cyclicImmunity = 0;
@@ -1857,24 +1879,24 @@ const tech = {
tech.isAoESlow = false
}
},
{
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>`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
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
},
requires: "a freezing or stunning effect",
effect() {
tech.isFreezeHarmImmune = true;
},
remove() {
tech.isFreezeHarmImmune = false;
}
},
// {
// 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>`,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// 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
// },
// requires: "a freezing or stunning effect",
// effect() {
// tech.isFreezeHarmImmune = true;
// },
// remove() {
// tech.isFreezeHarmImmune = false;
// }
// },
{
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>`,
@@ -1911,22 +1933,6 @@ const tech = {
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",
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() {
tech.isMACHO = false;
tech.isHarmMACHO = false;
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isMACHO) mob[i].alive = false;
}
@@ -2218,7 +2225,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -2232,22 +2239,6 @@ const tech = {
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",
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",
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,
count: 0,
frequency: 1,
@@ -2686,7 +2677,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 3,
@@ -2722,6 +2713,22 @@ const tech = {
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",
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",
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,
count: 0,
frequency: 1,
@@ -2922,144 +2929,6 @@ const tech = {
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",
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() {
return !tech.isExtraChoice && !tech.isExtraGunField
},
requires: "not emergence, cross disciplinary",
requires: "NOT EXPERIMENT MODE, not emergence, cross disciplinary",
effect: () => {
tech.isDeterminism = true;
//if you change the number spawned also change it in Born rule
@@ -3154,7 +3023,7 @@ const tech = {
allowed() {
return tech.isDeterminism && !tech.isAnsatz
},
requires: "determinism, not ansatz",
requires: "NOT EXPERIMENT MODE, determinism, not ansatz",
effect: () => {
tech.isSuperDeterminism = true;
//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",
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
}
},
{
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",
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;
}
},
{
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",
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,
count: 0,
frequency: 1,
@@ -3365,7 +3432,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -3496,63 +3563,6 @@ const tech = {
// },
// 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
//************************************************** tech
@@ -4985,8 +4995,8 @@ const tech = {
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 4,
frequencyDefault: 4,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.haveGunCheck("spores") || tech.sporesOnDeath > 0 || tech.isSporeField || tech.isWormholeSpores
},
@@ -4998,6 +5008,25 @@ const tech = {
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",
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() {
return tech.isSporeWorm || tech.isWormShot
},
requires: "spore gun, worms",
requires: "spore gun, shotgun, worms",
effect() {
tech.wormSurviveDmg = true
},
@@ -5447,7 +5476,7 @@ const tech = {
{
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
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,
maxCount: 1,
count: 0,
@@ -5881,7 +5910,7 @@ const tech = {
},
{
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",
isFieldTech: true,
maxCount: 1,
@@ -6104,6 +6133,26 @@ const tech = {
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",
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)
}
},
{
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",
// 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() {
const unit = { x: 1, y: 0 }
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()))
spawn.sucker(where.x, where.y, 250)
mob[mob.length - 1].damageReduction = 0.2
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, 200)
const who = mob[mob.length - 1]
who.locatePlayer()
// who.damageReduction = 0.2
}
},
remove() {}
@@ -8993,7 +9024,7 @@ const tech = {
nailInstantFireRate: null,
isCapacitor: null,
isEnergyNoAmmo: null,
isFreezeHarmImmune: null,
// isFreezeHarmImmune: null,
isSmallExplosion: null,
isExplosionHarm: null,
extraMaxHealth: null,
@@ -9163,5 +9194,6 @@ const tech = {
needleTunnel: null,
isBrainstorm: null,
isBrainstormActive: null,
brainStormDelay: null
brainStormDelay: null,
wormSize: null
}
+8
View File
@@ -129,6 +129,14 @@ summary {
transition: opacity 5s ease-in;
}
#training-button {
position: absolute;
bottom: 58px;
right: 4px;
z-index: 12;
transition: opacity 5s ease-in;
}
#construct {
display: none;
position: absolute;
+52 -6
View File
@@ -1,20 +1,67 @@
******************************************************** NEXT PATCH **************************************************
powerUpBoss no longer gets invulnerability after death
but powerUpBossBaby still has it
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
tech: brainstorming - randomize your tech choice menu every 2s for 10s
JUNK tech: brainstorm - randomize your tech choice menu every 0.5s for 10s
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
******************************************************** 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: 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
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
overwrite the key event listeners?
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.
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
name: auto-gon
auto-gon - auto battler with n-gon mob AI and tech
you build a group of mobs and bosses from n-gon
they fight other mobs and bosses
similar research and tech system to n-gon