endless experimental mode

"labs" is now in the normal map rotation
experimental mode is now endless  (no gauntlet, finalBoss, ...)
fixed a bug that was giving experimental mode full life at the start

perfect diamagnetism field has a 10% larger radius and arc
the 1/15 second cooldown after blocking with perfect diamagnetism no longer stops you from blocking
  it still disables field damage effects and player recoil after blocking  (for 1/15 of a second)

mass-energy now works with catabolism by removing max energy to make ammo
ergodicity - now reduces difficulty by 2 levels and prevent healing from heal power ups (was all healing)
Noether violation gives even more forward recoil
blinkBoss has more health, but it's much slower at easy difficulty
This commit is contained in:
landgreen
2021-08-01 06:33:53 -07:00
parent 1a5071cf06
commit 7e6fc208a9
10 changed files with 239 additions and 214 deletions

View File

@@ -95,18 +95,21 @@ const b = {
},
outOfAmmo() { //triggers after firing when you have NO ammo
simulation.makeTextLog(`${b.guns[b.activeGun].name}.<span class='color-gun'>ammo</span><span class='color-symbol'>:</span> 0`);
m.fireCDcycle = m.cycle + 30; //fire cooldown
if (tech.isAmmoFromHealth && m.maxHealth > 0.01) {
tech.extraMaxHealth -= 0.01 //decrease max health
m.setMaxHealth();
m.fireCDcycle = m.cycle + 30; //fire cooldown
if (tech.isAmmoFromHealth) {
if (tech.isEnergyHealth) {
tech.healMaxEnergyBonus -= 0.01
m.setMaxEnergy();
} else if (m.maxHealth > 0.01) {
tech.extraMaxHealth -= 0.01 //decrease max health
m.setMaxHealth();
}
for (let i = 0; i < 4; i++) powerUps.spawn(m.pos.x + 50 * (Math.random() - 0.5), m.pos.y + 50 * (Math.random() - 0.5), "ammo");
// if (m.health > 0.03) {
// m.damage(0.03 / m.harmReduction()); // /m.harmReduction() undoes damage increase from difficulty
// if (!(tech.isRewindAvoidDeath && m.energy > 0.66)) { //don't give ammo if CPT triggered
//
// }
// }
}
// if (tech.isAmmoFromHealth && m.maxHealth > 0.01) {
// tech.extraMaxHealth -= 0.01 //decrease max health
// m.setMaxHealth();
// }
},
giveGuns(gun = "random", ammoPacks = 10) {
if (tech.isOneGun) b.removeAllGuns();
@@ -3794,8 +3797,8 @@ const b = {
}
if (tech.isShotgunReversed) {
player.force.x += 2 * knock * Math.cos(m.angle)
player.force.y += 2 * knock * Math.sin(m.angle) - 6 * player.mass * simulation.g
player.force.x += 4 * knock * Math.cos(m.angle)
player.force.y += 4 * knock * Math.sin(m.angle) - 6 * player.mass * simulation.g
} else if (tech.isShotgunRecoil) {
m.fireCDcycle -= 0.66 * (45 * b.fireCDscale)
player.force.x -= 2 * knock * Math.cos(m.angle)

View File

@@ -106,7 +106,7 @@ window.addEventListener('load', () => {
simulation.difficultyMode = Number(set[property])
document.getElementById("difficulty-select-experiment").value = Number(set[property])
}
if (property === "level") document.getElementById("starting-level").value = Number(set[property])
if (property === "level") document.getElementById("starting-level").value = Math.max(Number(set[property]) - 1, 0)
if (property === "noPower") document.getElementById("no-power-ups").checked = Number(set[property])
}
}
@@ -275,7 +275,7 @@ const build = {
document.getElementById("pause-grid-right").style.display = "none"
window.scrollTo(0, 0);
},
isExperimentSelection: true,
isExperimentSelection: false,
choosePowerUp(who, index, type, isAllowed = false) {
if (type === "gun") {
let isDeselect = false
@@ -413,7 +413,7 @@ const build = {
</svg>
</div>
<div style="align-items: center; text-align:center; font-size: 1.00em; line-height: 190%;background-color:var(--build-bg-color);">
<div>starting level: <input id='starting-level' type="number" step="1" value="0" min="0" max="99"></div>
<div>starting level: <input id='starting-level' type="number" step="1" value="1" min="0" max="99"></div>
<div>
<label for="difficulty-select" title="effects: number of mobs, damage done by mobs, damage done to mobs, mob speed, heal effects">difficulty:</label>
<select name="difficulty-select" id="difficulty-select-experiment">
@@ -466,7 +466,7 @@ const build = {
},
reset() {
simulation.startGame(true); //starts game, but pauses it
build.isExperimentSelection = true;
build.isExperimentSelection = false;
simulation.paused = true;
m.setField(0)
b.inventory = []; //removes guns and ammo
@@ -537,7 +537,7 @@ const build = {
}
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
bullet = []; //remove any bullets that might have spawned from tech
const levelsCleared = Math.abs(Number(document.getElementById("starting-level").value))
const levelsCleared = Math.abs(Number(document.getElementById("starting-level").value) - 1)
level.difficultyIncrease(Math.min(99, levelsCleared * simulation.difficultyMode)) //increase difficulty based on modes
level.levelsCleared += levelsCleared;
simulation.isNoPowerUps = document.getElementById("no-power-ups").checked
@@ -573,6 +573,7 @@ function openExperimentMenu() {
document.body.style.overflowY = "scroll";
document.body.style.overflowX = "hidden";
document.getElementById("info").style.display = 'none'
build.isExperimentSelection = true
build.reset();
}

View File

@@ -7,7 +7,7 @@ const level = {
defaultZoom: 1400,
onLevel: -1,
levelsCleared: 0,
playableLevels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber"],
playableLevels: ["skyscrapers", "rooftops", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "labs"],
levels: [],
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
@@ -17,16 +17,9 @@ const level = {
// tech.isFieldFree = true
// m.setField("perfect diamagnetism")
// b.giveGuns("shotgun")
// tech.isNeedleShot = true
// tech.isIceShot = true
// tech.isFoamShot = true
// tech.isWormShot = true
// tech.giveTech("CPT reversal")
// tech.giveTech("causality bombs")
// tech.giveTech("Noether violation")
// b.giveGuns("wave beam")
// tech.giveTech("phonon")
// tech.giveTech("cardinality")
// tech.giveTech("isotropic radiator")
// tech.giveTech("Lenz's law")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length")
// for (let i = 0; i < 4; i++) tech.giveTech()
@@ -233,6 +226,9 @@ const level = {
player.force.y = 0;
Matter.Body.setPosition(player, m.spawnPos);
Matter.Body.setVelocity(player, m.spawnVel);
//makes perfect diamagnetism tech: Lenz's law show up in the right spot at the start of a level
m.fieldPosition = { x: m.pos.x, y: m.pos.y }
m.fieldAngle = m.angle
},
enter: {
x: 0,
@@ -1082,6 +1078,7 @@ const level = {
doCustom = []
doCustomTopLayer = []
offset = { x: 0, y: 0 }
const mobSpawnChance = 0 // Math.random() < chance + 0.07 * simulation.difficulty
enterOptions = [
(x = offset.x, y = offset.y) => { //lasers
level.setPosToSpawn(x + 1750, y - 800);
@@ -1127,12 +1124,12 @@ const level = {
hazard4.opticalQuery();
if (!isSpawnedMobs && !toggle.isOn) {
isSpawnedMobs = true
spawn.randomMob(x + 150, y + -1100, Infinity);
spawn.randomMob(x + 175, y + -775, Infinity);
spawn.randomMob(x + 150, y + -350, Infinity);
spawn.randomMob(x + 150, y + -75, Infinity);
spawn.randomMob(x + 650, y + -125, Infinity);
spawn.randomMob(x + 1200, y + -75, Infinity);
spawn.randomMob(x + 150, y + -1100, mobSpawnChance);
spawn.randomMob(x + 175, y + -775, mobSpawnChance);
spawn.randomMob(x + 150, y + -350, mobSpawnChance);
spawn.randomMob(x + 150, y + -75, mobSpawnChance);
spawn.randomMob(x + 650, y + -125, mobSpawnChance);
spawn.randomMob(x + 1200, y + -75, mobSpawnChance);
}
}
)
@@ -1168,11 +1165,11 @@ const level = {
() => {
if (!isInRoom && m.pos.x > x - 100 && m.pos.x < x + 2700 && m.pos.y > y - 1300 && m.pos.y < y) { //check if player is in this room and run code once
isInRoom = true
spawn.randomMob(x + 1175, y - 725, Infinity);
spawn.randomMob(x + 1450, y - 725, Infinity);
spawn.randomMob(x + 425, y - 100, Infinity);
spawn.randomMob(x + 1200, y - 125, Infinity);
spawn.randomMob(x + 1300, y - 375, Infinity);
spawn.randomMob(x + 1175, y - 725, mobSpawnChance);
spawn.randomMob(x + 1450, y - 725, mobSpawnChance);
spawn.randomMob(x + 425, y - 100, mobSpawnChance);
spawn.randomMob(x + 1200, y - 125, mobSpawnChance);
spawn.randomMob(x + 1300, y - 375, mobSpawnChance);
}
ctx.fillStyle = "#d4f4f4"
ctx.fillRect(x + 1550, y - 1300, 450, 350)
@@ -1237,11 +1234,11 @@ const level = {
() => {
if (!isInRoom && m.pos.x > x - 100 && m.pos.x < x + 2700 && m.pos.y > y - 1300 && m.pos.y < y) { //check if player is in this room and run code once
isInRoom = true
spawn.randomMob(x + 1175, y - 725, Infinity);
spawn.randomMob(x + 1450, y - 725, Infinity);
spawn.randomMob(x + 425, y - 100, Infinity);
spawn.randomMob(x + 1200, y - 125, Infinity);
spawn.randomMob(x + 1300, y - 375, Infinity);
spawn.randomMob(x + 1175, y - 725, mobSpawnChance);
spawn.randomMob(x + 1450, y - 725, mobSpawnChance);
spawn.randomMob(x + 425, y - 100, mobSpawnChance);
spawn.randomMob(x + 1200, y - 125, mobSpawnChance);
spawn.randomMob(x + 1300, y - 375, mobSpawnChance);
}
ctx.fillStyle = "#d4f4f4"
ctx.fillRect(x + 1600, y - 1300, 400, 350)
@@ -1290,11 +1287,11 @@ const level = {
}
}
)
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 300, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
spawn.randomMob(x + 2000 - 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 2000 - 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 2000 - 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 2000 - 650, y + -875)
@@ -1322,11 +1319,11 @@ const level = {
}
}
)
spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
spawn.randomMob(x + 300, y + -1200, Infinity);
spawn.randomMob(x + 800, y + -125, Infinity);
spawn.randomMob(x + 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y + -875)
@@ -1382,11 +1379,11 @@ const level = {
}
}
)
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 300, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
spawn.randomMob(x + 2000 - 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 2000 - 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 2000 - 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y + -875)
@@ -1439,11 +1436,11 @@ const level = {
}
}
)
spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
spawn.randomMob(x + 300, y + -1200, Infinity);
spawn.randomMob(x + 800, y + -125, Infinity);
spawn.randomMob(x + 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
@@ -1510,11 +1507,11 @@ const level = {
}
}
)
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 300, y + -1200, Infinity);
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
spawn.randomMob(x + 2000 - 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 2000 - 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 2000 - 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 2000 - 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
@@ -1578,11 +1575,11 @@ const level = {
}
}
)
spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
spawn.randomMob(x + 300, y + -1200, Infinity);
spawn.randomMob(x + 800, y + -125, Infinity);
spawn.randomMob(x + 1600, y + -425, mobSpawnChance);
spawn.randomMob(x + 1725, y + -1250, mobSpawnChance);
spawn.randomMob(x + 1250, y + -1200, mobSpawnChance);
spawn.randomMob(x + 300, y + -1200, mobSpawnChance);
spawn.randomMob(x + 800, y + -125, mobSpawnChance);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
@@ -1678,17 +1675,17 @@ const level = {
} else if (!isSpawnedMobs) {
isSpawnedMobs = true
if (chamberY === -650) { //lower chamber
spawn.randomGroup(x + 275, y + -1050, Infinity);
spawn.randomGroup(x + 675, y + -975, Infinity);
spawn.randomMob(x + 250, y + -650, mobSpawnChance);
spawn.randomMob(x + 1825, y + -600, mobSpawnChance);
spawn.randomGroup(x + 275, y + -1050, mobSpawnChance);
spawn.randomGroup(x + 675, y + -975, mobSpawnChance);
spawn.randomGroup(x + 1225, y + -975, Infinity);
spawn.randomMob(x + 250, y + -650, Infinity);
spawn.randomMob(x + 1825, y + -600, Infinity);
} else { //upper chamber
spawn.randomGroup(x + 300, y + -300, Infinity);
spawn.randomGroup(x + 650, y + -275, Infinity);
spawn.randomMob(x + 250, y + -650, mobSpawnChance);
spawn.randomMob(x + 1800, y + -625, mobSpawnChance);
spawn.randomGroup(x + 300, y + -300, mobSpawnChance);
spawn.randomGroup(x + 650, y + -275, mobSpawnChance);
spawn.randomGroup(x + 1125, y + -300, Infinity);
spawn.randomMob(x + 250, y + -650, Infinity);
spawn.randomMob(x + 1800, y + -625, Infinity);
}
}
}
@@ -1797,12 +1794,12 @@ const level = {
// simulation.draw.setPaths() //update map graphics
// }
// })
// spawn.randomMob(x + 225, y + -1025, Infinity);
// spawn.randomMob(x + 200, y + -675, Infinity);
// spawn.randomMob(x + 225, y + -200, Infinity);
// spawn.randomMob(x + 1750, y + -1075, Infinity);
// spawn.randomMob(x + 1700, y + -650, Infinity);
// spawn.randomMob(x + 1675, y + -175, Infinity);
// spawn.randomMob(x + 225, y + -1025, mobSpawnChance);
// spawn.randomMob(x + 200, y + -675, mobSpawnChance);
// spawn.randomMob(x + 225, y + -200, mobSpawnChance);
// spawn.randomMob(x + 1750, y + -1075, mobSpawnChance);
// spawn.randomMob(x + 1700, y + -650, mobSpawnChance);
// spawn.randomMob(x + 1675, y + -175, mobSpawnChance);
// spawn.randomGroup(x + 300, y + -2200);
// spawn.randomGroup(x + 1625, y + -2200);
@@ -1847,12 +1844,12 @@ const level = {
const numberOfMapElementsAdded = 12
for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i])
spawn.randomMob(x + 225, y + -1775, Infinity);
spawn.randomMob(x + 700, y + -1750, Infinity);
spawn.randomMob(x + 1175, y + -1725, Infinity);
spawn.randomMob(x + 1700, y + -1700, Infinity);
spawn.randomMob(x + 1750, y + -250, Infinity);
spawn.randomMob(x + 125, y + -250, Infinity);
spawn.randomMob(x + 225, y + -1775, mobSpawnChance);
spawn.randomMob(x + 700, y + -1750, mobSpawnChance);
spawn.randomMob(x + 1175, y + -1725, mobSpawnChance);
spawn.randomMob(x + 1700, y + -1700, mobSpawnChance);
spawn.randomMob(x + 1750, y + -250, mobSpawnChance);
spawn.randomMob(x + 125, y + -250, mobSpawnChance);
} else {
spawn.mapVertex(x + 775, y + -260, hexagon);
spawn.mapVertex(x + 1225, y + -260, hexagon);
@@ -1873,12 +1870,12 @@ const level = {
const numberOfMapElementsAdded = 12
for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i])
spawn.randomMob(x + 225, y + -1025, Infinity);
spawn.randomMob(x + 200, y + -675, Infinity);
spawn.randomMob(x + 225, y + -200, Infinity);
spawn.randomMob(x + 1750, y + -1075, Infinity);
spawn.randomMob(x + 1700, y + -650, Infinity);
spawn.randomMob(x + 1675, y + -175, Infinity);
spawn.randomMob(x + 225, y + -1025, mobSpawnChance);
spawn.randomMob(x + 200, y + -675, mobSpawnChance);
spawn.randomMob(x + 225, y + -200, mobSpawnChance);
spawn.randomMob(x + 1750, y + -1075, mobSpawnChance);
spawn.randomMob(x + 1700, y + -650, mobSpawnChance);
spawn.randomMob(x + 1675, y + -175, mobSpawnChance);
}
simulation.draw.setPaths() //update map graphics
spawn.randomGroup(x + 300, y + -2200);
@@ -1940,15 +1937,15 @@ const level = {
const numberOfMapElementsAdded = 13
for (let i = 0; i < numberOfMapElementsAdded; i++) addMapToLevelInProgress(map[map.length - 1 - i])
spawn.randomMob(x + 1075, y + -1500, Infinity);
spawn.randomMob(x + 325, y + -550, Infinity);
spawn.randomMob(x + 800, y + -925, Infinity);
spawn.randomMob(x + 1400, y + -1250, Infinity);
spawn.randomMob(x + 1350, y + -1725, Infinity);
spawn.randomMob(x + 575, y + -1375, Infinity);
spawn.randomMob(x + 225, y + -2275, Infinity);
spawn.randomMob(x + 875, y + -2450, Infinity);
spawn.randomMob(x + 1550, y + -2525, Infinity);
spawn.randomMob(x + 1075, y + -1500, mobSpawnChance);
spawn.randomMob(x + 325, y + -550, mobSpawnChance);
spawn.randomMob(x + 800, y + -925, mobSpawnChance);
spawn.randomMob(x + 1400, y + -1250, mobSpawnChance);
spawn.randomMob(x + 1350, y + -1725, mobSpawnChance);
spawn.randomMob(x + 575, y + -1375, mobSpawnChance);
spawn.randomMob(x + 225, y + -2275, mobSpawnChance);
spawn.randomMob(x + 875, y + -2450, mobSpawnChance);
spawn.randomMob(x + 1550, y + -2525, mobSpawnChance);
if (simulation.difficulty > 3) spawn.randomLevelBoss(x + 1075, y + -1500);
simulation.draw.setPaths() //update map graphics
}

View File

@@ -470,7 +470,7 @@ const m = {
}
},
addHealth(heal) {
if (!tech.isEnergyHealth && !tech.isNoHeals) {
if (!tech.isEnergyHealth) {
m.health += heal * simulation.healScale;
if (m.health > m.maxHealth) m.health = m.maxHealth;
m.displayHealth();
@@ -495,7 +495,7 @@ const m = {
if (tech.isHarmMACHO) dmg *= 0.33
if (tech.isImmortal) dmg *= 0.66
if (tech.isHarmReduceAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 0.33 : 1.15
if (tech.healthDrain) dmg *= 1 + 2.667 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
if (tech.healthDrain) dmg *= 1 + 3.33 * tech.healthDrain //tech.healthDrain = 0.03 at one stack //cause more damage
if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage
if (tech.isBlockHarm && m.isHolding) dmg *= 0.15
if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0165, 0.66)
@@ -1611,59 +1611,63 @@ const m = {
Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
) {
mob[i].locatePlayer();
m.fieldCDcycle = m.cycle + m.fieldBlockCD;
if (tech.blockingIce) {
for (let i = 0; i < tech.blockingIce; i++) b.iceIX(10, m.fieldAngle + Math.random() - 0.5, m.fieldPosition)
}
const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
if (tech.blockDmg) {
mob[i].damage(tech.blockDmg * b.dmgScale)
//draw electricity
const step = 40
ctx.beginPath();
for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) {
let x = m.fieldPosition.x - 20 * unit.x;
let y = m.fieldPosition.y - 20 * unit.y;
ctx.moveTo(x, y);
for (let i = 0; i < 8; i++) {
x += step * (-unit.x + 1.5 * (Math.random() - 0.5))
y += step * (-unit.y + 1.5 * (Math.random() - 0.5))
ctx.lineTo(x, y);
}
if (m.fieldCDcycle < m.cycle) {
m.fieldCDcycle = m.cycle + m.fieldBlockCD;
if (tech.blockingIce) {
for (let i = 0; i < tech.blockingIce; i++) b.iceIX(10, m.fieldAngle + Math.random() - 0.5, m.fieldPosition)
}
ctx.lineWidth = 3;
ctx.strokeStyle = "#f0f";
ctx.stroke();
} else if (!isFree) {
//when blocking draw this graphic
const eye = 15;
const len = mob[i].vertices.length - 1;
ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
ctx.lineWidth = 1;
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
ctx.lineTo(mob[i].vertices[len].x, mob[i].vertices[len].y);
ctx.lineTo(mob[i].vertices[0].x, mob[i].vertices[0].y);
ctx.fill();
ctx.stroke();
for (let j = 0; j < len; j++) {
if (tech.blockDmg) {
mob[i].damage(tech.blockDmg * b.dmgScale)
//draw electricity
const step = 40
ctx.beginPath();
for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) {
let x = m.fieldPosition.x - 20 * unit.x;
let y = m.fieldPosition.y - 20 * unit.y;
ctx.moveTo(x, y);
for (let i = 0; i < 8; i++) {
x += step * (-unit.x + 1.5 * (Math.random() - 0.5))
y += step * (-unit.y + 1.5 * (Math.random() - 0.5))
ctx.lineTo(x, y);
}
}
ctx.lineWidth = 3;
ctx.strokeStyle = "#f0f";
ctx.stroke();
} else if (!isFree) {
//when blocking draw this graphic
const eye = 15;
const len = mob[i].vertices.length - 1;
ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
ctx.lineWidth = 1;
ctx.strokeStyle = "#000";
ctx.beginPath();
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
ctx.lineTo(mob[i].vertices[j].x, mob[i].vertices[j].y);
ctx.lineTo(mob[i].vertices[j + 1].x, mob[i].vertices[j + 1].y);
ctx.lineTo(mob[i].vertices[len].x, mob[i].vertices[len].y);
ctx.lineTo(mob[i].vertices[0].x, mob[i].vertices[0].y);
ctx.fill();
ctx.stroke();
for (let j = 0; j < len; j++) {
ctx.beginPath();
ctx.moveTo(m.fieldPosition.x + eye * Math.cos(m.fieldAngle), m.fieldPosition.y + eye * Math.sin(m.fieldAngle));
ctx.lineTo(mob[i].vertices[j].x, mob[i].vertices[j].y);
ctx.lineTo(mob[i].vertices[j + 1].x, mob[i].vertices[j + 1].y);
ctx.fill();
ctx.stroke();
}
}
if (tech.isStunField) mobs.statusStun(mob[i], tech.isStunField)
//knock backs
const massRoot = Math.sqrt(Math.max(0.15, mob[i].mass)); // masses above 12 can start to overcome the push back
Matter.Body.setVelocity(mob[i], {
x: player.velocity.x - (20 * unit.x) / massRoot,
y: player.velocity.y - (20 * unit.y) / massRoot
});
if (mob[i].isOrbital) Matter.Body.setVelocity(mob[i], { x: 0, y: 0 });
}
if (tech.isStunField) mobs.statusStun(mob[i], tech.isStunField)
//knock backs
const massRoot = Math.sqrt(Math.max(0.15, mob[i].mass)); // masses above 12 can start to overcome the push back
Matter.Body.setVelocity(mob[i], {
x: player.velocity.x - (20 * unit.x) / massRoot,
y: player.velocity.y - (20 * unit.y) / massRoot
});
if (mob[i].isOrbital) Matter.Body.setVelocity(mob[i], { x: 0, y: 0 });
if (isFree) {
} else {
@@ -1682,14 +1686,14 @@ const m = {
m.hold = function() {
const wave = Math.sin(m.cycle * 0.022);
m.fieldRange = 170 + 12 * wave
m.fieldArc = 0.33 + 0.045 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
m.fieldRange = 190 + 12 * wave
m.fieldArc = 0.36 + 0.04 * wave //run calculateFieldThreshold after setting fieldArc, used for powerUp grab and mobPush with lookingAt(mob)
m.calculateFieldThreshold();
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
m.throwBlock();
} else if ((input.field && m.fieldCDcycle < m.cycle)) { //not hold but field button is pressed
} else if (input.field) { //not hold but field button is pressed
m.grabPowerUp();
m.lookForPickUp();
m.fieldPosition = { x: m.pos.x, y: m.pos.y }
@@ -1724,7 +1728,7 @@ const m = {
m.pickUp();
} else {
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
if (tech.isFieldFree && !input.field && m.fieldCDcycle < m.cycle) {
if (tech.isFieldFree && !input.field) {
//draw field free of player
ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"

View File

@@ -322,7 +322,7 @@ const powerUps = {
// }
// }
// }
if (!tech.isEnergyHealth && m.alive) {
if (!tech.isEnergyHealth && m.alive && !tech.isNoHeals) {
const heal = powerUps.heal.calculateHeal(this.size)
if (heal > 0) {
const overHeal = m.health + heal * simulation.healScale - m.maxHealth //used with tech.isOverHeal

View File

@@ -538,10 +538,11 @@ const simulation = {
} else {
level.levels = shuffle(level.levels); //shuffles order of maps
}
level.levels.unshift("intro"); //add level to the start of the randomized levels list
level.levels.push("labs"); //add level to the end of the randomized levels list
level.levels.push("gauntlet"); //add level to the end of the randomized levels list
level.levels.push("final"); //add level to the end of the randomized levels list
if (!build.isExperimentSelection) { //experimental mode is endless
level.levels.unshift("intro"); //add level to the start of the randomized levels list
level.levels.push("gauntlet"); //add level to the end of the randomized levels list
level.levels.push("final"); //add level to the end of the randomized levels list
}
input.endKeySensing();
b.removeAllGuns();

View File

@@ -1973,18 +1973,18 @@ const spawn = {
mobs.spawn(x, y, 5, 50, "rgb(215,80,190)"); //"rgb(221,102,119)"
let me = mob[mob.length - 1];
Matter.Body.rotate(me, Math.PI * 0.1);
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
me.damageReduction = 0.25;
me.frictionStatic = 0;
me.friction = 0;
me.memory = 240
me.seePlayerFreq = 60
me.delay = 20 + 20 * simulation.CDScale;
me.delay = 16 + 30 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
me.blinkRange = 235
me.grenadeDelay = 30 + 50 * simulation.CDScale
me.pulseRadius = 2 * Math.min(550, 250 + simulation.difficulty * 3)
me.grenadeDelay = 30 + 60 * simulation.CDScale
me.pulseRadius = 2 * Math.min(550, 220 + simulation.difficulty * 4)
spawn.shield(me, x, y, 1);
me.onDamage = function() {
// this.cd = simulation.cycle + this.delay;
@@ -2001,6 +2001,7 @@ const spawn = {
y: speed * Math.sin(angle)
});
}
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}
me.do = function() {
this.seePlayerByHistory()
@@ -3310,8 +3311,8 @@ const spawn = {
};
me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet;
// me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
me.collisionFilter.mask = 0
me.collisionFilter.mask = cat.map | cat.body
// me.collisionFilter.mask = 0
me.do = function() {
this.timeLimit();
ctx.beginPath(); //draw explosion outline

View File

@@ -333,9 +333,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return (tech.isDamageForGuns || tech.isFireRateForGuns) && (b.inventory.length + 5) < b.guns.length
return (tech.isDamageForGuns || tech.isFireRateForGuns) && b.inventory.length + 5 < b.guns.length
},
requires: "arsenal or active cooling",
requires: "arsenal or active cooling and less than 7 guns",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 8; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
@@ -447,9 +447,9 @@
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isEnergyHealth && !tech.isEnergyNoAmmo
return !tech.isEnergyNoAmmo
},
requires: "not mass-energy equivalence or exciton-lattice",
requires: "exciton-lattice",
effect: () => {
tech.isAmmoFromHealth = true;
},
@@ -2189,9 +2189,9 @@
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isZeno && !tech.isAmmoFromHealth && !tech.isNoHeals && !tech.isEnergyLoss && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isSpeedHarm && m.fieldUpgrades[m.fieldMode].name !== "negative mass field" && !tech.isHealLowHealth && !tech.isTechDamage
return !tech.isZeno && !tech.isNoHeals && !tech.isPiezo && !tech.isRewindAvoidDeath && !tech.isRewindGun && !tech.isTechDamage && !tech.isMutualism
},
requires: "not exothermic, Zeno, piezoelectricity, CPT, 1st law, negative mass, ...",
requires: "not Zeno, ergodicity, piezoelectricity, CPT, rewind gun, antiscience, mutualism",
effect: () => {
m.health = 0
document.getElementById("health").style.display = "none"
@@ -2202,13 +2202,15 @@
m.displayHealth();
},
remove() {
tech.isEnergyHealth = false;
document.getElementById("health").style.display = "inline"
document.getElementById("health-bg").style.display = "inline"
document.getElementById("dmg").style.backgroundColor = "#f67";
m.health = Math.max(Math.min(m.maxHealth, m.energy), 0.1);
simulation.mobDmgColor = "rgba(255,0,0,0.7)"
m.displayHealth();
if (tech.isEnergyHealth) {
tech.isEnergyHealth = false;
document.getElementById("health").style.display = "inline"
document.getElementById("health-bg").style.display = "inline"
document.getElementById("dmg").style.backgroundColor = "#f67";
m.health = Math.max(Math.min(m.maxHealth, m.energy), 0.1);
simulation.mobDmgColor = "rgba(255,0,0,0.7)"
m.displayHealth();
}
}
},
{
@@ -2219,9 +2221,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isEnergyHealth && !tech.isNoHeals
return tech.isEnergyHealth
},
requires: "mass-energy equivalence, not ergodicity",
requires: "mass-energy equivalence",
effect() {
tech.healGiveMaxEnergy = true; //tech.healMaxEnergyBonus given from heal power up
powerUps.heal.color = "#0ae"
@@ -2282,9 +2284,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return true //m.maxEnergy > 1 || tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isBlockExplosion
return true
},
requires: "", //"increased energy regen or max energy",
requires: "",
effect: () => {
tech.isEnergyDamage = true
},
@@ -2300,9 +2302,9 @@
frequency: 1,
frequencyDefault: 1,
allowed() {
return true //(tech.haveGunCheck("nail gun") && tech.isIceCrystals) || tech.haveGunCheck("laser") || m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing" || m.fieldUpgrades[m.fieldMode].name === "pilot wave"
return true
},
requires: "", //"energy based damage",
requires: "",
effect() {
tech.isEnergyNoAmmo = true;
},
@@ -2318,9 +2320,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isEnergyHealth
return true
},
requires: "not mass-energy equivalence",
requires: "",
effect() {
tech.isEnergyLoss = true;
},
@@ -2400,11 +2402,11 @@
},
requires: "a source of overfilled energy",
effect() {
tech.overfillDrain = 0.87 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87)
tech.overfillDrain = 0.85 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87)
tech.addJunkTechToPool(18)
},
remove() {
tech.overfillDrain = 0.75
tech.overfillDrain = 0.7
if (this.count > 0) tech.removeJunkTechFromPool(18)
}
},
@@ -2453,9 +2455,9 @@
frequencyDefault: 1,
isHealTech: true,
allowed() {
return !tech.isEnergyHealth && !tech.isNoHeals
return !tech.isEnergyHealth
},
requires: "not mass-energy equivalence, ergodicity",
requires: "not mass-energy equivalence",
effect() {
tech.isHealthRecovery = true;
},
@@ -2556,16 +2558,16 @@
},
{
name: "entropy exchange",
description: "<strong class='color-h'>heal</strong> for <strong>3%</strong> of <strong class='color-d'>damage</strong> done<br>take <strong>8%</strong> more <strong class='color-harm'>harm</strong>",
description: "<strong class='color-h'>heal</strong> for <strong>3%</strong> of <strong class='color-d'>damage</strong> done<br>take <strong>10%</strong> more <strong class='color-harm'>harm</strong>",
maxCount: 9,
count: 0,
frequency: 2,
frequencyDefault: 2,
isHealTech: true,
allowed() {
return !tech.isEnergyHealth && !tech.isNoHeals
return !tech.isEnergyHealth
},
requires: "not mass-energy equivalence, ergodicity",
requires: "not mass-energy equivalence",
effect() {
tech.healthDrain += 0.03;
},
@@ -2599,9 +2601,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isEnergyHealth && !tech.isNoHeals
return !tech.isEnergyHealth
},
requires: "not mass-energy equivalence, ergodicity",
requires: "not mass-energy equivalence",
effect() {
tech.isFallingDamage = true;
m.setMaxHealth();
@@ -2678,9 +2680,9 @@
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return !tech.isNoHeals
return true
},
requires: "not ergodicity",
requires: "",
effect() {
for (let i = 0; i < 11; i++) powerUps.spawn(m.pos.x + 60 * (Math.random() - 0.5), m.pos.y + 60 * (Math.random() - 0.5), "heal");
for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -3451,15 +3453,15 @@
},
{
name: "ergodicity",
description: "reduce combat <strong>difficulty</strong> by <strong>2 levels</strong><br>all <strong class='color-h'>healing</strong> has <strong>no</strong> effect",
description: "reduce combat <strong>difficulty</strong> by <strong>2 levels</strong><br><strong class='color-h'>heal</strong> power ups have <strong>no</strong> effect",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return level.onLevel > 1 && m.health > m.maxHealth - 0.1 && !tech.isEnergyHealth
return level.onLevel > 1 && !tech.isEnergyHealth
},
requires: "past levels 1, full health, not mass-energy",
requires: "past levels 1, not mass-energy",
effect() {
tech.isNoHeals = true;
level.difficultyDecrease(simulation.difficultyMode * 2)