difficulty

difficulty rework
  difficulty adjusted through a power up on the initial level
  difficulty parameters are more precisely explained
  JUNK tech: difficulty - spawns a difficulty power up (only works before level 6)

bots no longer benefit from increased fireRate
shields have a chance spawn on almost all mobs (but not stealth mobs)
level exit door animation is 33% faster
power ups have fewer sides.  It might improve game performance, but I can't tell the difference.
1.15x base wave bullets damage (bots, particles, and phonon)
metamaterial absorber 25->30% chance to get power ups from mobs left alive
apomixis is now a JUNK tech, and it requires duplication > 99%
pilot wave field 2->3 extra choices
plasma torch slows mobs more, and don't push mobs back as much
  fixed bug where plasma torch didn't get tech degenerate matter
laserLayerBoss and layerLayer do 33% less damage
mines aren't triggered by invulnerable mobs

bug fixes
This commit is contained in:
landgreen
2024-06-02 21:43:42 -07:00
parent 507b0605d6
commit 63bfaba4a1
12 changed files with 1082 additions and 734 deletions

View File

@@ -46,19 +46,124 @@
<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)"> <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)">
<text x="10" y="33">training</text> <text x="10" y="33">training</text>
</svg> </svg>
<div id='info'> <div id='info'>
<!-- <div id="constraint">
<details id = 'constraint-details'>
<summary>difficulty</summary>
<div class="details-div">
<style>
.grid-container {
display: grid;
grid-template-columns: 0fr 5fr 0fr;
line-height: 150%;
}
#difficulty-slider {
margin-top: 3rem;
height: 30rem;
width: 2rem;
writing-mode: vertical-lr;
/* direction: rtl; */
}
.far-right-column {
display: grid;
grid-template-rows: repeat(6, 1fr);
/* grid-gap: 55px; */
font-size: 2rem;
align-self: center;
justify-self: center;
}
.far-right-column > div{
padding-top: 60px;
}
.left-column {
grid-row: 1 / span 6
}
.right-column {
display: grid;
grid-template-rows: repeat(6, 1fr);
}
.row {
transition: opacity 0.4s ease-out;
border: 2px #000 solid;
margin-top: -2px;;
font-size: 1.2rem;
padding: 10px;
}
#constraint-0{
background-color: hsl(240, 18%, 98%);
border-radius: 10px 10px 0 0;
}
#constraint-1{
background-color: hsl(240, 18%, 96%);;
/* border-radius: 10px 10px 0 0; */
}
#constraint-2{
background-color: hsl(240, 18%, 94%);;
}
#constraint-3{
background-color: hsl(240, 18%, 92%);;
}
#constraint-4{
background-color: hsl(240, 18%, 90%);;
}
#constraint-5{
background-color: hsl(240, 18%, 88%);;
border-radius: 0 0 10px 10px;
}
</style>
<div class="grid-container">
<div class="left-column">
<input type="range" id="difficulty-slider" name="temp" type="range" step="1" value="0" min="0" max="5" list="values" />
<datalist id="values">
<option value="0"></option>
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
<option value="4"></option>
<option value="5"></option>
</datalist>
</div>
<div class="right-column">
<div class="row" id="constraint-0"><strong>2x</strong> <strong class='color-defense'>damage taken</strong> per level
<br><strong>0.82x</strong> <strong class='color-d'>damage</strong> per level</div>
<div class="row" id="constraint-1"><strong>-5</strong> initial <strong>power ups</strong>
<br><strong>5%</strong> chance for <strong>shielded</strong> mobs</div>
<div class="row" id="constraint-2"><strong>2x</strong> <strong class='color-defense'>damage taken</strong> per level
<br><strong>0.82x</strong> <strong class='color-d'>damage</strong> per level</div>
<div class="row" id="constraint-3"><strong>+1</strong> boss per level, <strong>-1</strong> <strong class='color-m'>tech</strong> per boss
<br><strong>1.5x</strong> mob movement and reactions</div>
<div class="row" id="constraint-4"><strong>2x</strong> <strong class='color-defense'>damage taken</strong> per level
<br><strong>0.82x</strong> <strong class='color-d'>damage</strong> per level</div>
<div class="row" id="constraint-5"><strong>10%</strong> chance for <strong>shielded</strong> mobs
<br><strong>-3</strong> initial power ups</div>
</div>
<div class="far-right-column">
<div id = "constraint-0-record"></div>
<div id = "constraint-1-record"></div>
<div id = "constraint-2-record"></div>
<div id = "constraint-3-record"></div>
<div id = "constraint-4-record"></div>
<div id = "constraint-5-record"></div>
</div>
</div>
confirm difficulty parameters
</div>
</details>
</div> -->
<div id="settings"> <div id="settings">
<details id = 'settings-details'> <details id = 'settings-details'>
<summary>settings</summary> <summary>settings</summary>
<div style="line-height: 150%;" class="details-div"> <div style="line-height: 150%;" class="details-div">
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">combat difficulty:</label> <!-- <label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">combat difficulty:</label>
<select name="difficulty-select" id="difficulty-select" style="background-color: #fff"> <select name="difficulty-select" id="difficulty-select" style="background-color: #fff">
<option value="1">easy</option> <option value="1">easy</option>
<option value="2" selected>normal ⚆</option> <option value="2" selected>normal ⚆</option>
<option value="4">hard ⚆</option> <option value="4">hard ⚆</option>
<option value="5">why ⚇</option> <option value="5">why ⚇</option>
</select> </select>
<br> <br> -->
<input onclick="build.showImages('settings')" type="checkbox" id="hide-images" name="hide-images" style="width:17px; height:17px;"> <input onclick="build.showImages('settings')" type="checkbox" id="hide-images" name="hide-images" style="width:17px; height:17px;">
<label for="hide-images" title="hide images for fields, guns, and tech">hide images</label> <label for="hide-images" title="hide images for fields, guns, and tech">hide images</label>
<br> <br>

View File

@@ -1,7 +1,7 @@
let bullet = []; let bullet = [];
const b = { const b = {
// dmgScale: null, //scales all damage, but not raw .dmg //set in levels.setDifficulty // dmgScale: null, //scales all damage, but not raw .dmg
gravity: 0.0006, //most other bodies have gravity = 0.001 gravity: 0.0006, //most other bodies have gravity = 0.001
activeGun: null, //current gun in use by player activeGun: null, //current gun in use by player
inventoryGun: 0, inventoryGun: 0,
@@ -2313,13 +2313,14 @@ const b = {
best.who.locatePlayer(); best.who.locatePlayer();
//push mobs away //push mobs away
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.01 * Math.min(5, best.who.mass)) if (best.who.speed > 3) {
Matter.Body.applyForce(best.who, path[1], force) const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.005 * Math.min(5, best.who.mass))
if (best.who.speed > 4) { Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { //friction Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.4, y: best.who.velocity.y * 0.4 });
x: best.who.velocity.x * 0.9, } else {
y: best.who.velocity.y * 0.9 const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
}); Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.7, y: best.who.velocity.y * 0.7 });
} }
//draw mob damage circle //draw mob damage circle
simulation.drawList.push({ simulation.drawList.push({
@@ -2702,28 +2703,13 @@ const b = {
this.lookFrequency = 55 + Math.floor(22 * Math.random()) this.lookFrequency = 55 + Math.floor(22 * Math.random())
simulation.drawList.push({ x: this.position.x, y: this.position.y, radius: 10, color: "#f00", time: 4 }); simulation.drawList.push({ x: this.position.x, y: this.position.y, radius: 10, color: "#f00", time: 4 });
this.do = function () { //overwrite the do method for this bullet this.do = function () { //overwrite the do method for this bullet
//make mobs think the mine is where the player is
// for (let i = 0; i < mob.length; i++) {
// mob[i].seePlayer.recall = mob[i].memory + Math.round(mob[i].memory * Math.random()); //cycles before mob falls a sleep
// mob[i].seePlayer.position.x = this.position.x;
// mob[i].seePlayer.position.y = this.position.y;
// mob[i].seePlayer.yes = true;
// }
this.force.y += this.mass * 0.002; //extra gravity this.force.y += this.mass * 0.002; //extra gravity
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
const random = 300 * Math.random() const random = 300 * Math.random()
for (let i = 0, len = mob.length; i < len; ++i) { for (let i = 0, len = mob.length; i < len; ++i) {
if ( if (
!mob[i].isBadTarget && !mob[i].isBadTarget &&
!mob[i].isInvulnerable &&
Vector.magnitude(Vector.sub(this.position, mob[i].position)) < this.range + mob[i].radius + random && Vector.magnitude(Vector.sub(this.position, mob[i].position)) < this.range + mob[i].radius + random &&
Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 &&
Matter.Query.ray(body, this.position, mob[i].position).length === 0 Matter.Query.ray(body, this.position, mob[i].position).length === 0
@@ -4892,7 +4878,7 @@ const b = {
minDmgSpeed: 2, minDmgSpeed: 2,
// lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20, // lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20,
lastLookCycle: simulation.cycle + 60 * Math.random(), lastLookCycle: simulation.cycle + 60 * Math.random(),
delay: Math.floor((tech.isNailBotUpgrade ? 18 : 85) * b.fireCDscale), delay: Math.floor((tech.isNailBotUpgrade ? 18 : 85)),
acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100,
endCycle: Infinity, endCycle: Infinity,
@@ -4954,7 +4940,7 @@ const b = {
minDmgSpeed: 2, minDmgSpeed: 2,
lookFrequency: 26 + Math.ceil(6 * Math.random()), lookFrequency: 26 + Math.ceil(6 * Math.random()),
cd: 0, cd: 0,
delay: Math.floor(60 * b.fireCDscale), delay: Math.floor(60),
range: 70 + 3 * b.totalBots(), range: 70 + 3 * b.totalBots(),
endCycle: Infinity, endCycle: Infinity,
classType: "bullet", classType: "bullet",
@@ -5030,7 +5016,7 @@ const b = {
cd: 0, cd: 0,
fireCount: 0, fireCount: 0,
fireLimit: 5 + 2 * tech.isFoamBotUpgrade, fireLimit: 5 + 2 * tech.isFoamBotUpgrade,
delay: Math.floor((145 + (tech.isFoamBotUpgrade ? 0 : 230)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, delay: Math.floor((145 + (tech.isFoamBotUpgrade ? 0 : 230))),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade,
acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move
endCycle: Infinity, endCycle: Infinity,
@@ -5150,7 +5136,7 @@ const b = {
cd: 0, cd: 0,
fireCount: 0, fireCount: 0,
fireLimit: 5 + 2 * tech.isSoundBotUpgrade, fireLimit: 5 + 2 * tech.isSoundBotUpgrade,
delay: Math.floor((120 + (tech.isSoundBotUpgrade ? 0 : 70)) * b.fireCDscale),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade, delay: Math.floor((120 + (tech.isSoundBotUpgrade ? 0 : 70))),// + 30 - 20 * tech.isFoamBotUpgrade,//20 + Math.floor(85 * b.fireCDscale) - 20 * tech.isFoamBotUpgrade,
acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()), acceleration: (isKeep ? 0.005 : 0.001) * (1 + 0.5 * Math.random()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move
endCycle: Infinity, endCycle: Infinity,
@@ -5646,8 +5632,19 @@ const b = {
best.who.damage(dmg); best.who.damage(dmg);
best.who.locatePlayer(); best.who.locatePlayer();
//push mobs away //push mobs away
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.007 * Math.min(5, best.who.mass)) // const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.007 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force) // Matter.Body.applyForce(best.who, path[1], force)
//push mobs away
if (best.who.speed > 3) {
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.005 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.4, y: best.who.velocity.y * 0.4 });
} else {
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.01 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.7, y: best.who.velocity.y * 0.7 });
}
if (best.who.speed > 2.5) Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.75, y: best.who.velocity.y * 0.75 }); if (best.who.speed > 2.5) Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.75, y: best.who.velocity.y * 0.75 });
//draw mob damage circle //draw mob damage circle
if (best.who.damageReduction) { if (best.who.damageReduction) {
@@ -7752,10 +7749,7 @@ const b = {
} }
let speed = 36 let speed = 36
if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map
b.mine(pos, { b.mine(pos, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }, 0)
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
}, 0)
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down
} }
} else { } else {
@@ -7765,10 +7759,7 @@ const b = {
} }
let speed = 23 let speed = 23
if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map
b.mine(pos, { b.mine(pos, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }, 0)
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
}, 0)
m.fireCDcycle = m.cycle + Math.floor(35 * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(35 * b.fireCDscale); // cool down
} }
} }
@@ -7809,11 +7800,6 @@ const b = {
ctx.arc(m.pos.x, m.pos.y, 60, this.angle - this.arcRange, this.angle + this.arcRange); ctx.arc(m.pos.x, m.pos.y, 60, this.angle - this.arcRange, this.angle + this.arcRange);
ctx.strokeStyle = '#fff' //'rgba(255,255,255,0.9)' //'hsl(189, 100%, 95%)' ctx.strokeStyle = '#fff' //'rgba(255,255,255,0.9)' //'hsl(189, 100%, 95%)'
ctx.stroke(); ctx.stroke();
// const a = { x: radius * Math.cos(this.angle + this.arcRange), y: radius * Math.sin(this.angle + this.arcRange) }
// const b = Vector.add(m.pos, a)
// ctx.lineTo(b.x, b.y)
// ctx.fillStyle = '#fff'
// ctx.fill()
}, },
stuckOn() { stuckOn() {
if (tech.isStuckOn) { if (tech.isStuckOn) {
@@ -7916,6 +7902,79 @@ const b = {
} }
// this.fire = this.firePhoton // this.fire = this.firePhoton
}, },
// fireLaser() {
// // console.log('hi')
// const drain = tech.laserDrain / b.fireCDscale
// if (m.energy < drain) {
// m.fireCDcycle = m.cycle + 100; // cool down if out of energy
// } else {
// m.fireCDcycle = m.cycle
// m.energy -= drain
// const range = {
// x: 5000 * Math.cos(m.angle),
// y: 5000 * Math.sin(m.angle)
// }
// const laserSeparation = 3
// const rangeOffPlus = {
// x: laserSeparation * Math.cos(m.angle + Math.PI / 2),
// y: laserSeparation * Math.sin(m.angle + Math.PI / 2)
// }
// const rangeOffMinus = {
// x: laserSeparation * Math.cos(m.angle - Math.PI / 2),
// y: laserSeparation * Math.sin(m.angle - Math.PI / 2)
// }
// const dmg = 0.70 * tech.laserDamage / b.fireCDscale * this.lensDamage // 3.5 * 0.55 = 200% more damage
// const where = {
// x: m.pos.x + 30 * Math.cos(m.angle),
// y: m.pos.y + 30 * Math.sin(m.angle)
// }
// const eye = {
// x: m.pos.x + 15 * Math.cos(m.angle),
// y: m.pos.y + 15 * Math.sin(m.angle)
// }
// // ctx.strokeStyle = tech.laserColor;
// // ctx.lineWidth = 8
// // ctx.beginPath();
// if (Matter.Query.ray(map, eye, where).length === 0 && Matter.Query.ray(body, eye, where).length === 0) {
// b.laser(eye, {
// x: eye.x + range.x,
// y: eye.y + range.y
// }, dmg)
// }
// for (let i = 1; i < 2; i++) {
// let whereOff = Vector.add(where, {
// x: i * rangeOffPlus.x,
// y: i * rangeOffPlus.y
// })
// if (Matter.Query.ray(map, eye, whereOff).length === 0 && Matter.Query.ray(body, eye, whereOff).length === 0) {
// ctx.moveTo(eye.x, eye.y)
// ctx.lineTo(whereOff.x, whereOff.y)
// b.laser(whereOff, {
// x: whereOff.x + range.x,
// y: whereOff.y + range.y
// }, dmg)
// }
// whereOff = Vector.add(where, {
// x: i * rangeOffMinus.x,
// y: i * rangeOffMinus.y
// })
// if (Matter.Query.ray(map, eye, whereOff).length === 0 && Matter.Query.ray(body, eye, whereOff).length === 0) {
// ctx.moveTo(eye.x, eye.y)
// ctx.lineTo(whereOff.x, whereOff.y)
// b.laser(whereOff, {
// x: whereOff.x + range.x,
// y: whereOff.y + range.y
// }, dmg)
// }
// }
// // ctx.stroke();
// // if (tech.isLaserLens && b.guns[11].lensDamage !== 1) {
// // ctx.lineWidth = 20 + 3 * b.guns[11].lensDamageOn
// // ctx.globalAlpha = 0.3
// // ctx.stroke();
// // }
// }
// },
fireLaser() { fireLaser() {
const drain = tech.laserDrain / b.fireCDscale const drain = tech.laserDrain / b.fireCDscale
if (m.energy < drain) { if (m.energy < drain) {

View File

@@ -251,11 +251,11 @@ window.addEventListener('load', () => {
} }
} }
if (property === "difficulty") { // if (property === "difficulty") {
simulation.difficultyMode = Number(set[property]) // simulation.difficultyMode = Number(set[property])
lore.setTechGoal() // lore.setTechGoal()
document.getElementById("difficulty-select-experiment").value = Number(set[property]) // document.getElementById("difficulty-select-experiment").value = Number(set[property])
} // }
if (property === "molMode") { if (property === "molMode") {
simulation.molecularMode = Number(set[property]) simulation.molecularMode = Number(set[property])
const i = 4 //update experiment text const i = 4 //update experiment text
@@ -477,34 +477,41 @@ const build = {
<label for="hide-hud" title="hide: tech, damage taken, damage, in game console" style="font-size:1.15em;">minimal HUD</label> <label for="hide-hud" title="hide: tech, damage taken, damage, in game console" style="font-size:1.15em;">minimal HUD</label>
<br> <br>
<br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)}x <span style="float: right;"><strong class='color-d'>difficulty:</strong> ${((m.dmgScale)).toPrecision(4)}x</span> <details> <summary>difficulty</summary>
<br><strong class='color-defense'>damage taken</strong>: ${(m.defense()).toPrecision(4)}x <span style="float: right;"><strong class='color-defense'>difficulty:</strong> ${(simulation.dmgScale).toPrecision(4)}x</span> <div style="display: ${simulation.difficultyMode === 1 ? "block" : "none"};"><strong>+6</strong> initial <strong>power ups</strong><br><strong>5%</strong> chance for mobs to a drop <strong class='color-m'>tech</strong></div>
<br><strong><em>fire rate</em></strong>: ${(1 / b.fireCDscale).toFixed(2)}x <div style="display: ${simulation.difficultyMode > 1 ? "block" : "none"};"><strong>10%</strong> chance for <strong>shielded</strong> mobs<br><strong>0.5x</strong> <strong class='color-h'>heal</strong> power ups</div>
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""} <div style="display: ${simulation.difficultyMode > 2 ? "block" : "none"};"><strong>1.5x</strong> mob movement and reactions<br><strong>0.5x</strong> <strong class='color-d'>damage</strong></div>
${m.coupling ? `<br><span style = 'font-size:90%;'>` + m.couplingDescription(m.coupling) + `</span> from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""} <div style="display: ${simulation.difficultyMode > 3 ? "block" : "none"};"><strong>+1</strong> boss per level, <strong>-1</strong> <strong class='color-m'>tech</strong> per boss<br><strong>2x</strong> <strong class='color-defense'>damage taken</strong></div>
${botText} <div style="display: ${simulation.difficultyMode > 4 ? "block" : "none"};"><strong>-3</strong> initial power ups<br><strong>0.5x</strong> <strong class='color-d'>damage</strong></div>
<br> <div style="display: ${simulation.difficultyMode > 5 ? "block" : "none"};"><strong>10%</strong> chance for <strong>shielded</strong> mobs<br><strong>2x</strong> <strong class='color-defense'>damage taken</strong></div>
<br><strong class='color-h'>health</strong>: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)}) </details>
<span style="float: right;">mass: ${player.mass.toFixed(1)}</span>
<br><strong class='color-f'>energy</strong>: (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000).toFixed(0)}/s)
<span style="float: right;">position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})</span> <br><strong class='color-d'>damage</strong>: ${((tech.damageFromTech())).toPrecision(4)}x <span style="float: right;"><strong class='color-d'>difficulty:</strong> ${((m.dmgScale)).toPrecision(4)}x</span>
<br><strong class='color-g'>gun</strong>: ${b.activeGun === null || b.activeGun === undefined ? "undefined" : b.guns[b.activeGun].name} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun === null || b.activeGun === undefined ? "0" : b.guns[b.activeGun].ammo} <br><strong class='color-defense'>damage taken</strong>: ${(m.defense()).toPrecision(4)}x <span style="float: right;"><strong class='color-defense'>difficulty:</strong> ${(simulation.dmgScale).toPrecision(4)}x</span>
<span style="float: right;">mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})</span> <br><strong><em>fire rate</em></strong>: ${(1 / b.fireCDscale).toFixed(2)}x
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count} ${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""}
<span style="float: right;">velocity: (${player.velocity.x.toFixed(3)}, ${player.velocity.y.toFixed(3)})</span> ${m.coupling ? `<br><span style = 'font-size:90%;'>` + m.couplingDescription(m.coupling) + `</span> from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""}
${tech.junkChance ? `<br><strong class='color-junk'>JUNK</strong>: ${(100 * tech.junkChance).toFixed(1)}% ` : ""} ${botText}
<br> <br>
<br>level: ${level.levelsCleared} ${level.levels[level.onLevel]} (${level.difficultyText()}) <br><strong class='color-h'>health</strong>: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
<br>mobs: ${spawn.pickList[0]}, ${spawn.pickList[0]} <span style="float: right;">mass: ${player.mass.toFixed(1)}</span>
<br>seed: ${Math.initialSeed} &nbsp; ${m.cycle} cycles <br><strong class='color-f'>energy</strong>: (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000).toFixed(0)}/s)
<br>mobs: ${mob.length} &nbsp; blocks: ${body.length} &nbsp; bullets: ${bullet.length} &nbsp; power ups: ${powerUp.length} <span style="float: right;">position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)})</span>
${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""} <br><strong class='color-g'>gun</strong>: ${b.activeGun === null || b.activeGun === undefined ? "undefined" : b.guns[b.activeGun].name} &nbsp; <strong class='color-g'>ammo</strong>: ${b.activeGun === null || b.activeGun === undefined ? "0" : b.guns[b.activeGun].ammo}
</span></div>`; <span style="float: right;">mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)})</span>
<br><strong class='color-m'>tech</strong>: ${tech.totalCount} &nbsp; <strong class='color-r'>research</strong>: ${powerUps.research.count}
<span style="float: right;">velocity: (${player.velocity.x.toFixed(3)}, ${player.velocity.y.toFixed(3)})</span>
${tech.junkChance ? `<br><strong class='color-junk'>JUNK</strong>: ${(100 * tech.junkChance).toFixed(1)}% ` : ""}
<br>
<br>mobs: ${spawn.pickList[0]}, ${spawn.pickList[0]}
<br>seed: ${Math.initialSeed} &nbsp; ${m.cycle} cycles
<br>mobs: ${mob.length} &nbsp; blocks: ${body.length} &nbsp; bullets: ${bullet.length} &nbsp; power ups: ${powerUp.length} ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}</span></div>`;
// deaths: ${mobs.mobDeaths} &nbsp; // deaths: ${mobs.mobDeaths} &nbsp;
// if (tech.isPauseSwitchField && !simulation.isChoosing) { // if (tech.isPauseSwitchField && !simulation.isChoosing) {
// const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` // const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
// text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} > // text += `<div class="pause-grid-module card-background" id="pause-field" ${style} >
// <div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;"> // <div class="card-text" style="animation: fieldColorCycle 1s linear infinite alternate;">
// <div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> // <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> </div>` // ${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
if ((tech.isPauseSwitchField || simulation.testing)) { //&& !simulation.isChoosing if ((tech.isPauseSwitchField || simulation.testing)) { //&& !simulation.isChoosing
@@ -515,21 +522,21 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
<div class="grid-title" style="text-align: center;">↑ <div class="circle-grid field"></div> ↑</div></div>` <div class="grid-title" style="text-align: center;">↑ <div class="circle-grid field"></div> ↑</div></div>`
//button for current //button for current
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} > text += `<div class="pause-grid-module card-background" id="pause-field" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> <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> </div>` ${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
//button below for next //button below for next
text += `<div class="pause-grid-module" id ="pause-field-next" style="animation: fieldColorCycle 3s linear infinite alternate;border-bottom: 1px solid #000;"> text += `<div class="pause-grid-module" id="pause-field-next" style="animation: fieldColorCycle 3s linear infinite alternate;border-bottom: 1px solid #000;">
<div class="grid-title" style="text-align: center;">↓ <div class="circle-grid field"></div> ↓</div></div>` <div class="grid-title" style="text-align: center;">↓ <div class="circle-grid field"></div> ↓</div></div>`
} else { } else {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/field/${m.fieldUpgrades[m.fieldMode].name}${m.fieldMode === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} > text += `<div class="pause-grid-module card-background" id="pause-field" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div> <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> </div>` ${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
} }
// for (let i = 0, len = b.inventory.length; i < len; i++) { // for (let i = 0, len = b.inventory.length; i < len; i++) {
// text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>` // text += `<div class="pause-grid-module"><div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> ${b.guns[b.inventory[i]].description}</div>`
@@ -537,26 +544,26 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
for (let i = 0, len = b.inventory.length; i < len; i++) { for (let i = 0, len = b.inventory.length; i < len; i++) {
const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/gun/${b.guns[b.inventory[i]].name}.webp');"` const style = localSettings.isHideImages ? `style="height:auto;"` : `style="background-image: url('img/gun/${b.guns[b.inventory[i]].name}.webp');"`
text += `<div class="pause-grid-module card-background" ${style} > text += `<div class="pause-grid-module card-background" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div> <div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[b.inventory[i]].name)} - <span style="font-size:100%;font-weight: 100;">${b.guns[b.inventory[i]].ammo}</span></div>
${b.guns[b.inventory[i]].descriptionFunction()}</div> </div>` ${b.guns[b.inventory[i]].descriptionFunction()}</div> </div>`
} }
if (!localSettings.isHideHUD) text += `<div class="pause-grid-module pause-console" style = "background-color: rgba(255,255,255,0.3);">${document.getElementById("text-log").innerHTML}</div>` //show last in game console message if (!localSettings.isHideHUD) text += `<div class="pause-grid-module pause-console" style="background-color: rgba(255,255,255,0.3);">${document.getElementById("text-log").innerHTML}</div>` //show last in game console message
let el = document.getElementById("pause-grid-left") let el = document.getElementById("pause-grid-left")
el.style.display = "grid" el.style.display = "grid"
el.innerHTML = text el.innerHTML = text
}, },
generatePauseRight() { generatePauseRight() {
let text = `<div class="sort"> let text = `<div class="sort">
<button onclick="build.sortTech('damage')" class='sort-button'><strong class='color-d'>damage</strong></button> <button onclick="build.sortTech('damage')" class='sort-button'><strong class='color-d'>damage</strong></button>
<button onclick="build.sortTech('guntech')" class='sort-button'><strong class='color-g'>gun</strong><strong class='color-m'>tech</strong></button> <button onclick="build.sortTech('guntech')" class='sort-button'><strong class='color-g'>gun</strong><strong class='color-m'>tech</strong></button>
<button onclick="build.sortTech('fieldtech')" class='sort-button'><strong class='color-f'>field</strong><strong class='color-m'>tech</strong></button> <button onclick="build.sortTech('fieldtech')" class='sort-button'><strong class='color-f'>field</strong><strong class='color-m'>tech</strong></button>
<button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button> <button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button>
<button onclick="build.sortTech('damage taken')" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">damage taken</strong></button> <button onclick="build.sortTech('damage taken')" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">damage taken</strong></button>
<button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button> <button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button>
<input type="search" id="sort-input" style="width: 8em;font-size: 0.6em;color:#000;" placeholder="sort by"/> <input type="search" id="sort-input" style="width: 8em;font-size: 0.6em;color:#000;" placeholder="sort by" />
<button onclick="build.sortTech('input')" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button> <button onclick="build.sortTech('input')" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button>
</div>`; </div>`;
const ejectClass = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'pause-eject' : '' const ejectClass = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'pause-eject' : ''
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) { if (tech.tech[i].count > 0) {
@@ -728,43 +735,43 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
isExperimentRun: false, isExperimentRun: false,
techText(i) { techText(i) {
return `<div class="card-text" > return `<div class="card-text" >
<div class="grid-title" ><div class="circle-grid tech"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> <div class="grid-title" ><div class="circle-grid tech"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
instantTechText(i) { instantTechText(i) {
// //
return `<div class="card-text" > return `<div class="card-text" >
<div class="grid-title" > <div class="circle-grid-instant"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> <div class="grid-title" > <div class="circle-grid-instant"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
skinTechText(i) { skinTechText(i) {
return `<div class="card-text"> <div class="grid-title"> return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;"> <span style="position:relative;">
<div class="circle-grid-skin"></div> <div class="circle-grid-skin"></div>
<div class="circle-grid-skin-eye"></div> <div class="circle-grid-skin-eye"></div>
</span> &nbsp; &nbsp; &nbsp;&nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> </span> &nbsp; &nbsp; &nbsp;&nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
gunTechText(i) { gunTechText(i) {
return `<div class="card-text"> <div class="grid-title"> return `<div class="card-text"> <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> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
fieldTechText(i) { fieldTechText(i) {
return `<div class="card-text"><div class="grid-title"> return `<div class="card-text"><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> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> </span> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
junkTechText(i) { junkTechText(i) {
return `<div class="card-text"> return `<div class="card-text">
<div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div> <div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}</div>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>` ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
}, },
choosePowerUp(index, type, isAllowed = false) { choosePowerUp(index, type, isAllowed = false) {
if (type === "gun") { if (type === "gun") {
@@ -804,8 +811,8 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
// document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}` // document.getElementById(`field-${i}`).innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> ${m.fieldUpgrades[i].description}`
document.getElementById(`field-${i}`).innerHTML = `<div class="card-text"> document.getElementById(`field-${i}`).innerHTML = `<div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> <div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div>` ${m.fieldUpgrades[i].description}</div>`
} }
} else if (type === "tech") { } else if (type === "tech") {
if (tech.tech[index].count < tech.tech[index].maxCount) { if (tech.tech[index].count < tech.tech[index].maxCount) {
@@ -877,72 +884,73 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
} }
} }
}, },
// <div>
// <select name="difficulty-select" id="difficulty-select-experiment">
// <option value="1">easy</option>
// <option value="2" selected>normal ⚆</option>
// <option value="4">hard ⚆</option>
// <option value="5">why ⚇</option>
// </select>
// &nbsp; &nbsp;
// <label for="hide-images-experiment" title="reload experiment with no images for fields, guns, and tech" style="font-size: 0.85em;">hide images</label>
// <input onclick="build.showImages('experiment')" type="checkbox" id="hide-images-experiment" name="hide-images-experiment" style="width:13px; height:13px;" ${localSettings.isHideImages ? "checked" : ""}>
// </div>
// <button onclick="build.sortTech('allowed', true)" class='sort-button' style="letter-spacing: 1px;font-weight: 400;">allowed</button>
// <button onclick="build.sortTech('have', true)" class='sort-button color-m' style="letter-spacing: 1px;font-weight: 800;">have</button>
populateGrid() { //background-color:var(--build-bg-color); populateGrid() { //background-color:var(--build-bg-color);
let text = ` let text = `
<div class="experiment-start-box"> <div class="experiment-start-box">
<div class="sort" style="border: 0px;"> <div class="sort" style="border: 0px;">
<button onclick="build.sortTech('guntech', true)" class='sort-button'><strong class='color-g'>gun</strong><strong class='color-m'>tech</strong></button> <button onclick="build.sortTech('guntech', true)" class='sort-button'><strong class='color-g'>gun</strong><strong class='color-m'>tech</strong></button>
<button onclick="build.sortTech('fieldtech', true)" class='sort-button'><strong class='color-f'>field</strong><strong class='color-m'>tech</strong></button> <button onclick="build.sortTech('fieldtech', true)" class='sort-button'><strong class='color-f'>field</strong><strong class='color-m'>tech</strong></button>
<button onclick="build.sortTech('damage', true)" class='sort-button'><strong class='color-d'>damage</strong></button> <button onclick="build.sortTech('damage', true)" class='sort-button'><strong class='color-d'>damage</strong></button>
<button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button> <button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button>
<button onclick="build.sortTech('damage taken', true)" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">damage taken</strong></button> <button onclick="build.sortTech('damage taken', true)" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">damage taken</strong></button>
<button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button> <button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button>
<button onclick="build.sortTech('have', true)" class='sort-button color-m' style="letter-spacing: 1px;font-weight: 800;">have</button> <input type="search" id="sort-input" style="width: 6em;font-size: 0.6em;color:#000;" placeholder="sort by" />
<button onclick="build.sortTech('allowed', true)" class='sort-button' style="letter-spacing: 1px;font-weight: 400;">allowed</button> <button onclick="build.sortTech('input', true)" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button>
<input type="search" id="sort-input" style="width: 8.7em;font-size: 0.6em;color:#000;" placeholder="sort by"/> </div>
<button onclick="build.sortTech('input', true)" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button> <div>
</div> <div style="display: grid;grid-template-columns: repeat(3, 1fr);row-gap: 10px;column-gap: 25px;grid-auto-rows: minmax(5px, auto);margin:-5px 0px 10px 25px;line-height: 100%;">
<div> <div style="grid-column: 1;grid-row: 2 / 4;">
<select name="difficulty-select" id="difficulty-select-experiment"> <svg class="SVG-button" onclick="build.startExperiment()" width="150" height="70" >
<option value="1">easy</option> <g stroke='none' fill='#333' stroke-width="2" font-size="65px" font-family="Ariel, sans-serif">
<option value="2" selected>normal ⚆</option> <text x="10" y="57">start</text>
<option value="4">hard ⚆</option> </g>
<option value="5">why ⚇</option> </svg>
</select> </div>
&nbsp; &nbsp; <div style="grid-column: 2;grid-row: 2;">
<label for="hide-images-experiment" title="reload experiment with no images for fields, guns, and tech" style="font-size: 0.85em;">hide images</label> <svg class="SVG-button" onclick="build.reset()" width="50" height="25">
<input onclick="build.showImages('experiment')" type="checkbox" id="hide-images-experiment" name="hide-images-experiment" style="width:13px; height:13px;" ${localSettings.isHideImages ? "checked" : ""}> <g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
</div> <text x="5" y="18">reset</text>
<div> </g>
<div style="display: grid;grid-template-columns: repeat(3, 1fr);row-gap: 10px;column-gap: 25px;grid-auto-rows: minmax(5px, auto);margin:-5px 0px 10px 25px;line-height: 100%;"> </svg>
<div style="grid-column: 1;grid-row: 2 / 4;"> </div>
<svg class="SVG-button" onclick="build.startExperiment()" width="150" height="70" > <div style="grid-column: 2;grid-row: 3/4;">
<g stroke='none' fill='#333' stroke-width="2" font-size="65px" font-family="Ariel, sans-serif"> <svg class="SVG-button" onclick="build.shareURL(true)" width="52" height="25">
<text x="10" y="57">start</text> <g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
</g> <text x="5" y="18">share</text>
</svg> </g>
</div> </svg>
<div style="grid-column: 2;grid-row: 2;"> </div>
<svg class="SVG-button" onclick="build.reset()" width="50" height="25"> </div>
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif"> </div>
<text x="5" y="18">reset</text> </div>`
</g>
</svg>
</div>
<div style="grid-column: 2;grid-row: 3/4;">
<svg class="SVG-button" onclick="build.shareURL(true)" width="52" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">share</text>
</g>
</svg>
</div>
</div>
</div>
</div>`
const hideStyle = `style="height:auto; border: none; background-color: transparent;"` const hideStyle = `style="height:auto; border: none; background-color: transparent;"`
for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) { for (let i = 0, len = m.fieldUpgrades.length; i < len; i++) {
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"` const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/field/${m.fieldUpgrades[i].name}${i === 0 ? m.fieldUpgrades[0].imageNumber : ""}.webp');"`
text += `<div id="field-${i}" class="experiment-grid-module card-background ${m.fieldMode === i ? "build-field-selected" : ""}" onclick="build.choosePowerUp(${i},'field')" ${style} > text += `<div id="field-${i}" class="experiment-grid-module card-background ${m.fieldMode === i ? " build-field-selected" : ""}" onclick="build.choosePowerUp(${i},'field')" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div> <div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div> </div>` ${m.fieldUpgrades[i].description}</div> </div>`
} }
for (let i = 0, len = b.guns.length; i < len; i++) { for (let i = 0, len = b.guns.length; i < len; i++) {
const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/gun/${b.guns[i].name}.webp');"` const style = localSettings.isHideImages ? hideStyle : `style="background-image: url('img/gun/${b.guns[i].name}.webp');"`
text += `<div id="gun-${i}" class="experiment-grid-module card-background ${b.guns[i].have ? "build-gun-selected" : ""}" onclick="build.choosePowerUp(${i},'gun')" ${style} > text += `<div id="gun-${i}" class="experiment-grid-module card-background ${b.guns[i].have ? " build-gun-selected" : ""}" onclick="build.choosePowerUp(${i},'gun')" ${style} >
<div class="card-text"> <div class="card-text">
<div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div> <div class="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div>
${b.guns[i].descriptionFunction()}</div> </div>` ${b.guns[i].descriptionFunction()}</div> </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].isJunk || localSettings.isJunkExperiment) && !tech.tech[i].isLore) { if ((!tech.tech[i].isJunk || localSettings.isJunkExperiment) && !tech.tech[i].isLore) {
@@ -982,14 +990,14 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
} }
document.getElementById("sort-input").addEventListener('keydown', pressEnterSort); document.getElementById("sort-input").addEventListener('keydown', pressEnterSort);
document.getElementById("difficulty-select-experiment").value = document.getElementById("difficulty-select").value // document.getElementById("difficulty-select-experiment").value = document.getElementById("difficulty-select").value
document.getElementById("difficulty-select-experiment").addEventListener("input", () => { // document.getElementById("difficulty-select-experiment").addEventListener("input", () => {
simulation.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value) // simulation.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value)
lore.setTechGoal() // lore.setTechGoal()
localSettings.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value) // localSettings.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value)
document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-experiment").value // document.getElementById("difficulty-select").value = document.getElementById("difficulty-select-experiment").value
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}); // });
//add tooltips //add tooltips
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
if (document.getElementById(`tech-${i}`)) { if (document.getElementById(`tech-${i}`)) {
@@ -1001,7 +1009,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
requestAnimationFrame(() => { document.getElementById("sort-input").focus(); }); requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
}, },
nameLink(text) { //converts text into a clickable wikipedia search nameLink(text) { //converts text into a clickable wikipedia search
return `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(text).replace(/'/g, '%27')}&title=Special:Search' class="link">${text}</a>` return `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(text).replace(/' /g, '%27')}&title=Special:Search' class="link">${text}</a>`
}, },
reset() { reset() {
build.isExperimentSelection = true; build.isExperimentSelection = true;
@@ -1437,59 +1445,59 @@ window.addEventListener("keydown", function (event) {
if (simulation.testing) tech.setCheating(); if (simulation.testing) tech.setCheating();
simulation.makeTextLog( simulation.makeTextLog(
`<table class="pause-table"> `<table class="pause-table">
<tr> <tr>
<td class='key-input-pause'>T</td> <td class='key-input-pause'>T</td>
<td class='key-used'><strong>toggle testing</strong></td> <td class='key-used'><strong>toggle testing</strong></td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>R</td> <td class='key-input-pause'>R</td>
<td class='key-used'>teleport to mouse</td> <td class='key-used'>teleport to mouse</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>F</td> <td class='key-input-pause'>F</td>
<td class='key-used'>cycle field</td> <td class='key-used'>cycle field</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>G</td> <td class='key-input-pause'>G</td>
<td class='key-used'>all guns</td> <td class='key-used'>all guns</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>H</td> <td class='key-input-pause'>H</td>
<td class='key-used'>+100% defense</td> <td class='key-used'>+100% defense</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>B</td> <td class='key-input-pause'>B</td>
<td class='key-used'>damage, research</td> <td class='key-used'>damage, research</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>N</td> <td class='key-input-pause'>N</td>
<td class='key-used'>fill health, energy</td> <td class='key-used'>fill health, energy</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>Y</td> <td class='key-input-pause'>Y</td>
<td class='key-used'>random tech</td> <td class='key-used'>random tech</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>U</td> <td class='key-input-pause'>U</td>
<td class='key-used'>next level</td> <td class='key-used'>next level</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>J</td> <td class='key-input-pause'>J</td>
<td class='key-used'>clear mobs</td> <td class='key-used'>clear mobs</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>I/O</td> <td class='key-input-pause'>I/O</td>
<td class='key-used'>zoom in / out</td> <td class='key-used'>zoom in / out</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>1-8</td> <td class='key-input-pause'>1-8</td>
<td class='key-used'>spawn things</td> <td class='key-used'>spawn things</td>
</tr> </tr>
<tr> <tr>
<td class='key-input-pause'>⇧X</td> <td class='key-input-pause'>⇧X</td>
<td class='key-used'>restart</td> <td class='key-used'>restart</td>
</tr> </tr>
</table>`, Infinity); </table>`, Infinity);
} }
} }
break break
@@ -1759,11 +1767,6 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
simulation.isCommunityMaps = localSettings.isCommunityMaps simulation.isCommunityMaps = localSettings.isCommunityMaps
document.getElementById("community-maps").checked = localSettings.isCommunityMaps document.getElementById("community-maps").checked = localSettings.isCommunityMaps
if (localSettings.difficultyMode === undefined) localSettings.difficultyMode = "2"
simulation.difficultyMode = localSettings.difficultyMode
lore.setTechGoal()
document.getElementById("difficulty-select").value = localSettings.difficultyMode
if (localSettings.fpsCapDefault === undefined) localSettings.fpsCapDefault = 'max' if (localSettings.fpsCapDefault === undefined) localSettings.fpsCapDefault = 'max'
if (localSettings.personalSeeds === undefined) localSettings.personalSeeds = []; if (localSettings.personalSeeds === undefined) localSettings.personalSeeds = [];
if (localSettings.fpsCapDefault === 'max') { if (localSettings.fpsCapDefault === 'max') {
@@ -1791,6 +1794,14 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
if (localSettings.isHideHUD === undefined) localSettings.isHideHUD = true if (localSettings.isHideHUD === undefined) localSettings.isHideHUD = true
document.getElementById("hide-hud").checked = localSettings.isHideHUD document.getElementById("hide-hud").checked = localSettings.isHideHUD
if (localSettings.difficultyCompleted === undefined) {
localSettings.difficultyCompleted = [null, false, false, false, false, false, false] //null because there isn't a difficulty zero
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
if (localSettings.difficultyMode === undefined) localSettings.difficultyMode = "2"
simulation.difficultyMode = localSettings.difficultyMode
lore.setTechGoal()
} else { } else {
console.log('setting default localSettings') console.log('setting default localSettings')
const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value
@@ -1801,6 +1812,7 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
isJunkExperiment: false, isJunkExperiment: false,
isCommunityMaps: false, isCommunityMaps: false,
difficultyMode: '2', difficultyMode: '2',
difficultyCompleted: [null, false, false, false, false, false, false],
fpsCapDefault: 'max', fpsCapDefault: 'max',
runCount: 0, runCount: 0,
isTrainingNotAttempted: true, isTrainingNotAttempted: true,
@@ -1817,18 +1829,30 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
document.getElementById("community-maps").checked = localSettings.isCommunityMaps document.getElementById("community-maps").checked = localSettings.isCommunityMaps
simulation.isCommunityMaps = localSettings.isCommunityMaps simulation.isCommunityMaps = localSettings.isCommunityMaps
document.getElementById("hide-images").checked = localSettings.isHideImages document.getElementById("hide-images").checked = localSettings.isHideImages
document.getElementById("difficulty-select").value = localSettings.difficultyMode
document.getElementById("fps-select").value = localSettings.fpsCapDefault document.getElementById("fps-select").value = localSettings.fpsCapDefault
document.getElementById("banned").value = localSettings.banList document.getElementById("banned").value = localSettings.banList
} }
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
// document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible" // document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
input.controlTextUpdate() input.controlTextUpdate()
//********************************************************************** //**********************************************************************
// settings // settings
//********************************************************************** //**********************************************************************
// difficulty-select-experiment event listener is set in build.makeGrid
// document.getElementById("difficulty-select").addEventListener("input", () => {
// simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
// lore.setTechGoal()
// localSettings.difficultyMode = simulation.difficultyMode
// localSettings.levelsClearedLastGame = 0 //after changing difficulty, reset run history
// localSettings.entanglement = undefined //after changing difficulty, reset stored tech
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// });
document.getElementById("fps-select").addEventListener("input", () => { document.getElementById("fps-select").addEventListener("input", () => {
let value = document.getElementById("fps-select").value let value = document.getElementById("fps-select").value
if (value === 'max') { if (value === 'max') {
@@ -1851,17 +1875,6 @@ document.getElementById("community-maps").addEventListener("input", () => {
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}); });
// difficulty-select-experiment event listener is set in build.makeGrid
document.getElementById("difficulty-select").addEventListener("input", () => {
simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
lore.setTechGoal()
localSettings.difficultyMode = simulation.difficultyMode
localSettings.levelsClearedLastGame = 0 //after changing difficulty, reset run history
localSettings.entanglement = undefined //after changing difficulty, reset stored tech
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
});
document.getElementById("updates").addEventListener("toggle", function () { document.getElementById("updates").addEventListener("toggle", function () {
function loadJSON(path, success, error) { //generic function to get JSON function loadJSON(path, success, error) { //generic function to get JSON
var xhr = new XMLHttpRequest(); var xhr = new XMLHttpRequest();

View File

@@ -18,7 +18,6 @@ const level = {
// 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
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// tech.giveTech("performance") // tech.giveTech("performance")
// level.difficultyIncrease(7 * 2) //30 is near max on hard //60 is near max on why
// m.maxHealth = m.health = 1//00000000 // m.maxHealth = m.health = 1//00000000
// m.maxEnergy = m.energy = 10000000 // m.maxEnergy = m.energy = 10000000
// tech.isRerollDamage = true // tech.isRerollDamage = true
@@ -38,6 +37,9 @@ const level = {
// b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser // b.giveGuns("laser") //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
// tech.laserColor = "#fff"
// tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
// b.guns[8].ammo = 100000000 // b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); // requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization") // for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization")
@@ -50,18 +52,17 @@ const level = {
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
// m.lastKillCycle = m.cycle // m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; ++i) tech.giveTech("anyon") // for (let i = 0; i < 1; ++i) tech.giveTech("plasma-bot")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech"); // 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 < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false);
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing
// level.towers(); // level.testing();
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500)
// Matter.Body.setPosition(player, { x: -200, y: -3330 }); // Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random()) // for (let i = 0; i < 4; ++i) spawn.ghoster(1300, -500 + 100 * Math.random())
// for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500) // spawn.hopper(1900, -500)
// spawn.sneakBoss(1900, -500)
// spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
// for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
// tech.addJunkTechToPool(2) // tech.addJunkTechToPool(2)
@@ -71,6 +72,7 @@ const level = {
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level ************************************************** level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 1; ++i) spawn.laserLayerBoss(1900, -500)
// for (let i = 0; i < 2; i++) spawn.ghoster(level.exit.x, level.exit.y) //ghosters need to spawn after the map loads // for (let i = 0; i < 2; i++) spawn.ghoster(level.exit.x, level.exit.y) //ghosters need to spawn after the map loads
// spawn.bodyRect(2425, -120, 200, 200); // spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass) // console.log(body[body.length - 1].mass)
@@ -90,6 +92,7 @@ const level = {
// lore.techCount = 1 // lore.techCount = 1
// level.levelsCleared = 10 // level.levelsCleared = 10
// localSettings.loreCount = 2 //this sets what conversation is heard // localSettings.loreCount = 2 //this sets what conversation is heard
// localSettings.levelsClearedLastGame = 10
// if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null() // level.null()
@@ -101,6 +104,8 @@ const level = {
// tech.giveTech("tinker"); //show junk tech in experiment mode // tech.giveTech("tinker"); //show junk tech in experiment mode
// m.storeTech() // m.storeTech()
// powerUps.spawn(m.pos.x, m.pos.y, "entanglement", false); // powerUps.spawn(m.pos.x, m.pos.y, "entanglement", false);
// for (let i = 0; i < 6; i++) localSettings.difficultyCompleted[i] = false
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
} else { } else {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.pickList = ["focuser", "focuser"] // spawn.pickList = ["focuser", "focuser"]
@@ -212,65 +217,65 @@ const level = {
trainingBackgroundColor: "#e1e1e1", trainingBackgroundColor: "#e1e1e1",
custom() { }, custom() { },
customTopLayer() { }, customTopLayer() { },
setDifficulty() { updateDifficulty() {
simulation.difficulty = 0 simulation.difficulty = level.levelsCleared * simulation.difficultyMode
m.dmgScale = 1; //damage done by player decreases each level if (simulation.isTraining) simulation.difficulty = 1
simulation.accelScale = 1 //mob acceleration increases each level
simulation.CDScale = 1 //mob CD time decreases each level // old
simulation.dmgScale = Math.max(0.1, 0.25 * simulation.difficulty) //damage done by mobs scales with total levels // normal mode m.dmgScale = 1, 0.81, 0.63, 0.5
simulation.healScale = 1 / (1 + simulation.difficulty * 0.043) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; // why mode m.dmgScale = 1, 0.56, 0.3, 0.17
}, // new
difficultyIncrease(num = 1) { //constraint 0,1 m.dmgScale = 1, 0.8, 0.6, 0.5
for (let i = 0; i < num; i++) { //constraint 2,3 m.dmgScale = 1,
simulation.difficulty++ //constraint 4,5 m.dmgScale = 1, 0.5, 0.3, 0.15
m.dmgScale *= 0.89; //damage done by player decreases each level
if (simulation.accelScale < 6) simulation.accelScale *= 1.024 //mob acceleration increases each level // old
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.964 //mob CD time decreases each level //normal: simulation.dmgScale = 0.1, 0.5 ,1 ,1.5 ,2 ,2.5
//hard: simulation.dmgScale = 0.1, 1 ,2 ,3 ,4 ,5
//why: simulation.dmgScale = 0.1, 1.25 ,2.5 ,3.75 ,5 ,6.25
// new
//0,1: simulation.dmgScale = 0.1, 0.5 ,1 ,1.5 ,2 ,2.5
//2,3: simulation.dmgScale = 0.1, 1 ,2 ,3 ,4 ,5
//3,4: simulation.dmgScale = 0.1, 1.25 ,2.5 ,3.75 ,5 ,6.25
let scale = 1
if (simulation.difficultyMode > 3) {
scale = 3
} else if (simulation.difficultyMode > 1) {
scale = 2
} }
simulation.dmgScale = Math.max(0.1, 0.25 * simulation.difficulty) //damage done by mobs scales with total levels m.dmgScale = Math.pow(0.82, level.levelsCleared * scale)
simulation.dmgScale = Math.max(0.1, 0.25 * level.levelsCleared * scale) //damage done by mobs scales with total levels
//
simulation.healScale = 1 / (1 + simulation.difficulty * 0.043) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale; simulation.healScale = 1 / (1 + simulation.difficulty * 0.043) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
// console.log(`CD = ${simulation.CDScale}`)
},
difficultyDecrease(num = 1) { //used in easy mode for simulation.reset()
for (let i = 0; i < num; i++) {
simulation.difficulty--
m.dmgScale /= 0.89; //damage done by player decreases each level
if (simulation.accelScale > 1) simulation.accelScale /= 1.024 //mob acceleration increases each level
if (simulation.CDScale < 1) simulation.CDScale /= 0.964 //mob CD time decreases each level
}
if (simulation.difficulty < 1) simulation.difficulty = 0;
simulation.dmgScale = Math.max(0.1, 0.25 * simulation.difficulty) //damage done by mobs scales with total levels
simulation.healScale = 1 / (1 + simulation.difficulty * 0.043)
},
difficultyText() {
if (simulation.difficultyMode === 1) { if (simulation.difficultyMode === 1) {
return "easy" simulation.accelScale = 1.1
} else if (simulation.difficultyMode === 2) { simulation.CDScale = 0.9
return "normal" } else {
} else if (simulation.difficultyMode === 4) { simulation.accelScale = Math.min(6, Math.pow(1.024, simulation.difficulty))
return "hard" simulation.CDScale = Math.max(0.15, Math.pow(0.964, simulation.difficulty))
} else if (simulation.difficultyMode === 5) {
return "why"
} }
}, },
// difficultyIncrease(num = 1) {
// for (let i = 0; i < num; i++) {
// simulation.difficulty++
// m.dmgScale *= 0.89; //damage done by player decreases each level
// if (simulation.accelScale < 6) simulation.accelScale *= 1.024 //mob acceleration increases each level
// if (simulation.CDScale > 0.15) simulation.CDScale *= 0.964 //mob CD time decreases each level
// }
// simulation.dmgScale = Math.max(0.1, 0.25 * simulation.difficulty) //damage done by mobs scales with total levels
// simulation.healScale = 1 / (1 + simulation.difficulty * 0.043) //a higher denominator makes for lower heals // m.health += heal * simulation.healScale;
// // console.log(`CD = ${simulation.CDScale}`)
// },
levelAnnounce() { levelAnnounce() {
const difficulty = simulation.isCheating ? "testing" : level.difficultyText() const cheating = simulation.isCheating ? "(testing)" : ""
if (level.levelsCleared === 0) { if (level.levelsCleared === 0) {
document.title = "n-gon: (" + difficulty + ")"; document.title = `n-gon: initial ${cheating}`;
} else { } else {
document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} (${difficulty})` document.title = `n-gon: ${level.levelsCleared} ${level.levels[level.onLevel]} ${cheating}`
simulation.makeTextLog(`<span class='color-var'>level</span>.onLevel <span class='color-symbol'>=</span> "<span class='color-text'>${level.levels[level.onLevel]}</span>"`); simulation.makeTextLog(`<span class='color-var'>level</span>.onLevel <span class='color-symbol'>=</span> "<span class='color-text'>${level.levels[level.onLevel]}</span>"`);
} }
// simulation.makeTextLog(`
// input.key.up = ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]
// <br>input.key.left = ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]
// <br>input.key.down = ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]
// <br>input.key.right = ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]
// <br>
// <br><span class='color-var'>m</span>.fieldMode = "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].name}</span>"
// <br>input.key.field = ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>right mouse</span>"]
// <br><span class='color-var'>m</span>.field.description = "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].description}</span>"
// `, 1200);
}, },
announceMobTypes() { announceMobTypes() {
simulation.makeTextLog(`spawn<span class='color-symbol'>.</span>${spawn.pickList[0]}<span class='color-symbol'>(</span>x<span class='color-symbol'>,</span>y<span class='color-symbol'>)</span>`) simulation.makeTextLog(`spawn<span class='color-symbol'>.</span>${spawn.pickList[0]}<span class='color-symbol'>(</span>x<span class='color-symbol'>,</span>y<span class='color-symbol'>)</span>`)
@@ -281,6 +286,7 @@ const level = {
if (!level.disableExit) { if (!level.disableExit) {
level.levelsCleared++; level.levelsCleared++;
level.onLevel++; //cycles map to next level level.onLevel++; //cycles map to next level
level.updateDifficulty()
if (simulation.isTraining) { if (simulation.isTraining) {
if (level.onLevel > level.levels.length - 1) { //if all training levels are completed if (level.onLevel > level.levels.length - 1) { //if all training levels are completed
@@ -301,14 +307,12 @@ const level = {
simulation.splashReturn(); simulation.splashReturn();
}, 6000); }, 6000);
return return
} else {
level.setDifficulty()
} }
} else { } else {
if (level.onLevel > level.levels.length - 1) level.onLevel = 0; if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
level.difficultyIncrease(simulation.difficultyMode)
} }
//reset lost tech display //reset lost tech display
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isLost) tech.tech[i].isLost = false; if (tech.tech[i].isLost) tech.tech[i].isLost = false;
@@ -573,9 +577,9 @@ const level = {
player.velocity.y < 0.15 player.velocity.y < 0.15
) { ) {
// level.exitCount += input.down ? 8 : 2 // level.exitCount += input.down ? 8 : 2
level.exitCount += 2 level.exitCount += 3
} else if (level.exitCount > 0) { } else if (level.exitCount > 0) {
level.exitCount -= 2 level.exitCount -= 3
} }
ctx.beginPath(); ctx.beginPath();
@@ -2181,7 +2185,6 @@ const level = {
document.body.style.backgroundColor = "#fff"; document.body.style.backgroundColor = "#fff";
// color.map = "#444" //custom map color // color.map = "#444" //custom map color
// level.difficultyIncrease(14); //hard mode level 7
level.defaultZoom = 1500 level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
@@ -2268,7 +2271,6 @@ const level = {
//??? //???
// level.difficultyIncrease(3 * 4) //30 is near max on hard //60 is near max on why
// m.addHealth(Infinity) // m.addHealth(Infinity)
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
@@ -2424,51 +2426,60 @@ const level = {
spawn.mapRect(-500, -25, 25, 50); //edge shelf spawn.mapRect(-500, -25, 25, 50); //edge shelf
spawn.mapRect(475, -25, 25, 50); //edge shelf spawn.mapRect(475, -25, 25, 50); //edge shelf
}, },
initialPowerUps() {
//wait to spawn power ups until unpaused
//power ups don't spawn in experiment mode, so they don't get removed at the start of experiment mode
const goal = simulation.cycle + 10
function cycle() {
if (simulation.cycle > goal) {
if (localSettings.loreCount === 6) {
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2170, "field", false);
} else {
powerUps.spawnStartingPowerUps(2095 + 20 * (Math.random() - 0.5), -2200);
}
if (simulation.difficultyMode === 1) {
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2600, "ammo", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2550, "ammo", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2400, "heal", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2350, "heal", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2350, "heal", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2100, "research", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2060, "research", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2120, "research", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2075, "research", false);
} else if (simulation.difficultyMode === 6) {
} else {
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2300, "heal", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2100, "heal", false);
powerUps.spawn(2095 + 20 * (Math.random() - 0.5), -2060, "research", false);
}
// if (level.levelsCleared === 0) powerUps.directSpawn(-50, -70, "difficulty", false);
} else {
requestAnimationFrame(cycle);
}
}
requestAnimationFrame(cycle);
},
initial() { initial() {
if (level.levelsCleared === 0) { //if this is the 1st level of the game 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 if (simulation.difficultyMode > 2) spawn.setSpawnList() // hard and why difficulty don't begin with starter mobs
level.initialPowerUps()
if (level.levelsCleared === 0) powerUps.directSpawn(-60, -950, "difficulty", false);
//wait to spawn power ups until unpaused if (!simulation.isCheating && !m.isShipMode && !build.isExperimentRun) {
//power ups don't spawn in experiment mode, so they don't get removed at the start of experiment mode spawn.wireFoot();
const goal = simulation.cycle + 10 spawn.wireFootLeft();
spawn.wireKnee();
function cycle() { spawn.wireKneeLeft();
if (simulation.cycle > goal) { spawn.wireHead();
if (localSettings.loreCount === 6) { } else {
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2170, "field", false); simulation.isCheating = true;
} else {
powerUps.spawnStartingPowerUps(2095 + 15 * (Math.random() - 0.5), -2070 - 125);
}
if (simulation.difficultyMode < 5) { //hard, normal and easy
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 25, "heal", false);
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070, "research", false);
}
if (simulation.difficultyMode < 3) { //normal and easy
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 75, "heal", false);
}
if (simulation.difficultyMode < 2) { //easy
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070 - 75, "heal", false);
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070, "research", false);
powerUps.spawn(2095 + 15 * (Math.random() - 0.5), -2070, "research", false);
}
} else {
requestAnimationFrame(cycle);
}
} }
requestAnimationFrame(cycle);
if (localSettings.levelsClearedLastGame < 3) { if (localSettings.levelsClearedLastGame < 3) {
if (!simulation.isCheating && !m.isShipMode && !build.isExperimentRun) {
spawn.wireFoot();
spawn.wireFootLeft();
spawn.wireKnee();
spawn.wireKneeLeft();
spawn.wireHead();
// for (let i = 0; i < 3; i++) powerUps.spawn(2095, -1220 - 50 * i, "tech", false); //unavailable tech spawns
// spawn.mapRect(2000, -1025, 200, 25);
}
} else if (!build.isExperimentRun) { } else if (!build.isExperimentRun) {
simulation.trails() simulation.trails(70)
//bonus power ups for clearing runs in the last game //bonus power ups for clearing runs in the last game
if (!simulation.isCheating && localSettings.levelsClearedLastGame > 1) { if (!simulation.isCheating && localSettings.levelsClearedLastGame > 1) {
for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) powerUps.spawn(2095 + 2 * Math.random(), -1270 - 50 * i, "tech", false); //spawn a tech for levels cleared in last game for (let i = 0; i < localSettings.levelsClearedLastGame / 3; i++) powerUps.spawn(2095 + 2 * Math.random(), -1270 - 50 * i, "tech", false); //spawn a tech for levels cleared in last game
@@ -2848,7 +2859,6 @@ const level = {
}, },
subway() { subway() {
// 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
// level.difficultyIncrease(10 * 4);
// m.maxHealth = m.health = 100 // m.maxHealth = m.health = 100
// color.map = "#333" //custom map color // color.map = "#333" //custom map color
document.body.style.backgroundColor = "#e3e3e3"//"#e3e3e3"//color.map//"#333"//"#000" document.body.style.backgroundColor = "#e3e3e3"//"#e3e3e3"//color.map//"#333"//"#000"
@@ -4226,7 +4236,6 @@ const level = {
}, },
towers() { towers() {
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
level.announceMobTypes() level.announceMobTypes()
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
@@ -4481,7 +4490,6 @@ const level = {
factory() { factory() {
level.announceMobTypes() level.announceMobTypes()
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
level.setPosToSpawn(2235, -1375); //normal spawn level.setPosToSpawn(2235, -1375); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
@@ -7141,7 +7149,6 @@ const level = {
ctx.fill() ctx.fill()
}; };
// simulation.difficulty = 4; //for testing to simulate possible mobs spawns
level.defaultZoom = 2100 level.defaultZoom = 2100
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
@@ -11330,9 +11337,7 @@ const level = {
anotherBoss = (x, y) => { anotherBoss = (x, y) => {
if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) { if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
tech.isScaleMobsWithDuplication = true
spawn.randomLevelBoss(x, y, ["historyBoss"]); spawn.randomLevelBoss(x, y, ["historyBoss"]);
tech.isScaleMobsWithDuplication = false
} else if (tech.isResearchBoss) { } else if (tech.isResearchBoss) {
if (powerUps.research.count > 2) { if (powerUps.research.count > 2) {
powerUps.research.changeRerolls(-3) powerUps.research.changeRerolls(-3)
@@ -12014,7 +12019,6 @@ const level = {
simulation.fallHeight = -15000; simulation.fallHeight = -15000;
powerUps.addResearchToLevel(); powerUps.addResearchToLevel();
powerUps.spawn(3000, -230, "heal"); powerUps.spawn(3000, -230, "heal");
// level.difficultyIncrease(60)
}, },
temple() { temple() {
simulation.makeTextLog(`<strong>temple</strong> by <span class='color-var'>Scar1337</span>`); simulation.makeTextLog(`<strong>temple</strong> by <span class='color-var'>Scar1337</span>`);
@@ -12139,7 +12143,7 @@ const level = {
if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo"); if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo");
if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5)); if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5));
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); me.damageReduction = 0.25
me.do = function () { me.do = function () {
// keep it slow, to stop issues from explosion knock backs // keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) { if (this.speed > 1) {
@@ -12242,7 +12246,7 @@ const level = {
if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo"); if (Math.random() > 0.5) powerUps.spawn(this.position.x, this.position.y, "ammo");
if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5)); if (Math.random() > 0.3) powerUps.spawn(this.position.x, this.position.y, "heal", true, null, 30 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals) * Math.sqrt(0.1 + Math.random() * 0.5));
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); me.damageReduction = 0.25
me.do = function () { me.do = function () {
// keep it slow, to stop issues from explosion knock backs // keep it slow, to stop issues from explosion knock backs
if (this.speed > 2) { if (this.speed > 2) {
@@ -12276,7 +12280,6 @@ const level = {
} }
} }
}; };
function secondRoomObstacle(x, y, isDark = false, size = 70) { function secondRoomObstacle(x, y, isDark = false, size = 70) {
mobs.spawn(x, y, isDark ? 3 : 4, size, isDark ? "#0004" : "#fff4"); mobs.spawn(x, y, isDark ? 3 : 4, size, isDark ? "#0004" : "#fff4");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -12288,7 +12291,7 @@ const level = {
me.leaveBody = false; me.leaveBody = false;
me.timeLeft = 1200; me.timeLeft = 1200;
me.isObstacle = true; me.isObstacle = true;
me.damageReduction = isDark ? 0.5 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) : 0; me.damageReduction = isDark ? 0.5 : 0
if (!isDark) { if (!isDark) {
me.isBadTarget = true; me.isBadTarget = true;
me.attackCycle = 0; me.attackCycle = 0;
@@ -12416,7 +12419,7 @@ const level = {
this.damageReduction = 0; this.damageReduction = 0;
} }
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); me.damageReduction = 0.25
me.rings = [{ me.rings = [{
colour: "#65f", colour: "#65f",
radius: 300, radius: 300,
@@ -12571,7 +12574,7 @@ const level = {
if (Math.floor(cycle / spawnDelay) >= spawnCycles - 1) { if (Math.floor(cycle / spawnDelay) >= spawnCycles - 1) {
this.trapCycle = 0; this.trapCycle = 0;
this.isInvulnerable = false; this.isInvulnerable = false;
this.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); this.damageReduction = 0.25
} }
} }
} }
@@ -14273,9 +14276,7 @@ const level = {
const anotherBoss = (x, y) => { const anotherBoss = (x, y) => {
if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) { if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
tech.isScaleMobsWithDuplication = true
spawn.historyBoss(x, y) spawn.historyBoss(x, y)
tech.isScaleMobsWithDuplication = false
} else if (tech.isResearchBoss) { } else if (tech.isResearchBoss) {
if (powerUps.research.count > 2) { if (powerUps.research.count > 2) {
powerUps.research.changeRerolls(-3) powerUps.research.changeRerolls(-3)
@@ -14657,7 +14658,7 @@ const level = {
me.deadOrbs = [] me.deadOrbs = []
me.energy = 1 me.energy = 1
// this boss has no orbitals, because it's not meant to ever attack on its own // this boss has no orbitals, because it's not meant to ever attack on its own
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
// has a shield and sustains that shield // has a shield and sustains that shield
spawn.shield(me, x, y, Infinity) spawn.shield(me, x, y, Infinity)
me.fireFreq = 30 me.fireFreq = 30
@@ -15020,7 +15021,7 @@ const level = {
me.onDeath = function () { me.onDeath = function () {
totalCoin++; totalCoin++;
}; };
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.35
me.do = function () { me.do = function () {
ctx.save() ctx.save()
ctx.translate(this.position.x, this.position.y) ctx.translate(this.position.x, this.position.y)
@@ -27367,14 +27368,13 @@ const level = {
spawn.mapRect(-100, 0, 1000, 100); spawn.mapRect(-100, 0, 1000, 100);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
}, },
ace() { //join us at discord.gg/Q8gY4WeUcm ace() {
simulation.makeTextLog(`<strong>ace</strong> by <span class='color-var'>Richard0820</span>`); simulation.makeTextLog(`<strong>ace</strong> by <span class='color-var'>Richard0820</span>`);
let isDestroyed = false; let isDestroyed = false;
const ace = { const ace = {
spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) { spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) {
if (Math.random() < chance) { if (Math.random() < chance) {
// simulation.difficulty = 50 const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty))) // simulation.difficulty = 40 on hard mode level 10
const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1) const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random() const offSet = 6.28 * Math.random()
for (let i = 0; i < len; i++) ace.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed) for (let i = 0; i < len; i++) ace.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed)
@@ -27431,7 +27431,7 @@ const level = {
me.stroke = "rgb(0,0,0)"; me.stroke = "rgb(0,0,0)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05
me.isUnblockable = true me.isUnblockable = true
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
@@ -27486,7 +27486,7 @@ const level = {
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.frictionAir = 0; me.frictionAir = 0;
me.shield = true; me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
@@ -27911,7 +27911,7 @@ const level = {
me.isBoss = true; me.isBoss = true;
me.isSlashBoss = true; me.isSlashBoss = true;
me.showHealthBar = false; me.showHealthBar = false;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.frictionAir = 0.02 me.frictionAir = 0.02
@@ -28646,8 +28646,7 @@ const level = {
const ace = { const ace = {
spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) { spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) {
if (Math.random() < chance) { if (Math.random() < chance) {
// simulation.difficulty = 50 const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty))) // simulation.difficulty = 40 on hard mode level 10
const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1) const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random() const offSet = 6.28 * Math.random()
for (let i = 0; i < len; i++) ace.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed) for (let i = 0; i < len; i++) ace.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed)
@@ -28704,7 +28703,7 @@ const level = {
me.stroke = "rgb(0,0,0)"; me.stroke = "rgb(0,0,0)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05
me.isUnblockable = true me.isUnblockable = true
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
@@ -28759,7 +28758,7 @@ const level = {
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.frictionAir = 0; me.frictionAir = 0;
me.shield = true; me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
@@ -29184,7 +29183,7 @@ const level = {
me.isBoss = true; me.isBoss = true;
me.isSlashBoss = true; me.isSlashBoss = true;
me.showHealthBar = false; me.showHealthBar = false;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.frictionAir = 0.02 me.frictionAir = 0.02
@@ -31211,7 +31210,7 @@ const level = {
*/ */
var boss = mob[mob.length - 1]; var boss = mob[mob.length - 1];
boss.isBoss = true; boss.isBoss = true;
boss.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) boss.damageReduction = 0.2
boss.onDeath = function () { boss.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y); powerUps.spawnBossPowerUp(this.position.x, this.position.y);
level.exit.x = 2560; level.exit.x = 2560;
@@ -31553,6 +31552,7 @@ const level = {
m.energy += 0.04; m.energy += 0.04;
} else { } else {
m.health += 0.001 * (dmg - mob[i].health); m.health += 0.001 * (dmg - mob[i].health);
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth(); m.displayHealth();
} }
} else { } else {
@@ -32317,7 +32317,7 @@ const level = {
// me.torque -= me.inertia * 0.002 // me.torque -= me.inertia * 0.002
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.isBoss = true; me.isBoss = true;
// spawn.shield(me, x, y, 1); //not working, not sure why // spawn.shield(me, x, y, 1); //not working, not sure why
me.onDeath = function () { me.onDeath = function () {
@@ -33223,7 +33223,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
}, },
nailGun() { nailGun() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33318,7 +33317,6 @@ const level = {
spawn.mapRect(1600, -600, 425, 250); spawn.mapRect(1600, -600, 425, 250);
}, },
shotGun() { shotGun() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33400,7 +33398,6 @@ const level = {
spawn.mapRect(1600, -600, 425, 250); spawn.mapRect(1600, -600, 425, 250);
}, },
superBall() { superBall() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33484,7 +33481,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
}, },
matterWave() { //fire wave through the map to kill mosb matterWave() { //fire wave through the map to kill mosb
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33571,7 +33567,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
}, },
missile() { //fire a missile to kill mobs and trigger button missile() { //fire a missile to kill mobs and trigger button
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33660,7 +33655,6 @@ const level = {
spawn.mapRect(2025, -2800, 1075, 2450); spawn.mapRect(2025, -2800, 1075, 2450);
}, },
stack() { //stack blocks to get to exit stack() { //stack blocks to get to exit
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33712,7 +33706,6 @@ const level = {
spawn.mapVertex(1300, 0, "400 0 -500 0 -300 -125 400 -125"); //base spawn.mapVertex(1300, 0, "400 0 -500 0 -300 -125 400 -125"); //base
}, },
mine() { //kill mobs and tack their bodies mine() { //kill mobs and tack their bodies
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(300, -50); //normal spawn level.setPosToSpawn(300, -50); //normal spawn
spawn.mapRect(250, -10, 100, 20); //small platform for player spawn.mapRect(250, -10, 100, 20); //small platform for player
level.exit.x = 1775; level.exit.x = 1775;
@@ -33796,7 +33789,6 @@ const level = {
spawn.mapVertex(1300, 0, "400 0 -600 0 -300 -125 400 -125"); //base spawn.mapVertex(1300, 0, "400 0 -600 0 -300 -125 400 -125"); //base
}, },
grenades() { //jump at the top of the elevator's path to go extra high grenades() { //jump at the top of the elevator's path to go extra high
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(0, -50); //normal spawn level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(-50, -10, 100, 20); //small platform for player spawn.mapRect(-50, -10, 100, 20); //small platform for player
level.exit.x = 1900; level.exit.x = 1900;
@@ -33916,7 +33908,6 @@ const level = {
spawn.nodeGroup(1200, -1500, "grenadier", 7); spawn.nodeGroup(1200, -1500, "grenadier", 7);
}, },
harpoon() { //jump at the top of the elevator's path to go extra high harpoon() { //jump at the top of the elevator's path to go extra high
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(0, -50); //normal spawn level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(-50, -10, 100, 20); //small platform for player spawn.mapRect(-50, -10, 100, 20); //small platform for player
level.exit.x = 1900; level.exit.x = 1900;

View File

@@ -358,7 +358,7 @@ const lore = {
setInterval(() => { setInterval(() => {
if (Math.random() < 0.5) { if (Math.random() < 0.5) {
spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5)); spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5));
level.difficultyIncrease(simulation.difficultyMode) // level.difficultyIncrease(simulation.difficultyMode)
} else { } else {
spawn.randomLevelBoss(500 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5)) spawn.randomLevelBoss(500 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5))
} }
@@ -693,9 +693,9 @@ const lore = {
setInterval(() => { setInterval(() => {
spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5)); spawn[spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]](1000 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5));
}, 500); //every 1/2 seconds }, 500); //every 1/2 seconds
setInterval(() => { // setInterval(() => {
level.difficultyIncrease(simulation.difficultyMode) // level.difficultyIncrease(simulation.difficultyMode)
}, 5000); //every 5 seconds // }, 5000); //every 5 seconds
}, },
() => { () => {
lore.talkingColor = "#dff"; lore.talkingColor = "#dff";

View File

@@ -418,7 +418,7 @@ const m = {
m.drop(); m.drop();
if (simulation.paused) build.pauseGrid() //update the build when paused if (simulation.paused) build.pauseGrid() //update the build when paused
}, },
dmgScale: null, //scales all damage, but not raw .dmg //set in levels.setDifficulty dmgScale: null, //scales all damage, but not raw .dmg
death() { death() {
if (tech.isImmortal) { //if player has the immortality buff, spawn on the same level with randomized damage if (tech.isImmortal) { //if player has the immortality buff, spawn on the same level with randomized damage
//remove immortality tech //remove immortality tech
@@ -482,7 +482,7 @@ const m = {
Engine.clear(engine); Engine.clear(engine);
simulation.splashReturn(); simulation.splashReturn();
//if you die after clearing fewer than 4 levels the difficulty settings automatically opens //if you die after clearing fewer than 4 levels the difficulty settings automatically opens
if ((level.levelsCleared < 4 || level.levelsCleared > 12) && !simulation.isTraining && !simulation.isCheating) document.getElementById("settings-details").open = true; if ((level.levelsCleared < 4 || level.levelsCleared > 12) && !simulation.isTraining && !simulation.isCheating) document.getElementById("constraint-details").open = true;
}, 5000); }, 5000);
} }
}, },
@@ -567,7 +567,7 @@ const m = {
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.3 if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.3
if (tech.squirrelFx !== 1) dmg *= 0.8//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4) if (tech.squirrelFx !== 1) dmg *= 0.8//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4)
if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1 if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1
if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min((tech.speedAdded + player.speed) * 0.0193, 0.8) //capped at speed of 55 if (tech.isSpeedHarm && (tech.speedAdded + player.speed) > 0.1) dmg *= 1 - Math.min((tech.speedAdded + player.speed) * 0.0193, 0.8) //capped at speed of 55
if (tech.isHarmReduce && input.field) dmg *= 0.1 if (tech.isHarmReduce && input.field) dmg *= 0.1
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05 if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
if (tech.isBotArmor) dmg *= 0.95 ** b.totalBots() if (tech.isBotArmor) dmg *= 0.95 ** b.totalBots()
@@ -716,7 +716,6 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
} }
setTimeout(function () { setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function () { //set wipe to normal simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
} }
@@ -745,7 +744,6 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.fillRect(0, 0, canvas.width, canvas.height);
} }
setTimeout(function () { setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function () { //set wipe to normal simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
} }
@@ -2178,7 +2176,7 @@ const m = {
} }
}, },
setMaxEnergy(isMessage = true) { setMaxEnergy(isMessage = true) {
m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 3 * tech.isGroundState + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`) if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`)
}, },
fieldMeterColor: "#0cf", fieldMeterColor: "#0cf",
@@ -2253,10 +2251,7 @@ const m = {
//calculate a vector from body to player and make it length 1 //calculate a vector from body to player and make it length 1
const diff = Vector.normalise(Vector.sub(who.position, m.pos)); const diff = Vector.normalise(Vector.sub(who.position, m.pos));
//make a vector for the player's direction of length 1 //make a vector for the player's direction of length 1
const dir = { const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) };
x: Math.cos(m.angle),
y: Math.sin(m.angle)
};
//the dot product of diff and dir will return how much over lap between the vectors //the dot product of diff and dir will return how much over lap between the vectors
if (Vector.dot(dir, diff) > m.fieldThreshold) { if (Vector.dot(dir, diff) > m.fieldThreshold) {
return true; return true;
@@ -2867,7 +2862,7 @@ const m = {
case 4: //assembler case 4: //assembler
return `<strong>+${(0.8 * couple).toFixed(1)}</strong> <strong class='color-f'>energy</strong> per second` return `<strong>+${(0.8 * couple).toFixed(1)}</strong> <strong class='color-f'>energy</strong> per second`
case 5: //plasma case 5: //plasma
return `<strong>${(1 + 1.5 * couple).toFixed(3)}x</strong> <strong class='color-d'>damage</strong>` return `<strong>${(1 + 0.015 * couple).toFixed(3)}x</strong> <strong class='color-d'>damage</strong>`
case 6: //time dilation case 6: //time dilation
return `<strong>+${(1 + 0.05 * couple).toFixed(2)}x</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and return `<strong>+${(1 + 0.05 * couple).toFixed(2)}x</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and
case 7: //cloaking case 7: //cloaking
@@ -4415,7 +4410,7 @@ const m = {
//<br><strong class='color-block'>blocks</strong> can't <strong>collide</strong> with <strong>intangible</strong> mobs //<br><strong class='color-block'>blocks</strong> can't <strong>collide</strong> with <strong>intangible</strong> mobs
//field <strong>radius</strong> decreases out of <strong>line of sight</strong> //field <strong>radius</strong> decreases out of <strong>line of sight</strong>
//<strong>unlock</strong> <strong class='color-m'>tech</strong> from other <strong class='color-f'>fields</strong> //<strong>unlock</strong> <strong class='color-m'>tech</strong> from other <strong class='color-f'>fields</strong>
description: "use <strong class='color-f'>energy</strong> to guide <strong class='color-block'>blocks</strong><br><strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>+2</strong> <strong>choices</strong><br><strong>10</strong> <strong class='color-f'>energy</strong> per second", description: "use <strong class='color-f'>energy</strong> to guide <strong class='color-block'>blocks</strong><br><strong class='color-m'>tech</strong>, <strong class='color-f'>fields</strong>, and <strong class='color-g'>guns</strong> have <strong>+3</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong><br><strong>10</strong> <strong class='color-f'>energy</strong> per second",
effect: () => { effect: () => {
m.fieldMeterColor = "#333" m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor

View File

@@ -189,7 +189,6 @@ const powerUps = {
} else { } else {
powerUps.do = () => powerUps.draw(); powerUps.do = () => powerUps.draw();
} }
tech.maxDuplicationEvent() //check to see if hitting 100% duplication
} else { } else {
powerUps.draw = powerUps.drawCircle powerUps.draw = powerUps.drawCircle
if (tech.isHealAttract) { if (tech.isHealAttract) {
@@ -325,7 +324,6 @@ const powerUps = {
if (tech.isCancelDuplication) { if (tech.isCancelDuplication) {
const value = 0.05 const value = 0.05
tech.duplication += value tech.duplication += value
tech.maxDuplicationEvent()
simulation.makeTextLog(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${value}`) simulation.makeTextLog(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${value}`)
simulation.circleFlare(value); simulation.circleFlare(value);
} }
@@ -386,6 +384,129 @@ const powerUps = {
}) })
}, },
difficulty: {
name: "difficulty",
color: "#000",
size() {
return 80 / Math.pow(localSettings.difficultyMode, 1.5);
},
effect() {
const initialDifficultyMode = simulation.difficultyMode
requestAnimationFrame(() => { //add a background behind the power up menu
ctx.fillStyle = `rgba(150,150,150,0.9)`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
});
powerUps.animatePowerUpGrab('rgba(0, 0, 0,0.6)')
if (!simulation.paused) {
simulation.paused = true;
simulation.isChoosing = true; //stops p from un pausing on key down
document.body.style.cursor = "auto";
document.getElementById("choose-grid").style.pointerEvents = "auto";
document.getElementById("choose-grid").style.transitionDuration = "0s";
}
//build level info
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
document.getElementById("choose-grid").style.gridTemplateColumns = "405px" //adjust this to increase the width of the whole menu, but mostly the center column
let text = `<div>
<div class="grid-container">
<div class="left-column">
<input type="range" id="difficulty-slider" name="temp" type="range" step="1" value="1" min="1" max="6" list="values" />
<datalist id="values">
<option value="1"></option>
<option value="2"></option>
<option value="3"></option>
<option value="4"></option>
<option value="5"></option>
<option value="6"></option>
</datalist>
</div>
<div class="right-column">
<div class="row" id="constraint-1"><strong>0.82x</strong> <strong class='color-d'>damage</strong> done per level
<br><strong>1.25x</strong> <strong class='color-defense'>damage taken</strong> per level</div>
<div class="row" id="constraint-2"><strong>-5</strong> initial <strong>power ups</strong>
<br><strong>faster</strong> and <strong>more</strong> mobs per level</div>
<div class="row" id="constraint-3"><strong>0.82x</strong> <strong class='color-d'>damage</strong> done per level
<br><strong>1.25x</strong> <strong class='color-defense'>damage taken</strong> per level</div>
<div class="row" id="constraint-4"><strong>+1</strong> boss per level, <strong>-1</strong> <strong class='color-m'>tech</strong> per boss
<br><strong>-1</strong> ${powerUps.orb.research()} per level</div>
<div class="row" id="constraint-5"><strong>0.82x</strong> <strong class='color-d'>damage</strong> done per level
<br><strong>1.25x</strong> <strong class='color-defense'>damage taken</strong> per level</div>
<div class="row" id="constraint-6"><strong>3x</strong> chance for <strong>shielded</strong> mobs
<br><strong>-3</strong> initial power ups</div>
</div>
<div class="far-right-column">
<div id = "constraint-1-record">${localSettings.difficultyCompleted[1] ? "⚆" : " "}</div>
<div id = "constraint-2-record">${localSettings.difficultyCompleted[2] ? "⚆" : " "}</div>
<div id = "constraint-3-record">${localSettings.difficultyCompleted[3] ? "⚆" : " "}</div>
<div id = "constraint-4-record">${localSettings.difficultyCompleted[4] ? "⚆" : " "}</div>
<div id = "constraint-5-record">${localSettings.difficultyCompleted[5] ? "⚇" : " "}</div>
<div id = "constraint-6-record">${localSettings.difficultyCompleted[6] ? "⚇" : " "}</div>
</div>
</div>
<div class="choose-grid-module" id="choose-difficulty">
confirm difficulty parameters
</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.3s"; //how long is the fade in on
document.getElementById("choose-grid").style.visibility = "visible"
document.getElementById("choose-difficulty").addEventListener("click", () => {
level.unPause()
document.body.style.cursor = "none";
//reset hide image style
if (localSettings.isHideImages) {
document.getElementById("choose-grid").classList.add('choose-grid-no-images');
document.getElementById("choose-grid").classList.remove('choose-grid');
} else {
document.getElementById("choose-grid").classList.add('choose-grid');
document.getElementById("choose-grid").classList.remove('choose-grid-no-images');
}
if (level.levelsCleared === 0 && initialDifficultyMode !== simulation.difficultyMode) {
//remove and respawn all power ups if difficulty mode was changed
for (let i = 0; i < powerUp.length; ++i) Matter.Composite.remove(engine.world, powerUp[i]);
powerUp = [];
level.initialPowerUps()
simulation.trails(30)
}
});
let setConstraintText = function (isReset = true) {
for (let i = 1; i < 7; i++) {
const id = document.getElementById("constraint-" + i)
if (simulation.difficultyMode < i) {
id.style.opacity = "0.15"
} else {
id.style.opacity = "1"
}
}
if (isReset) {
lore.setTechGoal()
localSettings.difficultyMode = simulation.difficultyMode
localSettings.levelsClearedLastGame = 0 //after changing difficulty, reset run history
localSettings.entanglement = undefined //after changing difficulty, reset stored tech
if (localSettings.isAllowed) localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
}
setConstraintText(false)
document.getElementById("difficulty-slider").value = simulation.difficultyMode
document.getElementById("difficulty-slider").addEventListener("input", () => {
simulation.difficultyMode = document.getElementById("difficulty-slider").value
setConstraintText()
});
for (let i = 1; i < 7; i++) {
document.getElementById("constraint-" + i).addEventListener("click", () => {
simulation.difficultyMode = i
document.getElementById("difficulty-slider").value = simulation.difficultyMode
setConstraintText()
});
}
},
},
coupling: { coupling: {
name: "coupling", name: "coupling",
color: "#0ae", //"#0cf", color: "#0ae", //"#0cf",
@@ -541,6 +662,7 @@ const powerUps = {
overHeal *= 2 //double the over heal converted to max health overHeal *= 2 //double the over heal converted to max health
//make sure overHeal doesn't kill player //make sure overHeal doesn't kill player
if (m.health - overHeal * m.defense() < 0) overHeal = m.health - 0.01 if (m.health - overHeal * m.defense() < 0) overHeal = m.health - 0.01
if (overHeal > m.maxHealth) overHeal = m.maxHealth //just in case overHeal gets too big
tech.extraMaxHealth += overHeal //increase max health tech.extraMaxHealth += overHeal //increase max health
m.setMaxHealth(); m.setMaxHealth();
m.damage(overHeal); m.damage(overHeal);
@@ -944,7 +1066,7 @@ const powerUps = {
} }
// console.log(options.length) // console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) { if (options.length > 0 || !tech.isSuperDeterminism) {
let totalChoices = 2 + tech.extraChoices + 2 * (m.fieldMode === 8) let totalChoices = 2 + tech.extraChoices + 3 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) { if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3 totalChoices *= 3
tech.cancelTechCount++ tech.cancelTechCount++
@@ -1011,8 +1133,7 @@ const powerUps = {
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
if (i !== m.fieldMode) options.push(i); if (i !== m.fieldMode) options.push(i);
} }
// let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8))) let totalChoices = 2 + tech.extraChoices + 3 * (m.fieldMode === 8)
let totalChoices = 2 + tech.extraChoices + 2 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) { if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3 totalChoices *= 3
tech.cancelTechCount++ tech.cancelTechCount++
@@ -1092,8 +1213,7 @@ const powerUps = {
} }
} }
//set total choices //set total choices
// let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8)) let totalChoices = 3 + tech.extraChoices + 3 * (m.fieldMode === 8)
let totalChoices = 3 + tech.extraChoices + 2 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) { if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3 totalChoices *= 3
tech.cancelTechCount++ tech.cancelTechCount++
@@ -1327,6 +1447,7 @@ const powerUps = {
}, },
spawnDelay(type, count, delay = 2) { spawnDelay(type, count, delay = 2) {
count *= delay count *= delay
// let totalSpawned = 0
let cycle = () => { let cycle = () => {
if (count > 0) { if (count > 0) {
if (m.alive) requestAnimationFrame(cycle); if (m.alive) requestAnimationFrame(cycle);
@@ -1335,6 +1456,8 @@ const powerUps = {
if (!(count % delay)) { if (!(count % delay)) {
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) } const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
powerUps.spawn(where.x, where.y, type); powerUps.spawn(where.x, where.y, type);
// totalSpawned++
// if (!(totalSpawned % 10)) delay++
} }
} }
} }
@@ -1400,11 +1523,10 @@ const powerUps = {
powerUps.randomPowerUpCounter++; powerUps.randomPowerUpCounter++;
powerUpChance(Math.max(level.levelsCleared, 10) * 0.1) powerUpChance(Math.max(level.levelsCleared, 10) * 0.1)
} }
if (!(simulation.difficulty > spawn.secondaryBossThreshold)) { if (!(simulation.difficultyMode > 2 && level.levelsCleared > 1)) {
powerUps.randomPowerUpCounter += 0.6; powerUps.randomPowerUpCounter += 0.6;
powerUpChance(Math.max(level.levelsCleared, 6) * 0.1) powerUpChance(Math.max(level.levelsCleared, 6) * 0.1)
} }
function powerUpChance(chanceToFail) { function powerUpChance(chanceToFail) {
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) { if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0; powerUps.randomPowerUpCounter = 0;
@@ -1446,8 +1568,8 @@ const powerUps = {
powerUps.spawn(x, y, "ammo", false); powerUps.spawn(x, y, "ammo", false);
} }
}, },
addResearchToLevel() { //add a random power up to a location that has a mob, mostly used to give each level one randomly placed research addResearchToLevel() { //add a random power up to a location that has a mob, mostly used to give each level a research
if (mob.length && Math.random() < 0.45 - 0.3 * (simulation.difficultyMode > 4)) { //lower chance on why difficulty if (simulation.difficultyMode < 4 && mob.length) { //don't spawn on higher difficulty settings
const index = Math.floor(Math.random() * mob.length) const index = Math.floor(Math.random() * mob.length)
powerUps.spawn(mob[index].position.x, mob[index].position.y, "research"); powerUps.spawn(mob[index].position.x, mob[index].position.y, "research");
} }
@@ -1535,7 +1657,7 @@ const powerUps = {
tech.tech[index].frequency = 0 //banish tech tech.tech[index].frequency = 0 //banish tech
powerUps.ejectTech(index) powerUps.ejectTech(index)
if (m.immuneCycle < m.cycle) m.damage(tech.pauseEjectTech * 0.01) if (m.immuneCycle < m.cycle) m.damage(tech.pauseEjectTech * 0.01)
tech.pauseEjectTech *= 1.2 tech.pauseEjectTech *= 1.3
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through" document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
document.getElementById(`${index}-pause-tech`).style.animation = "" document.getElementById(`${index}-pause-tech`).style.animation = ""
document.getElementById(`${index}-pause-tech`).onclick = null document.getElementById(`${index}-pause-tech`).onclick = null
@@ -1614,7 +1736,7 @@ const powerUps = {
properties.isDuplicated = true properties.isDuplicated = true
} else { } else {
properties.inertia = Infinity //prevents rotation for circles only properties.inertia = Infinity //prevents rotation for circles only
polygonSides = 0 polygonSides = 12
} }
powerUp[index] = Matter.Bodies.polygon(x, y, polygonSides, size, properties); powerUp[index] = Matter.Bodies.polygon(x, y, polygonSides, size, properties);
if (mode) powerUp[index].mode = mode if (mode) powerUp[index].mode = mode

View File

@@ -192,10 +192,11 @@ const simulation = {
levelsCleared: 0, levelsCleared: 0,
difficultyMode: 2, //normal difficulty is 2 difficultyMode: 2, //normal difficulty is 2
difficulty: 0, difficulty: 0,
dmgScale: null, //set in levels.setDifficulty constraint: 0,
dmgScale: null,
healScale: 1, healScale: 1,
accelScale: null, //set in levels.setDifficulty accelScale: null,
CDScale: null, //set in levels.setDifficulty CDScale: null,
molecularMode: Math.floor(4 * Math.random()), //0 spores, 1 missile, 2 ice IX, 3 drones //randomize molecular assembler field type molecularMode: Math.floor(4 * Math.random()), //0 spores, 1 missile, 2 ice IX, 3 drones //randomize molecular assembler field type
// dropFPS(cap = 40, time = 15) { // dropFPS(cap = 40, time = 15) {
// simulation.fpsCap = cap // simulation.fpsCap = cap
@@ -625,8 +626,8 @@ const simulation = {
restoreCamera() { restoreCamera() {
ctx.restore(); ctx.restore();
}, },
trails() { trails(swapPeriod = 150) {
const swapPeriod = 150 // const swapPeriod = 150
const len = 30 const len = 30
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
setTimeout(function () { setTimeout(function () {
@@ -846,10 +847,7 @@ const simulation = {
level.onLevel = 0; level.onLevel = 0;
level.levelsCleared = 0; level.levelsCleared = 0;
//resetting difficulty level.updateDifficulty()
// simulation.difficulty = 0;
level.setDifficulty()
simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
simulation.clearNow = true; simulation.clearNow = true;
document.getElementById("text-log").style.display = "none" document.getElementById("text-log").style.display = "none"
@@ -1143,15 +1141,6 @@ const simulation = {
simulation.updateGunHUD(); simulation.updateGunHUD();
} }
// for (i = 0, len = b.guns.length; i < len; i++) { //find which gun is mine
// if (b.guns[i].name === "mine") {
// b.guns[i].ammo += count
// if (tech.ammoCap) b.guns[i].ammo = Math.min(tech.ammoCap, b.guns[i].ammo)
// simulation.updateGunHUD();
// break;
// }
// }
if (tech.isMutualism && !tech.isEnergyHealth) { if (tech.isMutualism && !tech.isEnergyHealth) {
for (let i = 0; i < bullet.length; i++) { for (let i = 0; i < bullet.length; i++) {
if (bullet[i].isMutualismActive) { if (bullet[i].isMutualismActive) {
@@ -1304,7 +1293,7 @@ const simulation = {
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isDropPowerUp && mob[i].alive) count++ if (mob[i].isDropPowerUp && mob[i].alive) count++
} }
count *= 0.25 //to fake the 25% chance, this makes it not random, and more predictable count *= 0.3 //to fake the 25% chance, this makes it not random, and more predictable
let cycle = () => { //run after waiting a cycle for the map to be cleared let cycle = () => { //run after waiting a cycle for the map to be cleared
const types = ["heal", "ammo", "heal", "ammo", "research", "coupling", "boost", "tech", "gun", "field"] const types = ["heal", "ammo", "heal", "ammo", "research", "coupling", "boost", "tech", "gun", "field"]
for (let i = 0; i < count; i++) powerUps.spawnDelay(types[Math.floor(Math.random() * types.length)], 1) for (let i = 0; i < count; i++) powerUps.spawnDelay(types[Math.floor(Math.random() * types.length)], 1)

View File

@@ -48,7 +48,8 @@ const spawn = {
// spawn.pickList.push(spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]); // spawn.pickList.push(spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]);
}, },
spawnChance(chance) { spawnChance(chance) {
return Math.random() < chance + 0.07 * simulation.difficulty && mob.length < -1 + 16 * Math.log10(simulation.difficulty + 1) const difficultyChance = simulation.difficultyMode === 1 ? 1 : simulation.difficulty
return (Math.random() < chance + 0.07 * difficultyChance) && (mob.length < -1 + 16 * Math.log10(simulation.difficulty + 1))
}, },
randomMob(x, y, chance = 1) { randomMob(x, y, chance = 1) {
if (spawn.spawnChance(chance) || chance === Infinity) { if (spawn.spawnChance(chance) || chance === Infinity) {
@@ -112,24 +113,8 @@ const spawn = {
} }
} }
}, },
secondaryBossThreshold: 22,
secondaryBossChance(x, y) { secondaryBossChance(x, y) {
// if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) { if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
// tech.isScaleMobsWithDuplication = true
// spawn.randomLevelBoss(x, y);
// tech.isScaleMobsWithDuplication = false
// return true
// } else if (tech.isResearchBoss) {
// if (powerUps.research.count > 2) {
// powerUps.research.changeRerolls(-3)
// simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 3<br>${powerUps.research.count}`)
// } else {
// tech.addJunkTechToPool(0.49)
// }
// spawn.randomLevelBoss(x, y);
// return true
// }
if (simulation.difficulty > spawn.secondaryBossThreshold) { //starts on hard mode level 6, level 12 on easy, level 4 on why?
spawn.randomLevelBoss(x, y); spawn.randomLevelBoss(x, y);
} else { } else {
return false return false
@@ -178,7 +163,7 @@ const spawn = {
// } // }
// } // }
if (tech.isMoveMACHO && m.crouch) { if (tech.isMoveMACHO && m.crouch && input.down) {
Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.97), Vector.mult(player.velocity, 0.03))) Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.97), Vector.mult(player.velocity, 0.03)))
Matter.Body.setPosition(this, Vector.add(Vector.mult(this.position, 0.95), Vector.mult(player.position, 0.05))) Matter.Body.setPosition(this, Vector.add(Vector.mult(this.position, 0.95), Vector.mult(player.position, 0.05)))
} }
@@ -934,6 +919,12 @@ const spawn = {
me.onDeath = function () { me.onDeath = function () {
if (!this.hasRunDeathScript) { if (!this.hasRunDeathScript) {
this.hasRunDeathScript = true this.hasRunDeathScript = true
//record win on this difficulty level to show up in the difficulty settings as a
if (!simulation.isCheating) {
localSettings.difficultyCompleted[simulation.difficultyMode] = true
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
}
//make a block body to replace this one //make a block body to replace this one
//this body is too big to leave behind in the normal way mobs.replace() //this body is too big to leave behind in the normal way mobs.replace()
const len = body.length; const len = body.length;
@@ -1029,8 +1020,6 @@ const spawn = {
} }
requestAnimationFrame(loop); requestAnimationFrame(loop);
} }
// for (let i = 0; i < 3; i++)
level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
//remove power Ups, to avoid spamming console //remove power Ups, to avoid spamming console
function removeAll(array) { function removeAll(array) {
for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]); for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]);
@@ -1274,7 +1263,7 @@ const spawn = {
const me = mob[mob.length - 1]; const me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.002); //normal density even though its a boss Matter.Body.setDensity(me, 0.002); //normal density even though its a boss
me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //extra reduction for a boss, because normal density me.damageReduction = 0.04
me.frictionAir = 0.01; me.frictionAir = 0.01;
me.accelMag = 0.0002; me.accelMag = 0.0002;
me.onDeath = function () { me.onDeath = function () {
@@ -1440,7 +1429,7 @@ const spawn = {
me.cellMassMax = 70 me.cellMassMax = 70
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map me.collisionFilter.mask = cat.player | cat.bullet //| cat.body | cat.map
Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001 Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001
me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal me.damageReduction = 0.17
const k = 642 //k=r^2/m const k = 642 //k=r^2/m
me.split = function () { me.split = function () {
@@ -1525,7 +1514,7 @@ const spawn = {
me.onHit = function () { //run this function on hitting player me.onHit = function () { //run this function on hitting player
this.explode(); this.explode();
}; };
me.damageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); me.damageReduction = 0.14
me.doAwake = function () { me.doAwake = function () {
this.alwaysSeePlayer(); this.alwaysSeePlayer();
this.checkStatus(); this.checkStatus();
@@ -1640,7 +1629,7 @@ const spawn = {
powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // manual power up spawn to avoid spawning too many tech with "symbiosis" powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // manual power up spawn to avoid spawning too many tech with "symbiosis"
} }
} }
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.2
//required setup for invulnerable //required setup for invulnerable
// me.isInvulnerable = false // me.isInvulnerable = false
me.invulnerabilityCountDown = 0 me.invulnerabilityCountDown = 0
@@ -1702,7 +1691,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.2
me.isInvulnerable = true me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.damageReduction = 0 me.damageReduction = 0
@@ -1780,7 +1769,7 @@ const spawn = {
me.foundPlayer(); me.foundPlayer();
} }
me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.22
me.isInvulnerable = true me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.damageReduction = 0 me.damageReduction = 0
@@ -2157,7 +2146,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)"); mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.09
me.accelMag = 0.05; //jump height me.accelMag = 0.05; //jump height
me.g = 0.003; //required if using this.gravity me.g = 0.003; //required if using this.gravity
me.frictionAir = 0.01; me.frictionAir = 0.01;
@@ -2207,7 +2196,7 @@ const spawn = {
// powerUps.spawnBossPowerUp(this.position.x, this.position.y) // powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// }; // };
// me.lastSpeed = me.speed // me.lastSpeed = me.speed
// me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.25
// me.do = function() { // me.do = function() {
// // this.armor(); // // this.armor();
// this.gravity(); // this.gravity();
@@ -2279,10 +2268,7 @@ const spawn = {
me.fill = "#28b"; me.fill = "#28b";
me.rememberFill = me.fill; me.rememberFill = me.fill;
me.cd = 0; me.cd = 0;
me.burstDir = { me.burstDir = { x: 0, y: 0 };
x: 0,
y: 0
};
me.frictionAir = 0.022; me.frictionAir = 0.022;
me.lookTorque = 0.0000014; me.lookTorque = 0.0000014;
me.restitution = 0; me.restitution = 0;
@@ -2386,6 +2372,7 @@ const spawn = {
ctx.fill(); ctx.fill();
} }
} }
if (simulation.difficultyMode === 6) spawn.shield(me, x, y);
}, },
// timeBoss(x, y, radius = 25) { // timeBoss(x, y, radius = 25) {
// mobs.spawn(x, y, 12, radius, "#000"); // mobs.spawn(x, y, 12, radius, "#000");
@@ -2403,7 +2390,7 @@ const spawn = {
// me.onDeath = function() { // me.onDeath = function() {
// powerUps.spawnBossPowerUp(this.position.x, this.position.y) // powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// }; // };
// me.damageReduction = 0.23 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.23
// me.do = function() { // me.do = function() {
// //keep it slow, to stop issues from explosion knock backs // //keep it slow, to stop issues from explosion knock backs
// if (!(simulation.cycle % this.seePlayerFreq)) { // if (!(simulation.cycle % this.seePlayerFreq)) {
@@ -2483,7 +2470,7 @@ const spawn = {
// toMe(bullet, this.position, this.eventHorizon)) // toMe(bullet, this.position, this.eventHorizon))
} }
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.do = function () { me.do = function () {
//keep it slow, to stop issues from explosion knock backs //keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) { if (this.speed > 1) {
@@ -2586,7 +2573,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.13 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25 me.damageReduction = 0.13 //normal is 1, most bosses have 0.25
targets.push(me.id) //add to shield protection targets.push(me.id) //add to shield protection
me.friction = 0; me.friction = 0;
@@ -2675,7 +2662,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.babyList = [] //list of mobs that are apart of this boss me.babyList = [] //list of mobs that are apart of this boss
Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision Matter.Body.setDensity(me, 0.0015); //extra dense //normal is 0.001 //makes effective life much larger and damage on collision
me.damageReduction = 0.13 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //normal is 1, most bosses have 0.25 me.damageReduction = 0.13 //normal is 1, most bosses have 0.25
me.isBoss = true; me.isBoss = true;
me.friction = 0; me.friction = 0;
@@ -2991,7 +2978,7 @@ const spawn = {
me.laserRange = 350; me.laserRange = 350;
me.seeAtDistance2 = 2000000; me.seeAtDistance2 = 2000000;
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReductionGoal me.damageReduction = 0.35 // me.damageReductionGoal
me.showHealthBar = false; //drawn in this.awake me.showHealthBar = false; //drawn in this.awake
me.delayLimit = 60 + Math.floor(30 * Math.random()); me.delayLimit = 60 + Math.floor(30 * Math.random());
@@ -3162,7 +3149,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, '#16576b'); mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.04
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front 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); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -3265,7 +3252,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, color); mobs.spawn(x, y, 7, radius, color);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0025); //extra dense //normal is 0.001 //makes effective life much larger 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.damageReduction = 0.04
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front 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); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -3416,7 +3403,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.07
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -3607,7 +3594,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.004); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.004); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front 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); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -3699,7 +3686,7 @@ const spawn = {
mobs.spawn(x, y, 3, radius, "rgb(0,235,255)"); mobs.spawn(x, y, 3, radius, "rgb(0,235,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front 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); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -3805,7 +3792,7 @@ const spawn = {
Matter.Body.rotate(me, Math.PI * 0.1); Matter.Body.rotate(me, Math.PI * 0.1);
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.034 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.034
me.frictionStatic = 0; me.frictionStatic = 0;
me.friction = 0; me.friction = 0;
@@ -3903,7 +3890,7 @@ const spawn = {
me.do = function () { me.do = function () {
if (player.speed > 5) this.do = this.fire //don't attack until player moves if (player.speed > 5) this.do = this.fire //don't attack until player moves
} }
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.fire = function () { me.fire = function () {
// this.armor(); // this.armor();
this.checkStatus(); this.checkStatus();
@@ -4004,6 +3991,7 @@ const spawn = {
me.pulseRadius = Math.min(400, 170 + simulation.difficulty * 3) me.pulseRadius = Math.min(400, 170 + simulation.difficulty * 3)
me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.isFiring = false me.isFiring = false
spawn.shield(me, x, y);
me.onHit = function () { }; me.onHit = function () { };
me.canSeeTarget = function () { me.canSeeTarget = function () {
const angle = this.angle + Math.PI / 2; const angle = this.angle + Math.PI / 2;
@@ -4124,7 +4112,7 @@ const spawn = {
} }
Matter.Body.rotate(me, Math.random() * Math.PI * 2); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0002 * simulation.accelScale; me.accelMag = 0.0002 * simulation.accelScale;
// me.frictionAir = 1 spawn.shield(me, x, y);
me.lasers = [] //keeps track of static laser beams me.lasers = [] //keeps track of static laser beams
me.laserLimit = simulation.difficultyMode < 3 ? 1 : 2 me.laserLimit = simulation.difficultyMode < 3 ? 1 : 2
@@ -4180,7 +4168,7 @@ const spawn = {
if (this.lasers[i].fade > 0.99) { if (this.lasers[i].fade > 0.99) {
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit
const dmg = 0.05 * simulation.dmgScale; const dmg = 0.03 * simulation.dmgScale;
m.damage(dmg); m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: best.x, x: best.x,
@@ -4270,14 +4258,12 @@ const spawn = {
} }
Matter.Body.rotate(me, Math.random() * Math.PI * 2); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale; me.accelMag = 0.0001 * simulation.accelScale;
me.isBoss = true; me.isBoss = true;
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -4286,17 +4272,13 @@ const spawn = {
if (this.health < this.nextHealthThreshold) { if (this.health < this.nextHealthThreshold) {
this.health = this.nextHealthThreshold - 0.01 this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25 this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
this.invulnerableCount = 120 this.invulnerableCount = 90
this.isInvulnerable = true this.isInvulnerable = true
this.damageReduction = 0 this.damageReduction = 0
// if (this.health > 0.74) this.laserLimit += 2 //increase total lasers once player gets into combat
// this.addLaser()
this.laserDelay = 130 this.laserDelay = 130
} }
}; };
me.lasers = [] //keeps track of static laser beams me.lasers = [] //keeps track of static laser beams
// me.laserLimit = 1 + 2 * (simulation.difficultyMode < 3 ? 1 : 2)
me.laserLimit = 2 + (simulation.difficultyMode < 3 ? 1 : 2) me.laserLimit = 2 + (simulation.difficultyMode < 3 ? 1 : 2)
me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.cycle = 0 me.cycle = 0
@@ -4349,7 +4331,7 @@ const spawn = {
if (this.lasers[i].fade > 0.99) { if (this.lasers[i].fade > 0.99) {
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit
const dmg = 0.05 * simulation.dmgScale; const dmg = 0.03 * simulation.dmgScale;
m.damage(dmg); m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: best.x, x: best.x,
@@ -4412,7 +4394,6 @@ const spawn = {
this.force.y += force.y; this.force.y += force.y;
} else { //drift } else { //drift
const force = Vector.mult(Vector.normalise(Vector.sub(this.driftGoal, this.position)), 0.00001 * this.mass) const force = Vector.mult(Vector.normalise(Vector.sub(this.driftGoal, this.position)), 0.00001 * this.mass)
// const force = Vector.mult(this.driftGoal, 0.0001 * this.mass)
this.force.x += force.x; this.force.x += force.x;
this.force.y += force.y; this.force.y += force.y;
} }
@@ -4452,6 +4433,7 @@ const spawn = {
Matter.Body.rotate(me, Math.random() * Math.PI * 2); Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale; me.accelMag = 0.0001 * simulation.accelScale;
me.laserInterval = 100 me.laserInterval = 100
spawn.shield(me, x, y);
me.onHit = function () { me.onHit = function () {
//run this function on hitting player //run this function on hitting player
this.explode(); this.explode();
@@ -4529,7 +4511,7 @@ const spawn = {
// me.torque -= me.inertia * 0.002 // me.torque -= me.inertia * 0.002
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random()) spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.isBoss = true; me.isBoss = true;
// spawn.shield(me, x, y, 1); //not working, not sure why // spawn.shield(me, x, y, 1); //not working, not sure why
me.onDeath = function () { me.onDeath = function () {
@@ -4743,7 +4725,7 @@ const spawn = {
// spawn.shield(me, x, y, 1); // spawn.shield(me, x, y, 1);
Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.005); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.12 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.12
me.isBoss = true; me.isBoss = true;
me.onDamage = function () { }; me.onDamage = function () { };
me.onDeath = function () { me.onDeath = function () {
@@ -4839,7 +4821,7 @@ const spawn = {
me.restitution = 1 me.restitution = 1
// spawn.spawnOrbitals(me, radius + 50 + 125 * Math.random(), 1) // spawn.spawnOrbitals(me, radius + 50 + 125 * Math.random(), 1)
Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.002 + 0.0001 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.09
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -4935,7 +4917,7 @@ const spawn = {
me.isBoss = true; me.isBoss = true;
me.isReactorBoss = true; me.isReactorBoss = true;
Matter.Body.setDensity(me, 0.001); //normal is 0.001 Matter.Body.setDensity(me, 0.001); //normal is 0.001
me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.04
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -5092,7 +5074,7 @@ const spawn = {
me.isBoss = true; me.isBoss = true;
me.isReactorBoss = true; me.isReactorBoss = true;
Matter.Body.setDensity(me, 0.003); //normal is 0.001 Matter.Body.setDensity(me, 0.003); //normal is 0.001
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.inertia = Infinity; me.inertia = Infinity;
me.isInvulnerable = false me.isInvulnerable = false
@@ -5185,7 +5167,7 @@ const spawn = {
// me.skipRate = 1 + Math.floor(simulation.difficulty*0.02) // me.skipRate = 1 + Math.floor(simulation.difficulty*0.02)
// spawn.shield(me, x, y, 1); // spawn.shield(me, x, y, 1);
Matter.Body.setDensity(me, 0.001); //normal is 0.001 Matter.Body.setDensity(me, 0.001); //normal is 0.001
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.onDamage = function () { me.onDamage = function () {
@@ -5292,7 +5274,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.rotate(me, 2 * Math.PI * Math.random()); Matter.Body.rotate(me, 2 * Math.PI * Math.random());
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.frictionAir = 0.02 me.frictionAir = 0.02
@@ -5740,7 +5722,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.15
me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale); me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01; me.frictionAir = 0.01;
@@ -5789,12 +5771,12 @@ const spawn = {
this.isCloaked = true; this.isCloaked = true;
this.isBadTarget = true; this.isBadTarget = true;
this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player this.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.mob //can't touch player
this.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) this.damageReduction = 0.04
} }
} }
me.deCloak = function () { me.deCloak = function () {
if (this.isCloaked) { if (this.isCloaked) {
this.damageReduction = 0.4 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) this.damageReduction = 0.4
this.isCloaked = false; this.isCloaked = false;
this.isBadTarget = false; this.isBadTarget = false;
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can touch player
@@ -5802,7 +5784,7 @@ const spawn = {
} }
me.do = function () { me.do = function () {
if (this.damageReduction === 0) { if (this.damageReduction === 0) {
this.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) this.damageReduction = 0.04
let i = this.status.length //clear bad status effects let i = this.status.length //clear bad status effects
while (i--) { while (i--) {
if (this.status[i].type === "stun" || this.status[i].type === "dot") this.status.splice(i, 1); if (this.status[i].type === "stun" || this.status[i].type === "dot") this.status.splice(i, 1);
@@ -5852,6 +5834,8 @@ const spawn = {
me.showHealthBar = false; me.showHealthBar = false;
me.memory = 240; me.memory = 240;
me.isVanished = false; me.isVanished = false;
// spawn.shield(me, x, y); //makes it too hard to stealth
me.onDamage = function () { me.onDamage = function () {
if (!this.isVanished && this.health < 0.1 && !this.isStunned && !this.isSlowed) { //if health is below 10% teleport to a random spot on player history, heal, and cloak if (!this.isVanished && this.health < 0.1 && !this.isStunned && !this.isSlowed) { //if health is below 10% teleport to a random spot on player history, heal, and cloak
this.health = 1; this.health = 1;
@@ -5931,6 +5915,7 @@ const spawn = {
me.memory = 900; me.memory = 900;
me.delay = 60 me.delay = 60
me.cd = 0; me.cd = 0;
spawn.shield(me, x, y, 1); // bad for stealth
me.onHit = function () { me.onHit = function () {
if (this.cd < simulation.cycle) { if (this.cd < simulation.cycle) {
this.cd = simulation.cycle + this.delay; this.cd = simulation.cycle + this.delay;
@@ -6063,7 +6048,7 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
spawn.shield(me, x, y, 1); spawn.shield(me, x, y, 1);
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty))) // simulation.difficulty = 40 on hard mode level 10 const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
const speed = (0.007 + 0.003 * Math.random() + 0.004 * Math.sqrt(simulation.difficulty)) const speed = (0.007 + 0.003 * Math.random() + 0.004 * Math.sqrt(simulation.difficulty))
let radiusOrbitals = radius + 125 + 350 * Math.random() let radiusOrbitals = radius + 125 + 350 * Math.random()
for (let i = 0; i < len; i++) spawn.orbital(me, radiusOrbitals, i / len * 2 * Math.PI, speed) for (let i = 0; i < len; i++) spawn.orbital(me, radiusOrbitals, i / len * 2 * Math.PI, speed)
@@ -6073,7 +6058,7 @@ const spawn = {
me.onDeath = function () { me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.2
me.do = function () { me.do = function () {
// this.armor(); // this.armor();
this.seePlayerCheckByDistance(); this.seePlayerCheckByDistance();
@@ -6106,7 +6091,7 @@ const spawn = {
me.onDeath = function () { //helps collisions functions work better after vertex have been changed me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
} }
// spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
this.checkStatus(); this.checkStatus();
@@ -6131,7 +6116,7 @@ const spawn = {
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.01 + 0.0004 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.01 + 0.0004 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.2
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
me.isVerticesChange = true me.isVerticesChange = true
@@ -6293,14 +6278,11 @@ const spawn = {
me.accelMag = 0.0005 * simulation.accelScale; me.accelMag = 0.0005 * simulation.accelScale;
me.frictionAir = 0.05; me.frictionAir = 0.05;
me.torque = 0.0001 * me.inertia; me.torque = 0.0001 * me.inertia;
me.fireDir = { me.fireDir = { x: 0, y: 0 };
x: 0,
y: 0
};
me.onDeath = function () { //helps collisions functions work better after vertex have been changed me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
} }
// spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
// this.seePlayerByLookingAt(); // this.seePlayerByLookingAt();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -6492,7 +6474,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.2
me.accelMag = 0.0001 * simulation.accelScale; me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(330 * simulation.CDScale) me.fireFreq = Math.floor(330 * simulation.CDScale)
@@ -6535,7 +6517,7 @@ const spawn = {
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
// me.isBoss = true; // me.isBoss = true;
// Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger // Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.2
// me.fireFreq = Math.floor(60 * simulation.CDScale) // me.fireFreq = Math.floor(60 * simulation.CDScale)
// me.seePlayerFreq = 15 // me.seePlayerFreq = 15
@@ -6636,7 +6618,7 @@ const spawn = {
// let me = mob[mob.length - 1]; // let me = mob[mob.length - 1];
// me.isBoss = true; // me.isBoss = true;
// Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger // Matter.Body.setDensity(me, 0.0022 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.2
// me.accelMag = 0.0001 * simulation.accelScale; // me.accelMag = 0.0001 * simulation.accelScale;
// me.fireFreq = Math.floor(180 * simulation.CDScale) // me.fireFreq = Math.floor(180 * simulation.CDScale)
@@ -6732,7 +6714,7 @@ const spawn = {
}); });
} }
}; };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.do = function () { me.do = function () {
// this.armor(); // this.armor();
if (this.grenadeLimiter > 1) this.grenadeLimiter-- if (this.grenadeLimiter > 1) this.grenadeLimiter--
@@ -6757,16 +6739,13 @@ const spawn = {
me.accelMag = 0.0006 * simulation.accelScale; me.accelMag = 0.0006 * simulation.accelScale;
me.frictionAir = 0.05; me.frictionAir = 0.05;
me.torque = 0.0001 * me.inertia * (Math.random() > 0.5 ? -1 : 1) me.torque = 0.0001 * me.inertia * (Math.random() > 0.5 ? -1 : 1)
me.fireDir = { me.fireDir = { x: 0, y: 0 };
x: 0,
y: 0
};
me.onDeath = function () { //helps collisions functions work better after vertex have been changed me.onDeath = function () { //helps collisions functions work better after vertex have been changed
spawn.grenade(this.position.x, this.position.y, 200 * simulation.CDScale); spawn.grenade(this.position.x, this.position.y, 200 * simulation.CDScale);
// mob[mob.length - 1].collisionFilter.category = 0 // mob[mob.length - 1].collisionFilter.category = 0
mob[mob.length - 1].collisionFilter.mask = cat.player | cat.map; mob[mob.length - 1].collisionFilter.mask = cat.player | cat.map;
} }
// spawn.shield(me, x, y); spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.seePlayerCheck(); this.seePlayerCheck();
this.checkStatus(); this.checkStatus();
@@ -6897,7 +6876,7 @@ const spawn = {
me.onDamage = function () { me.onDamage = function () {
this.cycle = 0 this.cycle = 0
}; };
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.35
me.do = function () { me.do = function () {
Matter.Body.rotate(this, 0.003) //gently spin around Matter.Body.rotate(this, 0.003) //gently spin around
this.checkStatus(); this.checkStatus();
@@ -6919,8 +6898,8 @@ const spawn = {
ctx.moveTo(this.position.x, this.position.y) ctx.moveTo(this.position.x, this.position.y)
ctx.lineTo(mob[i].position.x, mob[i].position.y) ctx.lineTo(mob[i].position.x, mob[i].position.y)
spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true); spawn.shield(mob[i], mob[i].position.x, mob[i].position.y, 1, true);
// me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReduction = 0.075
mob[mob.length - 1].damageReduction = 0.5 * 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //shields are extra strong mob[mob.length - 1].damageReduction = 0.5 * 0.075 //shields are extra strong
} }
} }
if (!this.isShielded && this.alive) spawn.shield(this, this.position.x, this.position.y, 1, true); if (!this.isShielded && this.alive) spawn.shield(this, this.position.x, this.position.y, 1, true);
@@ -6943,7 +6922,7 @@ const spawn = {
spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random()) spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random())
Matter.Body.setDensity(me, 0.0025); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0025); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.07
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.onDeath = function () { me.onDeath = function () {
@@ -7033,7 +7012,7 @@ const spawn = {
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed // this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //helps collisions functions work better after vertex have been changed
}; };
me.onDamage = function () { }; me.onDamage = function () { };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.do = function () { me.do = function () {
// this.armor(); // this.armor();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -7167,49 +7146,6 @@ const spawn = {
// this.attraction(); // this.attraction();
}; };
}, },
// exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
// mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
// let me = mob[mob.length - 1];
// me.onHit = function() { //run this function on hitting player
// this.explode();
// };
// me.g = 0.0003; //required if using this.gravity
// me.seePlayerFreq = 50 + Math.floor(Math.random() * 20)
// me.do = function() {
// this.gravity();
// if (!(simulation.cycle % this.seePlayerFreq)) {
// if (
// this.distanceToPlayer2() < this.seeAtDistance2 &&
// Matter.Query.ray(map, this.position, this.playerPosRandomY()).length === 0 &&
// Matter.Query.ray(body, this.position, this.playerPosRandomY()).length === 0 &&
// !m.isCloak
// ) {
// this.foundPlayer();
// } else if (this.seePlayer.recall) {
// for (let i = 0; i < 20; i++) {
// let history = m.history[(m.cycle - 30 * i) % 600]
// if (Matter.Query.ray(map, this.position, history.position).length === 0) {
// this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //seconds before mob falls a sleep
// this.seePlayer.position.x = history.position.x;
// this.seePlayer.position.y = history.position.y;
// ctx.beginPath();
// ctx.moveTo(this.position.x, this.position.y);
// ctx.lineTo(history.position.x, history.position.y);
// ctx.lineWidth = 5;
// ctx.strokeStyle = "#000";
// ctx.stroke();
// break
// }
// }
// this.lostPlayer();
// }
// }
// this.checkStatus();
// this.attraction();
// };
// },
exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) { exploder(x, y, radius = 40 + Math.ceil(Math.random() * 50)) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)"); mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -7218,6 +7154,7 @@ const spawn = {
this.explode(); this.explode();
}; };
me.g = 0.0004; //required if using this.gravity me.g = 0.0004; //required if using this.gravity
spawn.shield(me, x, y);
me.do = function () { me.do = function () {
this.gravity(); this.gravity();
this.seePlayerCheck(); this.seePlayerCheck();
@@ -7238,7 +7175,7 @@ const spawn = {
me.memory = 250; me.memory = 250;
me.laserRange = 500; me.laserRange = 500;
Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.startingDamageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.startingDamageReduction = 0.14
me.damageReduction = 0 me.damageReduction = 0
me.isInvulnerable = true me.isInvulnerable = true
@@ -7367,7 +7304,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.startingDamageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.startingDamageReduction = 0.1
me.damageReduction = 0 me.damageReduction = 0
me.isInvulnerable = true me.isInvulnerable = true
@@ -7497,7 +7434,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0005 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.25
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -7589,14 +7526,15 @@ const spawn = {
} }
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) { //chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()
shield(target, x, y, chance = (simulation.difficultyMode === 6 ? 3 : 1) * Math.min(0.02 + simulation.difficulty * 0.005, 0.2)) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)"; me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05
me.isUnblockable = true me.isUnblockable = true
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
@@ -7652,7 +7590,7 @@ const spawn = {
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.frictionAir = 0; me.frictionAir = 0;
me.shield = true; me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
@@ -7689,8 +7627,7 @@ const spawn = {
}, },
spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) { spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) {
if (Math.random() < chance) { if (Math.random() < chance) {
// simulation.difficulty = 50 const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty)))
const len = Math.floor(Math.min(15, 3 + Math.sqrt(simulation.difficulty))) // simulation.difficulty = 40 on hard mode level 10
const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1) const speed = (0.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random() const offSet = 6.28 * Math.random()
for (let i = 0; i < len; i++) spawn.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed) for (let i = 0; i < len; i++) spawn.orbital(who, radius, i / len * 2 * Math.PI + offSet, speed)
@@ -7747,7 +7684,7 @@ const spawn = {
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
Matter.Body.setDensity(me, 0.0017 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.0017 + 0.0002 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.1
me.stroke = "transparent"; //used for drawGhost me.stroke = "transparent"; //used for drawGhost
me.seeAtDistance2 = 2000000; me.seeAtDistance2 = 2000000;
@@ -7956,13 +7893,18 @@ const spawn = {
this.force.x += -0.003; this.force.x += -0.003;
player.force.x += 0.06; player.force.x += 0.06;
// player.force.y -= 0.15; // player.force.y -= 0.15;
//remove difficulty power up if the wire breaks to prevent getting power ups and then making the difficulty harder
for (let i = 0; i < powerUp.length; ++i) {
if (powerUp[i].name === "difficulty") {
Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
}
}
} }
//player is extra heavy from wires //player is extra heavy from wires
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, { x: player.velocity.x, y: player.velocity.y + 0.3 })
x: player.velocity.x,
y: player.velocity.y + 0.3
})
//player friction from the wires //player friction from the wires
if (m.pos.x > 700 && player.velocity.x > -2) { if (m.pos.x > 700 && player.velocity.x > -2) {
@@ -7974,10 +7916,7 @@ const spawn = {
}) })
} }
//move to player //move to player
Matter.Body.setPosition(this, { Matter.Body.setPosition(this, { x: m.pos.x + (42 * Math.cos(m.angle + Math.PI)), y: m.pos.y + (42 * Math.sin(m.angle + Math.PI)) })
x: m.pos.x + (42 * Math.cos(m.angle + Math.PI)),
y: m.pos.y + (42 * Math.sin(m.angle + Math.PI))
})
} }
//draw wire //draw wire
ctx.beginPath(); ctx.beginPath();

View File

@@ -248,22 +248,6 @@ const tech = {
duplicationChance() { duplicationChance() {
return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.duplication + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + 0.08 * tech.isDuplicateMobs + 0.03 * tech.isMassProduction + 0.04 * tech.isHealAttract + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.6 : 0) + 0.06 * tech.isDupEnergy)) return Math.min(1, Math.max(0, (tech.isPowerUpsVanish ? 0.13 : 0) + (tech.isStimulatedEmission ? 0.2 : 0) + tech.duplication + tech.duplicateChance + 0.05 * tech.isExtraGunField + m.duplicateChance + tech.fieldDuplicate + 0.08 * tech.isDuplicateMobs + 0.03 * tech.isMassProduction + 0.04 * tech.isHealAttract + tech.cloakDuplication + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.6 : 0) + 0.06 * tech.isDupEnergy))
}, },
isScaleMobsWithDuplication: false,
maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false
const range = 1300
tech.isScaleMobsWithDuplication = true
for (let i = 0, len = 9; i < len; i++) {
const angle = 2 * Math.PI * i / len
spawn.randomLevelBoss(m.pos.x + range * Math.cos(angle), m.pos.y + range * Math.sin(angle), spawn.nonCollideBossList);
}
spawn.historyBoss(0, 0)
spawn.pulsarBoss(level.exit.x, level.exit.y, 70, true)
spawn.blockBoss(level.enter.x, level.enter.y)
tech.isScaleMobsWithDuplication = false
}
},
setTechFrequency(name, frequency) { setTechFrequency(name, frequency) {
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].name === name) tech.tech[i].frequency = frequency if (tech.tech[i].name === name) tech.tech[i].frequency = frequency
@@ -2485,7 +2469,7 @@ const tech = {
}, },
{ {
name: "entropic gravity", name: "entropic gravity",
description: "<strong>crouching</strong> pulls the <strong class='color-MACHO'>MACHO</strong> towards you<br> <strong>1.5x</strong> to all <strong class='color-MACHO'>MACHO</strong> effects", description: "<strong>crouching</strong> pulls the <strong class='color-MACHO'>MACHO</strong> towards you<br> <strong>1.5x</strong> for all <strong class='color-MACHO'>MACHO</strong> effects",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -2651,7 +2635,7 @@ const tech = {
} }
}, },
{ {
name: "Abelian group", name: "abelian group",
description: `<strong>4x</strong> <strong class='color-d'>damage</strong> while <strong class="color-invulnerable">invulnerable</strong>`, description: `<strong>4x</strong> <strong class='color-d'>damage</strong> while <strong class="color-invulnerable">invulnerable</strong>`,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -2709,7 +2693,7 @@ const tech = {
}, },
{ {
name: "ground state", name: "ground state",
description: "<strong>+266</strong> maximum <strong class='color-f'>energy</strong><br><strong>0.66x</strong> passive <strong class='color-f'>energy</strong> generation", description: "<strong>+300</strong> maximum <strong class='color-f'>energy</strong><br><strong>0.66x</strong> passive <strong class='color-f'>energy</strong> generation",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -4269,26 +4253,6 @@ const tech = {
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{
name: "apomixis",
description: `when you reach <strong>100%</strong> <strong class='color-dup'>duplication</strong><br>spawn <strong>11 bosses</strong> with <strong>2x</strong> <strong>durability</strong>`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
// isInstant: true,
allowed() {
return tech.duplicationChance() > 0.5
},
requires: "duplication chance above 50%",
effect() {
tech.is100Duplicate = true;
tech.maxDuplicationEvent()
},
remove() {
tech.is100Duplicate = false;
}
},
{ {
name: "stimulated emission", name: "stimulated emission",
description: "<strong>+20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>,<br><strong>collisions</strong> <span class='color-remove'>eject</span> a random <strong class='color-m'>tech</strong>", description: "<strong>+20%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>,<br><strong>collisions</strong> <span class='color-remove'>eject</span> a random <strong class='color-m'>tech</strong>",
@@ -4482,7 +4446,7 @@ const tech = {
{ {
name: "paradigm shift", name: "paradigm shift",
descriptionFunction() { descriptionFunction() {
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>${tech.pauseEjectTech.toFixed(1)}</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} cost <em>(1.2x cost each use)</em>` return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>${tech.pauseEjectTech.toFixed(1)}</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} cost <em>(1.3x cost each use)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5149,7 +5113,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 2 || m.fieldMode === 0))
}, },
requires: "a freeze effect", requires: "a freeze effect",
effect() { effect() {
@@ -5446,11 +5410,11 @@ const tech = {
requires: "wave", requires: "wave",
effect() { effect() {
tech.waveBeamSpeed *= 0.75; tech.waveBeamSpeed *= 0.75;
tech.waveBeamDamage += 0.27 * 0.4 //this sets base wave damage tech.waveBeamDamage += 0.3 * 0.4 //this sets base wave damage
}, },
remove() { remove() {
tech.waveBeamSpeed = 11; tech.waveBeamSpeed = 11;
tech.waveBeamDamage = 0.27 //this sets base wave damage tech.waveBeamDamage = 0.3 //this sets base wave damage
} }
}, },
{ {
@@ -8071,7 +8035,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (m.fieldMode === 10 || m.fieldMode === 4 || m.fieldMode === 8) return (m.fieldMode === 10 || m.fieldMode === 5 || m.fieldMode === 8) //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
}, },
requires: "plasma torch, grappling hook, pilot wave", requires: "plasma torch, grappling hook, pilot wave",
effect() { effect() {
@@ -8353,7 +8317,7 @@ const tech = {
{ {
name: "metamaterial absorber", //quantum eraser name: "metamaterial absorber", //quantum eraser
descriptionFunction() { descriptionFunction() {
return `for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br>there is a <strong>25%</strong> chance to spawn a random <strong>power up</strong>` return `for each mob left <strong>alive</strong> after you exit a <strong>level</strong><br>there is a <strong>30%</strong> chance to spawn a random <strong>power up</strong>`
}, },
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
@@ -9135,7 +9099,7 @@ const tech = {
// }, // },
{ {
name: "return", name: "return",
description: "return to the start of the game<br>reduce combat <strong>difficulty</strong> by <strong>2 levels</strong>", description: "return to the start of the game",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -9144,7 +9108,6 @@ const tech = {
allowed: () => true, allowed: () => true,
requires: "", requires: "",
effect() { effect() {
level.difficultyDecrease(simulation.difficultyMode * 2)
level.onLevel = 0 level.onLevel = 0
simulation.clearNow = true //end current level simulation.clearNow = true //end current level
}, },
@@ -10657,7 +10620,7 @@ const tech = {
remove() { } remove() { }
}, },
{ {
name: "stubs", name: "wall jump",
description: "no knees or toes are drawn on the player<br>you can wall climb though", description: "no knees or toes are drawn on the player<br>you can wall climb though",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -10670,11 +10633,12 @@ const tech = {
requires: "", requires: "",
effect() { effect() {
m.skin.stubs() m.skin.stubs()
Matter.Body.scale(player.parts[3], 2, 2); jumpSensor.vertices[0].x += -22
jumpSensor.vertices[3].x += -22
jumpSensor.vertices[1].x += 22
jumpSensor.vertices[2].x += 22
}, },
remove() { remove() { }
// if (this.count) m.resetSkin();
}
}, },
{ {
name: "Sleipnir", name: "Sleipnir",
@@ -10767,25 +10731,6 @@ const tech = {
if (this.count) m.resetSkin(); if (this.count) m.resetSkin();
} }
}, },
{
name: "wall jump",
description: "jump on walls",
maxCount: 1,
count: 0,
frequency: 0,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "",
effect() {
jumpSensor.vertices[0].x += -22
jumpSensor.vertices[3].x += -22
jumpSensor.vertices[1].x += 22
jumpSensor.vertices[2].x += 22
},
remove() { }
},
{ {
name: "posture", name: "posture",
description: "stand a bit taller", description: "stand a bit taller",
@@ -10869,7 +10814,7 @@ const tech = {
// }, // },
{ {
name: "ship", name: "ship",
description: "fly around with no legs<br>reduce combat <strong>difficulty</strong> by <strong>1 level</strong>", description: "fly around with no legs",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -10882,7 +10827,6 @@ const tech = {
effect() { effect() {
m.isAltSkin = true m.isAltSkin = true
m.shipMode() m.shipMode()
level.difficultyDecrease(simulation.difficultyMode)
//unlock relativistic rotation //unlock relativistic rotation
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].name === "relativistic rotation") tech.tech[i].frequency = 10 if (tech.tech[i].name === "relativistic rotation") tech.tech[i].frequency = 10
@@ -10983,23 +10927,6 @@ const tech = {
}, },
remove() { } remove() { }
}, },
{
name: "growth hacking",
description: "increase combat <strong>difficulty</strong> by <strong>1 level</strong>",
maxCount: 1,
count: 0,
frequency: 0,
isInstant: true,
isJunk: true,
allowed() {
return true
},
requires: "",
effect() {
level.difficultyIncrease(simulation.difficultyMode)
},
remove() { }
},
{ {
name: "stun", name: "stun",
description: "<strong>stun</strong> all mobs for up to <strong>8</strong> seconds", description: "<strong>stun</strong> all mobs for up to <strong>8</strong> seconds",
@@ -11045,6 +10972,23 @@ const tech = {
}, },
remove() { } remove() { }
}, },
{
name: "difficulty",
description: "spawn a power up that lets you<br>adjust the simulation <strong>difficulty</strong> parameters",
maxCount: 1,
count: 0,
frequency: 0,
isInstant: true,
isJunk: true,
allowed() {
return level.levelsCleared < 6
},
requires: "before level 6",
effect() {
powerUps.spawn(m.pos.x, m.pos.y, "difficulty");
},
remove() { }
},
{ {
name: "re-research", name: "re-research",
description: `<strong>eject</strong> all your ${powerUps.orb.research(1)}`, description: `<strong>eject</strong> all your ${powerUps.orb.research(1)}`,
@@ -11083,6 +11027,31 @@ const tech = {
}, },
remove() { } remove() { }
}, },
{
name: "apomixis",
description: `spawn <strong>11 bosses</strong>`,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
isInstant: true,
isJunk: true,
allowed() {
return tech.duplicationChance() > 0.99
},
requires: "duplication chance above 99%",
effect() {
const range = 1300
for (let i = 0, len = 9; i < len; i++) {
const angle = 2 * Math.PI * i / len
spawn.randomLevelBoss(m.pos.x + range * Math.cos(angle), m.pos.y + range * Math.sin(angle), spawn.nonCollideBossList);
}
spawn.historyBoss(0, 0)
spawn.pulsarBoss(level.exit.x, level.exit.y, 70, true)
spawn.blockBoss(level.enter.x, level.enter.y)
},
remove() { }
},
{ {
name: "mobs!", name: "mobs!",
descriptionFunction() { descriptionFunction() {
@@ -11762,7 +11731,6 @@ const tech = {
pauseEjectTech: null, pauseEjectTech: null,
isShieldPierce: null, isShieldPierce: null,
isDuplicateMobs: null, isDuplicateMobs: null,
is100Duplicate: null,
isDynamoBotUpgrade: null, isDynamoBotUpgrade: null,
isBlockPowerUps: null, isBlockPowerUps: null,
isDamageAfterKillNoRegen: null, isDamageAfterKillNoRegen: null,

132
style.css
View File

@@ -587,6 +587,17 @@ summary {
background-color: #fff; background-color: #fff;
} }
#dmg { #dmg {
position: absolute; position: absolute;
z-index: 2; z-index: 2;
@@ -1502,3 +1513,124 @@ summary {
stroke-dashoffset: 300; stroke-dashoffset: 300;
animation: dash 2.5s ease-in forwards; animation: dash 2.5s ease-in forwards;
} }
.grid-container {
display: grid;
grid-template-columns: 0fr 5fr 0fr;
line-height: 150%;
background-color: #fff;
padding: 15px 0 14px 0;
border-radius: 5px;
}
.far-right-column {
display: grid;
grid-template-rows: repeat(6, 1fr);
font-size: 2rem;
font-family: monospace;
align-self: center;
justify-self: center;
width: 22px;
}
.far-right-column>div {
padding-top: 50px;
}
#difficulty-slider {
margin-top: 2.3rem;
height: 26.3rem;
width: 2rem;
writing-mode: vertical-lr;
}
.left-column {
grid-row: 1 / span 6
}
.right-column {
display: grid;
grid-template-rows: repeat(6, 1fr);
/* to adjust the width of this column edit the "gridTemplateColumns" in the difficulty power up js code*/
}
.row {
transition: opacity 0.4s ease-out;
/* border: 2px #444 solid; */
/* margin-top: -2px; */
font-size: 1.2rem;
padding: 10px;
}
#constraint-1 {
background-color: hsl(240, 18%, 95%);
border-radius: 7px 7px 0 0;
}
#constraint-2 {
background-color: hsl(240, 18%, 93%);
}
#constraint-3 {
background-color: hsl(240, 18%, 89%);
}
#constraint-4 {
background-color: hsl(240, 18%, 85%);
}
#constraint-5 {
background-color: hsl(240, 18%, 81%);
}
#constraint-6 {
background-color: hsl(240, 18%, 77%);
border-radius: 0 0 7px 7px;
}
#constraint-1:hover {
background-color: hsl(240, 18%, 93%);
border: 1px #444 solid;
padding: 9px;
}
#constraint-2:hover {
background-color: hsl(240, 18%, 91%);
border: 1px #444 solid;
padding: 9px;
}
#constraint-3:hover {
background-color: hsl(240, 18%, 87%);
border: 1px #444 solid;
padding: 9px;
}
#constraint-4:hover {
background-color: hsl(240, 18%, 83%);
border: 1px #444 solid;
padding: 9px;
}
#constraint-5:hover {
background-color: hsl(240, 18%, 79%);
border: 1px #444 solid;
padding: 9px;
}
#constraint-6:hover {
background-color: hsl(240, 18%, 75%);
border: 1px #444 solid;
padding: 9px;
}
#choose-difficulty {
text-align: center;
font-size: 1.1em;
padding: 5px;
margin-top: 10px;
color: #333;
border-radius: 5px;
}

119
todo.txt
View File

@@ -1,31 +1,24 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
tech: anyon - 2x energy after duplicating a power up, +6% duplication chance difficulty rework
tech: Abelian group - 4x damage while invulnerable difficulty adjusted through a power up on the initial level
tech: fermion - become invulnerable for 5 seconds after a mob dies difficulty parameters are more precisely explained
tech: entropic gravity - crouching pulls MACHO towards the player, and 1.5x to all MACHO effects (damage, damage reduction, AoE damage) JUNK tech: difficulty - spawns a difficulty power up (only works before level 6)
tech: modified Newtonian dynamics - +20 speed for all Newtonian law tech
choice, MACHO, invulnerable, speed - have text keyword CSS style bots no longer benefit from increased fireRate
removed chance to find a random tech in early levels from mobs shields have a chance spawn on almost all mobs (but not stealth mobs)
this reduces tech per full game by about 2 level exit door animation is 33% faster
tower level has a few changes power ups have fewer sides. It might improve game performance, but I can't tell the difference.
options exchange only works once per level, but it gives 3x choices after randomizing 1.15x base wave bullets damage (bots, particles, and phonon)
dark star has a 1.2->1.3x MACHO radius metamaterial absorber 25->30% chance to get power ups from mobs left alive
autocannon fires 1->2 extra super balls, but balls have higher gravity apomixis is now a JUNK tech, and it requires duplication > 99%
grappling hook field starts with 0.6x damage reduction pilot wave field 2->3 extra choices
super balls + uncertainty principle makes all balls start in the same spot and only separate after teleporting plasma torch slows mobs more, and don't push mobs back as much
ablative drones spawns 50% more drones on collision fixed bug where plasma torch didn't get tech degenerate matter
von Neumann probe gives 40% more drones per block mass laserLayerBoss and layerLayer do 33% less damage
also added text clarification that it uses 5 energy mines aren't triggered by invulnerable mobs
tech lens rotates 50% faster
ghoster mobs are more aggressive once they have lost 20% health
sneakBoss doesn't start accelerating until it is partly uncloaked, but it spawns sneaker mobs after cloaking
fixed bug with 2 different boost power up sizes bug fixes
paradigm shift doesn't do damage while player is invulnerable
random internet JUNK images disabled because some of the images are bad
entanglement bug fix, maybe
******************************************************* DESIGN ****************************************************** ******************************************************* DESIGN ******************************************************
@@ -53,30 +46,70 @@ powerful synergies
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
make each difficulty level have specific listed changes difficulty rework: explicit changes to the game to increase difficulty
to motivate people to try that difficulty to see the difference UI -
make difficulty easier to see add difficulty display to pause menu
in pause menu update pause menu text to match opening screen menu
before game begins just make it a square like field or gun on left pause column
automatically increase difficulty when player wins? add a wire attached to difficulty power up
difficulty based changes (maybe in the order) like the one attached to player, but thinner
more bosses add new difficulty to game code
more mobs todo
mobs attack faster check for any undocumented side effects
mobs move faster heal power ups (small effect)
reduced heals (remove, keep, or add to parameters)
reduced damage done balance testing log:
increased damage taken difficultyMode=5 died on level 5 with a good drone build, seemed similar balance to old why mode, maybe slightly harder...
mobs regen health difficultyMode=2 won with a good spore build, seemed similar balance to old normal mode
-1 choice for tech, field, gun
no starting power ups (heal, research) tokamak synergy tech
starting JUNK chance? tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?)
tech: inertial confinement - while charging tokamak you can fly, and invulnerable
but energy drains
bullets should trigger shrinking platforms level element?
level element - player activated elevators
could be fast and throw player
could just rise up slow (slow might have a bad jerky animation)
tech: super balls split after 3 seconds, but they fire with less speed
buff plasma torch
buff plasma tech?
buff plasma field defense?
buff plasma damage?
rework energy and health HUD
make both diegetic?
should health be red or green?
white laser
what to name? not much in wikipedia
goes through shields?
damage, energy cost
3+ closely overlapping beams (but reflecting, not like diffusion)
tech.laserColor = "#fff"
tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
bug Newton's 1st law image not showing up on github server bug Newton's 1st law image not showing up on github server
shows up on n-gon, and landgreen github, but webp file isn't loading onto server? shows up on n-gon, and landgreen github, but webp file isn't loading onto server?
try name change, try name change,
wait and see if next patch fixes it wait and see if next patch fixes it
tech: atomic pile - lose 1 health if you are above the maximum energy
generate energy for each nearby mob?
do damage?
plasma torch tech?
boss mob - several squares that move like the snake in the game snake/light cycles
moves towards player (is smell history pathing good enough?)
doesn't have inertia/force? or it obeys normal physics kinda?
gets longer when
you hit it with bullets?
it gets near a power up?
it gets near mobs
Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots. Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots.
after snap shot is stored draw outline of body positions for a second to show the change after snap shot is stored draw outline of body positions for a second to show the change
immune after snapshot? or immune after teleport? immune after snapshot? or immune after teleport?
@@ -1270,6 +1303,8 @@ possible names for tech
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
ergosphere - region of a spinning black hole that might allow FTL or alternate realities. ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
equivalence principle - gravity and acceleration are the same equivalence principle - gravity and acceleration are the same
Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer
******************************************************** IMAGES ******************************************************** ******************************************************** IMAGES ********************************************************