weak anthropic principle

tech: weak anthropic principle - after anthropic principle prevents your death, gain 50% duplication for that level
anthropic principle now correctly gives 6 seconds of harm immunity after preventing your death

almost all energy regen is disabled while immune to harm
  you aren't immune very often so you may not notice, but it will limit some builds that let you get almost constant immunity
  Pauli exclusion gives 1 s of harm immunity (was .75 s)
  CPT reversal requires 10% less energy (min energy is 60% to activate)
    CPT grenades gives many more bombs
    CPT bots gives many more bots

growBoss balance: a bit smaller and slower, and a extra high chance to drop a random power up when you kill one
sneaker mobs are a bit slower, and have much lower health
starter mobs are no longer aggressive

gun tech will now only show up for your active gun
set CSS max width of the update element to match other elements
This commit is contained in:
landgreen
2021-07-23 07:27:00 -07:00
parent 3f8517b27e
commit a57639987a
12 changed files with 119 additions and 88 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -202,7 +202,7 @@
<div> <div>
<details id="updates"> <details id="updates">
<summary>updates</summary> <summary>updates</summary>
<div id="updates-div" class="details-div" style="font-size: 70%;height: 400px;overflow: scroll;"> <div id="updates-div" class="details-div" style="font-size: 70%;height: 400px;overflow: scroll;max-width: 450px;">
</div> </div>
</details> </details>

View File

@@ -2071,7 +2071,7 @@ const b = {
mobs.statusSlow(who, 180) mobs.statusSlow(who, 180)
this.endCycle = simulation.cycle this.endCycle = simulation.cycle
// if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300) // if (tech.isHeavyWater) mobs.statusDoT(who, 0.15, 300)
if (tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) { if (m.immuneCycle < m.cycle && tech.iceEnergy && !who.shield && !who.isShielded && who.isDropPowerUp && who.alive && m.immuneCycle < m.cycle) {
setTimeout(function() { setTimeout(function() {
if (!who.alive) { if (!who.alive) {
m.energy += tech.iceEnergy * 0.8 m.energy += tech.iceEnergy * 0.8
@@ -2908,7 +2908,7 @@ const b = {
//check for damage //check for damage
if (!m.isBodiesAsleep) { if (!m.isBodiesAsleep) {
if (!((m.cycle + this.phase) % 30)) { //twice a second if (m.immuneCycle < m.cycle && !((m.cycle + this.phase) % 30)) { //twice a second
if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250 && m.immuneCycle < m.cycle) { //give energy if (Vector.magnitude(Vector.sub(this.position, player.position)) < 250 && m.immuneCycle < m.cycle) { //give energy
Matter.Body.setAngularVelocity(this, this.spin) Matter.Body.setAngularVelocity(this, this.spin)
if (this.isUpgraded) { if (this.isUpgraded) {
@@ -4843,7 +4843,7 @@ const b = {
if (tech.isCapacitor) { if (tech.isCapacitor) {
if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1) if (m.immuneCycle < m.cycle) m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1)
m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale); m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale);
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, { bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
@@ -4970,7 +4970,7 @@ const b = {
bullet[me].charge = 0; bullet[me].charge = 0;
bullet[me].do = function() { bullet[me].do = function() {
if (m.energy < 0.005 && !tech.isRailEnergyGain) { if (m.energy < 0.005 && !tech.isRailEnergyGain) {
m.energy += 0.05 + this.charge * 0.3 if (m.immuneCycle < m.cycle) m.energy += 0.05 + this.charge * 0.3
m.fireCDcycle = m.cycle + 120; // cool down if out of energy m.fireCDcycle = m.cycle + 120; // cool down if out of energy
this.endCycle = 0; this.endCycle = 0;
return return

View File

@@ -43,7 +43,7 @@ function playerOnGroundCheck(event) {
//falling damage //falling damage
if (tech.isFallingDamage && m.immuneCycle < m.cycle && momentum > 150) { if (tech.isFallingDamage && m.immuneCycle < m.cycle && momentum > 150) {
m.damage(Math.min(Math.sqrt(momentum - 133) * 0.01, 0.25)); m.damage(Math.min(Math.sqrt(momentum - 133) * 0.01, 0.25));
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
} }
} else { } else {
m.yOffGoal = m.yOffWhen.stand; m.yOffGoal = m.yOffWhen.stand;
@@ -90,7 +90,7 @@ function collisionChecks(event) {
for (let i = 0, j = pairs.length; i != j; i++) { for (let i = 0, j = pairs.length; i != j; i++) {
//mob + (player,bullet,body) collisions //mob + (player,bullet,body) collisions
for (let k = 0; k < mob.length; k++) { for (let k = 0; k < mob.length; k++) {
if (mob[k].alive && m.alive) { if (mob[k].alive) {
if (pairs[i].bodyA === mob[k]) { if (pairs[i].bodyA === mob[k]) {
collideMob(pairs[i].bodyB); collideMob(pairs[i].bodyB);
break; break;
@@ -137,7 +137,7 @@ function collisionChecks(event) {
if (tech.isPiezo) m.energy += 20.48; if (tech.isPiezo) m.energy += 20.48;
if (tech.isStimulatedEmission) powerUps.ejectTech() if (tech.isStimulatedEmission) powerUps.ejectTech()
if (mob[k].onHit) mob[k].onHit(k); if (mob[k].onHit) mob[k].onHit(k);
m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, {
@@ -151,7 +151,7 @@ function collisionChecks(event) {
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy) {
m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
m.immuneCycle = 0; //player doesn't go immune to collision damage if (m.immuneCycle === m.cycle + tech.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death(); mob[k].death();
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: pairs[i].activeContacts[0].vertex.x, x: pairs[i].activeContacts[0].vertex.x,
@@ -233,7 +233,7 @@ function collisionChecks(event) {
Events.on(engine, "collisionStart", function(event) { Events.on(engine, "collisionStart", function(event) {
playerOnGroundCheck(event); playerOnGroundCheck(event);
// playerHeadCheck(event); // playerHeadCheck(event);
collisionChecks(event); if (m.alive) collisionChecks(event);
}); });
Events.on(engine, "collisionActive", function(event) { Events.on(engine, "collisionActive", function(event) {
playerOnGroundCheck(event); playerOnGroundCheck(event);

View File

@@ -57,7 +57,7 @@ const level = {
// lore.techCount = 6 // lore.techCount = 6
// simulation.isCheating = false //true; // simulation.isCheating = false //true;
// localSettings.loreCount = 4; //this sets what conversation is heard // localSettings.loreCount = 3; //this sets what conversation is heard
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage // localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
// level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation // level.onLevel = -1 //this sets level.levels[level.onLevel] = undefined which is required to run the conversation
// level.null() // level.null()
@@ -2257,7 +2257,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
spawn.buffBossCulture(1900, -500) spawn.growBossCulture(1900, -500)
// spawn.pulsarBoss(1900, -500) // spawn.pulsarBoss(1900, -500)
// spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
@@ -5880,6 +5880,7 @@ const level = {
} }
}, },
perplex() { //by Oranger from discord perplex() { //by Oranger from discord
document.body.style.backgroundColor = "#dcdcde";
level.setPosToSpawn(-600, 400); level.setPosToSpawn(-600, 400);
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20);
level.exit.x = 550; level.exit.x = 550;
@@ -7059,7 +7060,7 @@ const level = {
spawn.randomGroup(2000, -5700, 0.6); spawn.randomGroup(2000, -5700, 0.6);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
let bosses = ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "laserBoss", "buffBossCulture"]; let bosses = ["shooterBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "laserBoss", "growBossCulture"];
let abc = Math.random(); let abc = Math.random();
if (simulation.difficulty > 3) { if (simulation.difficulty > 3) {
if (abc < 0.6) { if (abc < 0.6) {

View File

@@ -19,9 +19,7 @@ const mobs = {
ctx.beginPath(); ctx.beginPath();
const vertices = mob[i].vertices; const vertices = mob[i].vertices;
ctx.moveTo(vertices[0].x, vertices[0].y); ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1, len = vertices.length; j < len; ++j) { for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[j].x, vertices[j].y);
}
ctx.lineTo(vertices[0].x, vertices[0].y); ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.fillStyle = mob[i].fill; ctx.fillStyle = mob[i].fill;
ctx.strokeStyle = mob[i].stroke; ctx.strokeStyle = mob[i].stroke;
@@ -49,9 +47,7 @@ const mobs = {
if (tech.isAoESlow) { if (tech.isAoESlow) {
const range2 = (180 + 170 * Math.random()) ** 2 const range2 = (180 + 170 * Math.random()) ** 2
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (who !== mob[i] && Vector.magnitudeSquared(Vector.sub(who.position, mob[i].position)) < range2 + mob[i].radius) { if (who !== mob[i] && Vector.magnitudeSquared(Vector.sub(who.position, mob[i].position)) < range2 + mob[i].radius) applySlow(mob[i])
applySlow(mob[i])
}
} }
simulation.drawList.push({ simulation.drawList.push({
x: who.position.x, x: who.position.x,
@@ -745,7 +741,7 @@ const mobs = {
this.force.y += force.y; this.force.y += force.y;
} }
}, },
repulsionRange: 500000, repulsionRange: 500000, //squared
repulsion() { repulsion() {
//accelerate towards the player //accelerate towards the player
if (this.seePlayer.recall && this.distanceToPlayer2() < this.repulsionRange) { if (this.seePlayer.recall && this.distanceToPlayer2() < this.repulsionRange) {

View File

@@ -513,7 +513,8 @@ const m = {
}, },
rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy))) rewind(steps) { // m.rewind(Math.floor(Math.min(599, 137 * m.energy)))
if (tech.isRewindGrenade) { if (tech.isRewindGrenade) {
const immunityCycle = m.cycle + 90 const immunityDuration = 65
const immunityCycle = m.cycle + immunityDuration + 10
if (m.immuneCycle < immunityCycle) m.immuneCycle = immunityCycle; //player is immune to damage until after grenades might explode... if (m.immuneCycle < immunityCycle) m.immuneCycle = immunityCycle; //player is immune to damage until after grenades might explode...
for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) { for (let i = 1, len = Math.floor(4 + steps / 40); i < len; i++) {
@@ -525,7 +526,7 @@ const m = {
y: who.velocity.y * 0.5 y: who.velocity.y * 0.5
}); });
} else if (tech.isRPG) { } else if (tech.isRPG) {
who.endCycle = (who.endCycle - simulation.cycle) * 0.2 + simulation.cycle + 10 * Math.random() who.endCycle = simulation.cycle + 10
} else if (tech.isNeutronBomb) { } else if (tech.isNeutronBomb) {
Matter.Body.setVelocity(who, { Matter.Body.setVelocity(who, {
x: who.velocity.x * 0.3, x: who.velocity.x * 0.3,
@@ -536,7 +537,7 @@ const m = {
x: who.velocity.x * 0.5, x: who.velocity.x * 0.5,
y: who.velocity.y * 0.5 y: who.velocity.y * 0.5
}); });
who.endCycle = (who.endCycle - simulation.cycle) * 0.5 + simulation.cycle + 10 * Math.random() who.endCycle = simulation.cycle + immunityDuration
} }
} }
} }
@@ -570,7 +571,7 @@ const m = {
}); });
} }
} }
m.energy = Math.max(m.energy - steps / 136, 0.01) m.energy = Math.max(m.energy - steps / 150, 0.01)
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
let isDrawPlayer = true let isDrawPlayer = true
@@ -619,8 +620,8 @@ const m = {
} }
}, },
damage(dmg) { damage(dmg) {
if (tech.isRewindAvoidDeath && m.energy > 0.66) { if (tech.isRewindAvoidDeath && m.energy > 0.6) {
const steps = Math.floor(Math.min(299, 137 * m.energy)) const steps = Math.floor(Math.min(299, 150 * m.energy))
simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${steps})`) simulation.makeTextLog(`<span class='color-var'>m</span>.rewind(${steps})`)
m.rewind(steps) m.rewind(steps)
return return
@@ -640,7 +641,7 @@ const m = {
tech.isDeathAvoidedThisLevel = true tech.isDeathAvoidedThisLevel = true
powerUps.research.changeRerolls(-1) powerUps.research.changeRerolls(-1)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span><br>${powerUps.research.count}`)
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x, m.pos.y, "heal", false); for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
m.energy = m.maxEnergy m.energy = m.maxEnergy
if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails simulation.wipe = function() { //set wipe to have trails
@@ -670,7 +671,7 @@ const m = {
powerUps.research.changeRerolls(-1) powerUps.research.changeRerolls(-1)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span> simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span><span class='color-symbol'>--</span>
<br>${powerUps.research.count}`) <br>${powerUps.research.count}`)
for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "heal", false); for (let i = 0; i < 6; i++) powerUps.spawn(m.pos.x + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "heal", false);
if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds if (m.immuneCycle < m.cycle + 360) m.immuneCycle = m.cycle + 360 //disable this.immuneCycle bonus seconds
simulation.wipe = function() { //set wipe to have trails simulation.wipe = function() { //set wipe to have trails
ctx.fillStyle = "rgba(255,255,255,0.03)"; ctx.fillStyle = "rgba(255,255,255,0.03)";
@@ -982,7 +983,7 @@ const m = {
fieldMeterColor: "#0cf", fieldMeterColor: "#0cf",
drawFieldMeter(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) { drawFieldMeter(bgColor = "rgba(0, 0, 0, 0.4)", range = 60) {
if (m.energy < m.maxEnergy) { if (m.energy < m.maxEnergy) {
m.energy += m.fieldRegen; if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0 if (m.energy < 0) m.energy = 0
ctx.fillStyle = bgColor; ctx.fillStyle = bgColor;
const xOff = m.pos.x - m.radius * m.maxEnergy const xOff = m.pos.x - m.radius * m.maxEnergy
@@ -1124,7 +1125,7 @@ const m = {
m.throwCharge = 0; m.throwCharge = 0;
m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds m.throwCycle = m.cycle + 180 //used to detect if a block was thrown in the last 3 seconds
m.definePlayerMass() //return to normal player mass m.definePlayerMass() //return to normal player mass
m.energy += 3 * Math.sqrt(m.holdingTarget.mass) if (m.immuneCycle < m.cycle) m.energy += 2.5 * Math.sqrt(m.holdingTarget.mass)
//remove block before pulse, so it doesn't get in the way //remove block before pulse, so it doesn't get in the way
for (let i = 0; i < body.length; i++) { for (let i = 0; i < body.length; i++) {
if (body[i] === m.holdingTarget) { if (body[i] === m.holdingTarget) {
@@ -1869,7 +1870,7 @@ const m = {
} else { } 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) 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)
} }
m.energy += m.fieldRegen; if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
m.drawFieldMeter() m.drawFieldMeter()
} }
} }
@@ -2160,7 +2161,7 @@ const m = {
} }
if (m.energy < m.maxEnergy) { // replaces m.drawFieldMeter() with custom code if (m.energy < m.maxEnergy) { // replaces m.drawFieldMeter() with custom code
m.energy += m.fieldRegen; if (m.immuneCycle < m.cycle) m.energy += m.fieldRegen;
if (m.energy < 0) m.energy = 0 if (m.energy < 0) m.energy = 0
const xOff = m.pos.x - m.radius * m.maxEnergy const xOff = m.pos.x - m.radius * m.maxEnergy
const yOff = m.pos.y - 50 const yOff = m.pos.y - 50
@@ -2601,7 +2602,7 @@ const m = {
Matter.World.remove(engine.world, body[i]); Matter.World.remove(engine.world, body[i]);
body.splice(i, 1); body.splice(i, 1);
m.fieldRange *= 0.8 m.fieldRange *= 0.8
if (tech.isWormholeEnergy) m.energy += 0.63 if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
if (tech.isSporeWorm) { if (tech.isSporeWorm) {
@@ -2635,7 +2636,7 @@ const m = {
body.splice(i, 1); body.splice(i, 1);
m.fieldRange *= 0.8 m.fieldRange *= 0.8
// if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2 // if (tech.isWormholeEnergy && m.energy < m.maxEnergy * 2) m.energy = m.maxEnergy * 2
if (tech.isWormholeEnergy) m.energy += 0.63 if (tech.isWormholeEnergy && m.immuneCycle < m.cycle) m.energy += 0.63
if (tech.isWormSpores) { //pandimensionalspermia if (tech.isWormSpores) { //pandimensionalspermia
for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) { for (let i = 0, len = Math.ceil(3 * (tech.isSporeWorm ? 0.5 : 1) * Math.random()); i < len; i++) {
if (tech.isSporeWorm) { if (tech.isSporeWorm) {

View File

@@ -5,7 +5,7 @@ const powerUps = {
lastTechIndex: null, lastTechIndex: null,
do() {}, do() {},
setDo() { setDo() {
if (tech.duplicationChance() > 0) { if (tech.duplicationChance() > 0 || tech.isAnthropicTech) {
if (tech.isPowerUpsVanish) { if (tech.isPowerUpsVanish) {
powerUps.do = powerUps.doDuplicatesVanish powerUps.do = powerUps.doDuplicatesVanish
} else if (tech.isPowerUpsAttract) { } else if (tech.isPowerUpsAttract) {
@@ -676,7 +676,7 @@ const powerUps = {
onPickUp(who) { onPickUp(who) {
powerUps.research.currentRerollCount = 0 powerUps.research.currentRerollCount = 0
if (tech.isTechDamage && who.name === "tech") m.damage(0.11) if (tech.isTechDamage && who.name === "tech") m.damage(0.11)
if (tech.isMassEnergy) m.energy += 2; if (tech.isMassEnergy && m.immuneCycle < m.cycle) m.energy += 2;
if (tech.isMineDrop) { if (tech.isMineDrop) {
if (tech.isLaserMine) { if (tech.isLaserMine) {
b.laserMine(who.position) b.laserMine(who.position)

View File

@@ -798,7 +798,7 @@ const simulation = {
if (m.energy > m.maxEnergy) m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25% if (m.energy > m.maxEnergy) m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25%
if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) { if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) {
if (tech.isFlipFlopOn) { if (tech.isFlipFlopOn) {
m.energy += 0.22; if (m.immuneCycle < m.cycle) m.energy += 0.22;
} else { } else {
m.energy -= 0.041; m.energy -= 0.041;
if (m.energy < 0) m.energy = 0 if (m.energy < 0) m.energy = 0
@@ -848,7 +848,7 @@ const simulation = {
// } // }
if (m.lastKillCycle + 300 > simulation.cycle) { //effects active for 5 seconds after killing a mob if (m.lastKillCycle + 300 > simulation.cycle) { //effects active for 5 seconds after killing a mob
if (tech.isEnergyRecovery) m.energy += m.maxEnergy * 0.05 if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05
if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth) if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth)
} }

View File

@@ -1,5 +1,10 @@
//main object for spawning things in a level //main object for spawning things in a level
const spawn = { const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "growBossCulture"],
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture"]) {
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
pickList: ["starter", "starter"], pickList: ["starter", "starter"],
fullPickList: [ fullPickList: [
"hopper", "hopper", "hopper", "hopper", "hopper", "hopper",
@@ -84,11 +89,6 @@ const spawn = {
} }
} }
}, },
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "orbitalBoss", "spawnerBossCulture", "buffBossCulture"],
randomLevelBoss(x, y, options = ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss", "powerUpBoss", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "buffBossCulture"]) {
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
spawn[options[Math.floor(Math.random() * options.length)]](x, y)
},
secondaryBossChance(x, y) { secondaryBossChance(x, y) {
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) { if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) {
spawn.randomLevelBoss(x, y); spawn.randomLevelBoss(x, y);
@@ -698,18 +698,20 @@ const spawn = {
} }
} }
}, },
starter(x, y, radius = Math.floor(20 + 20 * Math.random())) { starter(x, y, radius = Math.floor(15 + 20 * Math.random())) {
//easy mob for on level 1 //easy mob for on level 1
mobs.spawn(x, y, 8, radius, "#9ccdc6"); mobs.spawn(x, y, 8, radius, "#9ccdc6");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// console.log(`mass=${me.mass}, radius = ${radius}`) // console.log(`mass=${me.mass}, radius = ${radius}`)
me.accelMag = 0.0005 * simulation.accelScale; me.accelMag = 0.0002
me.memory = 60; me.repulsionRange = 100000; //squared
me.seeAtDistance2 = 1400000 //1200 vision range // me.memory = 120;
me.seeAtDistance2 = 2000000 //1400 vision range
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
me.do = function() { me.do = function() {
this.seePlayerByLookingAt(); this.seePlayerByLookingAt();
this.attraction(); this.attraction();
this.repulsion();
this.checkStatus(); this.checkStatus();
}; };
}, },
@@ -881,22 +883,17 @@ const spawn = {
} }
}, },
buffBossCulture(x, y, radius = 17, nodes = 12 + Math.min(10, simulation.difficulty * 0.27)) { growBossCulture(x, y, radius = 17, nodes = 12 + Math.min(10, simulation.difficulty * 0.25)) {
const buffID = Math.random() const buffID = Math.random()
const sideLength = 200 + 50 * Math.sqrt(nodes) // distance between each node mob const sideLength = 200 + 50 * Math.sqrt(nodes) // distance between each node mob
const targets = []
for (let i = 0; i < nodes; ++i) { for (let i = 0; i < nodes; ++i) {
const angle = 2 * Math.PI * Math.random() const angle = 2 * Math.PI * Math.random()
spawn.buffBoss(x + sideLength * Math.cos(angle) * Math.random(), y + sideLength * Math.sin(angle) * Math.random(), radius, buffID); const mag = Math.max(radius, sideLength * (1 - Math.pow(Math.random(), 1.5))) //working on a distribution that is circular, random, but not too focused in the center
// spawn.buffBoss(x + sideLength * nodes * (Math.random() - 0.5), y + sideLength * nodes * (Math.random() - 0.5), radius, buffID); spawn.growBoss(x + mag * Math.cos(angle), y + mag * Math.sin(angle), radius, buffID);
targets.push(mob[mob.length - 1].id) //track who is in the group, for shields
} }
const attachmentStiffness = 0.0001 spawn.constrain2AdjacentMobs(nodes, 0.0001, false); //loop mobs together
spawn.constrain2AdjacentMobs(nodes, attachmentStiffness, false); //loop mobs together
// if (simulation.difficulty > 15) this.groupShield(targets, x, y, sideLength + radius * 2);
}, },
buffBoss(x, y, radius, buffID) { growBoss(x, y, radius, buffID) {
mobs.spawn(x + Math.random(), y + Math.random(), 6, radius, "hsl(144, 15%, 50%)") //); mobs.spawn(x + Math.random(), y + Math.random(), 6, radius, "hsl(144, 15%, 50%)") //);
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.isBoss = true; me.isBoss = true;
@@ -913,13 +910,13 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)" me.collisionFilter.mask = cat.player | cat.bullet //| cat.body //| cat.map //"rgba(255,60,0,0.3)"
me.buffCount = 0 me.buffCount = 0
me.accelMag = 0.0001 //* simulation.accelScale; me.accelMag = 0.00006 //* simulation.accelScale;
me.setBuffed = function() { me.setBuffed = function() {
this.buffCount++ this.buffCount++
this.accelMag += 0.00005 //* Math.sqrt(simulation.accelScale) this.accelMag += 0.000035 //* Math.sqrt(simulation.accelScale)
// Matter.Body.setDensity(this, 0.001 + 0.0003 * this.buffCount) // normal density is 0.001 //+ 0.0005 * Math.sqrt(simulation.difficulty) // Matter.Body.setDensity(this, 0.001 + 0.0003 * this.buffCount) // normal density is 0.001 //+ 0.0005 * Math.sqrt(simulation.difficulty)
this.fill = `hsl(144, ${5+10*this.buffCount}%, 50%)` this.fill = `hsl(144, ${5+10*this.buffCount}%, 50%)`
const scale = 1.14; const scale = 1.13;
Matter.Body.scale(this, scale, scale); Matter.Body.scale(this, scale, scale);
this.radius *= scale; this.radius *= scale;
// this.health += 0.03 // this.health += 0.03
@@ -938,7 +935,7 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
} else { } else {
this.leaveBody = false; this.leaveBody = false;
// this.isDropPowerUp = false; //these guys can still drop power ups since they are hard to kill if (!count % 2) powerUps.spawnRandomPowerUp(this.position.x, this.position.y) // higher then normal chance to drop heals and ammo
} }
} }
me.do = function() { me.do = function() {
@@ -2521,8 +2518,8 @@ const spawn = {
sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 25)) { sneaker(x, y, radius = 15 + Math.ceil(Math.random() * 25)) {
mobs.spawn(x, y, 5, radius, "transparent"); mobs.spawn(x, y, 5, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.001); //extra dense //normal is 0.001 //makes effective life much larger
me.accelMag = 0.0011 * simulation.accelScale; me.accelMag = 0.0012 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01; me.frictionAir = 0.01;
me.g = 0.0002; //required if using 'gravity' me.g = 0.0002; //required if using 'gravity'
me.stroke = "transparent"; //used for drawSneaker me.stroke = "transparent"; //used for drawSneaker

View File

@@ -141,18 +141,24 @@
} }
}, },
haveGunCheck(name) { haveGunCheck(name) {
if ( // if (
!build.isExperimentSelection && // !build.isExperimentSelection &&
b.inventory.length > 2 && // b.inventory.length > 2 &&
name !== b.guns[b.activeGun].name && // name !== b.guns[b.activeGun].name &&
Math.random() > 2 - b.inventory.length * 0.5 // Math.random() > 2 - b.inventory.length * 0.5
) { // ) {
return false // return false
// }
// for (i = 0, len = b.inventory.length; i < len; i++) {
// if (b.guns[b.inventory[i]].name === name) return true
// }
// return false
if (build.isExperimentSelection) {
for (i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].name === name) return true
}
} }
for (i = 0, len = b.inventory.length; i < len; i++) { return b.inventory.length > 0 && b.guns[b.activeGun].name === name
if (b.guns[b.inventory[i]].name === name) return true
}
return false
}, },
damageFromTech() { damageFromTech() {
let dmg = 1 //m.fieldDamage let dmg = 1 //m.fieldDamage
@@ -182,12 +188,12 @@
return dmg * tech.slowFire * tech.aimDamage return dmg * tech.slowFire * tech.aimDamage
}, },
duplicationChance() { duplicationChance() {
return (tech.isPowerUpsVanish ? 0.2 : 0) + (tech.isStimulatedEmission ? 0.22 : 0) + tech.cancelCount * 0.05 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate return (tech.isPowerUpsVanish ? 0.2 : 0) + (tech.isStimulatedEmission ? 0.22 : 0) + tech.cancelCount * 0.05 + tech.duplicateChance + m.duplicateChance + tech.wormDuplicate + (tech.isAnthropicTech && tech.isDeathAvoidedThisLevel ? 0.5 : 0)
}, },
maxDuplicationEvent() { maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) { if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false tech.is100Duplicate = false
const range = 700 const range = 600
spawn.randomLevelBoss(m.pos.x + range, m.pos.y, spawn.nonCollideBossList); spawn.randomLevelBoss(m.pos.x + range, m.pos.y, spawn.nonCollideBossList);
spawn.randomLevelBoss(m.pos.x, m.pos.y + range, spawn.nonCollideBossList); spawn.randomLevelBoss(m.pos.x, m.pos.y + range, spawn.nonCollideBossList);
spawn.randomLevelBoss(m.pos.x - range, m.pos.y, spawn.nonCollideBossList); spawn.randomLevelBoss(m.pos.x - range, m.pos.y, spawn.nonCollideBossList);
@@ -1597,7 +1603,7 @@
}, },
{ {
name: "Pauli exclusion", name: "Pauli exclusion",
description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for an extra <strong>0.75</strong> seconds`, description: `after receiving <strong class='color-harm'>harm</strong> from a <strong>collision</strong> become<br><strong>immune</strong> to <strong class='color-harm'>harm</strong> for <strong>1</strong> extra second`,
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1607,7 +1613,7 @@
}, },
requires: "", requires: "",
effect() { effect() {
tech.collisionImmuneCycles += 45; tech.collisionImmuneCycles += 60;
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage for 30 cycles
}, },
remove() { remove() {
@@ -2597,9 +2603,29 @@
tech.isDeathAvoid = false; tech.isDeathAvoid = false;
} }
}, },
{
name: "weak anthropic principle",
description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>add <strong>50%</strong> <strong class='color-dup'>duplication</strong> chance for that level",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isDeathAvoid
},
requires: "anthropic principle",
effect() {
tech.isAnthropicTech = true
powerUps.setDo(); //needed after adjusting duplication chance
},
remove() {
tech.isAnthropicTech = false
powerUps.setDo(); //needed after adjusting duplication chance
}
},
{ {
name: "strong anthropic principle", name: "strong anthropic principle",
description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>increase <strong class='color-d'>damage</strong> by <strong>137.03599%</strong> on that level", description: "after <strong>anthropic principle</strong> prevents your <strong>death</strong><br>increase <strong class='color-d'>damage</strong> by <strong>137.03599%</strong> for that level",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 3, frequency: 3,
@@ -7527,5 +7553,6 @@
isFieldHarmReduction: null, isFieldHarmReduction: null,
isFastTime: null, isFastTime: null,
isDroneTeleport: null, isDroneTeleport: null,
isSporeWorm: null isSporeWorm: null,
isAnthropicTech: null
} }

View File

@@ -1,18 +1,27 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
tech: weak anthropic principle - after anthropic principle prevents your death, gain 50% duplication for that level
anthropic principle now correctly gives 6 seconds of harm immunity after preventing your death
buffBoss: group of mobs that buff their group after they die almost all energy regen is disabled while immune to harm
this boss maybe unbalanced in some situations, let me know you aren't immune very often so you may not notice, but it will limit some builds that let you get almost constant immunity
(get them all low on health before you start killing them) Pauli exclusion gives 1 s of harm immunity (was .75 s)
CPT reversal requires 10% less energy (min energy is 60% to activate)
CPT grenades gives many more bombs
CPT bots gives many more bots
complex spin-statistics gives 1.5/7 harm immunity (was 1/7) growBoss balance: a bit smaller and slower, and a extra high chance to drop a random power up when you kill one
also tech frequency was halved sneaker mobs are a bit slower, and have much lower health
starter mobs are no longer aggressive
tech fermions is now on by default: thrown blocks can collide with intangible mobs gun tech will now only show up for your active gun
pilot wave uses 5% more energy for balance set CSS max width of the update element to match other elements
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
try out making the player's "eye" a bigger circle
CPT reversal should drain less energy?
pink seeker boss is cool as heck, make an alt version of it
perfect diamagnetism field stays when you aren't holding field perfect diamagnetism field stays when you aren't holding field
good for perfect because it doesn't use energy good for perfect because it doesn't use energy