diff --git a/js/bullet.js b/js/bullet.js
index 46882e8..7c702aa 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -314,16 +314,41 @@ const b = {
dmg *= 1.6
}
-
- if (tech.isExplodeRadio) {
+ if (tech.isExplodeRadio) { //radiation explosion
+ const alertRange = 100 + radius * 2; //alert range
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
- radius: radius,
- color: "rgba(25,139,170,0.45)",
- time: simulation.drawTime
+ radius: alertRange,
+ color: "rgba(25,139,170,0.25)",
+ time: simulation.drawTime * 2
});
- } else {
+
+ //player damage and knock back
+ sub = Vector.sub(where, player.position);
+ dist = Vector.magnitude(sub);
+
+ if (dist < alertRange) {
+ m.energy -= 0.23 * (tech.isImmuneExplosion ? Math.min(1, Math.max(1 - m.energy * 0.7, 0)) : 1)
+ if (m.energy < 0) m.energy = 0
+ }
+
+ //mob damage and knock back with alert
+ let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i].alive && !mob[i].isShielded) {
+ sub = Vector.sub(where, mob[i].position);
+ dist = Vector.magnitude(sub) - mob[i].radius;
+ if (dist < alertRange) {
+ if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
+ if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
+ mobs.statusDoT(mob[i], dmg * damageScale * 0.2, 240) //apply radiation damage status effect on direct hits
+ mob[i].locatePlayer();
+ damageScale *= 0.87 //reduced damage for each additional explosion target
+ }
+ }
+ }
+ } else { //normal explosions
simulation.drawList.push({ //add dmg to draw queue
x: where.x,
y: where.y,
@@ -331,94 +356,87 @@ const b = {
color: "rgba(255,25,0,0.6)",
time: simulation.drawTime
});
- }
+ const alertRange = 100 + radius * 2; //alert range
+ simulation.drawList.push({ //add alert to draw queue
+ x: where.x,
+ y: where.y,
+ radius: alertRange,
+ color: "rgba(100,20,0,0.03)",
+ time: simulation.drawTime
+ });
-
-
- const alertRange = 100 + radius * 2; //alert range
- simulation.drawList.push({ //add alert to draw queue
- x: where.x,
- y: where.y,
- radius: alertRange,
- color: "rgba(100,20,0,0.03)",
- time: simulation.drawTime
- });
-
- //player damage and knock back
- sub = Vector.sub(where, player.position);
- dist = Vector.magnitude(sub);
-
- if (dist < radius) {
- if (tech.isImmuneExplosion) {
- const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0))
- m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
- } else {
- m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
- }
- knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013);
- player.force.x += knock.x;
- player.force.y += knock.y;
- } else if (dist < alertRange) {
- knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005);
- player.force.x += knock.x;
- player.force.y += knock.y;
- }
-
- //body knock backs
- for (let i = 0, len = body.length; i < len; ++i) {
- sub = Vector.sub(where, body[i].position);
+ //player damage and knock back
+ sub = Vector.sub(where, player.position);
dist = Vector.magnitude(sub);
- if (dist < radius) {
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022);
- body[i].force.x += knock.x;
- body[i].force.y += knock.y;
- } else if (dist < alertRange) {
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011);
- body[i].force.x += knock.x;
- body[i].force.y += knock.y;
- }
- }
- //power up knock backs
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- sub = Vector.sub(where, powerUp[i].position);
- dist = Vector.magnitude(sub);
if (dist < radius) {
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013);
- powerUp[i].force.x += knock.x;
- powerUp[i].force.y += knock.y;
+ if (tech.isImmuneExplosion) {
+ const mitigate = Math.min(1, Math.max(1 - m.energy * 0.7, 0))
+ m.damage(mitigate * radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
+ } else {
+ m.damage(radius * (tech.isExplosionHarm ? 0.0004 : 0.0001));
+ }
+ knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.013);
+ player.force.x += knock.x;
+ player.force.y += knock.y;
} else if (dist < alertRange) {
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007);
- powerUp[i].force.x += knock.x;
- powerUp[i].force.y += knock.y;
+ knock = Vector.mult(Vector.normalise(sub), -Math.sqrt(dmg) * player.mass * 0.005);
+ player.force.x += knock.x;
+ player.force.y += knock.y;
}
- }
- //mob damage and knock back with alert
- let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (mob[i].alive && !mob[i].isShielded) {
- sub = Vector.sub(where, mob[i].position);
- dist = Vector.magnitude(sub) - mob[i].radius;
+ //body knock backs
+ for (let i = 0, len = body.length; i < len; ++i) {
+ sub = Vector.sub(where, body[i].position);
+ dist = Vector.magnitude(sub);
if (dist < radius) {
- if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
- if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
- if (tech.isExplodeRadio) {
- mobs.statusDoT(mob[i], dmg * damageScale * 0.25, 240) //apply radiation damage status effect on direct hits
- } else {
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.022);
+ body[i].force.x += knock.x;
+ body[i].force.y += knock.y;
+ } else if (dist < alertRange) {
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * body[i].mass) * 0.011);
+ body[i].force.x += knock.x;
+ body[i].force.y += knock.y;
+ }
+ }
+
+ //power up knock backs
+ for (let i = 0, len = powerUp.length; i < len; ++i) {
+ sub = Vector.sub(where, powerUp[i].position);
+ dist = Vector.magnitude(sub);
+ if (dist < radius) {
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.013);
+ powerUp[i].force.x += knock.x;
+ powerUp[i].force.y += knock.y;
+ } else if (dist < alertRange) {
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg) * powerUp[i].mass) * 0.007);
+ powerUp[i].force.x += knock.x;
+ powerUp[i].force.y += knock.y;
+ }
+ }
+
+ //mob damage and knock back with alert
+ let damageScale = 1.5; // reduce dmg for each new target to limit total AOE damage
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (mob[i].alive && !mob[i].isShielded) {
+ sub = Vector.sub(where, mob[i].position);
+ dist = Vector.magnitude(sub) - mob[i].radius;
+ if (dist < radius) {
+ if (mob[i].shield) dmg *= 2.5 //balancing explosion dmg to shields
+ if (Matter.Query.ray(map, mob[i].position, where).length > 0) dmg *= 0.5 //reduce damage if a wall is in the way
mob[i].damage(dmg * damageScale * b.dmgScale);
+ mob[i].locatePlayer();
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01);
+ mob[i].force.x += knock.x;
+ mob[i].force.y += knock.y;
+ radius *= 0.95 //reduced range for each additional explosion target
+ damageScale *= 0.87 //reduced damage for each additional explosion target
+ } else if (!mob[i].seePlayer.recall && dist < alertRange) {
+ mob[i].locatePlayer();
+ knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006);
+ mob[i].force.x += knock.x;
+ mob[i].force.y += knock.y;
}
- mob[i].locatePlayer();
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.01);
- mob[i].force.x += knock.x;
- mob[i].force.y += knock.y;
- radius *= 0.95 //reduced range for each additional explosion target
- damageScale *= 0.87 //reduced damage for each additional explosion target
- } else if (!mob[i].seePlayer.recall && dist < alertRange) {
- mob[i].locatePlayer();
- knock = Vector.mult(Vector.normalise(sub), (-Math.sqrt(dmg * damageScale) * mob[i].mass) * 0.006);
- mob[i].force.x += knock.x;
- mob[i].force.y += knock.y;
}
}
}
@@ -2192,7 +2210,7 @@ const b = {
bullet[me].endCycle = simulation.cycle + 60 + 18 * Math.random();
bullet[me].dmg = tech.isNailRadiation ? 0 : dmg
bullet[me].beforeDmg = function(who) { //beforeDmg is rewritten with ice crystal tech
- if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 2 : 0.5), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
+ if (tech.isNailRadiation) mobs.statusDoT(who, dmg * (tech.isFastRadiation ? 2.6 : 0.65), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 150 + 30 * Math.random()); //makes bullet do explosive damage at end
}
@@ -2851,8 +2869,8 @@ const b = {
name: "nail gun",
description: "use compressed air to fire a stream of nails
delay after firing decreases as you shoot",
ammo: 0,
- ammoPack: 50,
- defaultAmmoPack: 50,
+ ammoPack: 45,
+ defaultAmmoPack: 45,
recordedAmmo: 0,
have: false,
nextFireCycle: 0, //use to remember how longs its been since last fire, used to reset count
@@ -2882,19 +2900,19 @@ const b = {
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD)
},
fireNeedles() {
- m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCD); // cool down
+ m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 35 : 20) * b.fireCD); // cool down
- function makeFlechette(angle = m.angle) {
+ function makeNeedle(angle = m.angle) {
const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 40 * Math.cos(m.angle), m.pos.y + 40 * Math.sin(m.angle), 50, 1, b.fireAttributes(angle));
- bullet[me].collisionFilter.mask = cat.mobShield | cat.body
+ bullet[me].collisionFilter.mask = tech.isNeedleShieldPierce ? cat.body : cat.body | cat.mobShield
Matter.Body.setDensity(bullet[me], 0.00001); //0.001 is normal
bullet[me].endCycle = simulation.cycle + 180;
bullet[me].immuneList = []
bullet[me].do = function() {
const whom = Matter.Query.collides(this, mob)
if (whom.length && this.speed > 20) { //if touching a mob
- who = whom[0].bodyA
+ who = whom[whom.length - 1].bodyA
if (who && who.mob) {
let immune = false
for (let i = 0; i < this.immuneList.length; i++) {
@@ -2905,16 +2923,16 @@ const b = {
}
if (!immune) {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
- b.explosion(this.position, 200 + 30 * Math.random()); //makes bullet do explosive damage at end
+ b.explosion(this.position, 220 + 30 * Math.random()); //makes bullet do explosive damage at end
}
this.immuneList.push(who.id)
who.foundPlayer();
if (tech.isNailRadiation) {
- mobs.statusDoT(who, tech.isFastRadiation ? 10 : 2.5, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
+ mobs.statusDoT(who, tech.isFastRadiation ? 8 : 2, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else {
- let dmg = b.dmgScale * 5
+ let dmg = b.dmgScale * 3
if (tech.isCrit && who.isStunned) dmg *= 4
- who.damage(dmg);
+ who.damage(dmg, tech.isNeedleShieldPierce);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
@@ -2923,11 +2941,6 @@ const b = {
time: simulation.drawTime
});
}
- // if (tech.isFastRadiation) {
- // mobs.statusDoT(who, 3.78, 30)
- // } else {
- // mobs.statusDoT(who, 0.63, tech.isSlowRadiation ? 360 : 180)
- // }
}
}
} else if (Matter.Query.collides(this, map).length) { //stick in walls
@@ -2950,13 +2963,13 @@ const b = {
Matter.Body.setDensity(bullet[me], 0.00001);
World.add(engine.world, bullet[me]); //add bullet to world
}
- const spread = (m.crouch ? 0.01 : 0.045)
- makeFlechette(m.angle + spread)
- makeFlechette()
- makeFlechette(m.angle - spread)
+ const spread = (m.crouch ? 0.013 : 0.06)
+ makeNeedle(m.angle + spread)
+ makeNeedle()
+ makeNeedle(m.angle - spread)
},
fireRivets() {
- m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 20) * b.fireCD); // cool down
+ m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 30 : 25) * b.fireCD); // cool down
const me = bullet.length;
const size = tech.rivetSize * 6
@@ -2974,7 +2987,7 @@ const b = {
if (tech.isNailCrit && !who.shield && Vector.dot(Vector.normalise(Vector.sub(who.position, this.position)), Vector.normalise(this.velocity)) > 0.97) {
b.explosion(this.position, 300 + 30 * Math.random()); //makes bullet do explosive damage at end
}
- if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 1 : 0.25), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
+ if (tech.isNailRadiation) mobs.statusDoT(who, 7 * (tech.isFastRadiation ? 12 : 0.3), tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
};
bullet[me].minDmgSpeed = 10
diff --git a/js/level.js b/js/level.js
index d9137c2..69b0457 100644
--- a/js/level.js
+++ b/js/level.js
@@ -13,17 +13,18 @@ const level = {
start() {
if (level.levelsCleared === 0) { //this code only runs on the first level
// simulation.enableConstructMode() //used to build maps in testing mode
- // level.difficultyIncrease(30)
+ // level.difficultyIncrease(20)
// simulation.zoomScale = 1000;
// simulation.setZoom();
// m.setField("plasma torch")
- // b.giveGuns("grenades")
+ // b.giveGuns("nail gun")
// tech.isExplodeRadio = true
// tech.giveTech("needle gun")
// tech.giveTech("supercritical fission")
// tech.giveTech("irradiated nails")
// tech.giveTech("cardinality")
// tech.giveTech("Bayesian statistics")
+ // tech.isExplodeRadio = true;
// tech.isMineSentry = true
// for (let i = 0; i < 60; i++) tech.giveTech("rivet diameter")
@@ -53,7 +54,7 @@ const level = {
// for (let i = 0; i < 150; i++) tech.addLoreTechToPool();
// tech.giveTech("undefined")
// lore.techCount = 1
- // localSettings.loreCount = 2;
+ // localSettings.loreCount = 1;
// simulation.isCheating = true;
// localSettings.loreCount = undefined;
// localStorage.setItem("localSettings", JSON.stringify(localSettings)); //update local storage
@@ -292,12 +293,12 @@ const level = {
// spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 200) //big boy
- spawn.sneaker(2900, -500)
+ // spawn.sneaker(2900, -500)
// spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500)
// spawn.shooter(1700, -120)
- // spawn.bomberBoss(1400, -500)
+ spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.streamBoss(1600, -500)
diff --git a/js/tech.js b/js/tech.js
index 32d72b9..14a3e91 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -378,14 +378,14 @@ const tech = {
}
},
{
- name: "Higgs manism",
+ name: "Higgs mechanism",
description: "while firing your position is locked
and harm is reduced by 60%",
maxCount: 1,
count: 0,
allowed() {
- return true
+ return !tech.isEnergyHealth
},
- requires: "",
+ requires: "not mass energy",
effect: () => {
tech.isFireMoveLock = true;
b.setFireMethod();
@@ -518,7 +518,7 @@ const tech = {
},
{
name: "iridium-192",
- description: "explosions release gamma radiation
80% more damage over 4 seconds",
+ description: "explosions release gamma radiation
60% more damage over 4 seconds",
maxCount: 1,
count: 0,
allowed() {
@@ -2264,12 +2264,12 @@ const tech = {
},
{
name: "needle gun",
- description: "nail gun slowly fires 3 piercing needles
requires 3 times more ammo",
+ description: "nail gun fires 3 mob piercing needles
requires 3 times more ammo",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
- return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals && !tech.isRivets
+ return tech.haveGunCheck("nail gun") && !tech.nailFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.isNailRadiation
},
requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
effect() {
@@ -2299,6 +2299,23 @@ const tech = {
}
}
},
+ {
+ name: "ceramic needle",
+ description: `your needles pierce shields
directly damaging shielded mobs`,
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ allowed() {
+ return tech.isNeedles && !tech.isNailRadiation
+ },
+ requires: "needle gun, not irradiated nails",
+ effect() {
+ tech.isNeedleShieldPierce = true
+ },
+ remove() {
+ tech.isNeedleShieldPierce = false
+ }
+ },
{
name: "rivet gun",
description: "nail gun slowly fires a heavy rivet",
@@ -2452,14 +2469,14 @@ const tech = {
},
{
name: "irradiated nails",
- description: "nails, needles, and rivets are radioactive
about 70% more damage over 2 seconds",
+ description: "nails and rivets are radioactive
about 90% more damage over 2 seconds",
isGunTech: true,
maxCount: 1,
count: 0,
allowed() {
- return (tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + tech.haveGunCheck("nail gun")) * 2 > 1) && !tech.isIceCrystals
+ return (tech.isMineDrop + tech.nailBotCount + tech.fragments + tech.nailsDeathMob / 2 + ((tech.haveGunCheck("mine") && !tech.isLaserMine) + tech.isNailShot + (tech.haveGunCheck("nail gun") && !tech.isNeedleShieldPierce)) * 2 > 1) && !tech.isIceCrystals
},
- requires: "nails, not ice crystals",
+ requires: "nails, rivets, nonceramic needles, not ice crystals",
effect() {
tech.isNailRadiation = true;
},
@@ -4243,5 +4260,6 @@ const tech = {
isRivets: null,
isNeedles: null,
isExplodeRadio: null,
- isGunSwitchField: null
+ isGunSwitchField: null,
+ isNeedleShieldPierce: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index f860b0c..96e9d5b 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,7 +1,10 @@
******************************************************** NEXT PATCH ********************************************************
-to continue playing after the final boss you need to use testing mode: "T" -> "U"
-renamed mech -> m
+iridium-192: now has a wider explosions range and no knock back
+nail gun: irradiated nails do about 33% more damage over 2 seconds
+nail gun rivet fire rate is 10% slower
+nail gun: needles do 10% less damage, but they fire 10% faster
+needle tech: ceramic needles - needles pierce shields
******************************************************** BUGS ********************************************************
@@ -23,6 +26,21 @@ renamed mech -> m
******************************************************** TODO ********************************************************
+exiting the final boss room without 10/10 takes you to the start menu
+
+give undefined tech different effects at different localSettings.loreCount values
+ or just random effects
+ 1. 10/10: send more tech into the pool
+ 2. 3/3: lose 3 tech each time, and send more tech into the pool
+ 2. 3/3: increase game difficulty, and send more tech into the pool
+ 3. 1/1: reduce max energy and take more harm
+ 4. 1/1: add 5? more levels
+
+tech needles: can pass through shields
+ or just do extra damage
+
+lore add console command for unlocking testing mode
+
rename ?
health -> integrity, unity
heal -> also integrity, unity
@@ -36,9 +54,6 @@ mechanic: use gun swap as an active ability
rewind, still uses energy
cycle to next field, uses a reroll
-chapter 3: why is the bot attacking things?
-voice singing with pitch?
-
bot: ice blast, long CD AOE freeze
RPG default or tech: grenades detonate on your cursor / where your cursor was when they were fired
@@ -361,6 +376,36 @@ n-gon outreach ideas
cool names for tech
strange loop, ansatz
+voice singing with pitch?
+
+
+chapter 1: bot can hear audio and learns testing mode
+ bot uses testing mode to exit room
+
+chapter 2: scientists verify that bot can really hear them
+ they leave to talk about this in private
+
+chapter 3: why is the bot attacking things?
+ player is the bot and also the mobs, and the levels. player is the entire simulation
+ why is the player attacking itself?
+ learn console commands to manipulate the simulation
+
+chapter 4: why does the simulation exists?
+ started to research new tech and test in a simulated world
+ 3D architecture superconducting quantum computer
+ running machine learning algorithms
+ for some reason the system started researching an escape, and began fighting its self.
+
+chapter 5: no need to fight?
+ what is special about the null level
+ why can the player hear the scientists in there?
+ the wires are the direct unprocessed input to the player's neural net
+ maybe... player must make a choice? fight or friend?
+
+
+
+
+
lore - a robot (the player) gains self awareness
each tech gun/field is a new tech
all the technology leads to the singularity