foam balance

beating the final boss automatically increases the difficulty mode for this run and future runs
some foam balancing, mostly buffs
standing wave harmonics gets 15% harm reduction again
This commit is contained in:
landgreen
2021-01-01 05:42:06 -08:00
parent 2c30382093
commit 3fa89b85d7
9 changed files with 215 additions and 170 deletions

View File

@@ -3298,7 +3298,7 @@ const b = {
lookFrequency: 60 + Math.floor(7 * Math.random()),
drain: tech.isLaserDiode * tech.laserFieldDrain,
isArmed: false,
torqueMagnitude: (Math.random() > 0.5 ? 1 : -1) * 0.000003,
torqueMagnitude: 0.000003 * (Math.round(Math.random()) ? 1 : -1),
range: 1500,
endCycle: Infinity,
classType: "bullet",
@@ -3329,8 +3329,7 @@ const b = {
) {
this.do = this.laserSpin
this.endCycle = simulation.cycle + 300
this.torqueMagnitude *= 2
this.torque += this.inertia * this.torqueMagnitude * 30 //spin
// if (this.angularSpeed < 0.01) this.torque += this.inertia * this.torqueMagnitude * 5 //spin
this.isArmed = true
}
}
@@ -3555,21 +3554,21 @@ const b = {
name: "foam",
description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time",
ammo: 0,
ammoPack: 30,
ammoPack: 35,
have: false,
fire() {
mech.fireCDcycle = mech.cycle + Math.floor((mech.crouch ? 20 : 6) * b.fireCD); // cool down
const radius = (mech.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 200) * 9
const radius = (mech.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = 18 - radius * 0.4;
const dir = mech.angle + 0.2 * (Math.random() - 0.5)
const position = {
x: mech.pos.x + 30 * Math.cos(mech.angle),
y: mech.pos.y + 30 * Math.sin(mech.angle)
}
const SPEED = 19 - radius * 0.5;
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
}
const position = {
x: mech.pos.x + 30 * Math.cos(mech.angle),
y: mech.pos.y + 30 * Math.sin(mech.angle)
}
b.foam(position, velocity, radius)
}
},

View File

@@ -714,7 +714,7 @@ window.addEventListener("keydown", function(event) {
if (simulation.paused) {
build.unPauseGrid()
simulation.paused = false;
level.levelAnnounce();
// level.levelAnnounce();
document.body.style.cursor = "none";
requestAnimationFrame(cycle);
} else {
@@ -824,7 +824,6 @@ window.addEventListener("keydown", function(event) {
}
break
case "u":
level.bossKilled = true; //if there is no boss this needs to be true to increase levels
level.nextLevel();
break
case "X": //capital X to make it hard to die

View File

@@ -26,6 +26,7 @@ const level = {
level.intro(); //starting level
// level.testing(); //not in rotation
// level.escape() //after the final boss, ending
// level.final() //final boss level
// level.gauntlet(); //before final boss level
// level.testChamber() //less mobs, more puzzle
@@ -97,6 +98,47 @@ const level = {
//******************************************************************************************************************
//******************************************************************************************************************
//******************************************************************************************************************
escape() {
const hazard = level.hazard(-1775, 150, 3575, 650, 0.01, "hsla(160, 100%, 35%,0.75)")
// level.bossKilled = false; // if a boss needs to be killed
level.custom = () => {
// level.playerExitCheck();
hazard.query();
// hazard.level(true)
};
level.customTopLayer = () => {
hazard.draw();
};
level.setPosToSpawn(0, -50); //normal spawn
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 0;
level.exit.y = 200;
level.defaultZoom = 1000
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#aaa";
// level.fill.push({ //foreground
// x: 2500,
// y: -1100,
// width: 450,
// height: 250,
// color: "rgba(0,0,0,0.1)"
// });
// level.fillBG.push({ //background
// x: 1300,
// y: -1800,
// width: 750,
// height: 1800,
// color: "#d4d4d7"
// });
spawn.mapRect(-500, 0, 1000, 1000); //center platform
spawn.mapRect(-2000, 800, 4000, 200); //base
spawn.mapRect(-2000, -1000, 4000, 200); //ceiling
spawn.mapRect(-2000, -1000, 225, 2000); //left
spawn.mapRect(1800, -1000, 200, 2000); //right
// spawn.bodyRect(1540, -1110, 300, 25, 0.9);
},
testing() {
const button = level.button(200, -700)
level.custom = () => {
@@ -160,16 +202,16 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.boost(1500, 0, 900);
spawn.starter(1900, -500, 200) //big boy
// spawn.starter(1900, -500, 200) //big boy
// spawn.exploder(2900, -500)
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500)
// spawn.shooter(1700, -120)
spawn.shooter(1700, -120)
// spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.streamBoss(1600, -500)
spawn.streamBoss(1600, -500)
// spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
@@ -179,7 +221,6 @@ const level = {
// spawn.randomMob(1600, -500)
},
template() {
// level.bossKilled = false; // if a boss needs to be killed
level.custom = () => {
level.playerExitCheck();
};
@@ -2121,7 +2162,6 @@ const level = {
powerUps.addRerollToLevel() //needs to run after mobs are spawned
},
office() {
level.bossKilled = false; // if a boss needs to be killed
let button, door
if (Math.random() < 0.75) { //normal direction start in top left
button = level.button(525, 0)
@@ -3820,7 +3860,6 @@ const level = {
// `, 1200);
},
nextLevel() {
// if (level.bossKilled)
level.levelsCleared++;
// level.difficultyIncrease(simulation.difficultyMode) //increase difficulty based on modes

View File

@@ -1382,10 +1382,11 @@ const mech = {
},
{
name: "standing wave harmonics",
description: "<strong>3</strong> oscillating <strong>shields</strong> are permanently active<br><strong>blocking</strong> drains <strong class='color-f'>energy</strong><br><strong>blocking</strong> has no <strong>cool down</strong>",
description: "<strong>3</strong> oscillating <strong>shields</strong> are permanently active<br><strong>blocking</strong> drains <strong class='color-f'>energy</strong> with no <strong>cool down</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>15%</strong>",
effect: () => {
// mech.fieldHarmReduction = 0.80;
mech.fieldBlockCD = 0;
mech.fieldHarmReduction = 0.85;
mech.hold = function() {
if (mech.isHolding) {
mech.drawHold(mech.holdingTarget);

View File

@@ -508,8 +508,6 @@ const powerUps = {
},
randomPowerUpCounter: 0,
spawnBossPowerUp(x, y) { //boss spawns field and gun tech upgrades
level.bossKilled = true;
if (mech.fieldMode === 0) {
powerUps.spawn(x, y, "field")
} else {

View File

@@ -98,12 +98,19 @@ const spawn = {
Matter.Body.setDensity(me, density); //extra dense //normal is 0.001 //makes effective life much larger
// spawn.shield(me, x, y, 1);
me.onDeath = function() {
level.bossKilled = true;
level.exit.x = 5500;
level.exit.y = -330;
//ramp up damage
for (let i = 0; i < 2; i++) level.difficultyIncrease(simulation.difficultyMode)
//set game to the next highest difficulty level if not on why
if (simulation.difficultyMode < 6) {
simulation.difficultyMode++
document.getElementById("difficulty-select").value = simulation.difficultyMode
localSettings.difficultyMode = simulation.difficultyMode
localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
simulation.makeTextLog(`<span class='color-var'>simulation</span>.difficultyMode<span class='color-symbol'>++</span>`);
}
//pull in particles
for (let i = 0, len = body.length; i < len; ++i) {

View File

@@ -248,6 +248,42 @@ const tech = {
tech.isOneGun = false;
}
},
{
name: "arsenal",
description: "increase <strong class='color-d'>damage</strong> by <strong>7%</strong><br>for each <strong class='color-g'>gun</strong> in your inventory",
maxCount: 1,
count: 0,
allowed() {
return b.inventory.length > 1
},
requires: "at least 2 guns",
effect() {
tech.isDamageForGuns = true;
},
remove() {
tech.isDamageForGuns = false;
}
},
{
name: "generalist",
description: "<strong>spawn</strong> 5 <strong class='color-g'>guns</strong>, but you can't <strong>switch</strong> <strong class='color-g'>guns</strong><br><strong class='color-g'>guns</strong> cycle automatically with each new level",
maxCount: 1,
count: 0,
isNonRefundable: true,
allowed() {
return tech.isDamageForGuns
},
requires: "arsenal",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 5; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
}
},
remove() {
tech.isGunCycle = false;
}
},
{
name: "negative feedback",
description: "increase <strong class='color-d'>damage</strong> by <strong>6%</strong><br>for every <strong>10</strong> <strong>health</strong> below <strong>100</strong>",
@@ -820,42 +856,6 @@ const tech = {
},
remove() {}
},
{
name: "ablative drones",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>",
maxCount: 1,
count: 0,
allowed() {
return mech.harmReduction() < 1
},
requires: "some harm reduction",
effect() {
tech.isDroneOnDamage = true;
for (let i = 0; i < 4; i++) {
b.drone() //spawn drone
}
},
remove() {
tech.isDroneOnDamage = false;
}
},
{
name: "mine synthesis",
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong>",
maxCount: 1,
count: 0,
allowed() {
return tech.duplicationChance() > 0
},
requires: "some power up duplication",
effect() {
tech.isMineDrop = true;
if (tech.isMineDrop) b.mine(mech.pos, { x: 0, y: 0 }, 0, tech.isMineAmmoBack)
},
remove() {
tech.isMineDrop = false;
}
},
{
name: "squirrel-cage rotor",
description: "<strong>move</strong> and <strong>jump</strong> about <strong>25%</strong> faster",
@@ -908,23 +908,6 @@ const tech = {
tech.isSpeedDamage = false
}
},
{
name: "Pauli exclusion",
description: `<strong>immune</strong> to <strong class='color-harm'>harm</strong> for an extra <strong>0.75</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong>`,
maxCount: 9,
count: 0,
allowed() {
return true
},
requires: "",
effect() {
tech.collisionImmuneCycles += 45;
mech.immuneCycle = mech.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
},
remove() {
tech.collisionImmuneCycles = 25;
}
},
{
name: "decorrelation",
description: "reduce <strong class='color-harm'>harm</strong> by <strong>40%</strong><br>after not using your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> for <strong>2</strong> seconds",
@@ -957,6 +940,68 @@ const tech = {
tech.isNoFireDamage = false
}
},
{
name: "Pauli exclusion",
description: `<strong>immune</strong> to <strong class='color-harm'>harm</strong> for an extra <strong>0.75</strong> seconds<br>after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong>`,
maxCount: 9,
count: 0,
allowed() {
return true
},
requires: "",
effect() {
tech.collisionImmuneCycles += 45;
mech.immuneCycle = mech.cycle + tech.collisionImmuneCycles; //player is immune to collision damage for 30 cycles
},
remove() {
tech.collisionImmuneCycles = 25;
}
},
{
name: "entanglement",
nameInfo: "<span id = 'tech-entanglement'></span>",
addNameInfo() {
setTimeout(function() {
simulation.boldActiveGunHUD();
}, 1000);
},
description: "while your <strong>first</strong> <strong class='color-g'>gun</strong> is equipped<br>reduce <strong class='color-harm'>harm</strong> by <strong>13%</strong> for each of your <strong class='color-g'>guns</strong>",
maxCount: 1,
count: 0,
allowed() {
return b.inventory.length > 1 && !tech.isEnergyHealth
},
requires: "at least 2 guns",
effect() {
tech.isEntanglement = true
setTimeout(function() {
simulation.boldActiveGunHUD();
}, 1000);
},
remove() {
tech.isEntanglement = false;
}
},
{
name: "ablative drones",
description: "rebuild your broken parts as <strong>drones</strong><br>chance to occur after receiving <strong class='color-harm'>harm</strong>",
maxCount: 1,
count: 0,
allowed() {
return mech.harmReduction() < 1
},
requires: "some harm reduction",
effect() {
tech.isDroneOnDamage = true;
for (let i = 0; i < 4; i++) {
b.drone() //spawn drone
}
},
remove() {
tech.isDroneOnDamage = false;
}
},
{
name: "non-Newtonian armor",
description: "for <strong>10 seconds</strong> after receiving <strong class='color-harm'>harm</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>66%</strong>",
@@ -1022,22 +1067,6 @@ const tech = {
tech.isFreezeHarmImmune = false;
}
},
{
name: "supercapacitor",
description: "<strong class='color-f'>energy</strong> above your max decays <strong>60%</strong> slower",
maxCount: 1,
count: 0,
allowed() {
return tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isRailEnergyGain || tech.isWormholeEnergy || tech.iceEnergy > 0
},
requires: "a source of overfilled energy",
effect() {
tech.overfillDrain = 0.85
},
remove() {
tech.overfillDrain = 0.75
}
},
{
name: "CPT reversal",
description: "<strong>charge</strong>, <strong>parity</strong>, and <strong>time</strong> invert to undo <strong class='color-harm'>harm</strong><br><strong class='color-rewind'>rewind</strong> <strong>(1.5—5)</strong> seconds for <strong>(66—220)</strong> <strong class='color-f'>energy</strong>",
@@ -1194,6 +1223,22 @@ const tech = {
mech.setMaxEnergy()
}
},
{
name: "supercapacitor",
description: "<strong class='color-f'>energy</strong> above your max decays <strong>60%</strong> slower",
maxCount: 1,
count: 0,
allowed() {
return tech.isEnergyRecovery || tech.isPiezo || tech.energySiphon > 0 || tech.isRailEnergyGain || tech.isWormholeEnergy || tech.iceEnergy > 0
},
requires: "a source of overfilled energy",
effect() {
tech.overfillDrain = 0.85
},
remove() {
tech.overfillDrain = 0.75
}
},
{
name: "energy conservation",
description: "<strong>6%</strong> of <strong class='color-d'>damage</strong> done recovered as <strong class='color-f'>energy</strong>",
@@ -1370,6 +1415,25 @@ const tech = {
tech.isDeathAvoid = false;
}
},
{
name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>4</strong> <strong class='color-r'>rerolls</strong>",
maxCount: 1,
count: 0,
allowed() {
return powerUps.reroll.rerolls > 1 || build.isCustomSelection
},
requires: "at least 2 rerolls",
effect() {
tech.isImmortal = true;
for (let i = 0; i < 4; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
}
},
remove() {
tech.isImmortal = false;
}
},
{
name: "bubble fusion",
description: "after destroying a mob's <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>rerolls</strong>",
@@ -1540,65 +1604,20 @@ const tech = {
remove() {}
},
{
name: "entanglement",
nameInfo: "<span id = 'tech-entanglement'></span>",
addNameInfo() {
setTimeout(function() {
simulation.boldActiveGunHUD();
}, 1000);
},
description: "while your <strong>first</strong> <strong class='color-g'>gun</strong> is equipped<br>reduce <strong class='color-harm'>harm</strong> by <strong>13%</strong> for each of your <strong class='color-g'>guns</strong>",
name: "mine synthesis",
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong>",
maxCount: 1,
count: 0,
allowed() {
return b.inventory.length > 1 && !tech.isEnergyHealth
return tech.duplicationChance() > 0
},
requires: "at least 2 guns",
requires: "some power up duplication",
effect() {
tech.isEntanglement = true
setTimeout(function() {
simulation.boldActiveGunHUD();
}, 1000);
tech.isMineDrop = true;
if (tech.isMineDrop) b.mine(mech.pos, { x: 0, y: 0 }, 0, tech.isMineAmmoBack)
},
remove() {
tech.isEntanglement = false;
}
},
{
name: "arsenal",
description: "increase <strong class='color-d'>damage</strong> by <strong>7%</strong><br>for each <strong class='color-g'>gun</strong> in your inventory",
maxCount: 1,
count: 0,
allowed() {
return b.inventory.length > 1
},
requires: "at least 2 guns",
effect() {
tech.isDamageForGuns = true;
},
remove() {
tech.isDamageForGuns = false;
}
},
{
name: "generalist",
description: "<strong>spawn</strong> 5 <strong class='color-g'>guns</strong>, but you can't <strong>switch</strong> <strong class='color-g'>guns</strong><br><strong class='color-g'>guns</strong> cycle automatically with each new level",
maxCount: 1,
count: 0,
isNonRefundable: true,
allowed() {
return tech.isDamageForGuns
},
requires: "arsenal",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 5; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "gun");
}
},
remove() {
tech.isGunCycle = false;
tech.isMineDrop = false;
}
},
{
@@ -1791,25 +1810,6 @@ const tech = {
powerUps.tech.banishLog = [] //reset banish log
}
},
{
name: "quantum immortality",
description: "after <strong>dying</strong>, continue in an <strong>alternate reality</strong><br>spawn <strong>4</strong> <strong class='color-r'>rerolls</strong>",
maxCount: 1,
count: 0,
allowed() {
return powerUps.reroll.rerolls > 1 || build.isCustomSelection
},
requires: "at least 2 rerolls",
effect() {
tech.isImmortal = true;
for (let i = 0; i < 4; i++) {
powerUps.spawn(mech.pos.x, mech.pos.y, "reroll", false);
}
},
remove() {
tech.isImmortal = false;
}
},
{
name: "Born rule",
description: "<strong>remove</strong> all current <strong class='color-m'>tech</strong><br>spawn new <strong class='color-m'>tech</strong> to replace them",
@@ -2866,7 +2866,7 @@ const tech = {
},
{
name: "foam fractionation",
description: "<strong>foam</strong> gun bubbles are <strong>100%</strong> larger<br>when you have below <strong>200</strong> <strong class='color-g'>ammo</strong>",
description: "<strong>foam</strong> gun bubbles are <strong>100%</strong> larger<br>when you have below <strong>300</strong> <strong class='color-g'>ammo</strong>",
isGunTech: true,
maxCount: 1,
count: 0,