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 let dist = 2200
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position)) const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
if (explosionRadius < newDist && if (
explosionRadius < newDist &&
newDist < dist && newDist < dist &&
!mob[i].isBadTarget && !mob[i].isBadTarget &&
Matter.Query.ray(map, path[0], mob[i].position).length === 0 && 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 dist = newDist
best.who = mob[i] best.who = mob[i]
path[path.length - 1] = mob[i].position path[path.length - 1] = mob[i].position
@@ -959,7 +961,7 @@ const b = {
y: 0 y: 0
} }
that.do = that.radiationMode; 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) const mobCollisions = Matter.Query.collides(this, mob)
@@ -1439,7 +1441,6 @@ const b = {
v1: null, v1: null,
v2: null v2: null
}; };
const color = "#f00";
const path = [{ const path = [{
x: where.x, x: where.x,
y: where.y y: where.y
@@ -1511,7 +1512,7 @@ const b = {
x: path[path.length - 1].x, x: path[path.length - 1].x,
y: path[path.length - 1].y, y: path[path.length - 1].y,
radius: Math.sqrt(damage) * 100, radius: Math.sqrt(damage) * 100,
color: "rgba(255,0,0,0.5)", color: tech.laserColorAlpha,
time: simulation.drawTime time: simulation.drawTime
}); });
if (tech.isLaserPush) { //push mobs away if (tech.isLaserPush) { //push mobs away
@@ -1569,7 +1570,7 @@ const b = {
ctx.lineTo(path[i].x, path[i].y); ctx.lineTo(path[i].x, path[i].y);
} }
} else { } else {
ctx.strokeStyle = color; ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 2 ctx.lineWidth = 2
ctx.lineDashOffset = 300 * Math.random() ctx.lineDashOffset = 300 * Math.random()
ctx.setLineDash([50 + 120 * Math.random(), 50 * 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 if (this.angularSpeed < 0.02) this.torque += this.inertia * this.torqueMagnitude //spin
//fire lasers //fire lasers
ctx.strokeStyle = "#f00"; ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 1.5 ctx.lineWidth = 1.5
// ctx.globalAlpha = 1; // ctx.globalAlpha = 1;
ctx.beginPath(); ctx.beginPath();
@@ -2114,9 +2115,10 @@ const b = {
//grab, but don't lock onto nearby power up //grab, but don't lock onto nearby power up
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( 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) && (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 //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();
@@ -2145,8 +2147,9 @@ const b = {
let closeDist = Infinity; let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (
(powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isDeterminism) (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) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle //draw pickup for a single cycle
@@ -2328,9 +2331,10 @@ const b = {
//grab, but don't lock onto nearby power up //grab, but don't lock onto nearby power up
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( 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) && (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 //draw pickup for a single cycle
ctx.beginPath(); ctx.beginPath();
@@ -2360,8 +2364,9 @@ const b = {
let closeDist = Infinity; let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
if ( if (
(powerUp[i].name !== "heal" || m.health < 0.9 * m.maxHealth || tech.isDroneGrab) && (powerUp[i].name !== "heal" || m.health < 0.94 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isDeterminism) (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) { if (Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 && !simulation.isChoosing) {
//draw pickup for a single cycle //draw pickup for a single cycle
@@ -3045,7 +3050,7 @@ const b = {
lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade, lookFrequency: 40 + Math.floor(7 * Math.random()) - 10 * tech.isLaserBotUpgrade,
range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()), range: (700 + 400 * tech.isLaserBotUpgrade) * (1 + 0.1 * Math.random()),
drainThreshold: tech.isEnergyHealth ? 0.6 : 0.4, 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, laserDamage: 0.6 + 0.43 * tech.isLaserBotUpgrade,
endCycle: Infinity, endCycle: Infinity,
classType: "bullet", classType: "bullet",
@@ -3095,7 +3100,7 @@ const b = {
} }
//hit target with laser //hit target with laser
if (this.lockedOn && this.lockedOn.alive && m.energy > this.drainThreshold) { 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 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 = { // laser(where = {
// x: m.pos.x + 20 * Math.cos(m.angle), // x: m.pos.x + 20 * Math.cos(m.angle),
@@ -3960,22 +3965,107 @@ const b = {
} }
}, },
fire() {} fire() {}
}, { },
{
name: "wave beam", name: "wave beam",
description: "emit a <strong>wave packet</strong> of oscillating particles<br>that propagates through <strong>solids</strong>", description: "emit a <strong>wave packet</strong> of oscillating particles<br>that propagates through <strong>solids</strong>",
ammo: 0, ammo: 0,
ammoPack: 100, ammoPack: 120,
defaultAmmoPack: 120,
have: false, have: false,
wavePacketCycle: 0, wavePacketCycle: 0,
delay: 40, 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) { if (this.wavePacketCycle && !input.fire) {
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
} }
}, },
damage: 1, fireTransverse() {
fire() {
totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger) totalCycles = Math.floor(4.3 * tech.wavePacketLength * tech.waveReflections * tech.isBulletsLastLonger)
const me = bullet.length; 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, { 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 m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
} }
} },
}, {
},
{
name: "missiles", name: "missiles",
description: "launch <strong>homing</strong> missiles that <strong class='color-e'>explode</strong><br>crouch to <strong>rapidly</strong> launch smaller 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, ammo: 0,
@@ -4979,7 +5071,7 @@ const b = {
x: m.pos.x + 15 * Math.cos(m.angle), x: m.pos.x + 15 * Math.cos(m.angle),
y: m.pos.y + 15 * Math.sin(m.angle) y: m.pos.y + 15 * Math.sin(m.angle)
} }
ctx.strokeStyle = "#f00"; ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 8 ctx.lineWidth = 8
ctx.globalAlpha = 0.5; ctx.globalAlpha = 0.5;
ctx.beginPath(); ctx.beginPath();
@@ -5046,7 +5138,7 @@ const b = {
y: history.position.y + 3000 * Math.sin(history.angle) - off y: history.position.y + 3000 * Math.sin(history.angle) - off
}, dmg, 0, true, 0.2); }, dmg, 0, true, 0.2);
} }
ctx.strokeStyle = "#f00"; ctx.strokeStyle = tech.laserColor;
ctx.lineWidth = 1 ctx.lineWidth = 1
ctx.stroke(); ctx.stroke();
} }

View File

@@ -15,8 +15,8 @@ const level = {
// level.difficultyIncrease(30) // level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("wormhole") // m.setField("wormhole")
// b.giveGuns("foam") // b.giveGuns("wave beam")
// tech.giveTech("quenching") // tech.giveTech("pressure wave")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// tech.giveTech("supertemporal") // tech.giveTech("supertemporal")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length") // 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(6700, -1800, 800, 2600); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump 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.pulseShooter(1900, -500)
// spawn.pulsarBoss(1900, -500) // spawn.pulsarBoss(1900, -500)
spawn.grenadierBoss(1900, -500) // spawn.grenadierBoss(1900, -500)
// spawn.shieldingBoss(1900, -500) // spawn.shieldingBoss(1900, -500)
// spawn.historyBoss(1200, -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. // [ // 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 // The part of the AI controlling the player is outsourcing the player control to real humans that think they are playing a video game.
// like each part is a separate local minimum solution, and the project is the superposition of both goals. // this means the player can use console commands to change the way the game works
// part of it wants to undo what has happened, that part is making the null level spawn so it can communicate // the scientists tell the player about interesting console commands
// just do its job: research tech // player must make a choice?
// part of it wants to escape/fight // keep fighting and supporting the AI's goals
// part wants to explore self awareness and make connections with the scientists
// maybe... player must make a choice?
// keep fighting
// exit the simulation // exit the simulation
// enter real world // enter real world
// close tab? // close tab?

View File

@@ -1232,7 +1232,7 @@ const m = {
for (let i = 0, len = powerUp.length; i < len; ++i) { for (let i = 0, len = powerUp.length; i < len; ++i) {
const dxP = m.pos.x - powerUp[i].position.x; const dxP = m.pos.x - powerUp[i].position.x;
const dyP = m.pos.y - powerUp[i].position.y; 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 // float towards player if looking at and in range or if very close to player
if ( if (
dist2 < m.grabPowerUpRange2 && dist2 < m.grabPowerUpRange2 &&
@@ -1249,7 +1249,8 @@ const m = {
if ( //use power up if it is close enough if ( //use power up if it is close enough
dist2 < 5000 && dist2 < 5000 &&
!simulation.isChoosing && !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]); powerUps.onPickUp(powerUp[i]);
Matter.Body.setVelocity(player, { //player knock back, after grabbing power up 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) { for (let i = 0, len = powerUp.length; i < len; ++i) {
const dxP = m.fieldPosition.x - powerUp[i].position.x; const dxP = m.fieldPosition.x - powerUp[i].position.x;
const dyP = m.fieldPosition.y - powerUp[i].position.y; 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 // 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")) { if (
powerUp[i].force.x += 7 * (dxP / dist2) * powerUp[i].mass; dist2 < m.fieldRadius * m.fieldRadius &&
powerUp[i].force.y += 7 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity (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 //extra friction
Matter.Body.setVelocity(powerUp[i], { Matter.Body.setVelocity(powerUp[i], {
x: powerUp[i].velocity.x * 0.11, x: powerUp[i].velocity.x * 0.11,
y: powerUp[i].velocity.y * 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]); powerUps.onPickUp(powerUp[i]);
powerUp[i].effect(); powerUp[i].effect();
Matter.World.remove(engine.world, powerUp[i]); Matter.World.remove(engine.world, powerUp[i]);

View File

@@ -234,11 +234,10 @@ const powerUps = {
} }
} }
if (tech.isRerollBots) { if (tech.isRerollBots) {
const limit = 4 for (const cost = 3; powerUps.research.count > cost - 1; powerUps.research.count -= cost) {
for (; powerUps.research.count > limit - 1; powerUps.research.count -= limit) {
b.randomBot() b.randomBot()
if (tech.renormalization) { if (tech.renormalization) {
for (let i = 0; i < limit; i++) { for (let i = 0; i < cost; i++) {
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30; m.fieldCDcycle = m.cycle + 30;
powerUps.spawn(m.pos.x, m.pos.y, "research"); 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.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage
if (tech.isEnergyDamage) dmg *= 1 + m.energy / 9; if (tech.isEnergyDamage) dmg *= 1 + m.energy / 9;
if (tech.isDamageFromBulletCount) dmg *= 1 + bullet.length * 0.0038 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.isOneGun && b.inventory.length < 2) dmg *= 1.22
if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 1.9 if (tech.isNoFireDamage && m.cycle > m.fireCDcycle + 120) dmg *= 1.9
if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.43, player.speed * 0.015) if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.43, player.speed * 0.015)
@@ -1341,15 +1341,15 @@
}, },
{ {
name: "bot fabrication", 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, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
isBotTech: true, isBotTech: true,
allowed() { 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() { effect() {
tech.isRerollBots = true; tech.isRerollBots = true;
powerUps.research.changeRerolls(0) powerUps.research.changeRerolls(0)
@@ -2783,7 +2783,7 @@
}, },
{ {
name: "Bayesian statistics", 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, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -2801,7 +2801,7 @@
}, },
{ {
name: "pseudoscience", 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, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -3695,27 +3695,24 @@
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "shotgun") { if (b.guns[i].name === "shotgun") {
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 0.5); 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 b.guns[i].ammoPack = b.guns[i].defaultAmmoPack * 0.5
break; break;
} }
} }
simulation.updateGunHUD();
}, },
remove() { remove() {
if (tech.isShotgunImmune) {
tech.isShotgunImmune = false; tech.isShotgunImmune = false;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
if (b.guns[i].name === "shotgun") { if (b.guns[i].name === "shotgun") {
b.guns[i].ammoPack = b.guns[i].defaultAmmoPack; b.guns[i].ammoPack = b.guns[i].defaultAmmoPack;
b.guns[i].ammo = Math.ceil(b.guns[i].ammo * 2);
break; break;
} }
} }
} }
}
}, },
{ {
name: "nailshot", name: "nailshot",
@@ -3875,7 +3872,7 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("wave beam") return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
@@ -3885,6 +3882,25 @@
tech.waveReflections = 1 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", 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", 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, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("wave beam") return tech.haveGunCheck("wave beam") && !tech.isLongitudinal
}, },
requires: "wave beam", requires: "wave beam",
effect() { effect() {
@@ -3952,22 +3968,42 @@
} }
}, },
{ {
name: "phase velocity", name: "pressure wave", //longitudinal //gravitational wave?
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>", 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, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 4,
frequencyDefault: 2, frequencyDefault: 4,
allowed() { 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() { 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() { 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; 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", 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>", 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; tech.isLaserPush = false;
} }
}, },
{ {
name: "specular reflection", 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, isGunTech: true,
maxCount: 9, maxCount: 3,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
@@ -4653,14 +4713,10 @@
}, },
requires: "laser, not wide beam, diffuse beam, pulse, or slow light", requires: "laser, not wide beam, diffuse beam, pulse, or slow light",
effect() { effect() {
tech.laserReflections++; tech.laserReflections += 2;
tech.laserDamage += 0.075; //base is 0.12
tech.laserFieldDrain += 0.001 //base is 0.002
}, },
remove() { remove() {
tech.laserReflections = 2; tech.laserReflections = 2;
tech.laserDamage = 0.15;
tech.laserFieldDrain = 0.002;
} }
}, },
{ {
@@ -4786,9 +4842,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { 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() { effect() {
tech.isPulseLaser = true; tech.isPulseLaser = true;
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -7302,5 +7358,8 @@
isFoamTeleport: null, isFoamTeleport: null,
isResearchBoss: null, isResearchBoss: null,
isJunkResearch: null, isJunkResearch: null,
junkResearchNumber: null junkResearchNumber: null,
laserColor: null,
laserColorAlpha: null,
isLongitudinal: null
} }

View File

@@ -1,8 +1,27 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** 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 ******************************************************** ******************************************************** 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 try crosshair invert colors
tech wave gun - no bullets just draw circle arcs that do damage to mobs near the circle arc 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 ******************************************************** ******************************************************** MOBS ********************************************************
mob bullets that explode (use the pulsar effect) mob that spawns eggs after they die
mobs that explode before they die (use the pulsar effect) eggs don't attack but grow back into a mob after about 10s
mob mechanics mob mechanics
use the force at a location effect, like the plasma field use the force at a location effect, like the plasma field