animated level load
animated new level load graphics for reactor and final level autoZoom code rewritten to work with pause better using the ephemera system this might cause bugs, I already found a few intro level renamed initial extra ammo power ups on why difficulty for final and reactor levels removed falling off the map damage on levels that still had falling off damage mob: stinger - has speed that adjusts as it flaps it's wings and a short range laser tech: strange loop - +9% damage, removing it gives null hypothesis and strange attractor tech: martingale - +11% damage, removing this has a 50% chance to not remove and to double it's damage paradigm shift removes 6 health when it ejects a tech, but now has a 85->97% chance to work ammo, heal, research tech spawn extra power ups after each time you take them tungsten carbide skin has a hexagon look and +222->300 max health Bayesian statistics spawn 3->6 research ansatz spawns 2->3 research if you have no research Ψ(t) collapse 16->21 research futures exchange 4.3->4.7% duplication replication 9->10 duplication stimulated emission 17->19% duplication anthropic principle spawn 5->16 heals when you die supply chain: no long gives JUNK instead triples the frequency of finding applied science electronegativity 0.22->0.26% damage per energy non-renewables 88->97% damage anticorrelation 100->111% damage decorrelation 70->77% defense parasitism 83->93% damage torpor 66->74% defense bug fix: recycling works with mass-energy (although it doesn't do much) ternary wasn't working in many situations, but it should now fixed bubble fusion exploit that triggers on mobs in factory endlessly bot fabrication was making 1 extra bot and giving negative research sometimes
This commit is contained in:
14
js/index.js
14
js/index.js
@@ -1409,14 +1409,16 @@ window.addEventListener("keydown", function (event) {
|
||||
if (event.key === "X") m.death(); //only uppercase
|
||||
switch (event.key.toLowerCase()) {
|
||||
case "o":
|
||||
simulation.isAutoZoom = false;
|
||||
simulation.zoomScale /= 0.9;
|
||||
simulation.setZoom();
|
||||
// simulation.isAutoZoom = false;
|
||||
// simulation.zoomScale /= 0.9;
|
||||
// simulation.setZoom();
|
||||
simulation.zoomTransition(simulation.zoomScale / 0.9)
|
||||
break;
|
||||
case "i":
|
||||
simulation.isAutoZoom = false;
|
||||
simulation.zoomScale *= 0.9;
|
||||
simulation.setZoom();
|
||||
// simulation.isAutoZoom = false;
|
||||
// simulation.zoomScale *= 0.9;
|
||||
// simulation.setZoom();
|
||||
simulation.zoomTransition(simulation.zoomScale * 0.9)
|
||||
break
|
||||
case "`":
|
||||
powerUps.directSpawn(simulation.mouseInGame.x, simulation.mouseInGame.y, "research");
|
||||
|
||||
195
js/level.js
195
js/level.js
@@ -9,7 +9,7 @@ const level = {
|
||||
onLevel: -1,
|
||||
levelsCleared: 0,
|
||||
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
|
||||
//see level.populateLevels: (intro, ... , reservoir or factory, reactor, ... , subway, final) added later
|
||||
//see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later
|
||||
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"],
|
||||
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo"],
|
||||
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon", "diamagnetism"],
|
||||
@@ -36,22 +36,24 @@ const level = {
|
||||
// b.giveGuns("harpoon") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
|
||||
// b.guns[8].ammo = 100000000
|
||||
// requestAnimationFrame(() => { tech.giveTech("Higgs mechanism") });
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("Higgs mechanism")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("topological defect")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("Hilbert space")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("martingale")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("paradigm shift")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
|
||||
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) tech.giveTech("orbital-bot") });
|
||||
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
|
||||
// m.skin.hexagon();
|
||||
|
||||
// for (let i = 0; i < 1; i++) tech.giveTech("cascading failure")
|
||||
|
||||
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("induction furnace")
|
||||
// for (let i = 0; i < 1; ++i) tech.giveTech("autonomous defense")
|
||||
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
|
||||
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
|
||||
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
|
||||
// level.skyscrapers();
|
||||
// level.testing();
|
||||
|
||||
// for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500)
|
||||
// for (let i = 0; i < 10; ++i) spawn.starter(1900, -500, 50)
|
||||
// for (let i = 0; i < 4; ++i) spawn.stinger(1900, -500)
|
||||
// for (let i = 0; i < 1; ++i) spawn.timeSkipBoss(1900, -2500)
|
||||
// spawn.beetleBoss(1900, -500, 25)
|
||||
// spawn.slasher2(2000, -1150)
|
||||
@@ -62,7 +64,7 @@ const level = {
|
||||
// spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
|
||||
// for (let i = 0; i < 40; ++i) tech.giveTech()
|
||||
|
||||
level[simulation.isTraining ? "walk" : "intro"]() //normal starting level **************************************************
|
||||
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
|
||||
|
||||
// spawn.bodyRect(2425, -120, 200, 200);
|
||||
// console.log(body[body.length - 1].mass)
|
||||
@@ -74,9 +76,9 @@ const level = {
|
||||
// for (let i = 0; i < 20; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
|
||||
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
|
||||
//lore testing
|
||||
// simulation.isCheating = false //true;
|
||||
// for (let i = 0; i < 5; i++) tech.giveTech("undefined")
|
||||
// lore.techCount = 2
|
||||
// simulation.isCheating = false //true;
|
||||
// level.levelsCleared = 10
|
||||
// localSettings.loreCount = 5 //this sets what conversation is heard
|
||||
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
|
||||
@@ -284,6 +286,150 @@ const level = {
|
||||
tech.isDeathAvoidedThisLevel = false;
|
||||
simulation.updateTechHUD();
|
||||
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
|
||||
|
||||
|
||||
//pop up new level info screen for a few seconds
|
||||
if (!simulation.isChoosing && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor")) { //level.levels[level.onLevel] === "subway" ||
|
||||
//pause
|
||||
if (!simulation.paused) {
|
||||
simulation.paused = true;
|
||||
simulation.isChoosing = true; //stops p from un pausing on key down
|
||||
// build.pauseGrid()
|
||||
// document.body.style.cursor = "auto";
|
||||
}
|
||||
//build level info
|
||||
document.getElementById("choose-grid").style.gridTemplateColumns = "250px"
|
||||
let text = `<div><div class="card-background" style="height:auto; border: none; background-color: transparent; line-height: 160%; background-color: var(--card-color); font-size: 1.15em;"> <div class="card-text">`
|
||||
for (let i = 0; i < level.levels.length; i++) {
|
||||
if (i < level.levelsCleared) {
|
||||
text += `<div style="user-select: none;">${level.levels[i]}</div>`
|
||||
} else if (i === level.levelsCleared) {
|
||||
// text += `<div><strong class="fade-in-faster">${level.levels[i]}</strong></div>`
|
||||
text += `<div class="unblur" style="user-select: none;"><strong>${level.levels[i]}</strong></div>`
|
||||
} else {
|
||||
text += `<div class= "blurry-text" style="user-select: none;">${level.levels[i]}</div>` //blurry text
|
||||
// ???????? text
|
||||
// text += `<div style="user-select: none; color: #bbb;">`
|
||||
// for (let j = 0; j < level.levels[i].length; j++) text += `?`
|
||||
// text += `</div>`
|
||||
}
|
||||
}
|
||||
text += `</div> </div></div>`
|
||||
|
||||
document.getElementById("choose-grid").innerHTML = text
|
||||
//show level info
|
||||
document.getElementById("choose-grid").style.opacity = "1"
|
||||
document.getElementById("choose-grid").style.transitionDuration = "0.25s"; //how long is the fade in on
|
||||
document.getElementById("choose-grid").style.visibility = "visible"
|
||||
|
||||
simulation.draw.cons();
|
||||
simulation.draw.body();
|
||||
level.customTopLayer();
|
||||
let count = simulation.testing ? 0 : 240
|
||||
let newLevelDraw = () => {
|
||||
count--
|
||||
if (count > 0) {
|
||||
requestAnimationFrame(newLevelDraw);
|
||||
} else { //unpause
|
||||
// document.body.style.cursor = "none";
|
||||
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles
|
||||
if (simulation.paused) requestAnimationFrame(cycle);
|
||||
if (m.alive) simulation.paused = false;
|
||||
simulation.isChoosing = false; //stops p from un pausing on key down
|
||||
build.unPauseGrid()
|
||||
document.getElementById("choose-grid").style.opacity = "0"
|
||||
setTimeout(() => {
|
||||
document.getElementById("choose-grid").style.visibility = "hidden"
|
||||
}, 1000);
|
||||
}
|
||||
//draw
|
||||
simulation.wipe();
|
||||
m.look();
|
||||
simulation.camera();
|
||||
// if (count < 30) {
|
||||
// }
|
||||
// if (count < 60) {
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.body();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.body();
|
||||
// simulation.draw.drawMapPath();
|
||||
// mobs.draw();
|
||||
// } else
|
||||
// if (count < 240) {
|
||||
simulation.draw.wireFrame();
|
||||
// }
|
||||
// else if (count === 91) { //hide text boss
|
||||
// document.getElementById("choose-grid").style.opacity = "0"
|
||||
// setTimeout(() => {
|
||||
// document.getElementById("choose-grid").style.visibility = "hidden"
|
||||
// }, 1000);
|
||||
// }
|
||||
ctx.restore();
|
||||
simulation.drawCursor();
|
||||
}
|
||||
requestAnimationFrame(newLevelDraw);
|
||||
|
||||
|
||||
// // clear
|
||||
// requestAnimationFrame(() => {
|
||||
// simulation.wipe();
|
||||
// });
|
||||
|
||||
// //wireframe
|
||||
// setTimeout(() => {
|
||||
// requestAnimationFrame(() => {
|
||||
// simulation.wipe();
|
||||
// simulation.camera();
|
||||
// simulation.draw.wireFrame();
|
||||
// ctx.restore();
|
||||
// });
|
||||
// }, 500);
|
||||
|
||||
// //almost normal draw
|
||||
// setTimeout(() => {
|
||||
// requestAnimationFrame(() => {
|
||||
// simulation.wipe();
|
||||
// simulation.camera();
|
||||
// // ctx.fillStyle = "rgba(0,0,0,0.66)"
|
||||
// // ctx.fill(simulation.draw.mapPath);
|
||||
// simulation.draw.drawMapPath();
|
||||
// ctx.restore();
|
||||
// });
|
||||
// }, 1000);
|
||||
|
||||
// //normal draw
|
||||
// setTimeout(() => {
|
||||
// requestAnimationFrame(() => {
|
||||
// simulation.wipe();
|
||||
// simulation.camera();
|
||||
// // level.custom();
|
||||
// simulation.draw.cons();
|
||||
// simulation.draw.body();
|
||||
// // m.draw();
|
||||
// // m.hold();
|
||||
// level.customTopLayer();
|
||||
// simulation.draw.drawMapPath();
|
||||
// ctx.restore();
|
||||
// });
|
||||
// }, 1500);
|
||||
|
||||
// //unpause
|
||||
// setTimeout(() => {
|
||||
// document.body.style.cursor = "none";
|
||||
// if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
|
||||
// if (simulation.paused) requestAnimationFrame(cycle);
|
||||
// if (m.alive) simulation.paused = false;
|
||||
// simulation.isChoosing = false; //stops p from un pausing on key down
|
||||
// build.unPauseGrid()
|
||||
|
||||
// document.getElementById("choose-grid").style.opacity = "0"
|
||||
// // document.getElementById("choose-grid").style.visibility = "hidden"
|
||||
// setTimeout(() => {
|
||||
// document.getElementById("choose-grid").style.visibility = "hidden"
|
||||
// }, 1000);
|
||||
// }, 2000);
|
||||
}
|
||||
}
|
||||
},
|
||||
populateLevels() { //run a second time if URL is loaded
|
||||
@@ -335,7 +481,7 @@ const level = {
|
||||
level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.6, level.levels.length)), 0, Math.random() < 0.5 ? "factory" : "reservoir"); //add level to the back half of the randomized levels list
|
||||
level.levels.splice(Math.floor(Math.seededRandom(level.levels.length * 0.6, level.levels.length)), 0, "reactor"); //add level to the back half of the randomized levels list
|
||||
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("initial"); //add level to the start of the randomized levels list
|
||||
level.levels.push("subway"); //add level to the end of the randomized levels list
|
||||
level.levels.push("final"); //add level to the end of the randomized levels list
|
||||
}
|
||||
@@ -1911,7 +2057,7 @@ const level = {
|
||||
powerUps.addResearchToLevel() //needs to run after mobs are spawned
|
||||
},
|
||||
testing() {
|
||||
simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
|
||||
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
|
||||
|
||||
document.body.style.backgroundColor = "#fff";
|
||||
// color.map = "#444" //custom map color
|
||||
@@ -2158,7 +2304,7 @@ const level = {
|
||||
spawn.mapRect(-500, -25, 25, 50); //edge shelf
|
||||
spawn.mapRect(475, -25, 25, 50); //edge shelf
|
||||
},
|
||||
intro() {
|
||||
initial() {
|
||||
if (level.levelsCleared === 0) { //if this is the 1st level of the game
|
||||
if (simulation.difficultyMode > 2) spawn.setSpawnList() // hard and why difficulty don't begin with starter mobs
|
||||
|
||||
@@ -2216,7 +2362,7 @@ const level = {
|
||||
} else {
|
||||
for (let i = 0; i < 60; i++) {
|
||||
setTimeout(() => {
|
||||
if (level.levels[level.onLevel] === "intro") spawn.sneaker(2100, -1500 - 50 * i);
|
||||
if (level.levels[level.onLevel] === "initial") spawn.sneaker(2100, -1500 - 50 * i);
|
||||
}, 2000 + 500 * i);
|
||||
}
|
||||
}
|
||||
@@ -2457,6 +2603,7 @@ const level = {
|
||||
document.body.style.backgroundColor = "#ddd";
|
||||
|
||||
for (let i = 0; i < 16; i++) powerUps.spawn(4600 + 40 * i, -30, "ammo");
|
||||
if (simulation.difficultyMode > 4) for (let i = 0; i < 8; i++) powerUps.spawn(4600 + 40 * i, -30, "ammo"); //extra ammo on why difficulty
|
||||
|
||||
spawn.mapRect(-1950, 0, 8200, 1800); //ground
|
||||
spawn.mapRect(-1950, -1500, 1800, 1900); //left wall
|
||||
@@ -3832,19 +3979,19 @@ const level = {
|
||||
for (let i = 0; i < 250; i++) spawn.starter(-2700 + 2400 * Math.random(), -1300 - 500 * Math.random())
|
||||
} else {
|
||||
if (Math.random() < 0.07 && simulation.difficulty > 35) {
|
||||
for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15
|
||||
for (let i = 0, len = scale * 0.22 / 6; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15
|
||||
for (let i = 0, len = scale * 0.1 / 6; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false);
|
||||
for (let i = 0, len = scale * 0.15 / 6; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false)
|
||||
for (let i = 0, len = scale * 0.26 / 6; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false);
|
||||
for (let i = 0, len = scale * 0.13 / 6; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false)
|
||||
for (let i = 0, len = scale * 0.25 / 6; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false);
|
||||
} else {
|
||||
if (Math.random() < 0.25) {
|
||||
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
|
||||
for (let i = 0, len = scale * 0.22; i < len; ++i) spawn.timeBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
|
||||
} else if (Math.random() < 0.33) {
|
||||
for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(-1327 - 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15
|
||||
} else if (Math.random() < 0.5) {
|
||||
for (let i = 0, len = scale * 0.15; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
|
||||
for (let i = 0, len = scale * 0.13; i < len; ++i) spawn.sprayBoss(-1327 - 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15
|
||||
} else {
|
||||
for (let i = 0, len = scale * 0.26; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15
|
||||
for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.mineBoss(-1327 - 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3919,6 +4066,7 @@ const level = {
|
||||
isDoorsLocked = true
|
||||
for (let i = 0; i < 9; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "ammo")
|
||||
for (let i = 0; i < 3; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "heal");
|
||||
if (simulation.difficultyMode > 4) for (let i = 0; i < 8; i++) powerUps.spawn(1200 + 550 * Math.random(), -1700, "ammo"); //extra ammo on why difficulty
|
||||
const scale = Math.pow(simulation.difficulty, 0.7) //hard around 30, why around 54
|
||||
if (mobs.mobDeaths < level.levelsCleared && !simulation.isCheating) {
|
||||
for (let i = 0; i < 250; i++) spawn.starter(300 + 2400 * Math.random(), -1300 - 500 * Math.random())
|
||||
@@ -12158,7 +12306,10 @@ const level = {
|
||||
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
|
||||
spawn.mapRect(1500, -10, 100, 20);
|
||||
level.defaultZoom = 1800
|
||||
simulation.setZoom(1200);
|
||||
// simulation.setZoom(1200);
|
||||
simulation.zoomTransition(1200)
|
||||
|
||||
|
||||
document.body.style.backgroundColor = "#daa69f";
|
||||
color.map = "#600";
|
||||
|
||||
@@ -12567,7 +12718,9 @@ const level = {
|
||||
level.exit.y = -2030;
|
||||
relocateTo(50, -2050);
|
||||
simulation.fallHeight = -1000;
|
||||
simulation.setZoom(1800);
|
||||
// simulation.setZoom(1800);
|
||||
simulation.zoomTransition(1800)
|
||||
|
||||
templePlayer.startAnim = -1;
|
||||
templePlayer.drawExit = false;
|
||||
}
|
||||
|
||||
@@ -1092,7 +1092,7 @@ const lore = {
|
||||
|
||||
() => {
|
||||
setTimeout(() => {
|
||||
lore.anand.text("How ever it thinks it can learn and, I think we showed it that nonviolence is an option,")
|
||||
lore.anand.text("How ever it thinks it can learn, and I think we showed it that nonviolence is an option,")
|
||||
}, 1000);
|
||||
},
|
||||
() => {
|
||||
@@ -1116,7 +1116,7 @@ const lore = {
|
||||
}, 1000);
|
||||
},
|
||||
() => {
|
||||
lore.anand.text("me too")
|
||||
lore.anand.text("Me too,")
|
||||
},
|
||||
() => {
|
||||
lore.anand.text("but I'm also pretty hungry, wanna go get some food?")
|
||||
|
||||
35
js/mob.js
35
js/mob.js
@@ -1350,16 +1350,7 @@ const mobs = {
|
||||
this.leaveBody = false; // no body since it turned into the bot
|
||||
}
|
||||
if (tech.isAddRemoveMaxHealth) {
|
||||
if (this.isBoss && this.isDropPowerUp) {
|
||||
powerUps.spawn(this.position.x + 20, this.position.y, "tech", false)
|
||||
powerUps.spawn(this.position.x - 20, this.position.y, "research", false)
|
||||
powerUps.spawn(this.position.x - 40, this.position.y, "research", false)
|
||||
powerUps.spawn(this.position.x + 40, this.position.y, "research", false)
|
||||
powerUps.spawn(this.position.x, this.position.y + 20, "research", false)
|
||||
powerUps.spawn(this.position.x, this.position.y - 20, "heal", false)
|
||||
powerUps.spawn(this.position.x, this.position.y + 40, "heal", false)
|
||||
powerUps.spawn(this.position.x, this.position.y - 40, "heal", false)
|
||||
} else {
|
||||
if (!this.isBoss) {
|
||||
const amount = 0.005
|
||||
if (tech.isEnergyHealth) {
|
||||
if (m.maxEnergy > amount) {
|
||||
@@ -1371,12 +1362,34 @@ const mobs = {
|
||||
m.setMaxHealth();
|
||||
}
|
||||
}
|
||||
|
||||
// if (this.isBoss && this.isDropPowerUp) {
|
||||
// powerUps.spawn(this.position.x + 20, this.position.y, "tech", false)
|
||||
// powerUps.spawn(this.position.x - 20, this.position.y, "research", false)
|
||||
// powerUps.spawn(this.position.x - 40, this.position.y, "research", false)
|
||||
// powerUps.spawn(this.position.x + 40, this.position.y, "research", false)
|
||||
// powerUps.spawn(this.position.x, this.position.y + 20, "research", false)
|
||||
// powerUps.spawn(this.position.x, this.position.y - 20, "heal", false)
|
||||
// powerUps.spawn(this.position.x, this.position.y + 40, "heal", false)
|
||||
// powerUps.spawn(this.position.x, this.position.y - 40, "heal", false)
|
||||
// } else {
|
||||
// const amount = 0.005
|
||||
// if (tech.isEnergyHealth) {
|
||||
// if (m.maxEnergy > amount) {
|
||||
// tech.healMaxEnergyBonus -= amount
|
||||
// m.setMaxEnergy();
|
||||
// }
|
||||
// } else if (m.maxHealth > amount) {
|
||||
// tech.extraMaxHealth -= amount //decrease max health
|
||||
// m.setMaxHealth();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
if (tech.cloakDuplication && !this.isBoss) {
|
||||
tech.cloakDuplication -= 0.01
|
||||
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
|
||||
}
|
||||
} else if (tech.isShieldAmmo && this.shield && !this.isExtraShield) {
|
||||
} else if (tech.isShieldAmmo && this.shield && !this.isExtraShield && this.isDropPowerUp) {
|
||||
let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
|
||||
if (Math.random() < 0.4) {
|
||||
type = "heal"
|
||||
|
||||
131
js/player.js
131
js/player.js
@@ -539,7 +539,7 @@ const m = {
|
||||
},
|
||||
baseHealth: 1,
|
||||
setMaxHealth() {
|
||||
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 2.22 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth
|
||||
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 3 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth
|
||||
document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
|
||||
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
|
||||
if (m.health > m.maxHealth) m.health = m.maxHealth;
|
||||
@@ -564,7 +564,7 @@ const m = {
|
||||
// if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
|
||||
if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.973 ** m.coupling
|
||||
if (tech.isLowHealthDefense) dmg *= 1 - Math.max(0, 1 - m.health) * 0.8
|
||||
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.33
|
||||
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.26
|
||||
if (tech.squirrelFx !== 1) dmg *= 0.78//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4)
|
||||
if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1
|
||||
if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min(player.speed * 0.0193, 0.88) //capped at speed of 55
|
||||
@@ -572,7 +572,7 @@ const m = {
|
||||
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
|
||||
if (tech.isBotArmor) dmg *= 0.94 ** b.totalBots()
|
||||
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
|
||||
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.3
|
||||
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.27
|
||||
if (tech.isTurret && m.crouch) dmg *= 0.34;
|
||||
if (tech.isFirstDer && b.inventory[0] === b.activeGun) dmg *= 0.85 ** b.inventory.length
|
||||
if (tech.isEnergyHealth) {
|
||||
@@ -725,7 +725,7 @@ const m = {
|
||||
tech.isDeathAvoidedThisLevel = true
|
||||
powerUps.research.changeRerolls(-1)
|
||||
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`)
|
||||
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
|
||||
for (let i = 0; i < 16; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
|
||||
m.energy = m.maxEnergy + 0.1
|
||||
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
|
||||
simulation.wipe = function () { //set wipe to have trails
|
||||
@@ -755,7 +755,7 @@ const m = {
|
||||
powerUps.research.changeRerolls(-1)
|
||||
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span>
|
||||
<br>${powerUps.research.count}`)
|
||||
for (let i = 0; i < 5; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
|
||||
for (let i = 0; i < 16; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
|
||||
if (m.immuneCycle < m.cycle + 300) m.immuneCycle = m.cycle + 300 //disable this.immuneCycle bonus seconds
|
||||
simulation.wipe = function () { //set wipe to have trails
|
||||
ctx.fillStyle = "rgba(255,255,255,0.03)";
|
||||
@@ -1274,23 +1274,29 @@ const m = {
|
||||
m.drawLeg("#5f5f5f");
|
||||
m.calcLeg(0, 1);
|
||||
m.drawLeg("#555");
|
||||
ctx.rotate(m.angle);
|
||||
|
||||
const size = 33
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
|
||||
ctx.lineTo(size * 1, size * 0)
|
||||
ctx.lineTo(size * 0.5, size * 0.866)
|
||||
ctx.lineTo(size * -0.5, size * 0.866)
|
||||
ctx.lineTo(size * -1, size * 0)
|
||||
ctx.lineTo(size * -0.5, size * -0.866)
|
||||
ctx.lineTo(size * 0.5, size * -0.866)
|
||||
ctx.lineTo(size * 1, size * 0)
|
||||
ctx.lineTo(size * 0.5, size * 0)
|
||||
ctx.fillStyle = m.bodyGradient
|
||||
ctx.fill();
|
||||
// ctx.fillStyle = grdRad
|
||||
// ctx.fill();
|
||||
ctx.strokeStyle = "#000";
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.lineWidth = 1.5;
|
||||
ctx.rotate(m.angle);
|
||||
ctx.beginPath();
|
||||
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#fff"
|
||||
ctx.fill();
|
||||
ctx.beginPath();
|
||||
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
|
||||
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
|
||||
ctx.stroke();
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.arc(15, 0, 3, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#333"
|
||||
ctx.fill();
|
||||
|
||||
ctx.restore();
|
||||
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
|
||||
powerUps.boost.draw()
|
||||
@@ -1482,8 +1488,6 @@ const m = {
|
||||
|
||||
// console.log(simulation.zoomScale)
|
||||
simulation.setZoom(1800 + 400 * Math.sin(m.cycle * 0.0075))
|
||||
|
||||
|
||||
}
|
||||
},
|
||||
dilate2() {
|
||||
@@ -1645,6 +1649,95 @@ const m = {
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
hexagon() {
|
||||
m.isAltSkin = true
|
||||
m.color = {
|
||||
hue: 0,
|
||||
sat: 0,
|
||||
light: 100,
|
||||
}
|
||||
// m.setFillColors();
|
||||
m.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
|
||||
m.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light - 35}%)`
|
||||
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
|
||||
grd.addColorStop(0, m.fillColorDark);
|
||||
grd.addColorStop(0.7, m.fillColor);
|
||||
// grd.addColorStop(1, m.fillColor);
|
||||
m.bodyGradient = grd
|
||||
|
||||
m.draw = function () {
|
||||
ctx.fillStyle = m.fillColor;
|
||||
m.walk_cycle += m.flipLegs * m.Vx;
|
||||
ctx.save();
|
||||
ctx.globalAlpha = (m.immuneCycle < m.cycle) ? 1 : 0.5 //|| (m.cycle % 40 > 20)
|
||||
ctx.translate(m.pos.x, m.pos.y);
|
||||
m.calcLeg(Math.PI, -3);
|
||||
m.drawLeg("#4a4a4a");
|
||||
m.calcLeg(0, 0);
|
||||
m.drawLeg("#333");
|
||||
ctx.rotate(m.angle);
|
||||
|
||||
const size = 32
|
||||
ctx.beginPath();
|
||||
ctx.lineTo(size * 1, size * 0)
|
||||
ctx.lineTo(size * 0.5, size * 0.866)
|
||||
ctx.lineTo(size * -0.5, size * 0.866)
|
||||
ctx.lineTo(size * -1, size * 0)
|
||||
ctx.lineTo(size * -0.5, size * -0.866)
|
||||
ctx.lineTo(size * 0.5, size * -0.866)
|
||||
ctx.lineTo(size * 1, size * 0)
|
||||
ctx.fillStyle = m.bodyGradient
|
||||
ctx.fill();
|
||||
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
|
||||
ctx.strokeStyle = "#333";
|
||||
ctx.lineWidth = 2;
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
m.yOff = m.yOff * 0.85 + m.yOffGoal * 0.15; //smoothly move leg height towards height goal
|
||||
powerUps.boost.draw()
|
||||
}
|
||||
m.drawLeg = function (stroke) {
|
||||
// if (simulation.mouseInGame.x > m.pos.x) {
|
||||
if (m.angle > -Math.PI / 2 && m.angle < Math.PI / 2) {
|
||||
m.flipLegs = 1;
|
||||
} else {
|
||||
m.flipLegs = -1;
|
||||
}
|
||||
ctx.save();
|
||||
ctx.scale(m.flipLegs, 1); //leg lines
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(m.hip.x, m.hip.y);
|
||||
ctx.lineTo(m.knee.x, m.knee.y);
|
||||
ctx.lineTo(m.foot.x, m.foot.y);
|
||||
ctx.strokeStyle = stroke;
|
||||
ctx.lineWidth = 6;
|
||||
ctx.stroke();
|
||||
|
||||
//toe lines
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(m.foot.x, m.foot.y);
|
||||
ctx.lineTo(m.foot.x - 15, m.foot.y + 5);
|
||||
ctx.moveTo(m.foot.x, m.foot.y);
|
||||
ctx.lineTo(m.foot.x + 15, m.foot.y + 5);
|
||||
ctx.lineWidth = 3;
|
||||
ctx.stroke();
|
||||
|
||||
//hip joint
|
||||
ctx.beginPath();
|
||||
ctx.arc(m.hip.x, m.hip.y, 11, 0, 2 * Math.PI);
|
||||
//knee joint
|
||||
ctx.moveTo(m.knee.x + 5, m.knee.y);
|
||||
ctx.arc(m.knee.x, m.knee.y, 5, 0, 2 * Math.PI);
|
||||
//foot joint
|
||||
ctx.moveTo(m.foot.x + 5, m.foot.y);
|
||||
ctx.arc(m.foot.x, m.foot.y, 5, 0, 2 * Math.PI);
|
||||
ctx.fillStyle = "#000";
|
||||
ctx.fill();
|
||||
// ctx.lineWidth = 2;
|
||||
// ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
},
|
||||
stubs() {
|
||||
m.isAltSkin = true
|
||||
m.draw = function () {
|
||||
|
||||
@@ -326,7 +326,7 @@ const powerUps = {
|
||||
return
|
||||
}
|
||||
if (tech.isCancelDuplication) {
|
||||
tech.duplication += 0.043
|
||||
tech.duplication += 0.047
|
||||
tech.maxDuplicationEvent()
|
||||
simulation.makeTextLog(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${0.043}`)
|
||||
simulation.circleFlare(0.043);
|
||||
@@ -361,7 +361,7 @@ const powerUps = {
|
||||
// }
|
||||
}
|
||||
if (tech.isAnsatz && powerUps.research.count < 1) {
|
||||
for (let i = 0; i < 2; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
||||
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
||||
}
|
||||
// document.getElementById("choose-grid").style.display = "none"
|
||||
document.getElementById("choose-grid").style.visibility = "hidden"
|
||||
@@ -466,28 +466,30 @@ const powerUps = {
|
||||
if (m.alive && powerUps.research.count >= cost) {
|
||||
requestAnimationFrame(cycle);
|
||||
this.isMakingBots = true
|
||||
} else {
|
||||
this.isMakingBots = false
|
||||
}
|
||||
if (!simulation.paused && !simulation.isChoosing && !(simulation.cycle % 60)) {
|
||||
powerUps.research.count -= cost
|
||||
b.randomBot()
|
||||
if (tech.renormalization) {
|
||||
for (let i = 0; i < cost; i++) {
|
||||
if (Math.random() < 0.46) {
|
||||
m.fieldCDcycle = m.cycle + 20;
|
||||
powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research");
|
||||
|
||||
if (!simulation.paused && !simulation.isChoosing && !(simulation.cycle % 60)) {
|
||||
powerUps.research.count -= cost
|
||||
b.randomBot()
|
||||
if (tech.renormalization) {
|
||||
for (let i = 0; i < cost; i++) {
|
||||
if (Math.random() < 0.47) {
|
||||
m.fieldCDcycle = m.cycle + 20;
|
||||
powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.isMakingBots = false
|
||||
}
|
||||
}
|
||||
requestAnimationFrame(cycle);
|
||||
}
|
||||
|
||||
if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) {
|
||||
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
|
||||
}
|
||||
if (tech.renormalization && Math.random() < 0.46 && amount < 0) {
|
||||
if (tech.renormalization && Math.random() < 0.47 && amount < 0) {
|
||||
for (let i = 0, len = -amount; i < len; i++) powerUps.spawn(m.pos.x, m.pos.y, "research");
|
||||
}
|
||||
if (tech.isRerollHaste) {
|
||||
@@ -1412,6 +1414,31 @@ const powerUps = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (tech.isAddRemoveMaxHealth) {
|
||||
powerUps.spawn(x + 20, y, "tech", false)
|
||||
powerUps.spawn(x - 20, y, "research", false)
|
||||
powerUps.spawn(x - 40, y, "research", false)
|
||||
powerUps.spawn(x + 40, y, "research", false)
|
||||
powerUps.spawn(x, y + 20, "research", false)
|
||||
powerUps.spawn(x, y - 20, "heal", false)
|
||||
powerUps.spawn(x, y + 40, "heal", false)
|
||||
powerUps.spawn(x, y - 40, "heal", false)
|
||||
// if (this.isBoss && this.isDropPowerUp) {
|
||||
// } else {
|
||||
// const amount = 0.005
|
||||
// if (tech.isEnergyHealth) {
|
||||
// if (m.maxEnergy > amount) {
|
||||
// tech.healMaxEnergyBonus -= amount
|
||||
// m.setMaxEnergy();
|
||||
// }
|
||||
// } else if (m.maxHealth > amount) {
|
||||
// tech.extraMaxHealth -= amount //decrease max health
|
||||
// m.setMaxHealth();
|
||||
// }
|
||||
// }
|
||||
}
|
||||
}
|
||||
},
|
||||
chooseRandomPowerUp(x, y) { //100% chance to drop a random power up //used in spawn.debris
|
||||
@@ -1501,11 +1528,11 @@ const powerUps = {
|
||||
},
|
||||
pauseEjectTech(index) {
|
||||
if ((tech.isPauseEjectTech || simulation.testing) && !simulation.isChoosing && !tech.tech[index].isNonRefundable) {
|
||||
if (Math.random() < 0.2 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
|
||||
if (Math.random() < 0.03 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
|
||||
tech.removeTech(index)
|
||||
// powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
||||
} else {
|
||||
powerUps.ejectTech(index)
|
||||
m.damage(0.06)
|
||||
}
|
||||
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
|
||||
document.getElementById(`${index}-pause-tech`).style.animation = ""
|
||||
|
||||
121
js/simulation.js
121
js/simulation.js
@@ -24,7 +24,6 @@ const simulation = {
|
||||
mobs.healthBar();
|
||||
m.draw();
|
||||
m.hold();
|
||||
// v.draw(); //working on visibility work in progress
|
||||
level.customTopLayer();
|
||||
simulation.draw.drawMapPath();
|
||||
b.fire();
|
||||
@@ -33,10 +32,8 @@ const simulation = {
|
||||
if (!m.isBodiesAsleep) b.bulletDo();
|
||||
simulation.drawCircle();
|
||||
simulation.runEphemera();
|
||||
// simulation.clip();
|
||||
ctx.restore();
|
||||
simulation.drawCursor();
|
||||
// simulation.pixelGraphics();
|
||||
},
|
||||
testingLoop() {
|
||||
simulation.gravity();
|
||||
@@ -505,47 +502,52 @@ const simulation = {
|
||||
simulation.zoom = canvas.height / zoomScale; //sets starting zoom scale
|
||||
},
|
||||
zoomTransition(newZoomScale, step = 2) {
|
||||
//old version
|
||||
// if (simulation.isAutoZoom) {
|
||||
// const isBigger = (newZoomScale - simulation.zoomScale > 0) ? true : false;
|
||||
// requestAnimationFrame(zLoop);
|
||||
// const currentLevel = level.onLevel
|
||||
|
||||
// function zLoop() {
|
||||
// if (currentLevel !== level.onLevel || simulation.isAutoZoom === false) return //stop the zoom if player goes to a new level
|
||||
|
||||
// if (isBigger) {
|
||||
// simulation.zoomScale += step
|
||||
// if (simulation.zoomScale >= newZoomScale) {
|
||||
// simulation.setZoom(newZoomScale);
|
||||
// return
|
||||
// }
|
||||
// } else {
|
||||
// simulation.zoomScale -= step
|
||||
// if (simulation.zoomScale <= newZoomScale) {
|
||||
// simulation.setZoom(newZoomScale);
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
|
||||
// simulation.setZoom();
|
||||
// requestAnimationFrame(zLoop);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
//rewrite using the ephemera system
|
||||
if (simulation.isAutoZoom) {
|
||||
const isBigger = (newZoomScale - simulation.zoomScale > 0) ? true : false;
|
||||
requestAnimationFrame(zLoop);
|
||||
const currentLevel = level.onLevel
|
||||
|
||||
function zLoop() {
|
||||
if (currentLevel !== level.onLevel || simulation.isAutoZoom === false) return //stop the zoom if player goes to a new level
|
||||
|
||||
if (isBigger) {
|
||||
simulation.ephemera.push({
|
||||
name: "zoom",
|
||||
count: simulation.testing ? 0 : 120, //cycles before it self removes
|
||||
currentLevel: level.onLevel,
|
||||
do() {
|
||||
this.count--
|
||||
const step = (newZoomScale - simulation.zoomScale) / this.count
|
||||
simulation.zoomScale += step
|
||||
if (simulation.zoomScale >= newZoomScale) {
|
||||
simulation.setZoom(newZoomScale);
|
||||
return
|
||||
if (this.count < 1 && this.currentLevel === level.onLevel && simulation.isAutoZoom) {
|
||||
simulation.zoomScale = newZoomScale
|
||||
simulation.removeEphemera(this.name)
|
||||
}
|
||||
} else {
|
||||
simulation.zoomScale -= step
|
||||
if (simulation.zoomScale <= newZoomScale) {
|
||||
simulation.setZoom(newZoomScale);
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
simulation.setZoom();
|
||||
requestAnimationFrame(zLoop);
|
||||
}
|
||||
}
|
||||
},
|
||||
zoomInFactor: 0,
|
||||
startZoomIn(time = 180) {
|
||||
simulation.zoom = 0;
|
||||
let count = 0;
|
||||
requestAnimationFrame(zLoop);
|
||||
|
||||
function zLoop() {
|
||||
simulation.zoom += canvas.height / simulation.zoomScale / time;
|
||||
count++;
|
||||
if (count < time) {
|
||||
requestAnimationFrame(zLoop);
|
||||
} else {
|
||||
simulation.setZoom();
|
||||
}
|
||||
simulation.setZoom(simulation.zoomScale);
|
||||
},
|
||||
})
|
||||
}
|
||||
},
|
||||
translatePlayerAndCamera(where) {
|
||||
@@ -974,8 +976,8 @@ const simulation = {
|
||||
} else {
|
||||
Matter.Body.setVelocity(player, { x: 0, y: 0 });
|
||||
Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 });
|
||||
m.damage(0.05 * simulation.difficultyMode);
|
||||
m.energy -= 0.05 * simulation.difficultyMode
|
||||
// m.damage(0.02 * simulation.difficultyMode);
|
||||
// m.energy -= 0.02 * simulation.difficultyMode
|
||||
// move bots
|
||||
for (let i = 0; i < bullet.length; i++) {
|
||||
if (bullet[i].botType) {
|
||||
@@ -1003,15 +1005,28 @@ const simulation = {
|
||||
});
|
||||
}
|
||||
if (tech.isHealthRecovery) {
|
||||
const heal = 0.005 * m.maxHealth
|
||||
m.addHealth(heal)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: m.pos.x,
|
||||
y: m.pos.y,
|
||||
radius: Math.sqrt(heal) * 150,
|
||||
color: "rgba(0,255,200,0.5)",
|
||||
time: 4
|
||||
});
|
||||
if (tech.isEnergyHealth) {
|
||||
if (m.immuneCycle < m.cycle) {
|
||||
m.energy += m.maxEnergy * 0.005
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: m.pos.x,
|
||||
y: m.pos.y,
|
||||
radius: Math.sqrt(m.maxEnergy * 0.02) * 60,
|
||||
color: "rgba(0, 204, 255,0.4)", //#0cf
|
||||
time: 4
|
||||
});
|
||||
}
|
||||
} else {
|
||||
const heal = 0.005 * m.maxHealth
|
||||
m.addHealth(heal)
|
||||
simulation.drawList.push({ //add dmg to draw queue
|
||||
x: m.pos.x,
|
||||
y: m.pos.y,
|
||||
radius: Math.sqrt(heal) * 150,
|
||||
color: "rgba(0,255,200,0.5)",
|
||||
time: 4
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1355,7 +1370,7 @@ const simulation = {
|
||||
ctx.textAlign = "center";
|
||||
ctx.fillText(`(${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})`, simulation.mouse.x, simulation.mouse.y - 20);
|
||||
},
|
||||
sight: { //credit to Cornbread for adding this algorithm to n-gon
|
||||
sight: { //credit to Cornbread2100 for adding this algorithm to n-gon
|
||||
// square: 0,
|
||||
intersectMap: [], //this is precalculated in simulation.draw.lineOfSightPrecalculation()
|
||||
getIntersection(v1, v1End, domain) {
|
||||
|
||||
201
js/spawn.js
201
js/spawn.js
@@ -22,9 +22,10 @@ const spawn = {
|
||||
fullPickList: [
|
||||
"slasher", "slasher", "slasher2", "slasher3",
|
||||
"hopper", "hopper", "hopMother", "hopMother",
|
||||
"flutter", "flutter", "flutter",
|
||||
"stabber", "stabber", "stabber",
|
||||
"springer", "springer", "springer",
|
||||
"stinger", "stinger", "stinger",
|
||||
"flutter", "flutter",
|
||||
"shooter", "shooter",
|
||||
"grenadier", "grenadier",
|
||||
"striker", "striker",
|
||||
@@ -34,7 +35,7 @@ const spawn = {
|
||||
],
|
||||
mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed
|
||||
mobTypeSpawnIndex: 0, //increases as the mob type cycles
|
||||
allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter"],
|
||||
allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter", "stinger"],
|
||||
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
|
||||
spawn.pickList.splice(0, 1);
|
||||
const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length]
|
||||
@@ -3837,6 +3838,202 @@ const spawn = {
|
||||
// }
|
||||
};
|
||||
},
|
||||
stinger(x, y, radius = 18 + 4 * Math.random()) {
|
||||
const color = '#5bc'
|
||||
mobs.spawn(x, y, 7, radius, color);
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.setDensity(me, 0.0025); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
// me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||
|
||||
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
|
||||
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
|
||||
me.accelMag = 0.0015 + 0.0007 * Math.sqrt(simulation.accelScale);
|
||||
me.frictionAir = 0.04;
|
||||
// me.seePlayerFreq = 40 + Math.floor(13 * Math.random())
|
||||
me.memory = 240;
|
||||
me.restitution = 0.8;
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.lookTorque = 0.000001 * (Math.random() > 0.5 ? -1 : 1);
|
||||
me.fireDir = { x: 0, y: 0 }
|
||||
spawn.shield(me, x, y);
|
||||
|
||||
// me.onDeath = function() {};
|
||||
me.flapRate = 0.06 + 0.03 * Math.random()
|
||||
me.flapRadius = 40 + radius * 3
|
||||
me.do = function () {
|
||||
this.seePlayerByHistory()
|
||||
this.checkStatus();
|
||||
if (this.seePlayer.recall) {
|
||||
this.force.x += Math.cos(this.angle) * this.accelMag * this.mass
|
||||
this.force.y += Math.sin(this.angle) * this.accelMag * this.mass
|
||||
|
||||
//set direction to turn to fire
|
||||
if (!(simulation.cycle % this.seePlayerFreq)) {
|
||||
this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
|
||||
//dot product can't tell if mob is facing directly away or directly towards, so check if pointed directly away from player every few cycles
|
||||
const mod = (a, n) => a - Math.floor(a / n) * n
|
||||
const sub = Vector.sub(m.pos, this.position) //check by comparing different between angles. Give this a nudge if angles are 180 degree different
|
||||
const diff = mod(Math.atan2(sub.y, sub.x) - this.angle + Math.PI, 2 * Math.PI) - Math.PI
|
||||
if (Math.abs(diff) > 2.8) this.torque += 0.0002 * this.inertia * Math.random();
|
||||
}
|
||||
|
||||
//rotate towards fireDir
|
||||
const angle = this.angle + Math.PI / 2;
|
||||
c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
|
||||
const threshold = 0.4;
|
||||
const turn = 0.00002 * this.inertia
|
||||
if (c > threshold) {
|
||||
this.torque += turn;
|
||||
} else if (c < -threshold) {
|
||||
this.torque -= turn;
|
||||
}
|
||||
|
||||
// this.accelMag = 0.0006 + 0.0007 * Math.sqrt(simulation.accelScale);
|
||||
this.frictionAir = 0.11 + 0.09 * Math.sin(simulation.cycle * this.flapRate - Math.PI / 2)
|
||||
|
||||
const flapArc = 0.8 //don't go past 1.57 for normal flaps
|
||||
ctx.fillStyle = `hsla(${160 + 40 * Math.random()}, 100%, ${25 + 25 * Math.random() * Math.random()}%, 0.2)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
|
||||
this.wing(this.angle + 2.1 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
|
||||
this.wing(this.angle - 2.1 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
|
||||
|
||||
const seeRange = 550 + 35 * simulation.difficultyMode;
|
||||
if (this.distanceToPlayer() < seeRange) {
|
||||
const vertexCollision = function (v1, v1End, domain) {
|
||||
for (let i = 0; i < domain.length; ++i) {
|
||||
let vertices = domain[i].vertices;
|
||||
const len = vertices.length - 1;
|
||||
for (let j = 0; j < len; j++) {
|
||||
results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
|
||||
best = {
|
||||
x: results.x,
|
||||
y: results.y,
|
||||
dist2: dist2,
|
||||
who: domain[i],
|
||||
v1: vertices[j],
|
||||
v2: vertices[j + 1]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
|
||||
if (results.onLine1 && results.onLine2) {
|
||||
const dx = v1.x - results.x;
|
||||
const dy = v1.y - results.y;
|
||||
const dist2 = dx * dx + dy * dy;
|
||||
if (dist2 < best.dist2) {
|
||||
best = {
|
||||
x: results.x,
|
||||
y: results.y,
|
||||
dist2: dist2,
|
||||
who: domain[i],
|
||||
v1: vertices[0],
|
||||
v2: vertices[len]
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
best = {
|
||||
x: null,
|
||||
y: null,
|
||||
dist2: Infinity,
|
||||
who: null,
|
||||
v1: null,
|
||||
v2: null
|
||||
};
|
||||
const seeRangeRandom = seeRange - 200 - 150 * Math.random()
|
||||
const look = {
|
||||
x: this.position.x + seeRangeRandom * Math.cos(this.angle),
|
||||
y: this.position.y + seeRangeRandom * Math.sin(this.angle)
|
||||
};
|
||||
vertexCollision(this.position, look, map);
|
||||
vertexCollision(this.position, look, body);
|
||||
if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]);
|
||||
|
||||
// hitting player
|
||||
if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
|
||||
const dmg = 0.002 * simulation.dmgScale;
|
||||
m.damage(dmg);
|
||||
//draw damage
|
||||
ctx.fillStyle = color;
|
||||
ctx.beginPath();
|
||||
ctx.arc(best.x, best.y, 5 + dmg * 1500, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
}
|
||||
//draw beam
|
||||
const vertex = 3
|
||||
if (best.dist2 === Infinity) best = look;
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(this.vertices[vertex].x, this.vertices[vertex].y);
|
||||
ctx.lineTo(best.x, best.y);
|
||||
ctx.strokeStyle = color;
|
||||
ctx.lineWidth = 2;
|
||||
ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
|
||||
ctx.stroke();
|
||||
ctx.setLineDash([]);
|
||||
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.vertices[vertex].x, this.vertices[vertex].y, 5, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
|
||||
// ctx.fillStyle = color;
|
||||
// ctx.fill();
|
||||
}
|
||||
// else {
|
||||
// ctx.beginPath();
|
||||
// ctx.arc(this.vertices[1].x, this.vertices[1].y, 1 + 0.3 * (simulation.cycle % this.laserInterval), 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
|
||||
// ctx.fillStyle = color;
|
||||
// ctx.fill();
|
||||
// }
|
||||
}
|
||||
// else { //flocking behavior (not working yet)
|
||||
// this.force.x += Math.cos(this.angle) * this.accelMag * this.mass
|
||||
// this.force.y += Math.sin(this.angle) * this.accelMag * this.mass
|
||||
// //set direction to turn to fire
|
||||
// if (!(simulation.cycle % this.seePlayerFreq)) {
|
||||
// //find nearest mob and maintain a distance
|
||||
// let nearestMob = null
|
||||
// let nearestMobDistance = Infinity
|
||||
// for (let i = 0; i < mob.length; i++) {
|
||||
// const newMobDistance = Vector.magnitude(Vector.sub(this.position, mob[i].position))
|
||||
// if (mob[i].isDropPowerUp && mob[i].alive && newMobDistance < nearestMobDistance) { //&& !mob[i].isBoss
|
||||
// nearestMobDistance = newMobDistance
|
||||
// nearestMob = mob[i]
|
||||
// }
|
||||
// }
|
||||
// if (nearestMob) {
|
||||
// // console.log(nearestMob)
|
||||
// this.fireDir = Vector.normalise(Vector.sub(nearestMob.position, this.position));
|
||||
// //dot product can't tell if mob is facing directly away or directly towards, so check if pointed directly away from player every few cycles
|
||||
// const mod = (a, n) => {
|
||||
// return a - Math.floor(a / n) * n
|
||||
// }
|
||||
// const sub = Vector.sub(nearestMob.position, this.position) //check by comparing different between angles. Give this a nudge if angles are 180 degree different
|
||||
// const diff = mod(Math.atan2(sub.y, sub.x) - this.angle + Math.PI, 2 * Math.PI) - Math.PI
|
||||
// if (Math.abs(diff) > 2.8) this.torque += 0.0002 * this.inertia * Math.random();
|
||||
// }
|
||||
// }
|
||||
// //rotate towards fireDir
|
||||
// const angle = this.angle + Math.PI / 2;
|
||||
// c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
|
||||
// const threshold = 0.4;
|
||||
// const turn = 0.000025 * this.inertia
|
||||
// if (c > threshold) {
|
||||
// this.torque += turn;
|
||||
// } else if (c < -threshold) {
|
||||
// this.torque -= turn;
|
||||
// }
|
||||
// const flapArc = 0.7 //don't go past 1.57 for normal flaps
|
||||
// ctx.fillStyle = `hsla(${160 + 40 * Math.random()}, 100%, ${25 + 25 * Math.random() * Math.random()}%, 0.2)`; //"rgba(0,235,255,0.3)"; // ctx.fillStyle = `hsla(44, 79%, 31%,0.4)`; //"rgba(0,235,255,0.3)";
|
||||
// this.wing(this.angle + Math.PI / 2 + flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
|
||||
// this.wing(this.angle - Math.PI / 2 - flapArc * Math.sin(simulation.cycle * this.flapRate), this.flapRadius)
|
||||
// }
|
||||
};
|
||||
},
|
||||
beetleBoss(x, y, radius = 50) {
|
||||
mobs.spawn(x, y, 7, radius, '#16576b');
|
||||
let me = mob[mob.length - 1];
|
||||
|
||||
242
js/tech.js
242
js/tech.js
@@ -231,7 +231,7 @@ const tech = {
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
if (tech.isDivisor && b.activeGun && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.77
|
||||
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.77
|
||||
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.85 : 2
|
||||
if (tech.isDilate) dmg *= 1.5 + 0.6 * Math.sin(m.cycle * 0.0075)
|
||||
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.31 * b.inventory.length
|
||||
@@ -250,11 +250,11 @@ const tech = {
|
||||
if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots()
|
||||
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
|
||||
if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy)
|
||||
if (tech.energyDamage) dmg *= 1 + m.energy * 0.22 * tech.energyDamage;
|
||||
if (tech.energyDamage) dmg *= 1 + m.energy * 0.26 * tech.energyDamage;
|
||||
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.007
|
||||
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
|
||||
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2.11
|
||||
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.88, player.speed * 0.0193)
|
||||
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.83
|
||||
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.93
|
||||
if (tech.isAxion && tech.isHarmMACHO) dmg *= 2 - m.defense()
|
||||
if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3;
|
||||
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit * (2 - m.defense()) // if (!simulation.paused) m.lastHit = 0
|
||||
@@ -314,7 +314,7 @@ const tech = {
|
||||
},
|
||||
tech: [{
|
||||
name: "tungsten carbide",
|
||||
description: "<strong>+222</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>",
|
||||
description: "<strong>+300</strong> maximum <strong class='color-h'>health</strong><br><strong>lose</strong> <strong class='color-h'>health</strong> after hard <strong>landings</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -328,7 +328,7 @@ const tech = {
|
||||
tech.hardLanding = 70
|
||||
tech.isFallingDamage = true;
|
||||
m.setMaxHealth();
|
||||
m.addHealth(2.22 / simulation.healScale)
|
||||
m.addHealth(3 / simulation.healScale)
|
||||
m.skin.tungsten()
|
||||
},
|
||||
remove() {
|
||||
@@ -402,9 +402,9 @@ const tech = {
|
||||
isAltRealityTech: true,
|
||||
isSkin: true,
|
||||
allowed() {
|
||||
return !tech.isResearchReality && !tech.isSwitchReality
|
||||
return !m.isAltSkin && !tech.isResearchReality && !tech.isSwitchReality
|
||||
},
|
||||
requires: "not Ψ(t) collapse, many-worlds",
|
||||
requires: "not skinned, Ψ(t) collapse, many-worlds",
|
||||
damage: 2.42,
|
||||
effect() {
|
||||
m.skin.anodize();
|
||||
@@ -672,6 +672,43 @@ const tech = {
|
||||
},
|
||||
remove() { }
|
||||
},
|
||||
{
|
||||
name: "supply chain",
|
||||
descriptionFunction() {
|
||||
return `<strong>double</strong> your current <strong class='color-ammo'>ammo</strong> for all your <strong class='color-g'>guns</strong><br><strong>triple</strong> the frequency of finding <strong>applied science</strong>`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
for (let i = 0; i < b.guns.length; i++) {
|
||||
if (b.guns[i].have) b.guns[i].ammo = Math.floor(2 * b.guns[i].ammo)
|
||||
}
|
||||
simulation.makeGunHUD();
|
||||
for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||
if (tech.tech[i].name === "applied science") tech.tech[i].frequency *= 3
|
||||
}
|
||||
},
|
||||
remove() {
|
||||
if (this.count) {
|
||||
for (let j = 0; j < this.count; j++) {
|
||||
for (let i = 0; i < b.guns.length; i++) {
|
||||
if (b.guns[i].have) b.guns[i].ammo = Math.floor(0.5 * b.guns[i].ammo)
|
||||
}
|
||||
}
|
||||
simulation.makeGunHUD();
|
||||
|
||||
for (let i = 0, len = tech.tech.length; i < len; i++) {
|
||||
if (tech.tech[i].name === "applied science") tech.tech[i].frequency = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "applied science",
|
||||
description: `get a random <strong class='color-g'>gun</strong><strong class='color-m'>tech</strong><br>for each of your <strong class='color-g'>guns</strong>`, //spawn ${powerUps.orb.research(1)} and
|
||||
@@ -812,40 +849,6 @@ const tech = {
|
||||
// }
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "supply chain",
|
||||
descriptionFunction() {
|
||||
return `double your current <strong class='color-ammo'>ammo</strong><br><strong>+4%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
effect() {
|
||||
for (let i = 0; i < b.guns.length; i++) {
|
||||
if (b.guns[i].have) b.guns[i].ammo = Math.floor(2 * b.guns[i].ammo)
|
||||
}
|
||||
simulation.makeGunHUD();
|
||||
this.refundAmount += tech.addJunkTechToPool(0.04)
|
||||
},
|
||||
refundAmount: 0,
|
||||
remove() {
|
||||
for (let j = 0; j < this.count; j++) {
|
||||
for (let i = 0; i < b.guns.length; i++) {
|
||||
if (b.guns[i].have) b.guns[i].ammo = Math.floor(0.5 * b.guns[i].ammo)
|
||||
}
|
||||
}
|
||||
simulation.makeGunHUD();
|
||||
if (this.count > 0 && this.refundAmount > 0) {
|
||||
tech.removeJunkTechFromPool(this.refundAmount)
|
||||
this.refundAmount = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
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>`,
|
||||
@@ -909,7 +912,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "non-renewables",
|
||||
description: `<strong>+88%</strong> <strong class='color-d'>damage</strong><br>${powerUps.orb.ammo()} can't <strong>spawn</strong>`,
|
||||
description: `<strong>+97%</strong> <strong class='color-d'>damage</strong><br>${powerUps.orb.ammo()} can't <strong>spawn</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -918,7 +921,7 @@ const tech = {
|
||||
return !tech.isAmmoFromHealth && !tech.isBoostReplaceAmmo
|
||||
},
|
||||
requires: "not catabolism, quasiparticles",
|
||||
damage: 1.88,
|
||||
damage: 1.97,
|
||||
effect() {
|
||||
tech.damage *= this.damage
|
||||
tech.isEnergyNoAmmo = true;
|
||||
@@ -2068,7 +2071,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "decorrelation",
|
||||
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>+70%</strong> <strong class='color-defense'>defense</strong>",
|
||||
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>+77%</strong> <strong class='color-defense'>defense</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -2086,7 +2089,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "anticorrelation",
|
||||
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>+100%</strong> <strong class='color-d'>damage</strong>",
|
||||
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>+111%</strong> <strong class='color-d'>damage</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -2785,7 +2788,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "overcharge",
|
||||
description: "<strong>+66</strong> maximum <strong class='color-f'>energy</strong><br><strong>+6%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
|
||||
description: "<strong>+66</strong> maximum <strong class='color-f'>energy</strong><br><strong>+5%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -2797,7 +2800,7 @@ const tech = {
|
||||
effect() {
|
||||
tech.bonusEnergy += 0.66
|
||||
m.setMaxEnergy()
|
||||
this.refundAmount += tech.addJunkTechToPool(0.06)
|
||||
this.refundAmount += tech.addJunkTechToPool(0.05)
|
||||
},
|
||||
refundAmount: 0,
|
||||
remove() {
|
||||
@@ -2876,7 +2879,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "parasitism",
|
||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><strong>+83%</strong> <strong class='color-d'>damage</strong>, inhibit <strong class='color-f'>energy</strong> generation",
|
||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br><strong>+93%</strong> <strong class='color-d'>damage</strong>, no passive <strong class='color-f'>energy</strong> generation",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -2917,7 +2920,10 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "recycling",
|
||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>recover <strong>0.5%</strong> of max <strong class='color-h'>health</strong> per second",
|
||||
descriptionFunction() {
|
||||
return `if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>recover <strong>0.5%</strong> of max ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} per second`
|
||||
},
|
||||
description: "",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -2936,7 +2942,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "torpor",
|
||||
description: "if a mob has <strong>not died</strong> in the last <strong>5 seconds</strong><br><strong>+66%</strong> <strong class='color-defense'>defense</strong>",
|
||||
description: "if a mob has <strong>not died</strong> in the last <strong>5 seconds</strong><br><strong>+74%</strong> <strong class='color-defense'>defense</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3280,7 +3286,7 @@ const tech = {
|
||||
}, 1000);
|
||||
},
|
||||
descriptionFunction() {
|
||||
return `once per level, instead of <strong>dying</strong><br>use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(5)}`
|
||||
return `once per level, instead of <strong>dying</strong><br>use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -3381,7 +3387,7 @@ const tech = {
|
||||
{
|
||||
name: "Ψ(t) collapse",
|
||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Wave_function_collapse' class="link">Ψ(t) collapse</a>`,
|
||||
description: `spawn ${powerUps.orb.research(16)}<br>after you <strong class='color-r'>research</strong> enter an <strong class='alt'>alternate reality</strong>`,
|
||||
description: `spawn ${powerUps.orb.research(21)}<br>after you <strong class='color-r'>research</strong> enter an <strong class='alt'>alternate reality</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3391,7 +3397,7 @@ const tech = {
|
||||
return !tech.isSwitchReality && !tech.isCollisionRealitySwitch && !tech.isJunkResearch
|
||||
},
|
||||
requires: "not many-worlds, Hilbert space, pseudoscience",
|
||||
bonusResearch: 16,
|
||||
bonusResearch: 21,
|
||||
effect() {
|
||||
tech.isResearchReality = true;
|
||||
for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + Math.random() * 60, m.pos.y + Math.random() * 60, "research", false);
|
||||
@@ -3431,7 +3437,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "renormalization",
|
||||
description: `<strong>46%</strong> chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}<br><strong>+3%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool`,
|
||||
description: `<strong>47%</strong> chance to spawn ${powerUps.orb.research(1)} after consuming ${powerUps.orb.research(1)}<br><strong>+5%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
@@ -3442,7 +3448,7 @@ const tech = {
|
||||
requires: "at least 4 research, not superdeterminism",
|
||||
effect() {
|
||||
tech.renormalization = true;
|
||||
this.refundAmount += tech.addJunkTechToPool(0.03)
|
||||
this.refundAmount += tech.addJunkTechToPool(0.05)
|
||||
|
||||
},
|
||||
refundAmount: 0,
|
||||
@@ -3481,7 +3487,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "ansatz",
|
||||
description: `after choosing a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>if you have no ${powerUps.orb.research(1)} in your inventory spawn ${powerUps.orb.research(2)}`,
|
||||
description: `after choosing a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>if you have no ${powerUps.orb.research(1)} in your inventory spawn ${powerUps.orb.research(3)}`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -3501,17 +3507,17 @@ const tech = {
|
||||
name: "Bayesian statistics",
|
||||
// description: `for each ${powerUps.orb.research(1)} in your inventory<br><strong>+3.8%</strong> <strong class='color-d'>damage</strong>`,
|
||||
descriptionFunction() {
|
||||
return `spawn ${powerUps.orb.research(this.bonusResearch)}<br><strong>+3%</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.research(1)} <em>(${(3 * powerUps.research.count).toFixed(0)}%)</em>`
|
||||
return `spawn ${powerUps.orb.research(this.bonusResearch)}<br><strong>+3%</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.research(1)} in your inventory <em>(${(3 * powerUps.research.count).toFixed(0)}%)</em>`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequencyDefault: 2,
|
||||
allowed() {
|
||||
return powerUps.research.count > 2 || build.isExperimentSelection
|
||||
return powerUps.research.count > 1 || build.isExperimentSelection
|
||||
},
|
||||
requires: "at least 3 research",
|
||||
bonusResearch: 3,
|
||||
requires: "at least 2 research",
|
||||
bonusResearch: 6,
|
||||
effect() {
|
||||
powerUps.spawnDelay("research", this.bonusResearch)
|
||||
tech.isRerollDamage = true;
|
||||
@@ -3526,7 +3532,7 @@ const tech = {
|
||||
{
|
||||
name: "mass production",
|
||||
descriptionFunction() {
|
||||
return `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.ammo(10)} ${powerUps.orb.heal(10)} or ${powerUps.orb.research(7)}`
|
||||
return `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>options for ${powerUps.orb.ammo(1)} or ${powerUps.orb.heal(1)} or ${powerUps.orb.research(1)}`
|
||||
},
|
||||
// description: `<strong class='color-m'>tech</strong> always have <strong>+3</strong> choices to spawn<br>${powerUps.orb.ammo(8)} ${powerUps.orb.heal(8)} or ${powerUps.orb.research(5)}`,
|
||||
maxCount: 1,
|
||||
@@ -3544,8 +3550,10 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "research",
|
||||
description: `spawn ${powerUps.orb.research(7)}`,
|
||||
maxCount: 1,
|
||||
descriptionFunction() {
|
||||
return `spawn ${this.value > 36 ? this.value + powerUps.orb.research(1) : powerUps.orb.research(this.value)}<br>next time this effect is improved by ${powerUps.orb.research(5)}`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
frequencyDefault: 0,
|
||||
@@ -3553,15 +3561,19 @@ const tech = {
|
||||
isMassProduction: true,
|
||||
allowed() { return true },
|
||||
requires: "",
|
||||
value: 8,
|
||||
effect() {
|
||||
powerUps.spawnDelay("research", 7);
|
||||
powerUps.spawnDelay("research", this.value);
|
||||
this.value += 5
|
||||
},
|
||||
remove() { }
|
||||
},
|
||||
{
|
||||
name: "ammo",
|
||||
description: `spawn ${powerUps.orb.ammo(10)}`,
|
||||
maxCount: 1,
|
||||
descriptionFunction() {
|
||||
return `spawn ${this.value > 33 ? this.value + powerUps.orb.ammo(1) : powerUps.orb.ammo(this.value)}<br>next time this effect is improved by ${powerUps.orb.ammo(7)}`
|
||||
},
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
frequencyDefault: 0,
|
||||
@@ -3569,26 +3581,30 @@ const tech = {
|
||||
isMassProduction: true,
|
||||
allowed() { return true },
|
||||
requires: "",
|
||||
value: 10,
|
||||
effect() {
|
||||
powerUps.spawnDelay("ammo", 10);
|
||||
powerUps.spawnDelay("ammo", this.value);
|
||||
this.value += 7
|
||||
},
|
||||
remove() { }
|
||||
},
|
||||
{
|
||||
name: "heals",
|
||||
descriptionFunction() {
|
||||
return `spawn ${powerUps.orb.heal(10)}`
|
||||
return `spawn ${this.value > 30 ? this.value + powerUps.orb.heal(1) : powerUps.orb.heal(this.value)}<br>next time this effect is improved by ${powerUps.orb.heal(7)}`
|
||||
},
|
||||
maxCount: 1,
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 0,
|
||||
frequencyDefault: 0,
|
||||
isNonRefundable: true,
|
||||
isMassProduction: true,
|
||||
allowed() { return true },
|
||||
requires: "mass production",
|
||||
requires: "",
|
||||
value: 10,
|
||||
effect() {
|
||||
powerUps.spawnDelay("heal", 10);
|
||||
powerUps.spawnDelay("heal", this.value);
|
||||
this.value += 7
|
||||
},
|
||||
remove() { }
|
||||
},
|
||||
@@ -3624,7 +3640,7 @@ const tech = {
|
||||
effect() {
|
||||
tech.isBrainstorm = true
|
||||
tech.isBrainstormActive = false
|
||||
tech.brainStormDelay = 1800 - simulation.difficultyMode * 100
|
||||
tech.brainStormDelay = 2000 - simulation.difficultyMode * 100
|
||||
},
|
||||
remove() {
|
||||
tech.isBrainstorm = false
|
||||
@@ -3921,7 +3937,11 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "paradigm shift",
|
||||
description: `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br>with a <strong>20%</strong> chance to remove without <strong>ejecting</strong>`,
|
||||
// description: `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br>with a <strong>20%</strong> chance to remove without <strong>ejecting</strong>`,
|
||||
// description: `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br>and a <strong>20%</strong> chance to remove without <strong>ejecting</strong>`,
|
||||
descriptionFunction() {
|
||||
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <strong>ejects</strong> it<br><strong>–6</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} each time and a <strong>3%</strong> chance to fail`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -4154,7 +4174,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "futures exchange",
|
||||
description: "clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>gives <strong>+4.3%</strong> power up <strong class='color-dup'>duplication</strong> chance",
|
||||
description: "clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>gives <strong>+4.7%</strong> power up <strong class='color-dup'>duplication</strong> chance",
|
||||
// descriptionFunction() {
|
||||
// return `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>gives <strong>+${4.9 - 0.15*simulation.difficultyMode}%</strong> power up <strong class='color-dup'>duplication</strong> chance`
|
||||
// },
|
||||
@@ -4177,7 +4197,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "replication",
|
||||
description: "<strong>+9%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+33%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
|
||||
description: "<strong>+10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+33%</strong> <strong class='color-junk'>JUNK</strong> to <strong class='color-m'>tech</strong> pool",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -4187,7 +4207,7 @@ const tech = {
|
||||
},
|
||||
requires: "below 100% duplication chance",
|
||||
effect() {
|
||||
tech.duplicateChance += 0.09
|
||||
tech.duplicateChance += 0.1
|
||||
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
|
||||
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
|
||||
this.refundAmount += tech.addJunkTechToPool(0.33)
|
||||
@@ -4204,7 +4224,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "stimulated emission",
|
||||
description: "<strong>+17%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>,<br>but after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
|
||||
description: "<strong>+19%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>,<br>but after a <strong>collision</strong> eject <strong>1</strong> <strong class='color-m'>tech</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
@@ -4328,6 +4348,34 @@ const tech = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "strange loop",
|
||||
// description: `<strong>+11%</strong> <strong class='color-d'>damage</strong><br><strong>removing</strong> this doubles it's damage if you take it again`,
|
||||
description: `<strong>+9%</strong> <strong class='color-d'>damage</strong><br><span style = 'font-size:87%;'><strong>removing</strong> this gives <strong>strange attractor</strong> and <strong>null hypothesis</strong></span>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
isBadRandomOption: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
damage: 1.09,
|
||||
effect() {
|
||||
tech.damage *= this.damage
|
||||
},
|
||||
remove() {
|
||||
if (this.count > 0 && m.alive) {
|
||||
tech.damage /= this.damage
|
||||
this.frequency = 0
|
||||
requestAnimationFrame(() => {
|
||||
tech.giveTech("null hypothesis")
|
||||
tech.giveTech("strange attractor")
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "null hypothesis",
|
||||
description: `<strong>+8%</strong> <strong class='color-d'>damage</strong><br><strong>removing</strong> this spawns ${powerUps.orb.research(15)}`,
|
||||
@@ -4352,6 +4400,35 @@ const tech = {
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
name: "martingale",
|
||||
descriptionFunction() {
|
||||
return `<span style = 'font-size:95%;'><strong>+${(100 * this.damage).toFixed(0)}%</strong> <strong class='color-d'>damage</strong>. After removing this there is a <strong>50%</strong><br>chance to get it back with <strong>double</strong> its <strong class='color-d'>damage</strong></span>`
|
||||
},
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 1,
|
||||
frequencyDefault: 1,
|
||||
isBadRandomOption: true,
|
||||
allowed() {
|
||||
return true
|
||||
},
|
||||
requires: "",
|
||||
damage: 0.11,
|
||||
effect() {
|
||||
tech.damage *= 1 + this.damage
|
||||
},
|
||||
remove() {
|
||||
if (this.count > 0 && m.alive) {
|
||||
tech.damage /= 1 + this.damage
|
||||
if (Math.random() < 0.5) {
|
||||
this.damage *= 2
|
||||
requestAnimationFrame(() => { tech.giveTech("chaos theory") });
|
||||
}
|
||||
this.frequency = 0
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
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",
|
||||
@@ -4744,6 +4821,8 @@ const tech = {
|
||||
b.guns[0].ammoPack = b.guns[0].defaultAmmoPack;
|
||||
if (b.guns[0].recordedAmmo) b.guns[0].ammo = b.guns[0].recordedAmmo
|
||||
simulation.updateGunHUD();
|
||||
|
||||
if (this.count) requestAnimationFrame(() => { simulation.updateGunHUD(); });
|
||||
}
|
||||
tech.isIceCrystals = false;
|
||||
if (b.guns[0].ammo === Infinity) b.guns[0].ammo = 0
|
||||
@@ -5377,6 +5456,7 @@ const tech = {
|
||||
if (this.count > 0 && b.guns[3].savedAmmo !== undefined) {
|
||||
b.guns[3].ammo = b.guns[3].savedAmmo
|
||||
simulation.updateGunHUD();
|
||||
requestAnimationFrame(() => { simulation.updateGunHUD(); });
|
||||
} else if (b.guns[3].ammo === Infinity) {
|
||||
b.guns[3].ammo = 0
|
||||
}
|
||||
@@ -7071,7 +7151,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "induction furnace",
|
||||
description: "after using <strong>harpoon</strong> or <strong>grapple</strong> to collect <strong>power ups</strong><br><strong>+77%</strong> <strong>harpoon</strong> or <strong>grapple</strong> <strong class='color-d'>damage</strong> for 8 seconds",
|
||||
description: "after using <strong>harpoon</strong>/<strong>grapple</strong> to collect <strong>power ups</strong><br><strong>+77%</strong> <strong>harpoon</strong> or <strong>grapple</strong> <strong class='color-d'>damage</strong> for 8 seconds",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -7091,7 +7171,7 @@ const tech = {
|
||||
},
|
||||
{
|
||||
name: "brittle",
|
||||
description: "<strong>+88%</strong> <strong>harpoon</strong> and <strong>grapple</strong> <strong class='color-d'>damage</strong><br>to <strong>mobs</strong> at maximum <strong>health</strong>",
|
||||
description: "<strong>+88%</strong> <strong>harpoon</strong>/<strong>grapple</strong> <strong class='color-d'>damage</strong><br>to <strong>mobs</strong> at maximum <strong>health</strong>",
|
||||
isGunTech: true,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
@@ -7595,7 +7675,7 @@ const tech = {
|
||||
{
|
||||
name: "electronegativity",
|
||||
descriptionFunction() {
|
||||
return `<strong>+0.22%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(+${(22 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
|
||||
return `<strong>+0.26%</strong> <strong class='color-d'>damage</strong> per current stored <strong class='color-f'>energy</strong><br><em>(+${(27 * m.maxEnergy).toFixed(0)}% damage at max energy)</em>`
|
||||
},
|
||||
// description: "<strong>+1%</strong> <strong class='color-d'>damage</strong> per <strong>8</strong> stored <strong class='color-f'>energy</strong>",
|
||||
isFieldTech: true,
|
||||
|
||||
Reference in New Issue
Block a user