@@ -1607,6 +1616,8 @@ const powerUps = {
}
}
}
+ powerUps.spawn(x + 25, y - 25, "ammo", false);
+ if (simulation.difficultyMode > 5) powerUps.spawn(x - 25, y - 50, "ammo", false);
if (tech.isAddRemoveMaxHealth) {
powerUps.spawn(x + 20, y, "tech", false)
powerUps.spawn(x - 20, y, "research", false)
diff --git a/js/spawn.js b/js/spawn.js
index 9b9f2a8..4f743bc 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1,6 +1,6 @@
//main object for spawning things in a level
const spawn = {
- nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
+ nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture", "snakeBoss"],
// other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss, mineBoss, hopMotherBoss //these need a particular level to work so they are not included in the random pool
randomBossList: [
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
@@ -114,9 +114,9 @@ const spawn = {
}
}
},
- secondaryBossChance(x, y) {
+ secondaryBossChance(x, y, options = []) {
if (simulation.difficultyMode > 2 && level.levelsCleared > 1) {
- spawn.randomLevelBoss(x, y);
+ spawn.randomLevelBoss(x, y, options);
powerUps.spawn(x - 30, y, "ammo");
powerUps.spawn(x + 30, y, "ammo");
} else {
@@ -3921,8 +3921,8 @@ const spawn = {
}
me.frictionStatic = 0;
me.friction = 0;
- me.memory = 240
- me.seePlayerFreq = 55
+ me.memory = 900;
+ me.seePlayerFreq = 41
me.delay = 5 + 2 * simulation.CDScale;//8 + 3 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
me.JumpDistance = 0//set in redMode()
@@ -4082,21 +4082,18 @@ const spawn = {
move()
} else if (this.seePlayer.recall) { //chase player's history
this.lostPlayer();
- if (!m.isCloak) {
- for (let i = 0; i < 50; i++) { //if lost player lock onto a player location in history
+ if (m.isCloak) {
+ move(this.seePlayer.position) //go after where you last saw the player
+ } else {
+ for (let i = 0; i < 55; i++) { //if lost player lock onto a player location in history
let history = m.history[(m.cycle - 10 * i) % 600]
if (Matter.Query.ray(map, this.position, history.position).length === 0) {
- this.seePlayer.recall = this.memory + Math.round(this.memory * Math.random()); //cycles before mob falls a sleep
- this.seePlayer.position.x = history.position.x;
- this.seePlayer.position.y = history.position.y;
- this.seePlayer.yes = true;
- move()
+ move(history.position) //go after where you last saw the player
break
}
}
}
}
-
}
this.checkStatus();
if (this.isInvulnerable) {
@@ -4170,7 +4167,7 @@ const spawn = {
me.fire = function () {
// this.armor();
this.checkStatus();
- if (!m.isCloak && !this.isStunned) {
+ if (!this.isStunned) {
if (this.isFiring) {
if (this.fireCycle > this.fireDelay) { //fire
this.isFiring = false
@@ -4221,7 +4218,9 @@ const spawn = {
}
} else { //aim at player
this.fireCycle++
- this.fireDir = Vector.normalise(Vector.sub(m.pos, this.position)); //set direction to turn to fire
+ //if cloaked, aim at player's history from 3 seconds ago
+ const whereIsPlayer = m.isCloak ? m.history[(m.cycle - 180) % 600].position : m.pos
+ this.fireDir = Vector.normalise(Vector.sub(whereIsPlayer, this.position)); //set direction to turn to fire
//rotate towards fireAngle
const angle = this.angle + Math.PI / 2;
const c = Math.cos(angle) * this.fireDir.x + Math.sin(angle) * this.fireDir.y;
@@ -4233,7 +4232,7 @@ const spawn = {
} else if (this.fireCycle > 45) { //fire
unit = Vector.mult(Vector.normalise(Vector.sub(this.vertices[1], this.position)), this.distanceToPlayer() - 100)
this.fireTarget = Vector.add(this.vertices[1], unit)
- if (Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
+ if (Vector.magnitude(Vector.sub(whereIsPlayer, this.fireTarget)) < 1000) { //if's possible for this to be facing 180 degrees away from the player, this makes sure that doesn't occur
Matter.Body.setAngularVelocity(this, 0)
this.fireLockCount = 0
this.isFiring = true
@@ -4277,7 +4276,7 @@ const spawn = {
}, Vector.normalise(Vector.sub(this.fireTarget, this.position)));
//distance between the target and the player's location
if (
- m.isCloak ||
+ // m.isCloak ||
dot > 0.03 || // not looking at target
Matter.Query.ray(map, this.fireTarget, this.position).length || Matter.Query.ray(body, this.fireTarget, this.position).length || //something blocking line of sight
Vector.magnitude(Vector.sub(m.pos, this.fireTarget)) > 1000 // distance from player to target is very far, (this is because dot product can't tell if facing 180 degrees away)
@@ -5056,7 +5055,7 @@ const spawn = {
me.laserSword = function (where, angle, length) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) };
- best = vertexCollision(where, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]);
+ best = vertexCollision(where, look, [map, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5663,7 +5662,7 @@ const spawn = {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+ best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
@@ -5762,7 +5761,7 @@ const spawn = {
me.laserSword = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+ best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5854,7 +5853,7 @@ const spawn = {
me.laserSword = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+ best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5964,7 +5963,7 @@ const spawn = {
me.laserSpear = function (where, angle) {
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+ best = vertexCollision(where, look, [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead)) {
this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player
@@ -6180,7 +6179,7 @@ const spawn = {
mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1];
me.seeAtDistance2 = 500000;
- me.accelMag = 0.00007 + 0.0001 * simulation.accelScale;
+ me.accelMag = 0.0002 + 0.0001 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
Matter.Body.setDensity(me, 0.0002); //normal is 0.001
me.damageReduction = 0.1
@@ -6222,7 +6221,7 @@ const spawn = {
if (this.health < 0.8) me.seeAtDistance2 = 2000000;
}
me.do = function () {
- if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
+ if (this.speed > 6) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
this.seePlayerCheckByDistance();
this.checkStatus();
this.attraction();
@@ -7215,6 +7214,7 @@ const spawn = {
me.do = function () {
this.seePlayerByHistory(60);
this.attraction();
+ if (this.distanceToPlayer2() > 9000000) this.attraction(); //extra attraction if far away
this.checkStatus();
this.eventHorizon = 950 + 250 * Math.sin(simulation.cycle * 0.005)
if (!simulation.isTimeSkipping) {
diff --git a/js/tech.js b/js/tech.js
index 778fa1b..954987c 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -141,7 +141,7 @@ const tech = {
if (tech.tech[index].isLost) tech.tech[index].isLost = false; //give specific tech
if (tech.isBanish && tech.tech[index].isBanished) tech.tech[index].isBanished = false //stops the bug where you can't gets stacks of tech you take with decoherence, I think
if (tech.isDamageFieldTech && tech.tech[index].isFieldTech) {
- tech.damage *= 1.15
+ tech.damage *= 1.2
// simulation.inGameConsole(`
damage *= ${1.05}`)
simulation.inGameConsole(`
tech.damage *= ${1.1} //hidden-variable theory`);
}
@@ -273,7 +273,7 @@ const tech = {
if (tech.isDamageCooldown) dmg *= m.lastKillCycle + tech.isDamageCooldownTime > m.cycle ? 0.4 : 4
if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 2
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9
- if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.9 : 2
+ if (tech.offGroundDamage && !m.onGround) dmg *= tech.offGroundDamage
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
if (tech.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length
if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage
@@ -294,11 +294,19 @@ const tech = {
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 2
if (tech.isSpeedDamage) dmg *= 1 + Math.min(2, ((tech.speedAdded + player.speed) * 0.033))//1 + Math.min(1, (tech.speedAdded + player.speed) * 0.0193)
if (tech.isAxion && tech.isHarmDarkMatter) dmg *= ((tech.isMoveDarkMatter || tech.isNotDarkMatter) ? 3.2 : 2)
- if (tech.isHarmDamage && m.lastHarmCycle + 480 > m.cycle) dmg *= 3;
+ if (tech.isHarmDamage && m.lastHarmCycle + 240 > m.cycle) dmg *= 4;
if (tech.lastHitDamage && m.lastHit) dmg *= 1 + tech.lastHitDamage * m.lastHit
// if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, 1 - (tech.isEnergyHealth ? m.energy : m.health))
if (tech.isLowHealthDmg) dmg *= 1 + 0.6 * Math.max(0, (tech.isEnergyHealth ? m.maxEnergy - m.energy : m.maxHealth - m.health))
if (tech.isJunkDNA) dmg *= 1 + 2 * (tech.junkChance + level.junkAdded)
+ if (tech.isDemineralize) {
+ //reduce mineral percent based on time since last check
+ const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
+ tech.mineralLastCheck = simulation.cycle
+ tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
+ tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
+ dmg *= tech.mineralDamage
+ }
return dmg
},
duplicationChance() {
@@ -430,7 +438,7 @@ const tech = {
},
{
name: "Hilbert space",
- description: "
4x damageafter a
collision enter an
alternate reality",
+ description: "
3x damageafter a
collision enter an
alternate reality",
maxCount: 1,
count: 0,
frequency: 1,
@@ -441,7 +449,7 @@ const tech = {
return !m.isAltSkin && !tech.isResearchReality && !tech.isSwitchReality
},
requires: "not skinned, Ψ(t) collapse, many-worlds",
- damage: 4,
+ damage: 3,
effect() {
m.skin.anodize();
tech.damage *= this.damage
@@ -549,8 +557,8 @@ const tech = {
},
maxCount: 1,
count: 0,
- frequency: 5,
- frequencyDefault: 5,
+ frequency: 4,
+ frequencyDefault: 4,
allowed() {
return tech.isEnergyHealth && !tech.isOverHeal
},
@@ -781,7 +789,7 @@ const tech = {
{
name: "pigeonhole principle",
descriptionFunction() {
- return `
1.4x damage per ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()}
cycles each level and you can't
switch`
+ return `
1.4x damage per ${powerUps.orb.gun()}, but your active ${powerUps.orb.gun()}
cycles each level and you can't
switch`
},
// descriptionFunction() {
// let info = ""
@@ -1010,7 +1018,7 @@ const tech = {
{
name: "Pareto efficiency",
descriptionFunction() {
- return `for each ${powerUps.orb.gun()} in your inventory
randomly get
5x or
0.2x ammo per ${powerUps.orb.ammo(1)}`
+ return `all you ${powerUps.orb.gun()} randomly get
5x or
0.2x ammo per ${powerUps.orb.ammo(1)}`
},
maxCount: 1,
count: 0,
@@ -1395,6 +1403,64 @@ const tech = {
tech.isCrit = false;
}
},
+ {
+ name: "remineralization",
+ descriptionFunction() {
+ //reduce mineral percent based on time since last check
+ const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
+ tech.mineralLastCheck = simulation.cycle
+ tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
+ tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
+
+ return `after
mobs die gain
0.85x damage takeneffects stack, but fade
10% every second
(${tech.mineralDamageReduction.toFixed(2)}x)`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() { return true },
+ requires: "",
+ effect() {
+ tech.isRemineralize = true
+ tech.mineralDamageReduction = 1
+ tech.mineralLastCheck = simulation.cycle
+ },
+ remove() {
+ tech.isRemineralize = false
+ tech.mineralDamageReduction = 1
+ tech.mineralLastCheck = simulation.cycle
+ }
+ },
+ {
+ name: "demineralization",
+ descriptionFunction() {
+ //reduce mineral percent based on time since last check
+ const seconds = (simulation.cycle - tech.mineralLastCheck) / 60
+ tech.mineralLastCheck = simulation.cycle
+ tech.mineralDamage = 1 + (tech.mineralDamage - 1) * Math.pow(0.9, seconds);
+ tech.mineralDamageReduction = 1 - (1 - tech.mineralDamageReduction) * Math.pow(0.9, seconds);
+
+ return `after
mobs die gain
1.08x damageeffects stack, but fade
10% every second
(${tech.mineralDamage.toFixed(2)}x)`
+ },
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.isDemineralize = true
+ tech.mineralDamage = 1
+ tech.mineralLastCheck = simulation.cycle
+ },
+ remove() {
+ tech.isDemineralize = false
+ tech.mineralDamage = 1
+ tech.mineralLastCheck = simulation.cycle
+ }
+ },
{
name: "shear stress",
description: "after mobs
diethey fire a
nail at nearby mobs",
@@ -1403,9 +1469,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
- return !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
+ return true
},
- requires: "no other mob death tech",
+ requires: "",
effect() {
tech.nailsDeathMob++
},
@@ -1421,9 +1487,9 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
- return !tech.sporesOnDeath && !tech.nailsDeathMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
+ return true
},
- requires: "no other mob death tech",
+ requires: "",
effect() {
tech.isExplodeMob = true;
},
@@ -1437,22 +1503,16 @@ const tech = {
descriptionFunction() {
return `after mobs
die there is a
13% chance
they grow ${b.guns[6].nameString('s')}`
},
- // description: "after mobs
diethey have a
+10% chance to grow
spores",
maxCount: 9,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
- return !tech.nailsDeathMob && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.iceIXOnDeath
+ return true
},
- requires: "no other mob death tech",
+ requires: "",
effect() {
tech.sporesOnDeath += 0.13;
- // if (tech.isSporeWorm) {
- // for (let i = 0; i < 4; i++) b.worm(m.pos)
- // } else {
- // for (let i = 0; i < 8; i++) b.spore(m.pos)
- // }
},
remove() {
tech.sporesOnDeath = 0;
@@ -2658,7 +2718,7 @@ const tech = {
{
name: "non-Newtonian armor",
link: `
non-Newtonian armor`,
- description: "after mob
collisions0.3x damage taken for
10 seconds",
+ description: "after mob
collisions0.4x damage taken for
10 seconds",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2735,7 +2795,7 @@ const tech = {
},
{
name: "fermion",
- description: `for
6 seconds after mobs
diebecome
invulnerable and
inhibit energy regen`,
+ description: `for
5 seconds after mobs
diebecome
invulnerable and
inhibit energy regen`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3066,7 +3126,7 @@ const tech = {
{
name: "stability",
descriptionFunction() {
- return `
0.2x damage takenwhile your
health is at maximum`
+ return `
0.1x damage takenwhile your
health is at maximum`
},
maxCount: 1,
count: 0,
@@ -3168,7 +3228,7 @@ const tech = {
{
name: "Zenos paradox",
descriptionFunction() {
- return `
0.15x damage taken–5% of current ${tech.isEnergyHealth ? "
energy" : "
health"} every
5 seconds`
+ return `
0.2x damage taken–5% of current ${tech.isEnergyHealth ? "
energy" : "
health"} every
5 seconds`
},
maxCount: 1,
count: 0,
@@ -3576,7 +3636,7 @@ const tech = {
{
name: "Ψ(t) collapse",
link: `
Ψ(t) collapse`,
- description: `after a
boss dies spawn ${powerUps.orb.research(6)}
if you
research enter an
alternate reality`,
+ description: `after a
boss dies spawn ${powerUps.orb.research(4)}
if you
research enter an
alternate reality`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -5812,7 +5872,7 @@ const tech = {
},
{
name: "launch system",
- description: `
5x missile fire rate1.2x missile
ammo per ${powerUps.orb.ammo(1)}`,
+ description: `
5x missile fire rate1.3x missile
ammo per ${powerUps.orb.ammo(1)}`,
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5822,7 +5882,7 @@ const tech = {
return tech.haveGunCheck("missiles") && !tech.isMissileBig
},
requires: "missiles, not cruise missile",
- ammoBonus: 1.2,
+ ammoBonus: 1.3,
effect() {
tech.missileFireCD = 10
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7898,7 +7958,7 @@ const tech = {
{
name: "radiative equilibrium",
descriptionFunction() {
- return `after losing ${tech.isEnergyHealth ? "
energy" : "
health"}
3x damage for
8 seconds`
+ return `after losing ${tech.isEnergyHealth ? "
energy" : "
health"}
4x damage for
4 seconds`
},
isFieldTech: true,
maxCount: 1,
@@ -7925,13 +7985,13 @@ const tech = {
maxCount: 3,
count: 0,
frequency: 2,
- frequencyDefault: 200,
+ frequencyDefault: 2,
allowed() {
return m.fieldMode === 8 || m.fieldMode === 3
},
requires: "negative mass, pilot wave",
effect() {
- tech.lastHitDamage += 6;
+ tech.lastHitDamage += 8;
},
remove() {
tech.lastHitDamage = 0;
@@ -7946,9 +8006,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return m.fieldMode === 3
+ return m.fieldMode === 3 && tech.negativeMassCost !== 0
},
- requires: "negative mass",
+ requires: "negative mass, not equivalence principle",
effect() {
tech.isNeutronium = true
tech.baseFx *= 0.86
@@ -7966,29 +8026,51 @@ const tech = {
}
},
{
- name: "aerostat",
- descriptionFunction() {
- return `
2x damage while
off the
ground0.9x damage while
on the
ground(${(m.onGround ? 0.9 : 2).toFixed(1)}x)`
- },
+ name: "equivalence principle",
+ description: `
negative mass field doesn't cost
energy`,
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
+ allowed() {
+ return m.fieldMode === 3 && !tech.isNeutronium
+ },
+ requires: "negative mass, not neutronium",
+ effect() {
+ tech.negativeMassCost = 0
+ },
+ //also removed in m.setHoldDefaults() if player switches into a bad field
+ remove() {
+ tech.negativeMassCost = 0.00035
+ }
+ },
+ {
+ name: "aerostat",
+ descriptionFunction() {
+ const damage = m.onGround ? 1 : (tech.offGroundDamage)
+ const infoText = this.count ? `
(${damage.toFixed(0)}x)` : ""
+ return `
2x damage while
off the
ground${infoText}`
+ },
+ isFieldTech: true,
+ maxCount: 3,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
allowed() {
return m.fieldMode === 3 || m.fieldMode === 10
},
requires: "negative mass, grappling hook",
effect() {
- tech.isNoGroundDamage = true
+ tech.offGroundDamage++
},
remove() {
- tech.isNoGroundDamage = false
+ tech.offGroundDamage = 1
}
},
{
name: "annihilation",
- description: "after
colliding with non-boss mobs
they are
annihilated and
–10 energy",
+ description: "
mobs you
collide with are
annihilated–8 energy each time",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8723,12 +8805,12 @@ const tech = {
},
{
name: "hidden-variable theory",
- description: `
1.15x damage each time you
choose ${powerUps.orb.fieldTech()}`,
+ description: `
1.2x damage after you
choose ${powerUps.orb.fieldTech()}`,
isFieldTech: true,
maxCount: 1,
count: 0,
- frequency: 1,
- frequencyDefault: 1,
+ frequency: 4,
+ frequencyDefault: 4,
allowed() {
return m.fieldMode === 8
},
@@ -8742,7 +8824,7 @@ const tech = {
},
{
name: "WIMPs",
- description: `at each
level's exit, spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly
chases you`,
+ description: `at the exit to each
level spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly
chases you`,
isFieldTech: true,
maxCount: 9,
count: 0,
@@ -8770,9 +8852,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
- return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2)
+ return (m.fieldMode === 8 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2)
},
- requires: "wormhole, time dilation, negative mass, pilot wave",
+ requires: "wormhole, pilot wave",
effect() {
tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -8792,7 +8874,7 @@ const tech = {
{
name: "transdimensional worms",
link: `
transdimensional worms`,
- description: "after a
block falls into a
wormholespawn a
worm",
+ description: "after a
block falls into a
wormholespawn
1-2 worms",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8812,7 +8894,7 @@ const tech = {
{
name: "anyon",
descriptionFunction() {
- return `
2x energy after
duplicating a power up
+6% chance to
duplicate spawned
power ups`
+ return `
2x stored
energy after
duplicating power ups
+6% chance to
duplicate spawned
power ups`
},
isFieldTech: true,
maxCount: 1,
@@ -8903,35 +8985,44 @@ const tech = {
},
{
name: "holographic principle",
- description: `
0.8x movement and
jumpingwormholes cost
zero energy`,
+ cost: 2,
+ descriptionFunction() {
+ return `use ${powerUps.orb.research(this.cost)}
making
wormholes doesn't cost
energy`
+ },
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
- return m.fieldMode === 9 && !tech.isWormholeMapIgnore
+ return m.fieldMode === 9 && !tech.isWormholeMapIgnore && (build.isExperimentSelection || powerUps.research.count > this.cost - 1)
},
requires: "wormhole, not affine connection",
effect() {
+ for (let i = 0; i < this.cost; i++) {
+ if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
+ }
tech.isFreeWormHole = true
- tech.baseFx *= 0.8
- tech.baseJumpForce *= 0.8
- m.setMovement()
+ // tech.baseFx *= 0.8
+ // tech.baseJumpForce *= 0.8
+ // m.setMovement()
},
//also removed in m.setHoldDefaults() if player switches into a bad field
remove() {
tech.isFreeWormHole = false
- if (!tech.isNeutronium) {
- tech.baseFx = 0.08
- tech.baseJumpForce = 10.5
- m.setMovement()
+ if (this.count) {
+ powerUps.research.changeRerolls(this.cost)
}
+ // if (!tech.isNeutronium) {
+ // tech.baseFx = 0.08
+ // tech.baseJumpForce = 10.5
+ // m.setMovement()
+ // }
}
},
{
name: "affine connection",
- description: "
wormholes can tunnel through
anythingfor
2x energy cost",
+ description: "
wormholes can tunnel through
anything2x energy cost going through
solids",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -10459,9 +10550,22 @@ const tech = {
requires: "",
effect() {
setInterval(() => {
+ const unit = {
+ x: 1,
+ y: 0
+ }
+ for (let i = 0; i < 5; i++) {
+ const where = Vector.add(m.pos, Vector.mult(Vector.rotate(unit, Math.random() * 2 * Math.PI), 2000 + 2000 * Math.random()))
+ spawn.sucker(where.x, where.y, 140)
+ const who = mob[mob.length - 1]
+ who.locatePlayer()
+ // who.damageReduction = 0.2
+ }
+
m.switchWorlds()
simulation.trails()
- }, 20000); //every 30 seconds
+
+ }, 20000); //every 20 seconds
},
remove() { }
},
@@ -10485,6 +10589,26 @@ const tech = {
},
remove() { }
},
+ {
+ name: "aerodynamics",
+ description: "reduce air friction for all power ups",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isInstant: true,
+ isJunk: true,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ const styleEl = document.createElement('style');
+ document.head.appendChild(styleEl);
+ const myStyle = styleEl.sheet;
+ myStyle.insertRule(".choose-grid-no-images {border-radius: 50%;}", 0);
+ },
+ remove() { }
+ },
{
name: "pop-ups",
description: "sign up to learn endless easy ways to win n-gon
that Landgreen doesn't want you to know!!!1!!",
@@ -12204,7 +12328,7 @@ const tech = {
collidePowerUps: null,
isDilate: null,
isDiaphragm: null,
- isNoGroundDamage: null,
+ offGroundDamage: null,
isSuperBounce: null,
isDivisor: null,
isFoamCavitation: null,
@@ -12236,4 +12360,9 @@ const tech = {
isWiki: null,
isStaticBlock: null,
isDamageFieldTech: null,
+ isRemineralize: null,
+ mineralDamageReduction: null,
+ isDemineralize: null,
+ mineralDamage: null,
+ negativeMassCost: null,
}
\ No newline at end of file
diff --git a/style.css b/style.css
index 9b15685..b72325c 100644
--- a/style.css
+++ b/style.css
@@ -746,6 +746,18 @@ summary {
background-color: rgba(255, 255, 255, 0.4);
}
+.constraint-module {
+ line-height: 160%;
+ padding: 20px;
+ border-radius: 5px;
+ font-size: 1.2em;
+ font-family: monospace;
+ font-weight: 800;
+ text-align: center;
+ color: #624;
+ background-color: rgba(255, 240, 250, 1);
+}
+
#right-HUD-constraint {
position: absolute;
top: 12px;
@@ -768,6 +780,39 @@ summary {
transition: all 0.5s linear;
}
+.constraint {
+ color: rgb(141, 23, 88);
+}
+
+.metallic-sparkle {
+ background: linear-gradient(90deg,
+ #c38aa6,
+ #e6c0d9,
+ #dca4c6,
+ #c38aa6,
+ #e6c0d9,
+ #dca4c6,
+ #c38aa6);
+ background-size: 200% 100%;
+ background-clip: text;
+ color: transparent;
+ animation: shimmer 4s infinite linear;
+}
+
+@keyframes shimmer {
+ 0% {
+ background-position: 0% 50%;
+ }
+
+ 50% {
+ background-position: 100% 50%;
+ }
+
+ 100% {
+ background-position: 0% 50%;
+ }
+}
+
#text-log {
z-index: 2;
position: absolute;
@@ -783,12 +828,6 @@ summary {
user-select: none;
}
-.constraint {
- color: rgb(141, 23, 88);
- /* font-weight: 100; */
- /* text-decoration: underline; */
-}
-
.color-text {
color: #000;
}
diff --git a/todo.txt b/todo.txt
index 7d47bf9..2802010 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,42 +1,65 @@
******************************************************** NEXT PATCH **************************************************
-new level corridor
- new level element fizzler - it removes blocks
-interferometer has wider platforms, a few helpful blocks, and fewer mobs
-level constraints are announced in console
+tech: demineralization - after mobs die gain 0.85x damage taken, effect stacks, but fades 10% every second
+tech: remineralization - after mobs die gain 1.08x damage, effect stacks, but fades 10% every second
+tech: equivalence principle - negative mass field doesn't cost energy
+new JUNK tech: aerodynamics
-foam gun no longer pushes the player back when firing
-wave gun buffs
- 1.2x base damage
- 1.1x base ammo
- 0.1->0.13x speed in map
- 0.25->0.30x speed in blocks
- tech: phase velocity 1.4->1.5x damage
-pigeonhole principle gives 1.3->1.4 damage per gun
- you can no longer switch guns, your gun cycles each level
-quenching 0.4->0.5x overheal converts into max health
-tungsten carbide no longer has reduced coyote cycles
-control theory 1.5->2x damage at max health
-stability 0.3->0.2 damage taken at max health
-overcharge +88->100 max energy, 4->5% JUNK
-zoospore vector 10->13% chance for spores on mob death
-replication 15->10% JUNK
-interest 6->5% of your power ups spawn each level
+interferometer
+ slower elevator and lasers
+ wider side ledges
+ large laser blocking blocks
+flocculation
+ fewer mobs
+ it's easier to get out of the slime
+pavilion
+ move vanish elements
+ easier traversal
+ secret tunnel
+ removed debris, but added power ups and blocks
+corridor
+ limited to bosses that don't interact with the movers poorly
+gravitron, substructure, corridor, interferometer
+ added more heal and ammo power ups to match other levels
+because some newer levels are zoomed out more
+ laser max range is 3000->5000
+ nails last 1/3 of a second longer
+bosses spawn an extra ammo power up
+ and 2 extra ammo on the hardest 2 difficulties
+slasher mob's laserSwords will now damage a cloaked player
+constraint announcement text looks more like computer code style to match game theme
-updated "about" details menu
- moved classic n-gon to here from settings
- added links to community content in "about"
- Are there more links I should add?
- added an n-gon SVG head image
+foam recoil is back: 1->0.7x horizontal force and 2->4.3x vertical up force
+ this makes it less annoying to horizontally and easier to kinda fly/float
+negative mass field damage reduction 0.4->0.5x
+holographic principle no longer slows player movement
+ added 2 research cost
+fermion gives 6->5 seconds of invulnerability after mobs die
+stability 0.2->0.1x damage taken at max health
+non-Newtonian armor 0.3->0.4x damage taken after collisions
+Zeno's paradox 0.15->0.2x damage taken
+annihilation energy cost 10->8 to destroy mobs after collisions
+radiative equilibrium damage is 3->4x for 8->4 seconds
+aerostat can be taken 1->3 times
+dynamic equilibrium damage increased by 6->8x damage per last damage taken
+aerostat no longer has 0.9x damage for being on the ground
+launch system 1.2->1.3x ammo for missiles
+research says that repeatedly entering alternate realities builds up some positive effects
+ Hilbert space 4x->3x damage
+ Ψ(t) collapse 6->4 research on boss death
+transdimensional worms: 50% chance for a second worm per block in wormhole
+wormhole 7->8 energy regen per second
+hidden-variable theory 1.15->1.2 damage after choosing a field tech
+ghoster mobs are less likely to get knocked far away from the player for long periods of time
-bugs
- fixed outline on splash screen doesn't sync right on safari browser
- fixed possible lock out on training levels: "hold", "throw", "throwAt"
- from losing block behind a door
- shortcut sort buttons in experiment mode properly order tech without clicking sort
- fixed/increased the horizontal velocity contribution for some guns
- this makes bullets shot on moving platforms more realistic
- nail gun, super balls, foam, harpoon
+bug fixes
+ dynamic equilibrium was set to 100 times higher frequency then normal
+ when constraints hide health bar's it's now hidden in the pause menu
+ mobs aiming at cloaked player
+ snakeBoss more intelligently chases player for a few seconds
+ pulsarBoss aims at player's history 3 seconds in past
+ pulsar will not stop firing
+ but it will still not fire at cloaked player
******************************************************** BUGS ********************************************************
@@ -59,14 +82,20 @@ player can become crouched while not touching the ground if they exit the ground
*********************************************************** TODO *****************************************************
-tech: demineralization - 0.2x damage taken, but it slowly reduces effect
- increase to full:
- at start of level?
- when you get the tech
- decrease:
- over time
- at start of new level
+tech synergy ideas
+ a tech that spawns mobs that the player can use to trigger mob death tech
+wormhole field needs a buff
+ it's good on wide open maps, but it needs a defensive effect on more closed maps
+ fix?
+ increase energy regen?
+ new tech?
+ a way to make more blocks
+ the block can feed into worms/coupling energy
+
+
+tech: - remove the research costs of all tech
+ there's about 15 tech with a research cost
!!conformal - similar rules for small and big scales linked to holographic principle
!!holonomy - parallel transport of a vector leads to movement (applies to curved space)
when far away from your wormhole regenerate 1% of your max energy per second
@@ -179,6 +208,31 @@ improve new player experience
When foam is in an explosion it also explodes with size proportional to the size of the foam bubble
Requires foam, explosion source, not aerogel
+new level similar to ash tray maze
+ !!not sure how this works with theme (most levels are locations that have industrial stuff)
+ this might work as another line of sight level?
+ could be fine without line of sight if rooms don't exist until they open up?
+ where to put in game sequence?
+ watch a run through https://www.youtube.com/watch?v=nudSXUMBEV4
+ close off doors as player gets close
+ open up doors as player gets close
+ holes in the floor
+ slide large walls back to open up levels below
+ show a zone, then close it off, but eventually reveal it later
+ rise up pillars during combat
+ small maze rooms, 1-2 really huge rooms, long corridors, medium combat rooms
+ triggers for changes
+ clearing mobs in a zone
+ or time based if player is too slow
+ player gets close to a zone
+ make map elements shift around as player moves through the game
+ start with map elements filling everywhere and slow open up new zones
+ need a cool way to animate adding and removing map elements
+ maybe for the entire level redraw the map every 15 cycles?
+ simulation.draw.setPaths() //update map graphics
+ slide map around
+ small map squares that each add in sequentially
+
Cosmological natural selection: do something with black holes
spawn black hole mobs
after bosses die?
@@ -1210,7 +1264,6 @@ possible names for tech
amalgam, amalgamation - the action, process, or result of combining or uniting.
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
- equivalence principle - gravity and acceleration are the same
Casimir effect - attractive force between two close conductive plates
difference engine - early calculator/computer
cyanoacrylate - superglue use for a slowing effect?
@@ -1254,25 +1307,4 @@ list of powerful synergies
interest + coupling, research + (peer review? or Bayesian statistics)
electronegativity and high energy?
electronegativity + anyon + duplication + Maxwells demon + interest + pair production
- chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
-
-
-************************************************* COMMUNITY LINKS *************************************************
-
-load old commits
- www.cornbread2100.com/n-gon-loader
-
-n-gon fork
- kgurchiek.github.io/n-gon-portal-gun
- 3xiondev.github.io/n-gon-upgraded
- coaldeficit.github.io/c-gon
- n-gon-enhanced.vercel.app
-
-bookmarlet
- github.com/Whyisthisnotavalable/n-scythe
- github.com/kgurchiek/n-gon-mobile
- github.com/kgurchiek/n-gon-controller
-
-text
- ngon.fandom.com/wiki/N-gon
- github.com/3xionDev/n-docs
\ No newline at end of file
+ chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
\ No newline at end of file