pressure wave

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)
This commit is contained in:
landgreen
2021-07-07 19:26:47 -07:00
parent 9da29484a0
commit d346afb2d0
8 changed files with 264 additions and 89 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -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 <strong>wave packet</strong> of oscillating particles<br>that propagates through <strong>solids</strong>",
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 <strong>homing</strong> missiles that <strong class='color-e'>explode</strong><br>crouch to <strong>rapidly</strong> 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();
}

View File

@@ -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)

View File

@@ -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?

View File

@@ -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]);

View File

@@ -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");

View File

@@ -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 <strong>4</strong> <strong class='color-r'>research</strong><br>use them to build a random <strong class='color-bot'>bot</strong>",
description: "anytime you collect <strong>3</strong> <strong class='color-r'>research</strong><br>use them to build a random <strong class='color-bot'>bot</strong>",
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 <strong class='color-d'>damage</strong> by <strong>3.9%</strong><br>for each <strong class='color-r'>research</strong> in your inventory",
description: "increase <strong class='color-d'>damage</strong> by <strong>4.2%</strong><br>for each <strong class='color-r'>research</strong> in your inventory",
maxCount: 1,
count: 0,
frequency: 2,
@@ -2801,7 +2801,7 @@
},
{
name: "pseudoscience",
description: "resetting power up choices costs no <strong class='color-r'>research</strong><br>but adds <strong>0-4</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "<strong>rerolling</strong> choices no longer costs <strong class='color-r'>research</strong><br>instead it adds <strong>0-4</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3695,27 +3695,24 @@
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() {
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;
}
}
}
}
},
{
name: "nailshot",
@@ -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 <strong>propagates</strong> faster through solids<br>up by <strong>3000%</strong> in the map and <strong>760%</strong> in <strong class='color-block'>blocks</strong>",
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 <strong>length</strong> and <strong>duration</strong><br>is increased by <strong>50%</strong>", // description: "holding fire allows the <strong>wave beam</strong> to emits a second <strong>packet</strong><br>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 <strong>propagates</strong> faster through solids<br>up by <strong>3000%</strong> in the map and <strong>760%</strong> in <strong class='color-block'>blocks</strong>",
name: "pressure wave", //longitudinal //gravitational wave?
description: "wave beam emits low <strong>frequency</strong>, high <strong class='color-d'>damage</strong><br><strong>expanding arcs</strong> 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 <strong class='color-laser'>laser</strong> <strong class='color-d'>damage</strong> by <strong>150%</strong><br>increase all <strong class='color-laser'>laser</strong> <strong class='color-f'>energy</strong> drain by <strong>200%</strong>",
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 <strong class='color-laser'>lasers</strong> push mobs away<br><em>affects laser-gun, laser-bot, and laser-mines</em>",
@@ -4639,12 +4700,11 @@
tech.isLaserPush = false;
}
},
{
name: "specular reflection",
description: "increase <strong class='color-d'>damage</strong> and <strong class='color-f'>energy</strong> drain by <strong>50%</strong><br>and <strong>+1</strong> reflection for all <strong class='color-laser'>lasers</strong> <em>(gun, bot, mine)</em>",
description: "<strong>+2</strong> reflection for all <strong class='color-laser'>lasers</strong><br><em>affects laser-gun, laser-bot, and laser-mines</em>",
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
}

View File

@@ -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