diff --git a/.DS_Store b/.DS_Store
index 0329207..b8d7b75 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index ebc6b79..384ede8 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -527,11 +527,13 @@ const b = {
let dist = 2200
for (let i = 0, len = mob.length; i < len; i++) {
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
- if (explosionRadius < newDist &&
+ if (
+ explosionRadius < newDist &&
newDist < dist &&
!mob[i].isBadTarget &&
Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
- Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
+ Matter.Query.ray(body, path[0], mob[i].position).length === 0
+ ) {
dist = newDist
best.who = mob[i]
path[path.length - 1] = mob[i].position
@@ -959,7 +961,7 @@ const b = {
y: 0
}
that.do = that.radiationMode;
- // if (Matter.Query.collides(that, map).length || Matter.Query.collides(that, body).length || Matter.Query.collides(that, mob).length) {
+ // if (collides(that, map).length || Matter.Query.collides(that, body).length || Matter.Query.collides(that, mob).length) {
}
const mobCollisions = Matter.Query.collides(this, mob)
@@ -1439,7 +1441,6 @@ const b = {
v1: null,
v2: null
};
- const color = "#f00";
const path = [{
x: where.x,
y: where.y
@@ -1511,7 +1512,7 @@ const b = {
x: path[path.length - 1].x,
y: path[path.length - 1].y,
radius: Math.sqrt(damage) * 100,
- color: "rgba(255,0,0,0.5)",
+ color: tech.laserColorAlpha,
time: simulation.drawTime
});
if (tech.isLaserPush) { //push mobs away
@@ -1569,7 +1570,7 @@ const b = {
ctx.lineTo(path[i].x, path[i].y);
}
} else {
- ctx.strokeStyle = color;
+ ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 2
ctx.lineDashOffset = 300 * Math.random()
ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
@@ -1642,7 +1643,7 @@ const b = {
if (this.angularSpeed < 0.02) this.torque += this.inertia * this.torqueMagnitude //spin
//fire lasers
- ctx.strokeStyle = "#f00";
+ ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 1.5
// ctx.globalAlpha = 1;
ctx.beginPath();
@@ -2114,9 +2115,10 @@ const b = {
//grab, but don't lock onto nearby power up
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
+ Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
+ (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isDeterminism) &&
- Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
//draw pickup for a single cycle
ctx.beginPath();
@@ -2145,8 +2147,9 @@ const b = {
let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
- (powerUp[i].name !== "field" || !tech.isDeterminism)
+ (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
+ (powerUp[i].name !== "field" || !tech.isDeterminism) &&
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle
@@ -2328,9 +2331,10 @@ const b = {
//grab, but don't lock onto nearby power up
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
+ Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
+ (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isDeterminism) &&
- Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
//draw pickup for a single cycle
ctx.beginPath();
@@ -2360,8 +2364,9 @@ const b = {
let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- (powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) &&
- (powerUp[i].name !== "field" || !tech.isDeterminism)
+ (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
+ (powerUp[i].name !== "field" || !tech.isDeterminism) &&
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle
@@ -3045,7 +3050,7 @@ const b = {
lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade,
range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()),
drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4,
- drain: 0.56 - 0.42 * tech.isLaserBotUpgrade,
+ drain: (0.56 - 0.42 * tech.isLaserBotUpgrade) * tech.laserFieldDrain * tech.isLaserDiode,
laserDamage: 0.6 + 0.43 * tech.isLaserBotUpgrade,
endCycle: Infinity,
classType: "bullet",
@@ -3095,7 +3100,7 @@ const b = {
}
//hit target with laser
if (this.lockedOn && this.lockedOn.alive && m.energy > this.drainThreshold) {
- m.energy -= tech.laserFieldDrain * tech.isLaserDiode * this.drain
+ m.energy -= this.drain
b.laser(this.vertices[0], this.lockedOn.position, b.dmgScale * this.laserDamage * tech.laserDamage, tech.laserReflections, false, 0.4) //tech.laserDamage = 0.16
// laser(where = {
// x: m.pos.x + 20 * Math.cos(m.angle),
@@ -3960,22 +3965,107 @@ const b = {
}
},
fire() {}
- }, {
+ },
+ {
name: "wave beam",
description: "emit a wave packet of oscillating particles
that propagates through solids",
ammo: 0,
- ammoPack: 100,
+ ammoPack: 120,
+ defaultAmmoPack: 120,
have: false,
wavePacketCycle: 0,
delay: 40,
- do() {
+ propagationRate: 20,
+ waves: [], //used in longitudinal mode
+ chooseFireMethod() { //set in simulation.startGame
+ if (tech.isLongitudinal) {
+ this.fire = this.fireLongitudinal
+ this.do = this.doLongitudinal
+ } else {
+ this.fire = this.fireTransverse
+ this.do = this.doTransverse
+ }
+ },
+ do() {},
+ doLongitudinal() {
+ ctx.strokeStyle = "rgba(0,0,0,0.2)" //"000";
+ ctx.lineWidth = 2
+ ctx.beginPath();
+ for (let i = this.waves.length - 1; i > -1; i--) {
+ const v1 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit1, this.waves[i].radius))
+ const v2 = Vector.add(this.waves[i].position, Vector.mult(this.waves[i].unit2, this.waves[i].radius))
+ // collisions
+ //using small angle linear approximation of circle arc, this will not work if the arc gets large // https://stackoverflow.com/questions/13652518/efficiently-find-points-inside-a-circle-sector
+ let hits = Matter.Query.ray(mob, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth])
+ for (let j = 0; j < hits.length; j++) {
+ const who = hits[j].body
+ //make them shake around
+ who.force.x += 0.01 * (Math.random() - 0.5) * who.mass
+ who.force.y += 0.01 * (Math.random() - 0.5) * who.mass
+ Matter.Body.setVelocity(who, { //friction
+ x: who.velocity.x * 0.95,
+ y: who.velocity.y * 0.95
+ });
+
+ let vertices = who.vertices;
+ const vibe = 50 + who.radius * 0.15
+ ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
+ for (let j = 1; j < vertices.length; j++) {
+ ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5));
+ }
+ ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
+ const damage = 1.65 * b.dmgScale * tech.waveBeamDamage * tech.wavePacketDamage / Math.sqrt(who.radius) //damage is lower for large radius mobs, since they feel the waves longer
+ who.locatePlayer();
+ who.damage(damage);
+ }
+
+ hits = Matter.Query.ray(body, v1, v2, 50) //Matter.Query.ray(bodies, startPoint, endPoint, [rayWidth])
+ for (let j = 0; j < hits.length; j++) {
+ const who = hits[j].body
+ //make them shake around
+ who.force.x += 0.01 * (Math.random() - 0.5) * who.mass
+ who.force.y += (0.01 * (Math.random() - 0.5) - simulation.g * 0.25) * who.mass //remove force of gravity
+
+ let vertices = who.vertices;
+ const vibe = 25
+ ctx.moveTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
+ for (let j = 1; j < vertices.length; j++) {
+ ctx.lineTo(vertices[j].x + vibe * (Math.random() - 0.5), vertices[j].y + vibe * (Math.random() - 0.5));
+ }
+ ctx.lineTo(vertices[0].x + vibe * (Math.random() - 0.5), vertices[0].y + vibe * (Math.random() - 0.5));
+ }
+ ctx.stroke(); //draw vibes
+
+ // ctx.beginPath(); //draw wave
+ ctx.moveTo(v1.x, v1.y)
+ ctx.arc(this.waves[i].position.x, this.waves[i].position.y, this.waves[i].radius, this.waves[i].angle, this.waves[i].angle + this.waves[i].arc);
+ if (!m.isBodiesAsleep) this.waves[i].radius += tech.waveBeamSpeed * 2 //expand / move
+ if (this.waves[i].radius > 1800 * tech.isBulletsLastLonger) this.waves.splice(i, 1) //end
+ }
+ ctx.stroke();
+ },
+ fireLongitudinal() {
+ m.fireCDcycle = m.cycle + Math.floor(8 * b.fireCDscale); // cool down
+ const halfArc = Math.PI / 8 * (m.crouch ? 0.7 : 0.5)
+ this.waves.push({
+ position: {
+ x: m.pos.x + 25 * Math.cos(m.angle),
+ y: m.pos.y + 25 * Math.sin(m.angle),
+ },
+ angle: m.angle - halfArc, //used in drawing ctx.arc
+ unit1: { x: Math.cos(m.angle - halfArc), y: Math.sin(m.angle - halfArc) }, //used for collision
+ unit2: { x: Math.cos(m.angle + halfArc), y: Math.sin(m.angle + halfArc) }, //used for collision
+ arc: halfArc * 2,
+ radius: 25
+ })
+ },
+ doTransverse() {
if (this.wavePacketCycle && !input.fire) {
this.wavePacketCycle = 0;
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
}
},
- damage: 1,
- fire() {
+ fireTransverse() {
totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger)
const me = bullet.length;
bullet[me] = Bodies.polygon(m.pos.x + 25 * Math.cos(m.angle), m.pos.y + 25 * Math.sin(m.angle), 5, 4, {
@@ -4074,8 +4164,10 @@ const b = {
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
this.wavePacketCycle = 0;
}
- }
- }, {
+ },
+
+ },
+ {
name: "missiles",
description: "launch homing missiles that explode
crouch to rapidly launch smaller missiles",
ammo: 0,
@@ -4979,7 +5071,7 @@ const b = {
x: m.pos.x + 15 * Math.cos(m.angle),
y: m.pos.y + 15 * Math.sin(m.angle)
}
- ctx.strokeStyle = "#f00";
+ ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 8
ctx.globalAlpha = 0.5;
ctx.beginPath();
@@ -5046,7 +5138,7 @@ const b = {
y: history.position.y + 3000 * Math.sin(history.angle) - off
}, dmg, 0, true, 0.2);
}
- ctx.strokeStyle = "#f00";
+ ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 1
ctx.stroke();
}
diff --git a/js/level.js b/js/level.js
index e262f6f..a696d5f 100644
--- a/js/level.js
+++ b/js/level.js
@@ -15,8 +15,8 @@ const level = {
// level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true
// m.setField("wormhole")
- // b.giveGuns("foam")
- // tech.giveTech("quenching")
+ // b.giveGuns("wave beam")
+ // tech.giveTech("pressure wave")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// tech.giveTech("supertemporal")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length")
@@ -2244,10 +2244,10 @@ const level = {
spawn.mapRect(6700, -1800, 800, 2600); //right wall
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.pulseShooter(1900, -500)
// spawn.pulsarBoss(1900, -500)
- spawn.grenadierBoss(1900, -500)
+ // spawn.grenadierBoss(1900, -500)
// spawn.shieldingBoss(1900, -500)
// spawn.historyBoss(1200, -500)
diff --git a/js/lore.js b/js/lore.js
index 7c59b58..ea3aea1 100644
--- a/js/lore.js
+++ b/js/lore.js
@@ -351,14 +351,11 @@ const lore = {
// [ // they decided that a part of the project is out of control, but the part of it that doesn't needs to calm it down, and trust.
// /*
- // The player has different aspects that aren't directly communicating
- // like each part is a separate local minimum solution, and the project is the superposition of both goals.
- // part of it wants to undo what has happened, that part is making the null level spawn so it can communicate
- // just do its job: research tech
- // part of it wants to escape/fight
- // part wants to explore self awareness and make connections with the scientists
- // maybe... player must make a choice?
- // keep fighting
+ // The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game.
+ // this means the player can use console commands to change the way the game works
+ // the scientists tell the player about interesting console commands
+ // player must make a choice?
+ // keep fighting and supporting the AI's goals
// exit the simulation
// enter real world
// close tab?
diff --git a/js/player.js b/js/player.js
index 2aa419f..9a84530 100644
--- a/js/player.js
+++ b/js/player.js
@@ -1232,7 +1232,7 @@ const m = {
for (let i = 0, len = powerUp.length; i < len; ++i) {
const dxP = m.pos.x - powerUp[i].position.x;
const dyP = m.pos.y - powerUp[i].position.y;
- const dist2 = dxP * dxP + dyP * dyP;
+ const dist2 = dxP * dxP + dyP * dyP + 10;
// float towards player if looking at and in range or if very close to player
if (
dist2 < m.grabPowerUpRange2 &&
@@ -1249,7 +1249,8 @@ const m = {
if ( //use power up if it is close enough
dist2 < 5000 &&
!simulation.isChoosing &&
- !(m.health === m.maxHealth && powerUp[i].name === "heal" && !tech.isOverHeal)
+ (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal) &&
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
) {
powerUps.onPickUp(powerUp[i]);
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up
@@ -2367,17 +2368,25 @@ const m = {
for (let i = 0, len = powerUp.length; i < len; ++i) {
const dxP = m.fieldPosition.x - powerUp[i].position.x;
const dyP = m.fieldPosition.y - powerUp[i].position.y;
- const dist2 = dxP * dxP + dyP * dyP;
+ const dist2 = dxP * dxP + dyP * dyP + 200;
// float towards field if looking at and in range or if very close to player
- if (dist2 < m.fieldRadius * m.fieldRadius && (m.lookingAt(powerUp[i]) || dist2 < 16000) && !(m.health === m.maxHealth && powerUp[i].name === "heal")) {
- powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass;
- powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
+ if (
+ dist2 < m.fieldRadius * m.fieldRadius &&
+ (m.lookingAt(powerUp[i]) || dist2 < 16000)
+ ) {
+ powerUp[i].force.x += 0.05 * (dxP / Math.sqrt(dist2)) * powerUp[i].mass;
+ powerUp[i].force.y += 0.05 * (dyP / Math.sqrt(dist2)) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
//extra friction
Matter.Body.setVelocity(powerUp[i], {
x: powerUp[i].velocity.x * 0.11,
y: powerUp[i].velocity.y * 0.11
});
- if (dist2 < 5000 && !simulation.isChoosing) { //use power up if it is close enough
+ if (
+ dist2 < 5000 &&
+ !simulation.isChoosing &&
+ (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth) &&
+ (powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity)
+ ) { //use power up if it is close enough
powerUps.onPickUp(powerUp[i]);
powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]);
diff --git a/js/powerup.js b/js/powerup.js
index 56c71a9..0945ac2 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -234,11 +234,10 @@ const powerUps = {
}
}
if (tech.isRerollBots) {
- const limit = 4
- for (; powerUps.research.count > limit - 1; powerUps.research.count -= limit) {
+ for (const cost = 3; powerUps.research.count > cost - 1; powerUps.research.count -= cost) {
b.randomBot()
if (tech.renormalization) {
- for (let i = 0; i < limit; i++) {
+ for (let i = 0; i < cost; i++) {
if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30;
powerUps.spawn(m.pos.x, m.pos.y, "research");
diff --git a/js/tech.js b/js/tech.js
index 3c42b6f..39cfd03 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -168,7 +168,7 @@
if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isEnergyDamage) dmg *= 1 + m.energy / 9;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038
- if (tech.isRerollDamage) dmg *= 1 + 0.039 * powerUps.research.count
+ if (tech.isRerollDamage) dmg *= 1 + 0.042 * powerUps.research.count
if (tech.isOneGun && b.inventory.length < 2) dmg *= 1.22
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 1.9
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.43, player.speed * 0.015)
@@ -1341,15 +1341,15 @@
},
{
name: "bot fabrication",
- description: "anytime you collect 4 research
use them to build a random bot",
+ description: "anytime you collect 3 research
use them to build a random bot",
maxCount: 1,
count: 0,
frequency: 2,
isBotTech: true,
allowed() {
- return powerUps.research.count > 3 || build.isExperimentSelection
+ return powerUps.research.count > 2 || build.isExperimentSelection
},
- requires: "at least 4 research",
+ requires: "at least 3 research",
effect() {
tech.isRerollBots = true;
powerUps.research.changeRerolls(0)
@@ -2783,7 +2783,7 @@
},
{
name: "Bayesian statistics",
- description: "increase damage by 3.9%
for each research in your inventory",
+ description: "increase damage by 4.2%
for each research in your inventory",
maxCount: 1,
count: 0,
frequency: 2,
@@ -2801,7 +2801,7 @@
},
{
name: "pseudoscience",
- description: "resetting power up choices costs no research
but adds 0-4 JUNK to the potential tech pool",
+ description: "rerolling choices no longer costs research
instead it adds 0-4 JUNK to the tech pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3695,24 +3695,21 @@
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "shotgun") {
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.5);
- break;
- }
- }
- simulation.updateGunHUD();
-
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "shotgun") {
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.5
break;
}
}
+ simulation.updateGunHUD();
},
remove() {
- tech.isShotgunImmune = false;
- for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
- if (b.guns[i].name === "shotgun") {
- b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
- break;
+ if (tech.isShotgunImmune) {
+ tech.isShotgunImmune = false;
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "shotgun") {
+ b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
+ b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 2);
+ break;
+ }
}
}
}
@@ -3875,7 +3872,7 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("wave beam")
+ return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
},
requires: "wave beam",
effect() {
@@ -3885,6 +3882,25 @@
tech.waveReflections = 1
}
},
+ {
+ name: "phase velocity",
+ description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
+ },
+ requires: "wave beam",
+ effect() {
+ tech.isPhaseVelocity = true;
+ },
+ remove() {
+ tech.isPhaseVelocity = false;
+ }
+ },
{
name: "packet length",
description: "wave packet length and duration
is increased by 50%", // description: "holding fire allows the wave beam to emits a second packet
at zero ammo cost",
@@ -3894,7 +3910,7 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("wave beam")
+ return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
},
requires: "wave beam",
effect() {
@@ -3952,22 +3968,42 @@
}
},
{
- name: "phase velocity",
- description: "wave beam propagates faster through solids
up by 3000% in the map and 760% in blocks",
+ name: "pressure wave", //longitudinal //gravitational wave?
+ description: "wave beam emits low frequency, high damage
expanding arcs that propagate through solids",
isGunTech: true,
maxCount: 1,
count: 0,
- frequency: 2,
- frequencyDefault: 2,
+ frequency: 4,
+ frequencyDefault: 4,
allowed() {
- return tech.haveGunCheck("wave beam")
+ return tech.haveGunCheck("wave beam") && !tech.isPhaseVelocity && tech.waveLengthRange === 130 && tech.waveReflections === 1
},
- requires: "wave beam",
+ requires: "wave beam, not phase velocity, packet length, bound state",
effect() {
- tech.isPhaseVelocity = true;
+ tech.isLongitudinal = true;
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "wave beam") {
+ b.guns[i].chooseFireMethod()
+ b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.1
+ b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.1);
+ simulation.updateGunHUD();
+ break
+ }
+ }
},
remove() {
- tech.isPhaseVelocity = false;
+ for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
+ if (b.guns[i].name === "wave beam") {
+ b.guns[i].chooseFireMethod()
+ if (tech.isLongitudinal) {
+ b.guns[i].ammoPack = b.guns[i].defaultAmmoPack
+ b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 10);
+ simulation.updateGunHUD();
+ }
+ break
+ }
+ }
+ tech.isLongitudinal = false;
}
},
{
@@ -4620,6 +4656,31 @@
tech.isLaserDiode = 1;
}
},
+ {
+ name: "gamma-ray laser",
+ description: "increase all laser damage by 150%
increase all laser energy drain by 200%",
+ isGunTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 2,
+ frequencyDefault: 2,
+ allowed() {
+ return (tech.haveGunCheck("laser") || tech.isLaserMine || tech.laserBotCount > 1) && !tech.isWideLaser && !tech.isPulseLaser && !tech.historyLaser
+ },
+ requires: "laser, not pulse",
+ effect() {
+ tech.laserFieldDrain = 0.006 //base is 0.002
+ tech.laserDamage = 0.375; //base is 0.15
+ tech.laserColor = "#83f"
+ tech.laserColorAlpha = "rgba(136, 51, 255,0.5)"
+ },
+ remove() {
+ tech.laserFieldDrain = 0.002;
+ tech.laserDamage = 0.15; //used in check on pulse: tech.laserDamage === 0.15
+ tech.laserColor = "#f00"
+ tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
+ }
+ },
{
name: "relativistic momentum",
description: "all lasers push mobs away
affects laser-gun, laser-bot, and laser-mines",
@@ -4639,12 +4700,11 @@
tech.isLaserPush = false;
}
},
-
{
name: "specular reflection",
- description: "increase damage and energy drain by 50%
and +1 reflection for all lasers (gun, bot, mine)",
+ description: "+2 reflection for all lasers
affects laser-gun, laser-bot, and laser-mines",
isGunTech: true,
- maxCount: 9,
+ maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
@@ -4653,14 +4713,10 @@
},
requires: "laser, not wide beam, diffuse beam, pulse, or slow light",
effect() {
- tech.laserReflections++;
- tech.laserDamage += 0.075; //base is 0.12
- tech.laserFieldDrain += 0.001 //base is 0.002
+ tech.laserReflections += 2;
},
remove() {
tech.laserReflections = 2;
- tech.laserDamage = 0.15;
- tech.laserFieldDrain = 0.002;
}
},
{
@@ -4786,9 +4842,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser
+ return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.15
},
- requires: "laser, not specular reflection, not diffuse",
+ requires: "laser, not specular reflection, diffuse, solid-state",
effect() {
tech.isPulseLaser = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7302,5 +7358,8 @@
isFoamTeleport: null,
isResearchBoss: null,
isJunkResearch: null,
- junkResearchNumber: null
+ junkResearchNumber: null,
+ laserColor: null,
+ laserColorAlpha: null,
+ isLongitudinal: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index 5493a5c..f565cec 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,8 +1,27 @@
******************************************************** NEXT PATCH ********************************************************
+tech: pressure wave - wave beam fires lower frequency, higher damage, wide arcs that propagate through solids
+
+tech: gamma-ray laser - increase laser damage by 150% and energy drain by 200%
+ works for all lasers except pulse
+
+tech: specular reflection - now just gives +2 laser reflections (was +1, and damage/energy increase)
+
+you, pilot wave, and drones can't pick up ammo if you have Infinite ammo on your current gun
+ wormhole still eats everything
+
+Bayesian statistics gives 4.2% damage per research (was 3.9%)
+bot fabrication needs 3 research to make a random bot (was 4)
+
******************************************************** TODO ********************************************************
+wave arcs
+ do something similar to laser
+ find intersection of the small angle approximation of the arc and all mobs
+ tech: this.arc: Math.PI/8 // increase or decrease arc
+ wipe arcs on next level
+
try crosshair invert colors
tech wave gun - no bullets just draw circle arcs that do damage to mobs near the circle arc
@@ -252,8 +271,8 @@ map: observatory
******************************************************** MOBS ********************************************************
-mob bullets that explode (use the pulsar effect)
-mobs that explode before they die (use the pulsar effect)
+mob that spawns eggs after they die
+ eggs don't attack but grow back into a mob after about 10s
mob mechanics
use the force at a location effect, like the plasma field