substructure

new level substructure
  featured element - motion triggered lasers

futures exchange 5->6% duplication per cancel
plasma torch coupling 0.015->0.025x damage per coupling
Gibbs free energy  1.005->1.006x damage per missing energy
compound lens arc adds 25->30 degrees
instability 2->2.5x damage when damage taken is 1x
constraint: after 30->40 seconds spawn WIMPs
constraint: 0.1->0.3x damage after getting power ups
renamed holographic principle -> charmed baryons

updates to community map: downpour
updated lasers in labs and testChamber to the new more realistic laser

bugs
  returning to the old console.log system from last patch
    I rather read bugs in the browser console not the n-gon console
  bots properly follow player when level flips vertically
  community map: arena's sword is properly removed at end of level
  rewrote shaped charge to be better at protecting you from all explosions
  pause correctly lists both mobs types for the level
  for quasiparticles "boost" replaces ammo in more edge cases
  bug with removing surfactant setting b.activeGun false and crashing game with checking active gun
    not sure if this is fixed or not?
This commit is contained in:
landgreen
2024-11-12 20:16:17 -08:00
parent 8bb8222b73
commit 1fde74d65a
10 changed files with 1254 additions and 476 deletions

View File

@@ -23,7 +23,7 @@ const b = {
},
fire() { },
fireNormal() {
if (b.inventory.length && b.activeGun !== null) {
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire)) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -36,7 +36,7 @@ const b = {
}
},
fireNotMove() { //added && player.speed < 0.5 && m.onGround
if (b.inventory.length && b.activeGun !== null) {
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
if (input.fire && m.fireCDcycle < m.cycle && (!input.field || m.fieldFire) && player.speed < 2.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -49,7 +49,7 @@ const b = {
}
},
fireAlwaysFire() { //added && player.speed < 0.5 && m.onGround //removed input.fire && (!input.field || m.fieldFire)
if (b.inventory.length && b.activeGun !== null) {
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
if (m.fireCDcycle < m.cycle && player.speed < 0.5 && m.onGround && Math.abs(m.yOff - m.yOffGoal) < 1) {
if (b.guns[b.activeGun].ammo > 0) {
b.fireWithAmmo()
@@ -60,7 +60,7 @@ const b = {
}
},
fireFloat() { //added && player.speed < 0.5 && m.onGround
if (b.inventory.length && b.activeGun !== null) {
if (b.inventory.length && (b.activeGun !== null && b.activeGun !== undefined)) {
if (input.fire && (!input.field || m.fieldFire)) {
if (m.fireCDcycle < m.cycle) {
if (b.guns[b.activeGun].ammo > 0) {
@@ -116,7 +116,7 @@ const b = {
}
},
refundAmmo() { //triggers after firing when you removed ammo for a gun, but didn't need to
if (tech.crouchAmmoCount && m.crouch && b.activeGun !== null) {
if (tech.crouchAmmoCount && m.crouch && (b.activeGun !== null && b.activeGun !== undefined)) {
tech.crouchAmmoCount--
if ((tech.crouchAmmoCount) % 2) {
b.guns[b.activeGun].ammo++;
@@ -377,7 +377,7 @@ const b = {
explosion(where, radius, color = "rgba(255,25,0,0.6)", reducedKnock = 1) { // typically explode is used for some bullets with .onEnd
radius *= tech.explosiveRadius
let dist, sub, knock;
let knock;
let dmg = radius * 0.019
if (tech.isExplosionHarm) radius *= 1.7 // 1/sqrt(2) radius -> area
if (tech.isSmallExplosion) {
@@ -385,10 +385,13 @@ const b = {
radius *= 0.7
dmg *= 1.7
}
let sub = Vector.sub(where, player.position);
let dist = Vector.magnitude(sub);
if (tech.isSmartRadius && radius > dist - 50) radius = Math.max(dist - 50, 1)
if (tech.isExplodeRadio) { //radiation explosion
radius *= 1.25; //alert range
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
// if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
color = "rgba(25,139,170,0.25)"
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
@@ -425,7 +428,7 @@ const b = {
}
}
} else { //normal explosions
if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
// if (tech.isSmartRadius) radius = Math.max(Math.min(radius, Vector.magnitude(Vector.sub(where, player.position)) - 25), 1)
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
@@ -444,9 +447,6 @@ const b = {
//player damage and knock back
if (m.immuneCycle < m.cycle) {
sub = Vector.sub(where, player.position);
dist = Vector.magnitude(sub);
if (dist < radius) {
if (simulation.dmgScale) {
const harm = tech.isExplosionHarm ? 0.067 : 0.05
@@ -7716,10 +7716,7 @@ const b = {
} else {
m.fireCDcycle = m.cycle
m.energy -= drain
const where = {
x: m.pos.x + 20 * Math.cos(m.angle),
y: m.pos.y + 20 * Math.sin(m.angle)
}
const where = { x: m.pos.x + 20 * Math.cos(m.angle), y: m.pos.y + 20 * Math.sin(m.angle) }
b.laser(where, {
x: where.x + 3000 * Math.cos(m.angle),
y: where.y + 3000 * Math.sin(m.angle)

View File

@@ -13,7 +13,9 @@ Math.hash = s => {
// document.getElementById("seed").placeholder = Math.initialSeed = Math.floor(Date.now() % 100000) //random every time: just the time in milliseconds UTC
window.addEventListener('error', error => {
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${error.message} <u>${error.filename}:${error.lineno}</u>`)
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${error.message} <u>${error.filename}:${error.lineno}</u>`)
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
});
document.getElementById("seed").placeholder = Math.initialSeed = String(Math.floor(Date.now() % 100000))
@@ -512,7 +514,7 @@ ${botText}
<span style="float: right;">mouse (${simulation.mouseInGame.x.toFixed(0)}, ${simulation.mouseInGame.y.toFixed(0)})</span>
<br>cycles ${m.cycle}
<span style="float: right;">velocity (${player.velocity.x.toFixed(2)}, ${player.velocity.y.toFixed(2)})</span>
<br>mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[0]})
<br>mobs ${mob.length} (${spawn.pickList[0]}, ${spawn.pickList[1]})
<span style="float: right;">blocks ${body.length}</span>
<br>bullets ${bullet.length}
<span style="float: right;">power ups ${powerUp.length}</span>

File diff suppressed because it is too large Load Diff

View File

@@ -455,6 +455,7 @@ const m = {
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
spawn.setSpawnList(); //new mob types
level.isFlipped = false
simulation.clearNow = true; //triggers a map reset
m.switchWorlds()
@@ -3389,7 +3390,7 @@ const m = {
case 4: //assembler
return `<strong>+${(0.6 * couple).toFixed(1)}</strong> <strong class='color-f'>energy</strong> per second`
case 5: //plasma
return `<strong>${(1 + 0.015 * couple).toFixed(3)}x</strong> <strong class='color-d'>damage</strong>`
return `<strong>${(1 + 0.025 * couple).toFixed(3)}x</strong> <strong class='color-d'>damage</strong>`
case 6: //time dilation
return `<strong>+${(1 + 0.05 * couple).toFixed(2)}x</strong> longer <strong style='letter-spacing: 2px;'>stopped time</strong>` //<strong>movement</strong>, <strong>jumping</strong>, and
case 7: //cloaking

View File

@@ -285,7 +285,7 @@ const powerUps = {
endDraft(type, isCanceled = false) { //type should be a gun, tech, or field
if (isCanceled) {
if (tech.isCancelDuplication) {
const value = 0.05
const value = 0.06
tech.duplication += value
simulation.inGameConsole(`tech.duplicationChance() <span class='color-symbol'>+=</span> ${value}`)
simulation.circleFlare(value);
@@ -883,7 +883,7 @@ const powerUps = {
const couplingExtraAmmo = (m.fieldMode === 10 || m.fieldMode === 0) ? 1 + 0.04 * m.coupling : 1
if (b.inventory.length > 0) {
powerUps.animatePowerUpGrab('rgba(68, 102, 119,0.25)')
if (tech.isAmmoForGun && b.activeGun !== null) { //give extra ammo to one gun only with tech logistics
if (tech.isAmmoForGun && (b.activeGun !== null && b.activeGun !== undefined)) { //give extra ammo to one gun only with tech logistics
const name = b.guns[b.activeGun]
if (name.ammo !== Infinity) {
if (tech.ammoCap) {
@@ -1618,7 +1618,7 @@ const powerUps = {
powerUps.spawn(x, y - 40, "heal", false)
}
if (tech.isResearchReality) powerUps.spawnDelay("research", 6)
if (tech.isBanish) powerUps.spawnDelay("research", 2)
if (tech.isBanish) powerUps.spawnDelay("research", 3)
if (tech.isCouplingNoHit) powerUps.spawnDelay("coupling", 9)
// if (tech.isRerollDamage) powerUps.spawnDelay("research", 1)
}
@@ -1735,9 +1735,10 @@ const powerUps = {
}
//count big power ups and small power ups
let options = ["heal", "research", "ammo"]
let options = ["heal", "research", tech.isBoostReplaceAmmo ? "boost" : "ammo"]
if (m.coupling) options.push("coupling")
if (tech.isBoostPowerUps) options.push("boost")
let bigIndexes = []
let smallIndexes = []
for (let i = 0; i < powerUp.length; i++) {

View File

@@ -2,152 +2,152 @@
//*********************************************************************
const simulation = {
loop() { }, //main game loop, gets set to normal or testing loop
normalLoop() {
try {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
simulation.textLog();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
}
m.move();
m.look();
simulation.camera();
level.custom();
powerUps.do();
mobs.draw();
simulation.draw.cons();
simulation.draw.body();
if (!m.isBodiesAsleep) mobs.loop();
mobs.healthBar();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.drawMapPath();
b.fire();
b.bulletRemove();
b.bulletDraw();
if (!m.isBodiesAsleep) b.bulletDo();
simulation.drawCircle();
simulation.runEphemera();
ctx.restore();
} catch (error) {
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
} finally {
simulation.drawCursor();
}
},
testingLoop() {
try {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
simulation.textLog();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
}
m.move();
m.look();
simulation.camera();
level.custom();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.wireFrame();
if (input.fire && m.fireCDcycle < m.cycle) {
m.fireCDcycle = m.cycle + 15; //fire cooldown
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
console.log(mob[i])
}
}
}
simulation.draw.cons();
simulation.draw.testing();
simulation.drawCircle();
simulation.runEphemera();
simulation.constructCycle()
} catch (error) {
simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
} finally {
ctx.restore();
simulation.testingOutput();
simulation.drawCursor();
}
},
// normalLoop() {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// try {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// powerUps.do();
// mobs.draw();
// simulation.draw.cons();
// simulation.draw.body();
// if (!m.isBodiesAsleep) mobs.loop();
// mobs.healthBar();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.drawMapPath();
// b.fire();
// b.bulletRemove();
// b.bulletDraw();
// if (!m.isBodiesAsleep) b.bulletDo();
// simulation.drawCircle();
// simulation.runEphemera();
// ctx.restore();
// } catch (error) {
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
// } finally {
// simulation.drawCursor();
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// powerUps.do();
// mobs.draw();
// simulation.draw.cons();
// simulation.draw.body();
// if (!m.isBodiesAsleep) mobs.loop();
// mobs.healthBar();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.drawMapPath();
// b.fire();
// b.bulletRemove();
// b.bulletDraw();
// if (!m.isBodiesAsleep) b.bulletDo();
// simulation.drawCircle();
// simulation.runEphemera();
// ctx.restore();
// simulation.drawCursor();
// },
// testingLoop() {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.wireFrame();
// if (input.fire && m.fireCDcycle < m.cycle) {
// m.fireCDcycle = m.cycle + 15; //fire cooldown
// for (let i = 0, len = mob.length; i < len; i++) {
// if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
// console.log(mob[i])
// try {
// simulation.gravity();
// Engine.update(engine, simulation.delta);
// simulation.wipe();
// simulation.textLog();
// if (m.onGround) {
// m.groundControl()
// } else {
// m.airControl()
// }
// m.move();
// m.look();
// simulation.camera();
// level.custom();
// m.draw();
// m.hold();
// level.customTopLayer();
// simulation.draw.wireFrame();
// if (input.fire && m.fireCDcycle < m.cycle) {
// m.fireCDcycle = m.cycle + 15; //fire cooldown
// for (let i = 0, len = mob.length; i < len; i++) {
// if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
// console.log(mob[i])
// }
// }
// }
// simulation.draw.cons();
// simulation.draw.testing();
// simulation.drawCircle();
// simulation.runEphemera();
// simulation.constructCycle()
// } catch (error) {
// simulation.inGameConsole(`<strong style='color:red;'>ERROR:</strong> ${(error.stack && error.stack.replace(/\n/g, "<br>")) || (error.message + ` <u>${error.filename}:${error.lineno}</u>`)}`);
// } finally {
// ctx.restore();
// simulation.testingOutput();
// simulation.drawCursor();
// }
// simulation.draw.cons();
// simulation.draw.testing();
// simulation.drawCircle();
// simulation.runEphemera();
// simulation.constructCycle()
// ctx.restore();
// simulation.testingOutput();
// simulation.drawCursor();
// },
normalLoop() {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
simulation.textLog();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
}
m.move();
m.look();
simulation.camera();
level.custom();
powerUps.do();
mobs.draw();
simulation.draw.cons();
simulation.draw.body();
if (!m.isBodiesAsleep) mobs.loop();
mobs.healthBar();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.drawMapPath();
b.fire();
b.bulletRemove();
b.bulletDraw();
if (!m.isBodiesAsleep) b.bulletDo();
simulation.drawCircle();
simulation.runEphemera();
ctx.restore();
simulation.drawCursor();
},
testingLoop() {
simulation.gravity();
Engine.update(engine, simulation.delta);
simulation.wipe();
simulation.textLog();
if (m.onGround) {
m.groundControl()
} else {
m.airControl()
}
m.move();
m.look();
simulation.camera();
level.custom();
m.draw();
m.hold();
level.customTopLayer();
simulation.draw.wireFrame();
if (input.fire && m.fireCDcycle < m.cycle) {
m.fireCDcycle = m.cycle + 15; //fire cooldown
for (let i = 0, len = mob.length; i < len; i++) {
if (Vector.magnitudeSquared(Vector.sub(mob[i].position, simulation.mouseInGame)) < mob[i].radius * mob[i].radius) {
console.log(mob[i])
}
}
}
simulation.draw.cons();
simulation.draw.testing();
simulation.drawCircle();
simulation.runEphemera();
simulation.constructCycle()
ctx.restore();
simulation.testingOutput();
simulation.drawCursor();
},
isTimeSkipping: false,
timeSkip(cycles = 60) {
simulation.isTimeSkipping = true;
@@ -712,7 +712,7 @@ const simulation = {
mouseMove = mouseMoveDefault
}
},
translatePlayerAndCamera(where) {
translatePlayerAndCamera(where, isTranslateBots = true) {
//infinite falling. teleport to sky after falling
const before = { x: player.position.x, y: player.position.y, }
Matter.Body.setPosition(player, { x: where.x, y: where.y });
@@ -728,14 +728,15 @@ const simulation = {
//is there a reason to update m.pos here?
// m.pos.x = player.position.x;
// m.pos.y = playerBody.position.y - m.yOff;
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) {
if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player
Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
} else { //close bots maintain relative distance to player on teleport
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
if (isTranslateBots) {
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) {
if (Vector.magnitudeSquared(Vector.sub(bullet[i].position, player.position)) > 1000000) { //far away bots teleport to player
Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
} else { //close bots maintain relative distance to player on teleport
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
}
}
}
}
@@ -996,7 +997,7 @@ const simulation = {
simulation.makeGunHUD();
simulation.lastLogTime = 0;
mobs.mobDeaths = 0
level.isFlipped = false
level.onLevel = 0;
level.levelsCleared = 0;
level.updateDifficulty()

View File

@@ -42,6 +42,7 @@ const spawn = {
spawn.pickList.splice(0, 1);
const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length]
spawn.pickList.push(push);
// if (spawn.mobTypeSpawnIndex > spawn.mobTypeSpawnOrder.length) spawn.mobTypeSpawnIndex = 0
//each level has 2 mobs: one new mob and one from the last level
// spawn.pickList.splice(0, 1);
@@ -116,8 +117,8 @@ const spawn = {
secondaryBossChance(x, y) {
if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
spawn.randomLevelBoss(x, y);
powerUps.directSpawn(x - 30, y, "ammo");
powerUps.directSpawn(x + 30, y, "ammo");
powerUps.spawn(x - 30, y, "ammo");
powerUps.spawn(x + 30, y, "ammo");
} else {
return false
}

View File

@@ -249,18 +249,7 @@ const tech = {
}
},
haveGunCheck(name, needActive = true) {
// if (
// !build.isExperimentSelection &&
// b.inventory.length > 2 &&
// name !== b.guns[b.activeGun].name &&
// Math.random() > 2 - b.inventory.length * 0.5
// ) {
// 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 (b.activeGun === null || b.activeGun === undefined) return false
if (build.isExperimentSelection || !needActive) {
for (i = 0, len = b.inventory.length; i < len; i++) {
if (b.guns[b.inventory[i]].name === name) return true
@@ -269,6 +258,15 @@ const tech = {
} else { //must be holding gun, this is the standard while playing
return b.inventory.length > 0 && b.guns[b.activeGun].name === name
}
// if (build.isExperimentSelection || !needActive) {
// for (i = 0, len = b.inventory.length; i < len; i++) {
// if (b.guns[b.inventory[i]].name === name) return true
// }
// return false
// } else { //must be holding gun, this is the standard while playing
// return b.inventory.length > 0 && b.guns[b.activeGun].name === name
// }
},
hasExplosiveDamageCheck() {
return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
@@ -276,9 +274,9 @@ const tech = {
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
let dmg = tech.damage * m.fieldDamage
if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.1
if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.3
if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 1.5
if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2
if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2.5
if (tech.isImmunityDamage && m.immuneCycle > m.cycle) dmg *= 3
if (tech.isPowerUpDamage) dmg *= 1 + 0.07 * powerUp.length
if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.4 : 4
@@ -288,7 +286,7 @@ const tech = {
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length
if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.015 * m.coupling
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.025 * m.coupling
if (tech.isVerlet) dmg *= 3
if (tech.isTechDebt) dmg *= tech.totalCount > 20 ? Math.pow(0.85, tech.totalCount - 20) : 4 - 0.15 * tech.totalCount
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828
@@ -299,7 +297,7 @@ const tech = {
if (tech.isRerollDamage) dmg *= 1 + Math.max(0, 0.05 * powerUps.research.count)
if (tech.isBotDamage) dmg *= 1 + 0.04 * b.totalBots()
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isLowEnergyDamage) dmg *= 1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)
if (tech.isLowEnergyDamage) dmg *= 1 + 0.6 * Math.max(0, m.maxEnergy - m.energy)
if (tech.energyDamage) dmg *= 1 + m.energy * 0.23 * tech.energyDamage;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.01
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
@@ -2874,7 +2872,7 @@ const tech = {
{
name: "Gibbs free energy",
descriptionFunction() {
return `<strong>1.005x</strong> <strong class='color-d'>damage</strong> for each missing <strong class='color-f'>energy</strong><br><em style ="float: right;">(${(1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)</em>`
return `<strong>1.006x</strong> <strong class='color-d'>damage</strong> for each missing <strong class='color-f'>energy</strong><br><em style ="float: right;">(${(1 + 0.5 * Math.max(0, m.maxEnergy - m.energy)).toFixed(2)}x)</em>`
},
maxCount: 1,
count: 0,
@@ -3086,7 +3084,7 @@ const tech = {
{
name: "instability",
descriptionFunction() {
return `<strong>2x</strong> <strong class='color-d'>damage</strong> while your <strong class='color-defense'>damage taken</strong> is <strong>1.00x</strong><br><em style ="float: right;">(current damage taken = ${(m.defense()).toFixed(2)}x)</em>`
return `<strong>2.5x</strong> <strong class='color-d'>damage</strong> while your <strong class='color-defense'>damage taken</strong> is <strong>1.00x</strong><br><em style ="float: right;">(current damage taken = ${(m.defense()).toFixed(2)}x)</em>`
},
maxCount: 1,
count: 0,
@@ -3597,7 +3595,7 @@ const tech = {
},
{
name: "decoherence",
description: `after a <strong>boss</strong> <strong>dies</strong> spawn ${powerUps.orb.research(2)}<br>${powerUps.orb.tech()} options you don't <strong class='color-choice'><span>ch</span><span>oo</span><span>se</span></strong> won't <strong>reoccur</strong>`,
description: `after a <strong>boss</strong> <strong>dies</strong> spawn ${powerUps.orb.research(3)}<br>${powerUps.orb.tech()} options you don't <strong class='color-choice'><span>ch</span><span>oo</span><span>se</span></strong> won't <strong>reoccur</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3606,7 +3604,6 @@ const tech = {
return !tech.isSuperDeterminism
},
requires: "not, superdeterminism",
bonusResearch: 7,
effect() {
tech.isBanish = true
},
@@ -3626,8 +3623,8 @@ const tech = {
description: `after observing a ${powerUps.orb.tech()} <strong class='color-choice'><span>ch</span><span>oi</span><span>ce</span></strong><br>that <strong class='color-choice'><span>ch</span><span>oi</span><span>ce</span></strong> is available for all <strong>all</strong> future ${powerUps.orb.tech()}`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isBanish
},
@@ -4301,7 +4298,7 @@ const tech = {
},
{
name: "futures exchange",
description: `clicking <strong class='color-cancel'>cancel</strong> for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}<br>gives <strong>+5%</strong> power up <strong class='color-dup'>duplication</strong> chance`,
description: `clicking <strong class='color-cancel'>cancel</strong> for ${powerUps.orb.field()}, ${powerUps.orb.tech()}, or ${powerUps.orb.gun()}<br>gives <strong>+6%</strong> power up <strong class='color-dup'>duplication</strong> chance`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -7448,7 +7445,7 @@ const tech = {
},
{
name: "compound lens",
description: "<strong>1.4x</strong> <strong class='color-laser'>laser</strong> lens <strong class='color-d'>damage</strong><br><strong>+25°</strong> lens arc",
description: "<strong>1.4x</strong> <strong class='color-laser'>laser</strong> lens <strong class='color-d'>damage</strong><br><strong>+30°</strong> lens arc",
isGunTech: true,
maxCount: 9,
count: 0,
@@ -7459,7 +7456,7 @@ const tech = {
},
requires: "lens",
effect() {
b.guns[11].arcRange += 25 * Math.PI / 180 / 2
b.guns[11].arcRange += 30 * Math.PI / 180 / 2
b.guns[11].lensDamageOn += 0.4
},
remove() {
@@ -8763,7 +8760,7 @@ const tech = {
},
{
name: "vacuum fluctuation",
description: `use ${powerUps.orb.research(3)}<br><strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`,
description: `use ${powerUps.orb.research(2)}<br><strong>+11%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong>`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8777,14 +8774,16 @@ const tech = {
tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
for (let i = 0; i < 3; i++) {
for (let i = 0; i < 2; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
}
},
remove() {
tech.fieldDuplicate = 0
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count > 0) powerUps.research.changeRerolls(3)
if (this.count) {
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
powerUps.research.changeRerolls(2)
}
}
},
{
@@ -8900,7 +8899,7 @@ const tech = {
}
},
{
name: "charmed baryons",
name: "holographic principle",
description: `<strong>0.8x</strong> <strong>movement</strong> and <strong>jumping</strong><br><strong class='color-worm'>wormholes</strong> cost <strong>zero</strong> <strong class='color-f'>energy</strong>`,
isFieldTech: true,
maxCount: 1,
@@ -9694,7 +9693,7 @@ const tech = {
effect() {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isDropPowerUp) {
powerUps.directSpawn(mob[i].position.x, mob[i].position.y, "ammo");
powerUps.spawn(mob[i].position.x, mob[i].position.y, "ammo");
mob[i].death();
}
}
@@ -11701,7 +11700,7 @@ const tech = {
bc.activated = false
bc.onmessage = function (ev) {
if (ev.data === 'tech') powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
if (ev.data === 'tech') powerUps.spawn(m.pos.x, m.pos.y, "tech");
if (ev.data === 'death') {
m.death()
bc.close(); //end session