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)">
<text x="10" y="33">training</text>
</svg>
<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">
<details id = 'settings-details'>
<summary>settings</summary>
<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">
<option value="1">easy</option>
<option value="2" selected>normal ⚆</option>
<option value="4">hard ⚆</option>
<option value="5">why ⚇</option>
</select>
<br>
<br> -->
<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>
<br>

View File

@@ -1,7 +1,7 @@
let bullet = [];
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
activeGun: null, //current gun in use by player
inventoryGun: 0,
@@ -2313,13 +2313,14 @@ const b = {
best.who.locatePlayer();
//push mobs away
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)
if (best.who.speed > 4) {
Matter.Body.setVelocity(best.who, { //friction
x: best.who.velocity.x * 0.9,
y: best.who.velocity.y * 0.9
});
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 });
}
//draw mob damage circle
simulation.drawList.push({
@@ -2702,28 +2703,13 @@ const b = {
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 });
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
if (!(simulation.cycle % this.lookFrequency)) { //find mob targets
const random = 300 * Math.random()
for (let i = 0, len = mob.length; i < len; ++i) {
if (
!mob[i].isBadTarget &&
!mob[i].isInvulnerable &&
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(body, this.position, mob[i].position).length === 0
@@ -4892,7 +4878,7 @@ const b = {
minDmgSpeed: 2,
// lookFrequency: 56 + Math.floor(17 * Math.random()) - isUpgraded * 20,
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()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100,
endCycle: Infinity,
@@ -4954,7 +4940,7 @@ const b = {
minDmgSpeed: 2,
lookFrequency: 26 + Math.ceil(6 * Math.random()),
cd: 0,
delay: Math.floor(60 * b.fireCDscale),
delay: Math.floor(60),
range: 70 + 3 * b.totalBots(),
endCycle: Infinity,
classType: "bullet",
@@ -5030,7 +5016,7 @@ const b = {
cd: 0,
fireCount: 0,
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()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move
endCycle: Infinity,
@@ -5150,7 +5136,7 @@ const b = {
cd: 0,
fireCount: 0,
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()),
range: 60 * (1 + 0.3 * Math.random()) + 3 * b.totalBots() + !isKeep * 100, //how far from the player the bot will move
endCycle: Infinity,
@@ -5646,8 +5632,19 @@ const b = {
best.who.damage(dmg);
best.who.locatePlayer();
//push mobs away
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)
// 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)
//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 });
//draw mob damage circle
if (best.who.damageReduction) {
@@ -7752,10 +7749,7 @@ const b = {
}
let speed = 36
if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map
b.mine(pos, {
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
}, 0)
b.mine(pos, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }, 0)
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down
}
} else {
@@ -7765,10 +7759,7 @@ const b = {
}
let speed = 23
if (Matter.Query.point(map, pos).length > 0) speed = -2 //don't launch if mine will spawn inside map
b.mine(pos, {
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
}, 0)
b.mine(pos, { x: speed * Math.cos(m.angle), y: speed * Math.sin(m.angle) }, 0)
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.strokeStyle = '#fff' //'rgba(255,255,255,0.9)' //'hsl(189, 100%, 95%)'
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() {
if (tech.isStuckOn) {
@@ -7916,6 +7902,79 @@ const b = {
}
// 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() {
const drain = tech.laserDrain / b.fireCDscale
if (m.energy < drain) {

View File

@@ -251,11 +251,11 @@ window.addEventListener('load', () => {
}
}
if (property === "difficulty") {
simulation.difficultyMode = Number(set[property])
lore.setTechGoal()
document.getElementById("difficulty-select-experiment").value = Number(set[property])
}
// if (property === "difficulty") {
// simulation.difficultyMode = Number(set[property])
// lore.setTechGoal()
// document.getElementById("difficulty-select-experiment").value = Number(set[property])
// }
if (property === "molMode") {
simulation.molecularMode = Number(set[property])
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>
<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>
<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>
<br><strong><em>fire rate</em></strong>: ${(1 / b.fireCDscale).toFixed(2)}x
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""}
${m.coupling ? `<br><span style = 'font-size:90%;'>` + m.couplingDescription(m.coupling) + `</span> from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""}
${botText}
<br>
<br><strong class='color-h'>health</strong>: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
<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-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 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>level: ${level.levelsCleared} ${level.levels[level.onLevel]} (${level.difficultyText()})
<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>`;
<details> <summary>difficulty</summary>
<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>
<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>
<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>
<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>
<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>
<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>
</details>
<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-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>
<br><strong><em>fire rate</em></strong>: ${(1 / b.fireCDscale).toFixed(2)}x
${tech.duplicationChance() ? `<br><strong class='color-dup'>duplication</strong>: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""}
${m.coupling ? `<br><span style = 'font-size:90%;'>` + m.couplingDescription(m.coupling) + `</span> from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""}
${botText}
<br>
<br><strong class='color-h'>health</strong>: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)})
<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-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 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;
// 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');"`
// text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
// <div class="card-text" style = "animation: fieldColorCycle 1s linear infinite alternate;">
// 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="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}</div>
// ${m.fieldUpgrades[m.fieldMode].description}</div> </div>`
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>`
//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');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text">
<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>`
text += `<div class="pause-grid-module card-background" id="pause-field" ${style} >
<div class="card-text">
<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>`
//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;">
<div class="grid-title" style="text-align: center;">↓ <div class="circle-grid field"></div> ↓</div></div>`
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>`
} 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');"`
text += `<div class="pause-grid-module card-background" id ="pause-field" ${style} >
<div class="card-text">
<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>`
text += `<div class="pause-grid-module card-background" id="pause-field" ${style} >
<div class="card-text">
<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>`
}
// 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>`
@@ -537,26 +544,26 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
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');"`
text += `<div class="pause-grid-module card-background" ${style} >
<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>
${b.guns[b.inventory[i]].descriptionFunction()}</div> </div>`
<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>
${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")
el.style.display = "grid"
el.innerHTML = text
},
generatePauseRight() {
let text = `<div class="sort">
<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('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('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>
<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>
</div>`;
<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('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('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>
<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>
</div>`;
const ejectClass = (tech.isPauseEjectTech && !simulation.isChoosing) ? 'pause-eject' : ''
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count > 0) {
@@ -728,43 +735,43 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
isExperimentRun: false,
techText(i) {
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>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</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>`
},
instantTechText(i) {
//
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>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</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>`
},
skinTechText(i) {
return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;">
<div class="circle-grid-skin"></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>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
<span style="position:relative;">
<div class="circle-grid-skin"></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>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</div>`
},
gunTechText(i) {
return `<div class="card-text"> <div class="grid-title">
<span style="position:relative;">
<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>
</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>`
<span style="position:relative;">
<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>
</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>`
},
fieldTechText(i) {
return `<div class="card-text"><div class="grid-title">
<span style="position:relative;">
<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>
</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>`
<span style="position:relative;">
<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>
</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>`
},
junkTechText(i) {
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>
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}</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>`
},
choosePowerUp(index, type, isAllowed = false) {
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="card-text">
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div>`
<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div>`
}
} else if (type === "tech") {
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);
let text = `
<div class="experiment-start-box">
<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('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('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('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>
<button onclick="build.sortTech('allowed', true)" class='sort-button' style="letter-spacing: 1px;font-weight: 400;">allowed</button>
<input type="search" id="sort-input" style="width: 8.7em;font-size: 0.6em;color:#000;" placeholder="sort by"/>
<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>
<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>
<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 style="grid-column: 1;grid-row: 2 / 4;">
<svg class="SVG-button" onclick="build.startExperiment()" width="150" height="70" >
<g stroke='none' fill='#333' stroke-width="2" font-size="65px" font-family="Ariel, sans-serif">
<text x="10" y="57">start</text>
</g>
</svg>
</div>
<div style="grid-column: 2;grid-row: 2;">
<svg class="SVG-button" onclick="build.reset()" width="50" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">reset</text>
</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>`
<div class="experiment-start-box">
<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('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('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('heal')" class='sort-button'><strong class='color-h'>heal</strong></button>
<input type="search" id="sort-input" style="width: 6em;font-size: 0.6em;color:#000;" placeholder="sort by" />
<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 style="grid-column: 1;grid-row: 2 / 4;">
<svg class="SVG-button" onclick="build.startExperiment()" width="150" height="70" >
<g stroke='none' fill='#333' stroke-width="2" font-size="65px" font-family="Ariel, sans-serif">
<text x="10" y="57">start</text>
</g>
</svg>
</div>
<div style="grid-column: 2;grid-row: 2;">
<svg class="SVG-button" onclick="build.reset()" width="50" height="25">
<g stroke='none' fill='#333' stroke-width="2" font-size="17px" font-family="Ariel, sans-serif">
<text x="5" y="18">reset</text>
</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;"`
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');"`
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="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div> </div>`
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="grid-title"><div class="circle-grid field"></div> &nbsp; ${build.nameLink(m.fieldUpgrades[i].name)}</div>
${m.fieldUpgrades[i].description}</div> </div>`
}
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');"`
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="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div>
${b.guns[i].descriptionFunction()}</div> </div>`
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="grid-title"><div class="circle-grid gun"></div> &nbsp; ${build.nameLink(b.guns[i].name)}</div>
${b.guns[i].descriptionFunction()}</div> </div>`
}
for (let i = 0, len = tech.tech.length; i < len; i++) {
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("difficulty-select-experiment").value = document.getElementById("difficulty-select").value
document.getElementById("difficulty-select-experiment").addEventListener("input", () => {
simulation.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value)
lore.setTechGoal()
localSettings.difficultyMode = Number(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
});
// document.getElementById("difficulty-select-experiment").value = document.getElementById("difficulty-select").value
// document.getElementById("difficulty-select-experiment").addEventListener("input", () => {
// simulation.difficultyMode = Number(document.getElementById("difficulty-select-experiment").value)
// lore.setTechGoal()
// localSettings.difficultyMode = Number(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
// });
//add tooltips
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (document.getElementById(`tech-${i}`)) {
@@ -1001,7 +1009,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>" : ""}
requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
},
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() {
build.isExperimentSelection = true;
@@ -1437,59 +1445,59 @@ window.addEventListener("keydown", function (event) {
if (simulation.testing) tech.setCheating();
simulation.makeTextLog(
`<table class="pause-table">
<tr>
<td class='key-input-pause'>T</td>
<td class='key-used'><strong>toggle testing</strong></td>
</tr>
<tr>
<td class='key-input-pause'>R</td>
<td class='key-used'>teleport to mouse</td>
</tr>
<tr>
<td class='key-input-pause'>F</td>
<td class='key-used'>cycle field</td>
</tr>
<tr>
<td class='key-input-pause'>G</td>
<td class='key-used'>all guns</td>
</tr>
<tr>
<td class='key-input-pause'>H</td>
<td class='key-used'>+100% defense</td>
</tr>
<tr>
<td class='key-input-pause'>B</td>
<td class='key-used'>damage, research</td>
</tr>
<tr>
<td class='key-input-pause'>N</td>
<td class='key-used'>fill health, energy</td>
</tr>
<tr>
<td class='key-input-pause'>Y</td>
<td class='key-used'>random tech</td>
</tr>
<tr>
<td class='key-input-pause'>U</td>
<td class='key-used'>next level</td>
</tr>
<tr>
<td class='key-input-pause'>J</td>
<td class='key-used'>clear mobs</td>
</tr>
<tr>
<td class='key-input-pause'>I/O</td>
<td class='key-used'>zoom in / out</td>
</tr>
<tr>
<td class='key-input-pause'>1-8</td>
<td class='key-used'>spawn things</td>
</tr>
<tr>
<td class='key-input-pause'>⇧X</td>
<td class='key-used'>restart</td>
</tr>
</table>`, Infinity);
<tr>
<td class='key-input-pause'>T</td>
<td class='key-used'><strong>toggle testing</strong></td>
</tr>
<tr>
<td class='key-input-pause'>R</td>
<td class='key-used'>teleport to mouse</td>
</tr>
<tr>
<td class='key-input-pause'>F</td>
<td class='key-used'>cycle field</td>
</tr>
<tr>
<td class='key-input-pause'>G</td>
<td class='key-used'>all guns</td>
</tr>
<tr>
<td class='key-input-pause'>H</td>
<td class='key-used'>+100% defense</td>
</tr>
<tr>
<td class='key-input-pause'>B</td>
<td class='key-used'>damage, research</td>
</tr>
<tr>
<td class='key-input-pause'>N</td>
<td class='key-used'>fill health, energy</td>
</tr>
<tr>
<td class='key-input-pause'>Y</td>
<td class='key-used'>random tech</td>
</tr>
<tr>
<td class='key-input-pause'>U</td>
<td class='key-used'>next level</td>
</tr>
<tr>
<td class='key-input-pause'>J</td>
<td class='key-used'>clear mobs</td>
</tr>
<tr>
<td class='key-input-pause'>I/O</td>
<td class='key-used'>zoom in / out</td>
</tr>
<tr>
<td class='key-input-pause'>1-8</td>
<td class='key-used'>spawn things</td>
</tr>
<tr>
<td class='key-input-pause'>⇧X</td>
<td class='key-used'>restart</td>
</tr>
</table>`, Infinity);
}
}
break
@@ -1759,11 +1767,6 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
simulation.isCommunityMaps = 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.personalSeeds === undefined) localSettings.personalSeeds = [];
if (localSettings.fpsCapDefault === 'max') {
@@ -1791,6 +1794,14 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
if (localSettings.isHideHUD === undefined) localSettings.isHideHUD = true
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 {
console.log('setting default localSettings')
const isAllowed = localSettings.isAllowed //don't overwrite isAllowed value
@@ -1801,6 +1812,7 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
isJunkExperiment: false,
isCommunityMaps: false,
difficultyMode: '2',
difficultyCompleted: [null, false, false, false, false, false, false],
fpsCapDefault: 'max',
runCount: 0,
isTrainingNotAttempted: true,
@@ -1817,18 +1829,30 @@ if (localSettings.isAllowed && !localSettings.isEmpty) {
document.getElementById("community-maps").checked = localSettings.isCommunityMaps
simulation.isCommunityMaps = localSettings.isCommunityMaps
document.getElementById("hide-images").checked = localSettings.isHideImages
document.getElementById("difficulty-select").value = localSettings.difficultyMode
document.getElementById("fps-select").value = localSettings.fpsCapDefault
document.getElementById("banned").value = localSettings.banList
}
document.getElementById("control-testing").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
// document.getElementById("experiment-button").style.visibility = (localSettings.loreCount === 0) ? "hidden" : "visible"
input.controlTextUpdate()
//**********************************************************************
// 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", () => {
let value = document.getElementById("fps-select").value
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
});
// 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 () {
function loadJSON(path, success, error) { //generic function to get JSON
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.isHorizontalFlipped = true
// 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.maxEnergy = m.energy = 10000000
// 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("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
// tech.laserColor = "#fff"
// tech.laserColorAlpha = "rgba(255, 255, 255, 0.5)"
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// 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") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
// 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 < 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");
// 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)
// 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 < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// spawn.sneakBoss(1900, -500)
// for (let i = 0; i < 4; ++i) spawn.ghoster(1300, -500 + 100 * Math.random())
// spawn.hopper(1900, -500)
// 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())
// tech.addJunkTechToPool(2)
@@ -71,6 +72,7 @@ const 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
// spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass)
@@ -90,6 +92,7 @@ const level = {
// lore.techCount = 1
// level.levelsCleared = 10
// localSettings.loreCount = 2 //this sets what conversation is heard
// localSettings.levelsClearedLastGame = 10
// 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.null()
@@ -101,6 +104,8 @@ const level = {
// tech.giveTech("tinker"); //show junk tech in experiment mode
// m.storeTech()
// 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 {
spawn.setSpawnList(); //picks a couple mobs types for a themed random mob spawns
// spawn.pickList = ["focuser", "focuser"]
@@ -212,65 +217,65 @@ const level = {
trainingBackgroundColor: "#e1e1e1",
custom() { },
customTopLayer() { },
setDifficulty() {
simulation.difficulty = 0
m.dmgScale = 1; //damage done by player decreases each level
simulation.accelScale = 1 //mob acceleration increases each level
simulation.CDScale = 1 //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;
},
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
updateDifficulty() {
simulation.difficulty = level.levelsCleared * simulation.difficultyMode
if (simulation.isTraining) simulation.difficulty = 1
// old
// normal mode m.dmgScale = 1, 0.81, 0.63, 0.5
// why mode m.dmgScale = 1, 0.56, 0.3, 0.17
// new
//constraint 0,1 m.dmgScale = 1, 0.8, 0.6, 0.5
//constraint 2,3 m.dmgScale = 1,
//constraint 4,5 m.dmgScale = 1, 0.5, 0.3, 0.15
// old
//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;
// 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) {
return "easy"
} else if (simulation.difficultyMode === 2) {
return "normal"
} else if (simulation.difficultyMode === 4) {
return "hard"
} else if (simulation.difficultyMode === 5) {
return "why"
simulation.accelScale = 1.1
simulation.CDScale = 0.9
} else {
simulation.accelScale = Math.min(6, Math.pow(1.024, simulation.difficulty))
simulation.CDScale = Math.max(0.15, Math.pow(0.964, simulation.difficulty))
}
},
// 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() {
const difficulty = simulation.isCheating ? "testing" : level.difficultyText()
const cheating = simulation.isCheating ? "(testing)" : ""
if (level.levelsCleared === 0) {
document.title = "n-gon: (" + difficulty + ")";
document.title = `n-gon: initial ${cheating}`;
} 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(`
// 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() {
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) {
level.levelsCleared++;
level.onLevel++; //cycles map to next level
level.updateDifficulty()
if (simulation.isTraining) {
if (level.onLevel > level.levels.length - 1) { //if all training levels are completed
@@ -301,14 +307,12 @@ const level = {
simulation.splashReturn();
}, 6000);
return
} else {
level.setDifficulty()
}
} else {
if (level.onLevel > level.levels.length - 1) level.onLevel = 0;
level.difficultyIncrease(simulation.difficultyMode)
}
//reset lost tech display
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isLost) tech.tech[i].isLost = false;
@@ -573,9 +577,9 @@ const level = {
player.velocity.y < 0.15
) {
// level.exitCount += input.down ? 8 : 2
level.exitCount += 2
level.exitCount += 3
} else if (level.exitCount > 0) {
level.exitCount -= 2
level.exitCount -= 3
}
ctx.beginPath();
@@ -2181,7 +2185,6 @@ const level = {
document.body.style.backgroundColor = "#fff";
// color.map = "#444" //custom map color
// level.difficultyIncrease(14); //hard mode level 7
level.defaultZoom = 1500
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)
// spawn.starter(1900, -500, 200) //big boy
@@ -2424,51 +2426,60 @@ const level = {
spawn.mapRect(-500, -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() {
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
level.initialPowerUps()
if (level.levelsCleared === 0) powerUps.directSpawn(-60, -950, "difficulty", false);
//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 + 15 * (Math.random() - 0.5), -2170, "field", false);
} 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);
}
if (!simulation.isCheating && !m.isShipMode && !build.isExperimentRun) {
spawn.wireFoot();
spawn.wireFootLeft();
spawn.wireKnee();
spawn.wireKneeLeft();
spawn.wireHead();
} else {
simulation.isCheating = true;
}
requestAnimationFrame(cycle);
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) {
simulation.trails()
simulation.trails(70)
//bonus power ups for clearing runs in the last game
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
@@ -2848,7 +2859,6 @@ const level = {
},
subway() {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// level.difficultyIncrease(10 * 4);
// m.maxHealth = m.health = 100
// color.map = "#333" //custom map color
document.body.style.backgroundColor = "#e3e3e3"//"#e3e3e3"//color.map//"#333"//"#000"
@@ -4226,7 +4236,6 @@ const level = {
},
towers() {
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
level.announceMobTypes()
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
@@ -4481,7 +4490,6 @@ const level = {
factory() {
level.announceMobTypes()
// 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
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
@@ -7141,7 +7149,6 @@ const level = {
ctx.fill()
};
// simulation.difficulty = 4; //for testing to simulate possible mobs spawns
level.defaultZoom = 2100
simulation.zoomTransition(level.defaultZoom)
@@ -11330,9 +11337,7 @@ const level = {
anotherBoss = (x, y) => {
if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
tech.isScaleMobsWithDuplication = true
spawn.randomLevelBoss(x, y, ["historyBoss"]);
tech.isScaleMobsWithDuplication = false
} else if (tech.isResearchBoss) {
if (powerUps.research.count > 2) {
powerUps.research.changeRerolls(-3)
@@ -12014,7 +12019,6 @@ const level = {
simulation.fallHeight = -15000;
powerUps.addResearchToLevel();
powerUps.spawn(3000, -230, "heal");
// level.difficultyIncrease(60)
},
temple() {
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.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 () {
// keep it slow, to stop issues from explosion knock backs
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.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 () {
// keep it slow, to stop issues from explosion knock backs
if (this.speed > 2) {
@@ -12276,7 +12280,6 @@ const level = {
}
}
};
function secondRoomObstacle(x, y, isDark = false, size = 70) {
mobs.spawn(x, y, isDark ? 3 : 4, size, isDark ? "#0004" : "#fff4");
let me = mob[mob.length - 1];
@@ -12288,7 +12291,7 @@ const level = {
me.leaveBody = false;
me.timeLeft = 1200;
me.isObstacle = true;
me.damageReduction = isDark ? 0.5 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) : 0;
me.damageReduction = isDark ? 0.5 : 0
if (!isDark) {
me.isBadTarget = true;
me.attackCycle = 0;
@@ -12416,7 +12419,7 @@ const level = {
this.damageReduction = 0;
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
me.damageReduction = 0.25
me.rings = [{
colour: "#65f",
radius: 300,
@@ -12571,7 +12574,7 @@ const level = {
if (Math.floor(cycle / spawnDelay) >= spawnCycles - 1) {
this.trapCycle = 0;
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) => {
if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
tech.isScaleMobsWithDuplication = true
spawn.historyBoss(x, y)
tech.isScaleMobsWithDuplication = false
} else if (tech.isResearchBoss) {
if (powerUps.research.count > 2) {
powerUps.research.changeRerolls(-3)
@@ -14657,7 +14658,7 @@ const level = {
me.deadOrbs = []
me.energy = 1
// 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
spawn.shield(me, x, y, Infinity)
me.fireFreq = 30
@@ -15020,7 +15021,7 @@ const level = {
me.onDeath = function () {
totalCoin++;
};
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.35
me.do = function () {
ctx.save()
ctx.translate(this.position.x, this.position.y)
@@ -27367,14 +27368,13 @@ const level = {
spawn.mapRect(-100, 0, 1000, 100);
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>`);
let isDestroyed = false;
const ace = {
spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) {
if (Math.random() < chance) {
// simulation.difficulty = 50
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.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random()
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)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.05
me.isUnblockable = true
me.collisionFilter.category = cat.mobShield
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
me.frictionAir = 0;
me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) {
@@ -27911,7 +27911,7 @@ const level = {
me.isBoss = true;
me.isSlashBoss = true;
me.showHealthBar = false;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.02
@@ -28646,8 +28646,7 @@ const level = {
const ace = {
spawnOrbitals(who, radius, chance = Math.min(0.25 + simulation.difficulty * 0.005)) {
if (Math.random() < chance) {
// simulation.difficulty = 50
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.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random()
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)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.05
me.isUnblockable = true
me.collisionFilter.category = cat.mobShield
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
me.frictionAir = 0;
me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
for (let i = 0; i < nodes; ++i) {
@@ -29184,7 +29183,7 @@ const level = {
me.isBoss = true;
me.isSlashBoss = true;
me.showHealthBar = false;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.02
@@ -31211,7 +31210,7 @@ const level = {
*/
var boss = mob[mob.length - 1];
boss.isBoss = true;
boss.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
boss.damageReduction = 0.2
boss.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y);
level.exit.x = 2560;
@@ -31553,6 +31552,7 @@ const level = {
m.energy += 0.04;
} else {
m.health += 0.001 * (dmg - mob[i].health);
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
}
} else {
@@ -32317,7 +32317,7 @@ const level = {
// me.torque -= me.inertia * 0.002
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
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.isBoss = true;
// spawn.shield(me, x, y, 1); //not working, not sure why
me.onDeath = function () {
@@ -33223,7 +33223,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
nailGun() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33318,7 +33317,6 @@ const level = {
spawn.mapRect(1600, -600, 425, 250);
},
shotGun() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33400,7 +33398,6 @@ const level = {
spawn.mapRect(1600, -600, 425, 250);
},
superBall() {
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(60, -50); //normal spawn
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33484,7 +33481,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
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
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33571,7 +33567,6 @@ const level = {
spawn.mapRect(1600, -400, 50, 225); //exit room left upper wall
},
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
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33660,7 +33655,6 @@ const level = {
spawn.mapRect(2025, -2800, 1075, 2450);
},
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
spawn.mapRect(10, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33712,7 +33706,6 @@ const level = {
spawn.mapVertex(1300, 0, "400 0 -500 0 -300 -125 400 -125"); //base
},
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
spawn.mapRect(250, -10, 100, 20); //small platform for player
level.exit.x = 1775;
@@ -33796,7 +33789,6 @@ const level = {
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
level.difficultyIncrease(1) //difficulty on training mode resets to zero with each new level
level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(-50, -10, 100, 20); //small platform for player
level.exit.x = 1900;
@@ -33916,7 +33908,6 @@ const level = {
spawn.nodeGroup(1200, -1500, "grenadier", 7);
},
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
spawn.mapRect(-50, -10, 100, 20); //small platform for player
level.exit.x = 1900;

View File

@@ -358,7 +358,7 @@ const lore = {
setInterval(() => {
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));
level.difficultyIncrease(simulation.difficultyMode)
// level.difficultyIncrease(simulation.difficultyMode)
} else {
spawn.randomLevelBoss(500 * (Math.random() - 0.5), -500 + 200 * (Math.random() - 0.5))
}
@@ -693,9 +693,9 @@ const lore = {
setInterval(() => {
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
setInterval(() => {
level.difficultyIncrease(simulation.difficultyMode)
}, 5000); //every 5 seconds
// setInterval(() => {
// level.difficultyIncrease(simulation.difficultyMode)
// }, 5000); //every 5 seconds
},
() => {
lore.talkingColor = "#dff";

View File

@@ -418,7 +418,7 @@ const m = {
m.drop();
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() {
if (tech.isImmortal) { //if player has the immortality buff, spawn on the same level with randomized damage
//remove immortality tech
@@ -482,7 +482,7 @@ const m = {
Engine.clear(engine);
simulation.splashReturn();
//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);
}
},
@@ -567,7 +567,7 @@ const m = {
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.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.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
if (tech.isBotArmor) dmg *= 0.95 ** b.totalBots()
@@ -716,7 +716,6 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
@@ -745,7 +744,6 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
setTimeout(function () {
tech.maxDuplicationEvent()
simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height);
}
@@ -2178,7 +2176,7 @@ const m = {
}
},
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))}`)
},
fieldMeterColor: "#0cf",
@@ -2253,10 +2251,7 @@ const m = {
//calculate a vector from body to player and make it length 1
const diff = Vector.normalise(Vector.sub(who.position, m.pos));
//make a vector for the player's direction of length 1
const dir = {
x: Math.cos(m.angle),
y: Math.sin(m.angle)
};
const dir = { 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
if (Vector.dot(dir, diff) > m.fieldThreshold) {
return true;
@@ -2867,7 +2862,7 @@ const m = {
case 4: //assembler
return `<strong>+${(0.8 * couple).toFixed(1)}</strong> <strong class='color-f'>energy</strong> per second`
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
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
@@ -4415,7 +4410,7 @@ const m = {
//<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>
//<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: () => {
m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor

View File

@@ -189,7 +189,6 @@ const powerUps = {
} else {
powerUps.do = () => powerUps.draw();
}
tech.maxDuplicationEvent() //check to see if hitting 100% duplication
} else {
powerUps.draw = powerUps.drawCircle
if (tech.isHealAttract) {
@@ -325,7 +324,6 @@ const powerUps = {
if (tech.isCancelDuplication) {
const value = 0.05
tech.duplication += value
tech.maxDuplicationEvent()
simulation.makeTextLog(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${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: {
name: "coupling",
color: "#0ae", //"#0cf",
@@ -541,6 +662,7 @@ const powerUps = {
overHeal *= 2 //double the over heal converted to max health
//make sure overHeal doesn't kill player
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
m.setMaxHealth();
m.damage(overHeal);
@@ -944,7 +1066,7 @@ const powerUps = {
}
// console.log(options.length)
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) {
totalChoices *= 3
tech.cancelTechCount++
@@ -1011,8 +1133,7 @@ const powerUps = {
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
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 + 2 * (m.fieldMode === 8)
let totalChoices = 2 + tech.extraChoices + 3 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3
tech.cancelTechCount++
@@ -1092,8 +1213,7 @@ const powerUps = {
}
}
//set total choices
// let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8))
let totalChoices = 3 + tech.extraChoices + 2 * (m.fieldMode === 8)
let totalChoices = 3 + tech.extraChoices + 3 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3
tech.cancelTechCount++
@@ -1327,6 +1447,7 @@ const powerUps = {
},
spawnDelay(type, count, delay = 2) {
count *= delay
// let totalSpawned = 0
let cycle = () => {
if (count > 0) {
if (m.alive) requestAnimationFrame(cycle);
@@ -1335,6 +1456,8 @@ const powerUps = {
if (!(count % delay)) {
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);
// totalSpawned++
// if (!(totalSpawned % 10)) delay++
}
}
}
@@ -1400,11 +1523,10 @@ const powerUps = {
powerUps.randomPowerUpCounter++;
powerUpChance(Math.max(level.levelsCleared, 10) * 0.1)
}
if (!(simulation.difficulty > spawn.secondaryBossThreshold)) {
if (!(simulation.difficultyMode > 2 && level.levelsCleared > 1)) {
powerUps.randomPowerUpCounter += 0.6;
powerUpChance(Math.max(level.levelsCleared, 6) * 0.1)
}
function powerUpChance(chanceToFail) {
if (Math.random() * chanceToFail < powerUps.randomPowerUpCounter) {
powerUps.randomPowerUpCounter = 0;
@@ -1446,8 +1568,8 @@ const powerUps = {
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
if (mob.length && Math.random() < 0.45 - 0.3 * (simulation.difficultyMode > 4)) { //lower chance on why difficulty
addResearchToLevel() { //add a random power up to a location that has a mob, mostly used to give each level a research
if (simulation.difficultyMode < 4 && mob.length) { //don't spawn on higher difficulty settings
const index = Math.floor(Math.random() * mob.length)
powerUps.spawn(mob[index].position.x, mob[index].position.y, "research");
}
@@ -1535,7 +1657,7 @@ const powerUps = {
tech.tech[index].frequency = 0 //banish tech
powerUps.ejectTech(index)
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.animation = ""
document.getElementById(`${index}-pause-tech`).onclick = null
@@ -1614,7 +1736,7 @@ const powerUps = {
properties.isDuplicated = true
} else {
properties.inertia = Infinity //prevents rotation for circles only
polygonSides = 0
polygonSides = 12
}
powerUp[index] = Matter.Bodies.polygon(x, y, polygonSides, size, properties);
if (mode) powerUp[index].mode = mode

View File

@@ -192,10 +192,11 @@ const simulation = {
levelsCleared: 0,
difficultyMode: 2, //normal difficulty is 2
difficulty: 0,
dmgScale: null, //set in levels.setDifficulty
constraint: 0,
dmgScale: null,
healScale: 1,
accelScale: null, //set in levels.setDifficulty
CDScale: null, //set in levels.setDifficulty
accelScale: null,
CDScale: null,
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) {
// simulation.fpsCap = cap
@@ -625,8 +626,8 @@ const simulation = {
restoreCamera() {
ctx.restore();
},
trails() {
const swapPeriod = 150
trails(swapPeriod = 150) {
// const swapPeriod = 150
const len = 30
for (let i = 0; i < len; i++) {
setTimeout(function () {
@@ -846,10 +847,7 @@ const simulation = {
level.onLevel = 0;
level.levelsCleared = 0;
//resetting difficulty
// simulation.difficulty = 0;
level.setDifficulty()
simulation.difficultyMode = Number(document.getElementById("difficulty-select").value)
level.updateDifficulty()
simulation.clearNow = true;
document.getElementById("text-log").style.display = "none"
@@ -1143,15 +1141,6 @@ const simulation = {
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) {
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].isMutualismActive) {
@@ -1304,7 +1293,7 @@ const simulation = {
for (let i = 0, len = mob.length; i < len; i++) {
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
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)

View File

@@ -48,7 +48,8 @@ const spawn = {
// spawn.pickList.push(spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)]);
},
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) {
if (spawn.spawnChance(chance) || chance === Infinity) {
@@ -112,24 +113,8 @@ const spawn = {
}
}
},
secondaryBossThreshold: 22,
secondaryBossChance(x, y) {
// if (tech.isDuplicateMobs && Math.random() < tech.duplicationChance()) {
// 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?
if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
spawn.randomLevelBoss(x, y);
} else {
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.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 () {
if (!this.hasRunDeathScript) {
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
//this body is too big to leave behind in the normal way mobs.replace()
const len = body.length;
@@ -1029,8 +1020,6 @@ const spawn = {
}
requestAnimationFrame(loop);
}
// for (let i = 0; i < 3; i++)
level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
//remove power Ups, to avoid spamming console
function removeAll(array) {
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];
me.isBoss = true;
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.accelMag = 0.0002;
me.onDeath = function () {
@@ -1440,7 +1429,7 @@ const spawn = {
me.cellMassMax = 70
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
me.damageReduction = 0.17 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1); //me.damageReductionGoal
me.damageReduction = 0.17
const k = 642 //k=r^2/m
me.split = function () {
@@ -1525,7 +1514,7 @@ const spawn = {
me.onHit = function () { //run this function on hitting player
this.explode();
};
me.damageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1);
me.damageReduction = 0.14
me.doAwake = function () {
this.alwaysSeePlayer();
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"
}
}
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.2
//required setup for invulnerable
// me.isInvulnerable = false
me.invulnerabilityCountDown = 0
@@ -1702,7 +1691,7 @@ const spawn = {
} else if (!m.isCloak) {
me.foundPlayer();
}
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.2
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
@@ -1780,7 +1769,7 @@ const spawn = {
me.foundPlayer();
}
me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.22
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
@@ -2157,7 +2146,7 @@ const spawn = {
mobs.spawn(x, y, 5, radius, "rgb(0,200,180)");
let me = mob[mob.length - 1];
me.isBoss = true;
me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.09
me.accelMag = 0.05; //jump height
me.g = 0.003; //required if using this.gravity
me.frictionAir = 0.01;
@@ -2207,7 +2196,7 @@ const spawn = {
// powerUps.spawnBossPowerUp(this.position.x, this.position.y)
// };
// me.lastSpeed = me.speed
// me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.damageReduction = 0.25
// me.do = function() {
// // this.armor();
// this.gravity();
@@ -2279,10 +2268,7 @@ const spawn = {
me.fill = "#28b";
me.rememberFill = me.fill;
me.cd = 0;
me.burstDir = {
x: 0,
y: 0
};
me.burstDir = { x: 0, y: 0 };
me.frictionAir = 0.022;
me.lookTorque = 0.0000014;
me.restitution = 0;
@@ -2386,6 +2372,7 @@ const spawn = {
ctx.fill();
}
}
if (simulation.difficultyMode === 6) spawn.shield(me, x, y);
},
// timeBoss(x, y, radius = 25) {
// mobs.spawn(x, y, 12, radius, "#000");
@@ -2403,7 +2390,7 @@ const spawn = {
// me.onDeath = function() {
// 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() {
// //keep it slow, to stop issues from explosion knock backs
// if (!(simulation.cycle % this.seePlayerFreq)) {
@@ -2483,7 +2470,7 @@ const spawn = {
// toMe(bullet, this.position, this.eventHorizon))
}
};
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.do = function () {
//keep it slow, to stop issues from explosion knock backs
if (this.speed > 1) {
@@ -2586,7 +2573,7 @@ const spawn = {
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
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
me.friction = 0;
@@ -2675,7 +2662,7 @@ const spawn = {
let me = mob[mob.length - 1];
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
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.friction = 0;
@@ -2991,7 +2978,7 @@ const spawn = {
me.laserRange = 350;
me.seeAtDistance2 = 2000000;
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.delayLimit = 60 + Math.floor(30 * Math.random());
@@ -3162,7 +3149,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, '#16576b');
let me = mob[mob.length - 1];
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
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
@@ -3265,7 +3252,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, color);
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.0025); //extra dense //normal is 0.001 //makes effective life much larger
// me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.damageReduction = 0.04
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);
@@ -3416,7 +3403,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
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.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -3607,7 +3594,7 @@ const spawn = {
let me = mob[mob.length - 1];
me.isBoss = true;
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
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)");
let me = mob[mob.length - 1];
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
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.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
me.damageReduction = 0.034 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.034
me.frictionStatic = 0;
me.friction = 0;
@@ -3903,7 +3890,7 @@ const spawn = {
me.do = function () {
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 () {
// this.armor();
this.checkStatus();
@@ -4004,6 +3991,7 @@ const spawn = {
me.pulseRadius = Math.min(400, 170 + simulation.difficulty * 3)
me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.isFiring = false
spawn.shield(me, x, y);
me.onHit = function () { };
me.canSeeTarget = function () {
const angle = this.angle + Math.PI / 2;
@@ -4124,7 +4112,7 @@ const spawn = {
}
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0002 * simulation.accelScale;
// me.frictionAir = 1
spawn.shield(me, x, y);
me.lasers = [] //keeps track of static laser beams
me.laserLimit = simulation.difficultyMode < 3 ? 1 : 2
@@ -4180,7 +4168,7 @@ const spawn = {
if (this.lasers[i].fade > 0.99) {
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
const dmg = 0.05 * simulation.dmgScale;
const dmg = 0.03 * simulation.dmgScale;
m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: best.x,
@@ -4270,14 +4258,12 @@ const spawn = {
}
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale;
me.isBoss = true;
me.onDeath = function () {
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
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -4286,17 +4272,13 @@ const spawn = {
if (this.health < this.nextHealthThreshold) {
this.health = this.nextHealthThreshold - 0.01
this.nextHealthThreshold = Math.floor(this.health * 4) / 4 //0.75,0.5,0.25
this.invulnerableCount = 120
this.invulnerableCount = 90
this.isInvulnerable = true
this.damageReduction = 0
// if (this.health > 0.74) this.laserLimit += 2 //increase total lasers once player gets into combat
// this.addLaser()
this.laserDelay = 130
}
};
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.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.cycle = 0
@@ -4349,7 +4331,7 @@ const spawn = {
if (this.lasers[i].fade > 0.99) {
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
const dmg = 0.05 * simulation.dmgScale;
const dmg = 0.03 * simulation.dmgScale;
m.damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: best.x,
@@ -4412,7 +4394,6 @@ const spawn = {
this.force.y += force.y;
} else { //drift
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.y += force.y;
}
@@ -4452,6 +4433,7 @@ const spawn = {
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
me.accelMag = 0.0001 * simulation.accelScale;
me.laserInterval = 100
spawn.shield(me, x, y);
me.onHit = function () {
//run this function on hitting player
this.explode();
@@ -4529,7 +4511,7 @@ const spawn = {
// me.torque -= me.inertia * 0.002
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
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.isBoss = true;
// spawn.shield(me, x, y, 1); //not working, not sure why
me.onDeath = function () {
@@ -4743,7 +4725,7 @@ const spawn = {
// spawn.shield(me, x, y, 1);
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.onDamage = function () { };
me.onDeath = function () {
@@ -4839,7 +4821,7 @@ const spawn = {
me.restitution = 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
me.damageReduction = 0.09 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.09
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -4935,7 +4917,7 @@ const spawn = {
me.isBoss = true;
me.isReactorBoss = true;
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.isInvulnerable = false
me.nextHealthThreshold = 0.75
@@ -5092,7 +5074,7 @@ const spawn = {
me.isBoss = true;
me.isReactorBoss = true;
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.inertia = Infinity;
me.isInvulnerable = false
@@ -5185,7 +5167,7 @@ const spawn = {
// me.skipRate = 1 + Math.floor(simulation.difficulty*0.02)
// spawn.shield(me, x, y, 1);
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.isInvulnerable = false
me.onDamage = function () {
@@ -5292,7 +5274,7 @@ const spawn = {
let me = mob[mob.length - 1];
Matter.Body.rotate(me, 2 * Math.PI * Math.random());
me.isBoss = true;
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.1
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.02
@@ -5740,7 +5722,7 @@ const spawn = {
let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger
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.frictionAir = 0.01;
@@ -5789,12 +5771,12 @@ const spawn = {
this.isCloaked = true;
this.isBadTarget = true;
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 () {
if (this.isCloaked) {
this.damageReduction = 0.4 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
this.damageReduction = 0.4
this.isCloaked = false;
this.isBadTarget = false;
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 () {
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
while (i--) {
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.memory = 240;
me.isVanished = false;
// spawn.shield(me, x, y); //makes it too hard to stealth
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
this.health = 1;
@@ -5931,6 +5915,7 @@ const spawn = {
me.memory = 900;
me.delay = 60
me.cd = 0;
spawn.shield(me, x, y, 1); // bad for stealth
me.onHit = function () {
if (this.cd < simulation.cycle) {
this.cd = simulation.cycle + this.delay;
@@ -6063,7 +6048,7 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body
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))
let radiusOrbitals = radius + 125 + 350 * Math.random()
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 () {
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 () {
// this.armor();
this.seePlayerCheckByDistance();
@@ -6106,7 +6091,7 @@ const spawn = {
me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
// spawn.shield(me, x, y);
spawn.shield(me, x, y);
me.do = function () {
this.seePlayerByLookingAt();
this.checkStatus();
@@ -6131,7 +6116,7 @@ const spawn = {
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
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.isVerticesChange = true
@@ -6293,14 +6278,11 @@ const spawn = {
me.accelMag = 0.0005 * simulation.accelScale;
me.frictionAir = 0.05;
me.torque = 0.0001 * me.inertia;
me.fireDir = {
x: 0,
y: 0
};
me.fireDir = { x: 0, y: 0 };
me.onDeath = function () { //helps collisions functions work better after vertex have been changed
// this.vertices = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices))
}
// spawn.shield(me, x, y);
spawn.shield(me, x, y);
me.do = function () {
// this.seePlayerByLookingAt();
this.seePlayerCheck();
@@ -6492,7 +6474,7 @@ const spawn = {
let me = mob[mob.length - 1];
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
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.2
me.accelMag = 0.0001 * simulation.accelScale;
me.fireFreq = Math.floor(330 * simulation.CDScale)
@@ -6535,7 +6517,7 @@ const spawn = {
// let me = mob[mob.length - 1];
// 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
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.damageReduction = 0.2
// me.fireFreq = Math.floor(60 * simulation.CDScale)
// me.seePlayerFreq = 15
@@ -6636,7 +6618,7 @@ const spawn = {
// let me = mob[mob.length - 1];
// 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
// me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.damageReduction = 0.2
// me.accelMag = 0.0001 * simulation.accelScale;
// 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 () {
// this.armor();
if (this.grenadeLimiter > 1) this.grenadeLimiter--
@@ -6757,16 +6739,13 @@ const spawn = {
me.accelMag = 0.0006 * simulation.accelScale;
me.frictionAir = 0.05;
me.torque = 0.0001 * me.inertia * (Math.random() > 0.5 ? -1 : 1)
me.fireDir = {
x: 0,
y: 0
};
me.fireDir = { x: 0, y: 0 };
me.onDeath = function () { //helps collisions functions work better after vertex have been changed
spawn.grenade(this.position.x, this.position.y, 200 * simulation.CDScale);
// mob[mob.length - 1].collisionFilter.category = 0
mob[mob.length - 1].collisionFilter.mask = cat.player | cat.map;
}
// spawn.shield(me, x, y);
spawn.shield(me, x, y);
me.do = function () {
this.seePlayerCheck();
this.checkStatus();
@@ -6897,7 +6876,7 @@ const spawn = {
me.onDamage = function () {
this.cycle = 0
};
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.35
me.do = function () {
Matter.Body.rotate(this, 0.003) //gently spin around
this.checkStatus();
@@ -6919,8 +6898,8 @@ const spawn = {
ctx.moveTo(this.position.x, this.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);
// me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
mob[mob.length - 1].damageReduction = 0.5 * 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) //shields are extra strong
// me.damageReduction = 0.075
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);
@@ -6943,7 +6922,7 @@ const spawn = {
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
me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.07
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
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
};
me.onDamage = function () { };
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.do = function () {
// this.armor();
this.seePlayerCheck();
@@ -7167,49 +7146,6 @@ const spawn = {
// 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)) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1];
@@ -7218,6 +7154,7 @@ const spawn = {
this.explode();
};
me.g = 0.0004; //required if using this.gravity
spawn.shield(me, x, y);
me.do = function () {
this.gravity();
this.seePlayerCheck();
@@ -7238,7 +7175,7 @@ const spawn = {
me.memory = 250;
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
me.startingDamageReduction = 0.14 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = 0.14
me.damageReduction = 0
me.isInvulnerable = true
@@ -7367,7 +7304,7 @@ const spawn = {
let me = mob[mob.length - 1];
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
me.startingDamageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = 0.1
me.damageReduction = 0
me.isInvulnerable = true
@@ -7497,7 +7434,7 @@ const spawn = {
let me = mob[mob.length - 1];
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
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.25
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
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) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1];
me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.05
me.isUnblockable = true
me.collisionFilter.category = cat.mobShield
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
me.frictionAir = 0;
me.shield = true;
me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.075
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
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)) {
if (Math.random() < chance) {
// simulation.difficulty = 50
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.003 + 0.004 * Math.random() + 0.002 * Math.sqrt(simulation.difficulty)) * ((Math.random() < 0.5) ? 1 : -1)
const offSet = 6.28 * Math.random()
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];
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
me.damageReduction = 0.1 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.1
me.stroke = "transparent"; //used for drawGhost
me.seeAtDistance2 = 2000000;
@@ -7956,13 +7893,18 @@ const spawn = {
this.force.x += -0.003;
player.force.x += 0.06;
// 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
Matter.Body.setVelocity(player, {
x: player.velocity.x,
y: player.velocity.y + 0.3
})
Matter.Body.setVelocity(player, { x: player.velocity.x, y: player.velocity.y + 0.3 })
//player friction from the wires
if (m.pos.x > 700 && player.velocity.x > -2) {
@@ -7974,10 +7916,7 @@ const spawn = {
})
}
//move to player
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))
})
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)) })
}
//draw wire
ctx.beginPath();

View File

@@ -248,22 +248,6 @@ const tech = {
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))
},
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) {
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].name === name) tech.tech[i].frequency = frequency
@@ -2485,7 +2469,7 @@ const tech = {
},
{
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,
count: 0,
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>`,
maxCount: 1,
count: 0,
@@ -2709,7 +2693,7 @@ const tech = {
},
{
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,
count: 0,
frequency: 1,
@@ -4269,26 +4253,6 @@ const tech = {
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",
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",
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,
count: 0,
@@ -5149,7 +5113,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5446,11 +5410,11 @@ const tech = {
requires: "wave",
effect() {
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() {
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,
frequencyDefault: 2,
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",
effect() {
@@ -8353,7 +8317,7 @@ const tech = {
{
name: "metamaterial absorber", //quantum eraser
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,
maxCount: 1,
@@ -9135,7 +9099,7 @@ const tech = {
// },
{
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,
count: 0,
frequency: 0,
@@ -9144,7 +9108,6 @@ const tech = {
allowed: () => true,
requires: "",
effect() {
level.difficultyDecrease(simulation.difficultyMode * 2)
level.onLevel = 0
simulation.clearNow = true //end current level
},
@@ -10657,7 +10620,7 @@ const tech = {
remove() { }
},
{
name: "stubs",
name: "wall jump",
description: "no knees or toes are drawn on the player<br>you can wall climb though",
maxCount: 1,
count: 0,
@@ -10670,11 +10633,12 @@ const tech = {
requires: "",
effect() {
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() {
// if (this.count) m.resetSkin();
}
remove() { }
},
{
name: "Sleipnir",
@@ -10767,25 +10731,6 @@ const tech = {
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",
description: "stand a bit taller",
@@ -10869,7 +10814,7 @@ const tech = {
// },
{
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,
count: 0,
frequency: 0,
@@ -10882,7 +10827,6 @@ const tech = {
effect() {
m.isAltSkin = true
m.shipMode()
level.difficultyDecrease(simulation.difficultyMode)
//unlock relativistic rotation
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].name === "relativistic rotation") tech.tech[i].frequency = 10
@@ -10983,23 +10927,6 @@ const tech = {
},
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",
description: "<strong>stun</strong> all mobs for up to <strong>8</strong> seconds",
@@ -11045,6 +10972,23 @@ const tech = {
},
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",
description: `<strong>eject</strong> all your ${powerUps.orb.research(1)}`,
@@ -11083,6 +11027,31 @@ const tech = {
},
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!",
descriptionFunction() {
@@ -11762,7 +11731,6 @@ const tech = {
pauseEjectTech: null,
isShieldPierce: null,
isDuplicateMobs: null,
is100Duplicate: null,
isDynamoBotUpgrade: null,
isBlockPowerUps: null,
isDamageAfterKillNoRegen: null,

132
style.css
View File

@@ -587,6 +587,17 @@ summary {
background-color: #fff;
}
#dmg {
position: absolute;
z-index: 2;
@@ -1502,3 +1513,124 @@ summary {
stroke-dashoffset: 300;
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 **************************************************
tech: anyon - 2x energy after duplicating a power up, +6% duplication chance
tech: Abelian group - 4x damage while invulnerable
tech: fermion - become invulnerable for 5 seconds after a mob dies
tech: entropic gravity - crouching pulls MACHO towards the player, and 1.5x to all MACHO effects (damage, damage reduction, AoE damage)
tech: modified Newtonian dynamics - +20 speed for all Newtonian law tech
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)
choice, MACHO, invulnerable, speed - have text keyword CSS style
removed chance to find a random tech in early levels from mobs
this reduces tech per full game by about 2
tower level has a few changes
options exchange only works once per level, but it gives 3x choices after randomizing
dark star has a 1.2->1.3x MACHO radius
autocannon fires 1->2 extra super balls, but balls have higher gravity
grappling hook field starts with 0.6x damage reduction
super balls + uncertainty principle makes all balls start in the same spot and only separate after teleporting
ablative drones spawns 50% more drones on collision
von Neumann probe gives 40% more drones per block mass
also added text clarification that it uses 5 energy
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
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
fixed bug with 2 different boost power up sizes
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
bug fixes
******************************************************* DESIGN ******************************************************
@@ -53,30 +46,70 @@ powerful synergies
*********************************************************** TODO *****************************************************
make each difficulty level have specific listed changes
to motivate people to try that difficulty to see the difference
make difficulty easier to see
in pause menu
before game begins
automatically increase difficulty when player wins?
difficulty based changes (maybe in the order)
more bosses
more mobs
mobs attack faster
mobs move faster
reduced heals
reduced damage done
increased damage taken
mobs regen health
-1 choice for tech, field, gun
no starting power ups (heal, research)
starting JUNK chance?
difficulty rework: explicit changes to the game to increase difficulty
UI -
add difficulty display to pause menu
update pause menu text to match opening screen menu
just make it a square like field or gun on left pause column
add a wire attached to difficulty power up
like the one attached to player, but thinner
add new difficulty to game code
todo
check for any undocumented side effects
heal power ups (small effect)
(remove, keep, or add to parameters)
balance testing log:
difficultyMode=5 died on level 5 with a good drone build, seemed similar balance to old why mode, maybe slightly harder...
difficultyMode=2 won with a good spore build, seemed similar balance to old normal mode
tokamak synergy tech
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
shows up on n-gon, and landgreen github, but webp file isn't loading onto server?
try name change,
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.
after snap shot is stored draw outline of body positions for a second to show the change
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
ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
equivalence principle - gravity and acceleration are the same
Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer
******************************************************** IMAGES ********************************************************