diff --git a/index.html b/index.html index 15483fc..02ba3f7 100644 --- a/index.html +++ b/index.html @@ -46,19 +46,124 @@ training +
+ +
settings
- +
diff --git a/js/bullet.js b/js/bullet.js index 9b564b1..65e4891 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -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) { diff --git a/js/index.js b/js/index.js index c19e3ba..85956c6 100644 --- a/js/index.js +++ b/js/index.js @@ -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 = {
-
damage: ${((tech.damageFromTech())).toPrecision(4)}x difficulty: ${((m.dmgScale)).toPrecision(4)}x -
damage taken: ${(m.defense()).toPrecision(4)}x difficulty: ${(simulation.dmgScale).toPrecision(4)}x -
fire rate: ${(1 / b.fireCDscale).toFixed(2)}x -${tech.duplicationChance() ? `
duplication: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""} -${m.coupling ? `
` + m.couplingDescription(m.coupling) + ` from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""} -${botText} -
-
health: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)}) -mass: ${player.mass.toFixed(1)} -
energy: (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000).toFixed(0)}/s) -position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) -
gun: ${b.activeGun === null || b.activeGun === undefined ? "undefined" : b.guns[b.activeGun].name}   ammo: ${b.activeGun === null || b.activeGun === undefined ? "0" : b.guns[b.activeGun].ammo} -mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) -
tech: ${tech.totalCount}   research: ${powerUps.research.count} -velocity: (${player.velocity.x.toFixed(3)}, ${player.velocity.y.toFixed(3)}) -${tech.junkChance ? `
JUNK: ${(100 * tech.junkChance).toFixed(1)}% ` : ""} -
-
level: ${level.levelsCleared} ${level.levels[level.onLevel]} (${level.difficultyText()}) -
mobs: ${spawn.pickList[0]}, ${spawn.pickList[0]} -
seed: ${Math.initialSeed}   ${m.cycle} cycles -
mobs: ${mob.length}   blocks: ${body.length}   bullets: ${bullet.length}   power ups: ${powerUp.length} -${simulation.isCheating ? "

lore disabled" : ""} -
`; +
difficulty +
+6 initial power ups
5% chance for mobs to a drop tech
+
10% chance for shielded mobs
0.5x heal power ups
+
1.5x mob movement and reactions
0.5x damage
+
+1 boss per level, -1 tech per boss
2x damage taken
+
-3 initial power ups
0.5x damage
+
10% chance for shielded mobs
2x damage taken
+
+ + +
damage: ${((tech.damageFromTech())).toPrecision(4)}x difficulty: ${((m.dmgScale)).toPrecision(4)}x +
damage taken: ${(m.defense()).toPrecision(4)}x difficulty: ${(simulation.dmgScale).toPrecision(4)}x +
fire rate: ${(1 / b.fireCDscale).toFixed(2)}x + ${tech.duplicationChance() ? `
duplication: ${(tech.duplicationChance() * 100).toFixed(0)}%` : ""} + ${m.coupling ? `
` + m.couplingDescription(m.coupling) + ` from ${(m.coupling).toFixed(0)} ${powerUps.orb.coupling(1)}` : ""} + ${botText} +
+
health: (${(m.health * 100).toFixed(0)} / ${(m.maxHealth * 100).toFixed(0)}) + mass: ${player.mass.toFixed(1)} +
energy: (${(m.energy * 100).toFixed(0)} / ${(m.maxEnergy * 100).toFixed(0)}) + (${(m.fieldRegen * 6000).toFixed(0)}/s) + position: (${player.position.x.toFixed(1)}, ${player.position.y.toFixed(1)}) +
gun: ${b.activeGun === null || b.activeGun === undefined ? "undefined" : b.guns[b.activeGun].name}   ammo: ${b.activeGun === null || b.activeGun === undefined ? "0" : b.guns[b.activeGun].ammo} + mouse: (${simulation.mouseInGame.x.toFixed(1)}, ${simulation.mouseInGame.y.toFixed(1)}) +
tech: ${tech.totalCount}   research: ${powerUps.research.count} + velocity: (${player.velocity.x.toFixed(3)}, ${player.velocity.y.toFixed(3)}) + ${tech.junkChance ? `
JUNK: ${(100 * tech.junkChance).toFixed(1)}% ` : ""} +
+
mobs: ${spawn.pickList[0]}, ${spawn.pickList[0]} +
seed: ${Math.initialSeed}   ${m.cycle} cycles +
mobs: ${mob.length}   blocks: ${body.length}   bullets: ${bullet.length}   power ups: ${powerUp.length} ${simulation.isCheating ? "

lore disabled" : ""}
`; // deaths: ${mobs.mobDeaths}   // 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 += `
- //
+ // text += `
+ //
//
  ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}
// ${m.fieldUpgrades[m.fieldMode].description}
` if ((tech.isPauseSwitchField || simulation.testing)) { //&& !simulation.isChoosing @@ -515,21 +522,21 @@ ${simulation.isCheating ? "

lore disabled" : ""}
` //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 += `
-
-
  ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}
- ${m.fieldUpgrades[m.fieldMode].description}
` + text += `
+
+
  ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}
+ ${m.fieldUpgrades[m.fieldMode].description}
` //button below for next - text += `
-
` + text += `
+
` } 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 += `
-
-
  ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}
- ${m.fieldUpgrades[m.fieldMode].description}
` + text += `
+
+
  ${build.nameLink(m.fieldUpgrades[m.fieldMode].name)}
+ ${m.fieldUpgrades[m.fieldMode].description}
` } // for (let i = 0, len = b.inventory.length; i < len; i++) { // text += `
  ${build.nameLink(b.guns[b.inventory[i]].name)} - ${b.guns[b.inventory[i]].ammo}
${b.guns[b.inventory[i]].description}
` @@ -537,26 +544,26 @@ ${simulation.isCheating ? "

lore disabled" : ""} 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 += `
-
-
  ${build.nameLink(b.guns[b.inventory[i]].name)} - ${b.guns[b.inventory[i]].ammo}
- ${b.guns[b.inventory[i]].descriptionFunction()}
` +
+
  ${build.nameLink(b.guns[b.inventory[i]].name)} - ${b.guns[b.inventory[i]].ammo}
+ ${b.guns[b.inventory[i]].descriptionFunction()}
` } - if (!localSettings.isHideHUD) text += `
${document.getElementById("text-log").innerHTML}
` //show last in game console message + if (!localSettings.isHideHUD) text += `
${document.getElementById("text-log").innerHTML}
` //show last in game console message let el = document.getElementById("pause-grid-left") el.style.display = "grid" el.innerHTML = text }, generatePauseRight() { let text = `
- - - - - - - - -
`; + + + + + + + + +
`; 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 ? "

lore disabled" : ""} isExperimentRun: false, techText(i) { return `
-
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` +
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
+ ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, instantTechText(i) { // return `
-
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` +
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
+ ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, skinTechText(i) { return `
- -
-
-
       ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` + +
+
+
       ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""} + ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, gunTechText(i) { return `
- -
-
-
          ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` + +
+
+
          ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""} + ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, fieldTechText(i) { return `
- -
-
-
          ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` + +
+
+
          ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""} + ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, junkTechText(i) { return `
-
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
- ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}
` +
  ${build.nameLink(tech.tech[i].name)} ${tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : ""}
+ ${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() : tech.tech[i].description}` }, choosePowerUp(index, type, isAllowed = false) { if (type === "gun") { @@ -804,8 +811,8 @@ ${simulation.isCheating ? "

lore disabled" : ""} // document.getElementById(`field-${i}`).innerHTML = `
  ${build.nameLink(m.fieldUpgrades[i].name)}
${m.fieldUpgrades[i].description}` document.getElementById(`field-${i}`).innerHTML = `
-
  ${build.nameLink(m.fieldUpgrades[i].name)}
- ${m.fieldUpgrades[i].description}
` +
  ${build.nameLink(m.fieldUpgrades[i].name)}
+ ${m.fieldUpgrades[i].description}` } } else if (type === "tech") { if (tech.tech[index].count < tech.tech[index].maxCount) { @@ -877,72 +884,73 @@ ${simulation.isCheating ? "

lore disabled" : ""} } } }, + //
+ // + //     + // + // + //
+ + // + // populateGrid() { //background-color:var(--build-bg-color); let text = ` -
-
- - - - - - - - - - -
-
- -     - - -
-
-
-
- - - start - - -
-
- - - reset - - -
-
- - - share - - -
-
-
-
` +
+
+ + + + + + + + +
+
+
+
+ + + start + + +
+
+ + + reset + + +
+
+ + + share + + +
+
+
+
` 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 += `
-
-
  ${build.nameLink(m.fieldUpgrades[i].name)}
- ${m.fieldUpgrades[i].description}
` + text += `
+
+
  ${build.nameLink(m.fieldUpgrades[i].name)}
+ ${m.fieldUpgrades[i].description}
` } 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 += `
-
-
  ${build.nameLink(b.guns[i].name)}
- ${b.guns[i].descriptionFunction()}
` + text += `
+
+
  ${build.nameLink(b.guns[i].name)}
+ ${b.guns[i].descriptionFunction()}
` } 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 ? "

lore disabled" : ""} } 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 ? "

lore disabled" : ""} requestAnimationFrame(() => { document.getElementById("sort-input").focus(); }); }, nameLink(text) { //converts text into a clickable wikipedia search - return `${text}` + return `${text}` }, reset() { build.isExperimentSelection = true; @@ -1010,7 +1018,7 @@ ${simulation.isCheating ? "

lore disabled" : ""} build.isExperimentSelection = true; build.isExperimentRun = true; simulation.paused = true; - b.inventory = []; //removes guns and ammo + b.inventory = []; //removes guns and ammo for (let i = 0, len = b.guns.length; i < len; ++i) { b.guns[i].count = 0; b.guns[i].have = false; @@ -1197,7 +1205,7 @@ const input = { document.getElementById("key-pause").innerHTML = cleanText(input.key.pause) document.getElementById("key-next-gun").innerHTML = cleanText(input.key.nextGun) document.getElementById("key-previous-gun").innerHTML = cleanText(input.key.previousGun) - document.getElementById("key-testing").innerHTML = cleanText(input.key.testing) //if (localSettings.loreCount > 0) + document.getElementById("key-testing").innerHTML = cleanText(input.key.testing) //if (localSettings.loreCount > 0) document.getElementById("splash-up").innerHTML = cleanText(input.key.up)[0] document.getElementById("splash-down").innerHTML = cleanText(input.key.down)[0] @@ -1437,59 +1445,59 @@ window.addEventListener("keydown", function (event) { if (simulation.testing) tech.setCheating(); simulation.makeTextLog( ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Ttoggle testing
Rteleport to mouse
Fcycle field
Gall guns
H+100% defense
Bdamage, research
Nfill health, energy
Yrandom tech
Unext level
Jclear mobs
I/Ozoom in / out
1-8spawn things
⇧Xrestart
`, Infinity); + + T + toggle testing + + + R + teleport to mouse + + + F + cycle field + + + G + all guns + + + H + +100% defense + + + B + damage, research + + + N + fill health, energy + + + Y + random tech + + + U + next level + + + J + clear mobs + + + I/O + zoom in / out + + + 1-8 + spawn things + + + ⇧X + restart + + `, 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 +// 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(); diff --git a/js/level.js b/js/level.js index f5cfa4f..8283da8 100644 --- a/js/level.js +++ b/js/level.js @@ -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(`level.onLevel = "${level.levels[level.onLevel]}"`); } - // simulation.makeTextLog(` - // input.key.up = ["${input.key.up}", "ArrowUp"] - //
input.key.left = ["${input.key.left}", "ArrowLeft"] - //
input.key.down = ["${input.key.down}", "ArrowDown"] - //
input.key.right = ["${input.key.right}", "ArrowRight"] - //
- //
m.fieldMode = "${m.fieldUpgrades[m.fieldMode].name}" - //
input.key.field = ["${input.key.field}", "right mouse"] - //
m.field.description = "${m.fieldUpgrades[m.fieldMode].description}" - // `, 1200); }, announceMobTypes() { simulation.makeTextLog(`spawn.${spawn.pickList[0]}(x,y)`) @@ -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(`temple by Scar1337`); @@ -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(`ace by Richard0820`); 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; diff --git a/js/lore.js b/js/lore.js index ff5372e..4a3ccb3 100644 --- a/js/lore.js +++ b/js/lore.js @@ -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"; diff --git a/js/player.js b/js/player.js index 7160cbf..4d0fc6c 100644 --- a/js/player.js +++ b/js/player.js @@ -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(`m.maxEnergy = ${(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 `+${(0.8 * couple).toFixed(1)} energy per second` case 5: //plasma - return `${(1 + 1.5 * couple).toFixed(3)}x damage` + return `${(1 + 0.015 * couple).toFixed(3)}x damage` case 6: //time dilation return `+${(1 + 0.05 * couple).toFixed(2)}x longer stopped time` //movement, jumping, and case 7: //cloaking @@ -4415,7 +4410,7 @@ const m = { //
blocks can't collide with intangible mobs //field radius decreases out of line of sight //unlock tech from other fields - description: "use energy to guide blocks
tech, fields, and guns have +2 choices
10 energy per second", + description: "use energy to guide blocks
tech, fields, and guns have +3 choices
10 energy per second", effect: () => { m.fieldMeterColor = "#333" m.eyeFillColor = m.fieldMeterColor diff --git a/js/powerup.js b/js/powerup.js index 9242508..baa954d 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -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() += ${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 = `
+
+
+ + + + + + + + + +
+
+
0.82x damage done per level +
1.25x damage taken per level
+
-5 initial power ups +
faster and more mobs per level
+
0.82x damage done per level +
1.25x damage taken per level
+
+1 boss per level, -1 tech per boss +
-1 ${powerUps.orb.research()} per level
+
0.82x damage done per level +
1.25x damage taken per level
+
3x chance for shielded mobs +
-3 initial power ups
+
+
+
${localSettings.difficultyCompleted[1] ? "⚆" : " "}
+
${localSettings.difficultyCompleted[2] ? "⚆" : " "}
+
${localSettings.difficultyCompleted[3] ? "⚆" : " "}
+
${localSettings.difficultyCompleted[4] ? "⚆" : " "}
+
${localSettings.difficultyCompleted[5] ? "⚇" : " "}
+
${localSettings.difficultyCompleted[6] ? "⚇" : " "}
+
+
+
+ confirm difficulty parameters +
+
` + 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 diff --git a/js/simulation.js b/js/simulation.js index e1f05d2..61aeffc 100644 --- a/js/simulation.js +++ b/js/simulation.js @@ -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) diff --git a/js/spawn.js b/js/spawn.js index 72b0b8b..ea1c27b 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -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(`m.research -= 3
${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(); diff --git a/js/tech.js b/js/tech.js index 9863578..e133801 100644 --- a/js/tech.js +++ b/js/tech.js @@ -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: "crouching pulls the MACHO towards you
1.5x to all MACHO effects", + description: "crouching pulls the MACHO towards you
1.5x for all MACHO effects", maxCount: 1, count: 0, frequency: 2, @@ -2651,7 +2635,7 @@ const tech = { } }, { - name: "Abelian group", + name: "abelian group", description: `4x damage while invulnerable`, maxCount: 1, count: 0, @@ -2709,7 +2693,7 @@ const tech = { }, { name: "ground state", - description: "+266 maximum energy
0.66x passive energy generation", + description: "+300 maximum energy
0.66x passive energy 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 100% duplication
spawn 11 bosses with 2x durability`, - 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: "+20% chance to duplicate spawned power ups,
collisions eject a random tech", @@ -4482,7 +4446,7 @@ const tech = { { name: "paradigm shift", descriptionFunction() { - return `when paused clicking a tech ejects it
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.2x cost each use)` + return `when paused clicking a tech ejects it
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.3x cost each use)` }, 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 alive after you exit a level
there is a 25% chance to spawn a random power up` + return `for each mob left alive after you exit a level
there is a 30% chance to spawn a random power up` }, isFieldTech: true, maxCount: 1, @@ -9135,7 +9099,7 @@ const tech = { // }, { name: "return", - description: "return to the start of the game
reduce combat difficulty by 2 levels", + 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
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
reduce combat difficulty by 1 level", + 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 difficulty by 1 level", - maxCount: 1, - count: 0, - frequency: 0, - isInstant: true, - isJunk: true, - allowed() { - return true - }, - requires: "", - effect() { - level.difficultyIncrease(simulation.difficultyMode) - }, - remove() { } - }, { name: "stun", description: "stun all mobs for up to 8 seconds", @@ -11045,6 +10972,23 @@ const tech = { }, remove() { } }, + { + name: "difficulty", + description: "spawn a power up that lets you
adjust the simulation difficulty 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: `eject all your ${powerUps.orb.research(1)}`, @@ -11083,6 +11027,31 @@ const tech = { }, remove() { } }, + { + name: "apomixis", + description: `spawn 11 bosses`, + 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, diff --git a/style.css b/style.css index 980ec5b..581b95c 100644 --- a/style.css +++ b/style.css @@ -587,6 +587,17 @@ summary { background-color: #fff; } + + + + + + + + + + + #dmg { position: absolute; z-index: 2; @@ -1501,4 +1512,125 @@ summary { stroke-dasharray: 300; 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; } \ No newline at end of file diff --git a/todo.txt b/todo.txt index 06eeddd..3cf5524 100644 --- a/todo.txt +++ b/todo.txt @@ -1,35 +1,28 @@ ******************************************************** 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 ****************************************************** -priorities +priorities synergies between tech difficult to achieve synergies that feel so powerful they are game breaking / changing randomized content adds repeatability @@ -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 ********************************************************