level - reactor

new level: reactor - midBoss fight
  it's not well balanced yet
  Let me know if there are any impossible gun combinations

for new players the training button at the start screen now cycles colors
  effect shows if you haven't cleared the first training level, and you haven't done at least a few normal runs

standing wave expansion tech is 40% larger and gives 25% deflecting efficiency
ammonium nitrate gives 30 -> 27% damage and range
heuristics gives 30 -> 33% fire rate
wormhole invariant tech drains energy much slower while time is paused

bug fixes
  null level now longer progresses level.onLevel
This commit is contained in:
landgreen
2022-01-30 19:15:09 -08:00
parent 53392df55e
commit 8bee75cf6e
10 changed files with 365 additions and 99 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -81,11 +81,9 @@
<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)"> <svg class="SVG-button" id="training-button" width="120" height="45" style="border: 2px #333 solid;" stroke='none' fill='#333' font-size="30px" font-family="Arial, sans-serif" onclick="simulation.startGame(false, true)">
<g stroke='none' fill='#333' stroke-width="2" font-size="30px" font-family="Arial, sans-serif"> <!-- <animate attributeName="fill" values="#f55;#cc5;#5c5;#5dd;#66f;#5dd;#5c5;#cc5;#f55" dur="4s" repeatCount="indefinite" /> -->
<!-- <animate attributeName="fill" values="#f00;#dd0;#0f0;#0ff;#66f;#0ff;#0f0;#dd0;#f77" dur="4s" repeatCount="indefinite" /> --> <text x="10" y="33">training</text>
<text x="10" y="33" class="lore">training</text>
</g>
</svg> </svg>
<div id='info'> <div id='info'>
<div id="settings"> <div id="settings">

View File

@@ -132,6 +132,25 @@ window.addEventListener('load', () => {
if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0) if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0)
if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property]) if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property])
} }
} else if (localSettings.isTrainingNotAttempted && localSettings.runCount < 30) { //make training button more obvious for new players
// document.getElementById("training-button").style.border = "0px #333 solid";
// document.getElementById("training-button").style.fill = "rgb(0, 150, 235)" //"#fff";
// document.getElementById("training-button").style.background = "rgb(0, 200, 255)";
//css classes not working for some reason
// document.getElementById("training-button").classList.add('lore-text');
let myanim = document.createElementNS("http://www.w3.org/2000/svg", 'animate');
myanim.setAttribute("id", "myAnimation");
myanim.setAttribute("attributeType", "XML");
myanim.setAttribute("attributeName", "fill");
// myanim.setAttribute("values", "#f55;#cc5;#5c5;#5dd;#66f;#5dd;#5c5;#cc5;#f55"); //rainbow
myanim.setAttribute("values", "#5dd;#66f;#5dd");
// myanim.setAttribute("values", "#333;rgb(0, 170, 255);#333");
myanim.setAttribute("dur", "3s");
myanim.setAttribute("repeatCount", "indefinite");
document.getElementById("training-button").appendChild(myanim);
document.getElementById("myAnimation").beginElement();
} }
}); });
@@ -252,25 +271,25 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
text += `<div class="pause-grid-module" id ="pause-field"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> ${m.fieldUpgrades[m.fieldMode].description}</div>` text += `<div class="pause-grid-module" id ="pause-field"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> ${m.fieldUpgrades[m.fieldMode].description}</div>`
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) { if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) {
const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isFieldTech) { if (tech.tech[i].isFieldTech) {
text += `<div class="pause-grid-module"><div class="grid-title"> text += `<div class="pause-grid-module"><div class="grid-title">
<span style="position:relative;"> <span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div> <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div> <div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span> </span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else if (tech.tech[i].isGunTech) { } else if (tech.tech[i].isGunTech) {
text += `<div class="pause-grid-module"><div class="grid-title"> text += `<div class="pause-grid-module"><div class="grid-title">
<span style="position:relative;"> <span style="position:relative;">
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div> <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div> <div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span> </span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else if (tech.tech[i].isLore) { } else if (tech.tech[i].isLore) {
text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` text += `<div class="pause-grid-module"><div class="grid-title lore-text"><div class="circle-grid lore"></div> &nbsp; ${tech.tech[i].name} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} else { } else {
text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
} }
} else if (tech.tech[i].isLost) { } else if (tech.tech[i].isLost) {
text += `<div class="pause-grid-module" style="text-decoration: line-through;"><div class="grid-title">${tech.tech[i].link}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>` text += `<div class="pause-grid-module" style="text-decoration: line-through;"><div class="grid-title">${tech.tech[i].link}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
@@ -355,7 +374,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode || (localSettings.isJunkExperiment && tech.tech[i].isJunk))) { if (!tech.tech[i].isExperimentHide && (!tech.tech[i].isNonRefundable || tech.tech[i].isExperimentalMode || (localSettings.isJunkExperiment && tech.tech[i].isJunk))) {
if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) { if (tech.tech[i].allowed() || isAllowed || tech.tech[i].count > 0) {
// console.log(tech.tech[i].name, isAllowed, tech.tech[i].count, tech.haveGunCheck("nail gun")) // console.log(tech.tech[i].name, isAllowed, tech.tech[i].count, tech.haveGunCheck("nail gun"))
const isCount = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""; const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
// <div class="circle-grid-small research" style="position:absolute; top:13px; left:30px;opacity:0.85;"></div> // <div class="circle-grid-small research" style="position:absolute; top:13px; left:30px;opacity:0.85;"></div>
if (tech.tech[i].isFieldTech) { if (tech.tech[i].isFieldTech) {
@@ -367,7 +386,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div> <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div> <div class="circle-grid field" style="position:absolute; top:0; left:10px;opacity:0.65;"></div>
</span> </span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description} &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
</div>` </div>`
// <div class="circle-grid gun" style="position:absolute; top:-3px; left:-3px; opacity:1; height: 33px; width:33px;"></div> // <div class="circle-grid gun" style="position:absolute; top:-3px; left:-3px; opacity:1; height: 33px; width:33px;"></div>
// <div class="circle-grid tech" style="position:absolute; top:5px; left:5px;opacity:1;height: 20px; width:20px;border: #fff solid 2px;"></div> // <div class="circle-grid tech" style="position:absolute; top:5px; left:5px;opacity:1;height: 20px; width:20px;border: #fff solid 2px;"></div>
@@ -380,15 +399,15 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
<div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div> <div class="circle-grid tech" style="position:absolute; top:0; left:0;opacity:0.8;"></div>
<div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div> <div class="circle-grid gun" style="position:absolute; top:0; left:10px; opacity:0.65;"></div>
</span> </span>
&nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description} &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
</div>` </div>`
} else } else
if (tech.tech[i].isJunk) { if (tech.tech[i].isJunk) {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>` techID.innerHTML = `<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
} else if (tech.tech[i].isExperimentalMode) { } else if (tech.tech[i].isExperimentalMode) {
techID.innerHTML = `<div class="grid-title">${tech.tech[i].name}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>` techID.innerHTML = `<div class="grid-title">${tech.tech[i].name}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>`
} else { } else {
techID.innerHTML = `<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${isCount}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div>` techID.innerHTML = `<div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
} }
//deselect selected tech options if you don't have the tech any more // for example: when bot techs are converted after a bot upgrade tech is taken //deselect selected tech options if you don't have the tech any more // for example: when bot techs are converted after a bot upgrade tech is taken
if (tech.tech[i].count === 0 && techID.classList.contains("build-tech-selected")) techID.classList.remove("build-tech-selected"); if (tech.tech[i].count === 0 && techID.classList.contains("build-tech-selected")) techID.classList.remove("build-tech-selected");
@@ -1161,6 +1180,7 @@ if (localSettings) {
difficultyMode: '2', difficultyMode: '2',
fpsCapDefault: 'max', fpsCapDefault: 'max',
runCount: 0, runCount: 0,
isTrainingNotAttempted: true,
levelsClearedLastGame: 0, levelsClearedLastGame: 0,
loreCount: 0, loreCount: 0,
isHuman: false, isHuman: false,

View File

@@ -7,7 +7,8 @@ const level = {
defaultZoom: 1400, defaultZoom: 1400,
onLevel: -1, onLevel: -1,
levelsCleared: 0, levelsCleared: 0,
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion"], //see level.populateLevels: (intro, ... , reservoir, ... , gauntlet, final) added later //see level.populateLevels: (intro, ... , reservoir, reactor, ... , gauntlet, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion"],
communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"], communityLevels: ["stronghold", "basement", "crossfire", "vats", "run", "n-gon", "house", "perplex", "coliseum", "tunnel"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [], levels: [],
@@ -15,23 +16,23 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level if (level.levelsCleared === 0) { //this code only runs on the first level
// m.immuneCycle = Infinity //you can't take damage // m.immuneCycle = Infinity //you can't take damage
// localSettings.levelsClearedLastGame = 10 // localSettings.levelsClearedLastGame = 10
// level.difficultyIncrease(1) //30 is near max on hard //60 is near max on why // spawn.setSpawnList();spawn.setSpawnList();
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("time dilation") // m.setField("standing wave")
// b.giveGuns("harpoon") // b.giveGuns("laser")
// for (let i = 0; i < 9; i++) tech.giveTech("slow light") // for (let i = 0; i < 100; i++) tech.giveTech("slow light")
// tech.giveTech("grenade production") // tech.giveTech("expansion")
// for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech"); // for (let i = 0; i < 2; i++) powerUps.directSpawn(0, 0, "tech");
// tech.giveTech("charmed baryons")
// tech.giveTech("tinsellated flagella") // tech.giveTech("tinsellated flagella")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// tech.giveTech("antiscience") // tech.giveTech("nail-bot")
// 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
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.pavilion(); // level.reactor();
// level.testing(); //not in rotation, used for testing // level.testing(); //not in rotation, used for testing
if (simulation.isTraining) { level.walk(); } else { level.intro(); } if (simulation.isTraining) { level.walk(); } else { level.intro(); }
@@ -41,7 +42,7 @@ const level = {
// for (let i = 0; i < 3; i++) tech.giveTech("undefined") // for (let i = 0; i < 3; i++) tech.giveTech("undefined")
// lore.techCount = 3 // lore.techCount = 3
// simulation.isCheating = false //true; // simulation.isCheating = false //true;
// localSettings.loreCount = 0; //this sets what conversation is heard // localSettings.loreCount = 2; //this sets what conversation is heard
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null() // level.null()
@@ -127,29 +128,29 @@ const level = {
b.dmgScale = 1; //damage done by player decreases each level b.dmgScale = 1; //damage done by player decreases each level
simulation.accelScale = 1 //mob acceleration increases each level simulation.accelScale = 1 //mob acceleration increases each level
simulation.CDScale = 1 //mob CD time decreases each level simulation.CDScale = 1 //mob CD time decreases each level
simulation.dmgScale = 0.41 * simulation.difficulty //damage done by mobs increases each level simulation.dmgScale = 0.38 * simulation.difficulty //damage done by mobs increases each level
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
}, },
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
simulation.difficulty++ simulation.difficulty++
b.dmgScale *= 0.914; //damage done by player decreases each level b.dmgScale *= 0.917; //damage done by player decreases each level
if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level if (simulation.accelScale < 6) simulation.accelScale *= 1.025 //mob acceleration increases each level
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level if (simulation.CDScale > 0.15) simulation.CDScale *= 0.965 //mob CD time decreases each level
} }
simulation.dmgScale = 0.39 * simulation.difficulty //damage done by mobs scales with total levels simulation.dmgScale = 0.38 * simulation.difficulty //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
// console.log(`CD = ${simulation.CDScale}`) // console.log(`CD = ${simulation.CDScale}`)
}, },
difficultyDecrease(num = 1) { //used in easy mode for simulation.reset() difficultyDecrease(num = 1) { //used in easy mode for simulation.reset()
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
simulation.difficulty-- simulation.difficulty--
b.dmgScale /= 0.914; //damage done by player decreases each level b.dmgScale /= 0.917; //damage done by player decreases each level
if (simulation.accelScale > 1) simulation.accelScale /= 1.025 //mob acceleration increases each level if (simulation.accelScale > 1) simulation.accelScale /= 1.025 //mob acceleration increases each level
if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level if (simulation.CDScale < 1) simulation.CDScale /= 0.965 //mob CD time decreases each level
} }
if (simulation.difficulty < 1) simulation.difficulty = 0; if (simulation.difficulty < 1) simulation.difficulty = 0;
simulation.dmgScale = 0.39 * simulation.difficulty //damage done by mobs scales with total levels simulation.dmgScale = 0.38 * simulation.difficulty //damage done by mobs scales with total levels
if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1; if (simulation.dmgScale < 0.1) simulation.dmgScale = 0.1;
simulation.healScale = 1 / (1 + simulation.difficulty * 0.055) simulation.healScale = 1 / (1 + simulation.difficulty * 0.055)
}, },
@@ -235,6 +236,7 @@ const level = {
level.levels = shuffle(level.levels); //shuffles order of maps level.levels = shuffle(level.levels); //shuffles order of maps
} }
level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reservoir"); //add level to the back half of the randomized levels list level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reservoir"); //add level to the back half of the randomized levels list
level.levels.splice(Math.floor(level.levels.length * (0.4 + 0.6 * Math.random())), 0, "reactor"); //add level to the back half of the randomized levels list
level.levels.splice(0, 2); //remove 2 levels from the start of the array level.levels.splice(0, 2); //remove 2 levels from the start of the array
if (!build.isExperimentSelection || (build.hasExperimentalMode && !simulation.isCheating)) { //experimental mode is endless, unless you only have an experiment Tech 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.unshift("intro"); //add level to the start of the randomized levels list
@@ -2364,6 +2366,8 @@ const level = {
}, },
null() { null() {
level.levels.pop(); //remove lore level from rotation level.levels.pop(); //remove lore level from rotation
level.onLevel--
console.log(level.onLevel, level.levels)
//start a conversation based on the number of conversations seen //start a conversation based on the number of conversations seen
if (localSettings.loreCount < lore.conversation.length && !simulation.isCheating) { if (localSettings.loreCount < lore.conversation.length && !simulation.isCheating) {
lore.testSpeechAPI() //see if speech is working lore.testSpeechAPI() //see if speech is working
@@ -2588,6 +2592,116 @@ const level = {
// spawn.suckerBoss(2900, -500) // spawn.suckerBoss(2900, -500)
// spawn.randomMob(1600, -500) // spawn.randomMob(1600, -500)
}, },
reactor() {
level.setPosToSpawn(-50, -800); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 3000;
level.exit.y = -35;
spawn.mapRect(level.exit.x, level.exit.y + 25, 100, 25);
level.defaultZoom = 2000
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5df" //"#d8dadf";
// powerUps.spawnStartingPowerUps(1475, -1175);
// spawn.debris(750, -2200, 3700, 16); //16 debris per level
spawn.mapRect(-1525, -2825, 1250, 3925);
spawn.mapRect(-400, -2025, 625, 925);
spawn.mapRect(-400, -750, 625, 1200);
spawn.mapRect(-425, 0, 4200, 1100);
spawn.mapRect(175, -1250, 50, 300);
spawn.mapRect(-475, -2825, 4250, 1025);
// spawn.mapRect(1200, -1300, 600, 800);
const a = 400 //side length
const c = 100 //corner offset
spawn.mapVertex(1487, -900, `${-a} ${-a+c} ${-a+c} ${-a} ${a-c} ${-a} ${a} ${-a+c} ${a} ${a-c} ${a-c} ${a} ${-a+c} ${a} ${-a} ${a-c}`); //square with edges cut off
//exit
spawn.mapRect(3300, -2825, 1125, 3925);
spawn.mapRect(2750, -2150, 1025, 1775);
spawn.mapRect(2750, -475, 50, 300);
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
// spawn.randomSmallMob(1300, -70);
// spawn.randomMob(2650, -975, 0.8);
// const doorIn = level.door(187, -450, 25, 250, 2) //x, y, width, height, distance, speed = 1
// doorIn.isClosing = false
// level.custom = () => {
// level.exit.drawAndCheck();
// // if (mob.length > 0) {
// // doorIn.isClosing = true
// // } else {
// // doorIn.isClosing = false
// // }
// doorIn.isClosing = !(mob.length > 0)
// doorIn.openClose();
const doorIn = level.door(187, -950, 25, 200, 190, 2) //x, y, width, height, distance, speed = 1
const doorOut = level.door(2762, -175, 25, 200, 190, 2) //x, y, width, height, distance, speed = 1
doorOut.isClosing = true
let isDoorsLocked = false
let isFightOver = false
let isSpawnedBoss = false
level.custom = () => {
if (isDoorsLocked) {
if (!isFightOver && !(simulation.cycle % 120)) { //once a second
let isFoundBoss = false
for (let i = 0; i < mob.length; i++) {
if (mob[i].isBoss) {
isFoundBoss = true
break
}
}
if (!isFoundBoss) {
isFightOver = true
doorIn.isClosing = false
doorOut.isClosing = false
powerUps.spawnBossPowerUp(2900, -100)
for (let i = 0; i < 3; ++i) powerUps.spawn(2900 + 30 * i, -300, "ammo");
}
}
// if (mob.length > 0) {
// doorIn.isClosing = true
// doorOut.isClosing = true
// } else if (!isFightOver) {
// isFightOver = true
// doorIn.isClosing = false
// doorOut.isClosing = false
// powerUps.spawnBossPowerUp(2900, -200)
// }
if (player.position.x < 0) { //if player gets trapped inside starting room open up again
isDoorsLocked = false
doorIn.isClosing = false
}
} else if (player.position.x > 225) {
isDoorsLocked = true
doorIn.isClosing = true
doorOut.isClosing = true
if (!isSpawnedBoss) {
isSpawnedBoss = true
for (let i = 0, len = simulation.difficulty / 20; i < len; ++i) spawn.bounceBoss(1487 + 300 * i, -1525, 80, false);
}
}
doorIn.openClose();
doorOut.openClose();
level.enter.draw();
level.exit.drawAndCheck();
};
level.customTopLayer = () => {
// if (isDoorsLocked) {
// ctx.fillStyle = "#333"
// ctx.fillRect(2800, -375, 500, 375);
// }
doorIn.draw();
doorOut.draw();
};
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
template() { template() {
level.custom = () => { level.custom = () => {
level.exit.drawAndCheck(); level.exit.drawAndCheck();
@@ -3309,12 +3423,7 @@ const level = {
vanish.push(level.vanish(-350, -225, 150, 225)) vanish.push(level.vanish(-350, -225, 150, 225))
vanish.push(level.vanish(-350, -450, 150, 223)) vanish.push(level.vanish(-350, -450, 150, 223))
spawn.mapRect(2475, -1800, 250, 2300); spawn.mapRect(2475, -1800, 250, 2300);
// vanish.push(level.vanish(1300, -375, 150, 225))
// vanish.push(level.vanish(1300, -450, 150, 223))
// spawn.mapRect(1200, -375, 250, 50);
// spawn.mapRect(1200, -375, 250, 225);
// spawn.mapRect(1200, -375, 175, 25);
spawn.mapRect(1200, -750, 100, 450); spawn.mapRect(1200, -750, 100, 450);
spawn.mapRect(1200, -375, 250, 75); spawn.mapRect(1200, -375, 250, 75);
powerUps.spawnStartingPowerUps(550, -100); powerUps.spawnStartingPowerUps(550, -100);
@@ -3322,11 +3431,6 @@ const level = {
spawn.mapRect(175, -25, 750, 50); spawn.mapRect(175, -25, 750, 50);
spawn.bodyRect(1350, -175, 150, 175, 0.5); spawn.bodyRect(1350, -175, 150, 175, 0.5);
spawn.bodyRect(1350, -600, 125, 225, 0.2); spawn.bodyRect(1350, -600, 125, 225, 0.2);
//entrance
// vanish.push(level.vanish(-300, -500, 100, 25))
// vanish.push(level.vanish(-450, -200, 100, 25))
// spawn.bodyRect(-450, -175, 100, 175, 0.7);
// spawn.bodyRect(-250, -550, 50, 50, 0.7);
//middle floor //middle floor
spawn.bodyRect(215, -1175, 100, 100, 0.3); spawn.bodyRect(215, -1175, 100, 100, 0.3);
@@ -5428,7 +5532,6 @@ const level = {
ctx.fillRect(3650, -110, 1000, 170); ctx.fillRect(3650, -110, 1000, 170);
ctx.fillRect(4865, -55, 100, 55); ctx.fillRect(4865, -55, 100, 55);
level.exit.drawAndCheck(); level.exit.drawAndCheck();
level.enter.draw(); level.enter.draw();
}; };
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -7378,8 +7481,6 @@ const level = {
level.custom = () => { level.custom = () => {
boost1.query(); boost1.query();
level.exit.drawAndCheck()
buttonGreen.query() buttonGreen.query()
buttonYellow.query() buttonYellow.query()
buttonRed.query() buttonRed.query()
@@ -7521,6 +7622,7 @@ const level = {
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
ctx.fillRect(3500, 675, 600, 450) ctx.fillRect(3500, 675, 600, 450)
level.enter.draw() level.enter.draw()
level.exit.drawAndCheck()
} }
level.customTopLayer = () => { level.customTopLayer = () => {
@@ -8864,6 +8966,11 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
}, },
crouch() { //learn to crouch crouch() { //learn to crouch
if (localSettings.isTrainingNotAttempted) { //after making it to the second training level
localSettings.isTrainingNotAttempted = false // this makes the training button less obvious at the start screen
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
m.addHealth(Infinity) m.addHealth(Infinity)
level.setPosToSpawn(75, -100); //normal spawn level.setPosToSpawn(75, -100); //normal spawn
spawn.mapRect(25, -60, 100, 20); //small platform for player spawn.mapRect(25, -60, 100, 20); //small platform for player

View File

@@ -1154,7 +1154,17 @@ const mobs = {
} }
if (tech.isBotSpawnerReset) { if (tech.isBotSpawnerReset) {
for (let i = 0, len = bullet.length; i < len; i++) { for (let i = 0, len = bullet.length; i < len; i++) {
if (bullet[i].botType && bullet[i].endCycle !== Infinity) bullet[i].endCycle = simulation.cycle + 840 //14 seconds if (bullet[i].botType && bullet[i].endCycle !== Infinity) {
bullet[i].endCycle = simulation.cycle + 840 //14 seconds
// //draw a flash on top of bot
// ctx.beginPath();
// const v = bullet[i].vertices;
// ctx.moveTo(v[0].x, v[0].y);
// for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y);
// ctx.lineTo(v[0].x, v[0].y);
// ctx.fillStyle = "#fff"
// ctx.fill();
}
} }
} }
if (Math.random() < tech.botSpawner) { if (Math.random() < tech.botSpawner) {

View File

@@ -1604,10 +1604,10 @@ const m = {
if (tech.isStandingWaveExpand) { if (tech.isStandingWaveExpand) {
if (input.field) { if (input.field) {
// const oldHarmonicRadius = m.harmonicRadius // const oldHarmonicRadius = m.harmonicRadius
m.harmonicRadius = 0.985 * m.harmonicRadius + 0.015 * 2.5 m.harmonicRadius = 0.99 * m.harmonicRadius + 0.01 * 4
// m.energy -= 0.1 * (m.harmonicRadius - oldHarmonicRadius) // m.energy -= 0.1 * (m.harmonicRadius - oldHarmonicRadius)
} else { } else {
m.harmonicRadius = 0.995 * m.harmonicRadius + 0.005 m.harmonicRadius = 0.994 * m.harmonicRadius + 0.006
} }
} }
m.harmonicShield() m.harmonicShield()
@@ -3064,7 +3064,7 @@ const m = {
if (input.field) { if (input.field) {
if (tech.isWormHolePause) { if (tech.isWormHolePause) {
const drain = m.fieldRegen + 0.0007 const drain = m.fieldRegen + 0.0004
if (m.energy > drain) { if (m.energy > drain) {
m.energy -= drain m.energy -= drain
if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1/4 seconds // and can't regen if (m.immuneCycle < m.cycle + 1) m.immuneCycle = m.cycle + 1; //player is immune to damage for 1/4 seconds // and can't regen

View File

@@ -397,8 +397,7 @@ const powerUps = {
const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2 const banishLength = tech.isDeterminism ? 1 : 3 + tech.isExtraChoice * 2
for (let i = 0; i < banishLength; i++) { for (let i = 0; i < banishLength; i++) {
const index = powerUps.tech.choiceLog.length - i - 1 const index = powerUps.tech.choiceLog.length - i - 1
// console.log(index, powerUps.tech.choiceLog[index], tech.tech[powerUps.tech.choiceLog[index]].name) if (powerUps.tech.choiceLog[index] !== undefined || powerUps.tech.choiceLog[index] !== null) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true
if (powerUps.tech.choiceLog[index] !== undefined) tech.tech[powerUps.tech.choiceLog[index]].isBanished = true
} }
simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`) simulation.makeTextLog(`powerUps.tech.length: ${Math.max(0,powerUps.tech.lastTotalChoices - banishLength)}`)
} }
@@ -470,7 +469,7 @@ const powerUps = {
} }
if (tech.healGiveMaxEnergy) { if (tech.healGiveMaxEnergy) {
tech.healMaxEnergyBonus += 0.07 tech.healMaxEnergyBonus += 0.08
m.setMaxEnergy(); m.setMaxEnergy();
} }
}, },
@@ -580,11 +579,14 @@ const powerUps = {
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("field",true)'>✕</div>` if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("field",true)'>✕</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>field</h3>` text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>field</h3>`
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice1})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice1].name}</div> ${m.fieldUpgrades[choice1].description}</div>` text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice1})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice1].name}</div> ${m.fieldUpgrades[choice1].description}</div>`
powerUps.field.choiceLog.push(choice1)
if (!tech.isDeterminism) { if (!tech.isDeterminism) {
choice2 = powerUps.field.pick(m.fieldUpgrades, choice1) choice2 = powerUps.field.pick(m.fieldUpgrades, choice1)
if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice2})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice2].name}</div> ${m.fieldUpgrades[choice2].description}</div>` if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice2})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice2].name}</div> ${m.fieldUpgrades[choice2].description}</div>`
choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2) choice3 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2)
if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice3].name}</div> ${m.fieldUpgrades[choice3].description}</div>` if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choice3})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choice3].name}</div> ${m.fieldUpgrades[choice3].description}</div>`
powerUps.field.choiceLog.push(choice2)
powerUps.field.choiceLog.push(choice3)
} }
if (tech.isExtraChoice) { if (tech.isExtraChoice) {
let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3) let choice4 = powerUps.field.pick(m.fieldUpgrades, choice1, choice2, choice3)
@@ -594,9 +596,6 @@ const powerUps = {
powerUps.field.choiceLog.push(choice4) powerUps.field.choiceLog.push(choice4)
powerUps.field.choiceLog.push(choice5) powerUps.field.choiceLog.push(choice5)
} }
powerUps.field.choiceLog.push(choice1)
powerUps.field.choiceLog.push(choice2)
powerUps.field.choiceLog.push(choice3)
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) { if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.junkResearchNumber = Math.floor(4 * Math.random()) tech.junkResearchNumber = Math.floor(4 * Math.random())
@@ -627,7 +626,7 @@ const powerUps = {
// banishLog: [], //records all tech permanently removed from the selection pool // banishLog: [], //records all tech permanently removed from the selection pool
effect() { effect() {
if (m.alive) { if (m.alive) {
function pick(skip1 = -1, skip2 = -1, skip3 = -1, skip4 = -1) { function pick(skip1 = null, skip2 = null, skip3 = null, skip4 = null) {
let options = []; let options = [];
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed() && !tech.tech[i].isBanished) { if (tech.tech[i].count < tech.tech[i].maxCount && i !== skip1 && i !== skip2 && i !== skip3 && i !== skip4 && tech.tech[i].allowed() && !tech.tech[i].isBanished) {
@@ -685,14 +684,17 @@ const powerUps = {
if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>✕</div>` if (!tech.isSuperDeterminism) text += `<div class='cancel' onclick='powerUps.endDraft("tech",true)'>✕</div>`
text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>` text += `<h3 style = 'color:#fff; text-align:left; margin: 0px;'>tech</h3>`
let choice1 = pick() let choice1 = pick()
let choice2 = -1 let choice2 = null
let choice3 = -1 let choice3 = null
if (choice1 > -1) { if (choice1 !== null) {
powerUps.tech.choiceLog.push(choice1)
if (!tech.isDeterminism) { if (!tech.isDeterminism) {
choice2 = pick(choice1) choice2 = pick(choice1)
// if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choice2})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choice2].name}</div> ${tech.tech[choice2].description}</div>` // if (choice2 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choice2})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choice2].name}</div> ${tech.tech[choice2].description}</div>`
choice3 = pick(choice1, choice2) choice3 = pick(choice1, choice2)
// if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choice3})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choice3].name}</div> ${tech.tech[choice3].description}</div>` // if (choice3 > -1) text += `<div class="choose-grid-module" onclick="powerUps.choose('tech',${choice3})"><div class="grid-title"><div class="circle-grid tech"></div> &nbsp; ${tech.tech[choice3].name}</div> ${tech.tech[choice3].description}</div>`
powerUps.tech.choiceLog.push(choice2)
powerUps.tech.choiceLog.push(choice3)
} }
if (tech.isExtraChoice) { if (tech.isExtraChoice) {
let choice4 = pick(choice1, choice2, choice3) let choice4 = pick(choice1, choice2, choice3)
@@ -702,9 +704,6 @@ const powerUps = {
powerUps.tech.choiceLog.push(choice4) powerUps.tech.choiceLog.push(choice4)
powerUps.tech.choiceLog.push(choice5) powerUps.tech.choiceLog.push(choice5)
} }
powerUps.tech.choiceLog.push(choice1)
powerUps.tech.choiceLog.push(choice2)
powerUps.tech.choiceLog.push(choice3)
// if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>` // if (powerUps.research.count) text += `<div class="choose-grid-module" onclick="powerUps.research.use('tech')"><div class="grid-title"><div class="circle-grid research"></div> &nbsp; research <span class="research-select">${powerUps.research.count}</span></div></div>`
if (tech.isExtraGunField) { if (tech.isExtraGunField) {
@@ -857,8 +856,6 @@ const powerUps = {
for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>` for (let i = 0, len = Math.min(powerUps.research.count, 30); i < len; i++) text += `<div class="circle-grid research" style="position:absolute; top:0; left:${(18 - len*0.3)*i}px ;opacity:0.8; border: 1px #fff solid;"></div>`
text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>` text += `</span>&nbsp; <span class='research-select'>${tech.isResearchReality?"<span class='alt'>alternate reality</span>": "research"}</span></div></div>`
} }
// console.log(powerUps.gun.choiceLog)
// console.log(choice1, choice2, choice3)
if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>` if (tech.isOneGun && b.inventory.length > 0) text += `<div style = "color: #f24">replaces your current gun</div>`
document.getElementById("choose-grid").innerHTML = text document.getElementById("choose-grid").innerHTML = text
powerUps.showDraft(); powerUps.showDraft();

View File

@@ -1197,7 +1197,7 @@ const spawn = {
} else if (!m.isCloak) { } else if (!m.isCloak) {
me.foundPlayer(); me.foundPlayer();
} }
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isInvulnerable = true me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.damageReduction = 0 me.damageReduction = 0
@@ -1276,7 +1276,7 @@ const spawn = {
me.foundPlayer(); me.foundPlayer();
} }
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.isInvulnerable = true // me.isInvulnerable = true
// me.startingDamageReduction = me.damageReduction // me.startingDamageReduction = me.damageReduction
// me.damageReduction = 0 // me.damageReduction = 0
@@ -2030,7 +2030,7 @@ const spawn = {
this.cons2.length = 100 + 1.5 * this.radius; this.cons2.length = 100 + 1.5 * this.radius;
this.isInvulnerable = false this.isInvulnerable = false
this.invulnerabilityCountDown = 60 + Math.max(0, 70 - simulation.difficulty * 0.5) this.invulnerabilityCountDown = 70 + Math.max(0, 70 - simulation.difficulty * 0.5)
this.damageReduction = this.startingDamageReduction this.damageReduction = this.startingDamageReduction
for (let i = 0; i < this.babyList.length; i++) { for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
@@ -2044,7 +2044,7 @@ const spawn = {
this.cons2.length = -200; this.cons2.length = -200;
this.isInvulnerable = false this.isInvulnerable = false
this.invulnerabilityCountDown = 60 + Math.max(0, 70 - simulation.difficulty) this.invulnerabilityCountDown = 70 + Math.max(0, 70 - simulation.difficulty)
this.damageReduction = this.startingDamageReduction this.damageReduction = this.startingDamageReduction
for (let i = 0; i < this.babyList.length; i++) { for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
@@ -3518,6 +3518,110 @@ const spawn = {
ctx.setLineDash([]); ctx.setLineDash([]);
} }
}, },
bounceBoss(x, y, radius = 80, isSpawnBossPOwerUp = true) {
mobs.spawn(x, y, 0, radius, "rgb(255,255,255)") // "rgb(201,202,225)");
let me = mob[mob.length - 1];
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
me.isBoss = true;
Matter.Body.setDensity(me, 0.003); //normal is 0.001
me.inertia = Infinity;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.01
me.restitution = 1
me.friction = 0
me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map | cat.mob
Matter.Body.setVelocity(me, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) });
me.seePlayer.recall = 1;
// spawn.shield(me, x, y, 1);
me.onDamage = function() {
if (this.health < this.nextHealthThreshold) {
this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
this.fireCount = 60 + simulation.difficulty * 1.5
this.isInvulnerable = true
this.damageReduction = 0
}
};
if (isSpawnBossPOwerUp) me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) };
me.cycle = 0
me.nextHealthThreshold = 0.75
me.fireCount = 0
// console.log(me.mass) //100
me.do = function() {
if (this.isInvulnerable) {
this.fireCount--
if (this.fireCount < 0) {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
}
if (this.mass > 10) Matter.Body.scale(this, 0.99, 0.99);
// for (let i = 0; i < 1; i++) {
const velocity = Vector.rotate(Vector.mult(Vector.normalise(this.velocity), -10 - 10 * Math.random()), 1 * (Math.random() - 0.5))
spawn.bounceBullet(this.position.x, this.position.y, velocity)
// }
//draw invulnerable
ctx.beginPath();
let vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 20;
ctx.strokeStyle = "rgba(255,255,255,0.7)";
ctx.stroke();
} else if (this.mass < 100) {
Matter.Body.scale(this, 1.01, 1.01); //grow back to normal size
}
this.checkStatus();
//horizontal attraction
// const xMag = 0.0005
// if (player.position.x > this.position.x + 200) {
// this.force.x += xMag * this.mass;
// } else if (player.position.x < this.position.x - 200) {
// this.force.x -= xMag * this.mass;
// }
//maintain speed //faster in the vertical to help avoid repeating patterns
if (Math.abs(this.velocity.y) < 15) {
Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.05 });
}
if (Math.abs(this.velocity.x) < 11) {
Matter.Body.setVelocity(this, { x: this.velocity.x * 1.05, y: this.velocity.y });
}
};
},
bounceBullet(x, y, velocity = { x: 0, y: 0 }, radius = 10, sides = 6) {
//bullets
mobs.spawn(x, y, sides, radius, "rgb(255,0,155)");
let me = mob[mob.length - 1];
me.stroke = "transparent";
Matter.Body.setDensity(me, 0.00003); //normal is 0.001
me.timeLeft = 360 + Math.floor(180 * Math.random())
me.inertia = Infinity;
me.damageReduction = 1
me.frictionAir = 0
me.friction = 0
me.restitution = 1
me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.bullet | cat.player | cat.body | cat.map | cat.mob
me.leaveBody = false;
me.isDropPowerUp = false;
me.isBadTarget = true;
me.isMobBullet = true;
me.showHealthBar = false;
me.onHit = function() {
this.explode(this.mass * 20);
};
me.do = function() {
this.timeLimit();
};
Matter.Body.setVelocity(me, velocity);
},
slashBoss(x, y, radius = 80) { slashBoss(x, y, radius = 80) {
mobs.spawn(x, y, 5, radius, "rgb(201,202,225)"); mobs.spawn(x, y, 5, radius, "rgb(201,202,225)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];

View File

@@ -795,7 +795,7 @@ const tech = {
}, },
{ {
name: "heuristics", name: "heuristics",
description: "<strong>30%</strong> decreased <strong><em>delay</em></strong> after firing", description: "<strong>33%</strong> decreased <strong><em>delay</em></strong> after firing",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -803,7 +803,7 @@ const tech = {
allowed() { return true }, allowed() { return true },
requires: "", requires: "",
effect() { effect() {
tech.fireRate *= 0.7 tech.fireRate *= 0.67
b.setFireCD(); b.setFireCD();
}, },
remove() { remove() {
@@ -4671,7 +4671,7 @@ const tech = {
}, },
{ {
name: "ammonium nitrate", name: "ammonium nitrate",
description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>30%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>30%</strong>", description: "increase <strong class='color-e'>explosive</strong> <strong class='color-d'>damage</strong> by <strong>27%</strong><br>increase <strong class='color-e'>explosive</strong> <strong>radius</strong> by <strong>27%</strong>",
isGunTech: true, isGunTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -4682,7 +4682,7 @@ const tech = {
}, },
requires: "an explosive damage source, not iridium-192", requires: "an explosive damage source, not iridium-192",
effect: () => { effect: () => {
tech.explosiveRadius += 0.3; tech.explosiveRadius += 0.27;
}, },
remove() { remove() {
tech.explosiveRadius = 1; tech.explosiveRadius = 1;
@@ -5955,7 +5955,7 @@ const tech = {
}, },
{ {
name: "spherical harmonics", name: "spherical harmonics",
description: "<strong>standing wave</strong> oscillates in a 3rd dimension<br>increasing <strong>deflecting</strong> efficiency by <strong>40%</strong>", description: "<strong>standing wave</strong> oscillates in a 3rd dimension<br>increase <strong>deflecting</strong> efficiency by <strong>40%</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -5967,18 +5967,18 @@ const tech = {
requires: "standing wave", requires: "standing wave",
effect() { effect() {
tech.harmonics++ tech.harmonics++
m.fieldShieldingScale = 1.3 * Math.pow(0.6, (tech.harmonics - 2)) m.fieldShieldingScale = (tech.isStandingWaveExpand ? 1.1 : 1.3) * Math.pow(0.6, (tech.harmonics - 2))
m.harmonicShield = m.harmonicAtomic m.harmonicShield = m.harmonicAtomic
}, },
remove() { remove() {
tech.harmonics = 2 tech.harmonics = 2
m.fieldShieldingScale = 1.3 * Math.pow(0.6, (tech.harmonics - 2)) m.fieldShieldingScale = (tech.isStandingWaveExpand ? 1.1 : 1.3) * Math.pow(0.6, (tech.harmonics - 2))
m.harmonicShield = m.harmonic3Phase m.harmonicShield = m.harmonic3Phase
} }
}, },
{ {
name: "expansion", name: "expansion",
description: "using <strong>standing wave</strong> field<br>temporarily <strong>expands</strong> its <strong>radius</strong>", description: "using <strong>standing wave</strong> field <strong>expands</strong> its <strong>radius</strong><br>increase <strong>deflecting</strong> efficiency by <strong>25%</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,
@@ -5991,9 +5991,11 @@ const tech = {
requires: "standing wave", requires: "standing wave",
effect() { effect() {
tech.isStandingWaveExpand = true tech.isStandingWaveExpand = true
m.fieldShieldingScale = (tech.isStandingWaveExpand ? 1.1 : 1.3) * Math.pow(0.6, (tech.harmonics - 2))
}, },
remove() { remove() {
tech.isStandingWaveExpand = false tech.isStandingWaveExpand = false
m.fieldShieldingScale = (tech.isStandingWaveExpand ? 1.1 : 1.3) * Math.pow(0.6, (tech.harmonics - 2))
m.harmonicRadius = 1 m.harmonicRadius = 1
} }
}, },
@@ -8468,7 +8470,7 @@ const tech = {
}, },
{ {
name: "energy investment", name: "energy investment",
description: "every 10 seconds drain your <strong class='color-f'>energy</strong><br>return it doubled 10 seconds later<br>lasts 180 seconds", description: "every 10 seconds drain your <strong class='color-f'>energy</strong><br>return it doubled 5 seconds later",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -8477,20 +8479,20 @@ const tech = {
allowed() { return true }, allowed() { return true },
requires: "", requires: "",
effect() { effect() {
for (let i = 0; i < 18; i++) { setInterval(() => {
setTimeout(() => { //drain energy if (!simulation.paused) {
const energy = m.energy const energy = m.energy
m.energy = 0 m.energy = 0
setTimeout(() => { //return energy setTimeout(() => { //return energy
m.energy += 2 * energy m.energy += 2 * energy
}, 5000); }, 5000);
}, i * 10000);
} }
}, 10000);
}, },
remove() {} remove() {}
}, },
{ {
name: "missile Launching System", name: "missile launching system",
description: "fire missiles for the next 120 seconds", description: "fire missiles for the next 120 seconds",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
@@ -8524,12 +8526,14 @@ const tech = {
requires: "", requires: "",
effect() { effect() {
setInterval(() => { setInterval(() => {
if (!simulation.paused && document.visibilityState !== "hidden") {
b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -Math.PI / 2) //fire different angles for each grenade b.grenade(Vector.add(m.pos, { x: 10 * (Math.random() - 0.5), y: 10 * (Math.random() - 0.5) }), -Math.PI / 2) //fire different angles for each grenade
const who = bullet[bullet.length - 1] const who = bullet[bullet.length - 1]
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.1, x: who.velocity.x * 0.1,
y: who.velocity.y * 0.1 y: who.velocity.y * 0.1
}); });
}
}, 2000); }, 2000);
}, },
remove() {} remove() {}

View File

@@ -1,20 +1,46 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
JUNK tech: tinker - unlock JUNK tech in experiment mode new level: reactor - midBoss fight
this effect is stored for future visits on the same browser it's not well balanced yet
several JUNK tech text have been cleaned up Let me know if there are any impossible gun combinations
your explosions do 8% more damage, but not more harm for new players the training button at the start screen now cycles colors
grenade gun fires 5% faster effect shows if you haven't cleared the first training level, and you haven't done at least a few normal runs
ruins/pavilion map is adjusted to be a bit easier to move around
crouching speeds up exit door animation
removed google analytics standing wave expansion tech is 40% larger and gives 25% deflecting efficiency
bug fix with power ups and frozen time ammonium nitrate gives 30 -> 27% damage and range
bug fix with elevators and map collision heuristics gives 30 -> 33% fire rate
wormhole invariant tech drains energy much slower while time is paused
bug fixes
null level now longer progresses level.onLevel
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
reactor
give map some background graphics
it's a little short
add alternate boss
add a boss that spawns after the first one dies
balance
boss damage reduction
bullet size
bullet spawn number
bounce speed
add horizontal flip mode
bug: possibly clearing away all bullets causes a problem
bullet.js 255 (.do() is missing)
I died and quantum immortality triggered (I had needles and ice-IX)
game crashed but recovered
go non-collide with mobs when immune to damage?
mobs that are invulnerable from the front
vertical reversed version of reservoir level, start at top and press buttons to lower slime
mechanic: push a very large block into slime in order to stand on it and avoid slime
add anticipation to more mob attacks add anticipation to more mob attacks
stabber stabber
striker striker
@@ -28,8 +54,6 @@ path finding system
figure out how to get friction effects on map/body to apply to player figure out how to get friction effects on map/body to apply to player
vertical reversed version of reservoir level, start at top and press buttons to lower slime
growBoss and cellBoss are too similar growBoss and cellBoss are too similar
variant of Occam's razor - remove 50% of your tech for each removed get: variant of Occam's razor - remove 50% of your tech for each removed get:
@@ -540,6 +564,8 @@ possible names for tech
hall effect thrusters hall effect thrusters
spaghettification spaghettification
particle accelerator particle accelerator
superluminal signalling
NP-complete
a tutorial / lore intro a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players