JUNK percents

JUNK tech: facsimile - copy current level and insert into level queue
JUNK tech: planetesimals - spawn a tech, and play planetesimals, an annoying asteroids like game with realistic physics

tech that previously added 1 junk tech now adds 1% (of current non-JUNK tech options)
  the percent values may seem like more but I actually lowered the JUNK chance about 10%

meta-analysis no longer requires replication - (if you choose a JUNK tech get a random tech and 3 research)
symbiosis: only gives 1 bonus tech (was 1 or 2)
blink boss rebalanced (it's easier, and has two modes)

bug fixes
This commit is contained in:
landgreen
2021-10-27 19:21:51 -07:00
parent 34b1a02981
commit 79e27978ec
11 changed files with 985 additions and 86 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -580,6 +580,10 @@
<script src="js/lore.js"></script>
<script src="js/engine.js"></script>
<script src="js/index.js"></script>
<!-- code for different game: planetesimals -->
<!-- <div id='hud'></div>
<script src="js/planetesimals.js"></script> -->
</body>
</html>

View File

@@ -1231,7 +1231,7 @@ const b = {
}
}
} else {
if (m.energy > 0.005) m.energy -= 0.005
if (m.energy > 0.005 && !m.isBodiesAsleep) m.energy -= 0.005
const sub = Vector.sub(this.position, m.pos)
const rangeScale = 1 + 0.000001 * Vector.magnitude(sub) * Vector.magnitude(sub) //return faster when far from player
const returnForce = Vector.mult(Vector.normalise(sub), rangeScale * this.thrustMag * this.mass)
@@ -1478,7 +1478,6 @@ const b = {
y: Math.sin(this.angle)
};
const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
// const target = Vector.normalise(Vector.sub(this.position, this.lockedOn.position));
const dot = Vector.dot(target, face)
const aim = Math.min(0.08, (1 + dot) * 1)
if (Vector.cross(target, face) > 0) {
@@ -1486,7 +1485,7 @@ const b = {
} else {
Matter.Body.rotate(this, -aim);
}
this.frictionAir = Math.min(0.1, Math.max(0.04, (1 + dot) * 1)) //0.08; //extra friction if turning
this.frictionAir = Math.min(0.1, Math.max(0.04, 1 + dot)) //0.08; //extra friction if turning
}
//accelerate in direction bullet is facing
const dir = this.angle;
@@ -4073,7 +4072,7 @@ const b = {
});
}
} else {
if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.025 * Math.cos(m.angle)
player.force.x -= 0.06 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
player.force.y -= 0.006 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
}
},
@@ -4239,7 +4238,9 @@ const b = {
});
}
} else {
if (Math.abs(player.velocity.x) < 12) player.force.x -= 0.06 * Math.cos(m.angle)
player.force.x -= 0.2 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
// player.force.x -= 0.06 * Math.cos(m.angle) * Math.min(1, 3 / (0.1 + Math.abs(player.velocity.x)))
player.force.y -= 0.02 * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
}
},
@@ -5333,7 +5334,6 @@ const b = {
m.fireCDcycle = m.cycle + 50 * b.fireCDscale; // cool down
// }
} else if (tech.extraHarpoons) {
const harpoons = tech.extraHarpoons + 1
const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1)
let targetCount = 0
for (let i = 0, len = mob.length; i < len; ++i) {
@@ -5345,15 +5345,15 @@ const b = {
this.ammo--
b.harpoon(where, mob[i], m.angle, length, true, totalCycles) //Vector.angle(Vector.sub(where, mob[i].position), { x: 0, y: 0 })
targetCount++
if (targetCount > harpoons) break
if (targetCount > tech.extraHarpoons) break
}
}
}
}
//if more harpoons and no targets left
if (targetCount < harpoons) {
if (targetCount < tech.extraHarpoons + 1) {
const SPREAD = 0.1
const num = harpoons - targetCount
const num = tech.extraHarpoons + 1 - targetCount
let dir = m.angle - SPREAD * (num - 1) / 2;
for (let i = 0; i < num; i++) {
if (this.ammo > 0) {

View File

@@ -22,7 +22,7 @@ const level = {
// tech.giveTech("rivet gun")
// for (let i = 0; i < 2; i++) tech.giveTech("refractory metal")
// tech.giveTech("all-stars")
// for (let i = 0; i < 9; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 1; i++) tech.giveTech("reticulum")
// for (let i = 0; i < 2; i++) tech.giveTech("laser-bot")
// tech.isCancelDuplication = true
@@ -2316,7 +2316,7 @@ const level = {
// spawn.laserBombingBoss(1900, -500)
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
// spawn.slashBoss(1900, -500)
spawn.sucker(1900, -500)
// spawn.sucker(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true
// spawn.growBossCulture(1200, -500)
@@ -2332,7 +2332,7 @@ const level = {
// spawn.nodeGroup(1200, -500, "grenadier")
// spawn.nodeGroup(1800, -500, "grenadier")
// spawn.nodeGroup(1200, 0, "grenadier")
// spawn.snakeBoss(1200, -500)
spawn.blinkBoss(1200, -500)
// spawn.suckerBoss(2900, -500)
// spawn.randomMob(1600, -500)
},
@@ -2931,12 +2931,7 @@ const level = {
spawn.randomMob(-75, -1475, 0);
spawn.randomGroup(600, -2600, 0);
}
if (simulation.difficulty < 10) {
spawn.randomMob(700, -1650, 0);
spawn.randomMob(600, -3500, 0.2);
spawn.randomMob(-75, -1175, 0.2);
powerUps.spawnBossPowerUp(-125, -1760);
} else {
if (simulation.difficulty < 1) {
if (Math.random() < 0.5) {
spawn.randomLevelBoss(700, -1550);
} else {

View File

@@ -1140,7 +1140,7 @@ const mobs = {
if (tech.isAddRemoveMaxHealth) {
if (this.isBoss && this.isDropPowerUp) {
powerUps.spawn(this.position.x, this.position.y, "tech", false)
if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false)
// if (0.5 < Math.random()) powerUps.spawn(this.position.x, this.position.y, "tech", false)
} else {
const amount = 0.01
if (tech.isEnergyHealth) {

807
js/planetesimals.js Normal file
View File

@@ -0,0 +1,807 @@
/* http://brm.io/matter-js/docs/
http://brm.io/matter-js/demo/#mixed
https://github.com/liabru/matter-js/blob/master/demo/js/Demo.js
git hub gist:
https://gist.github.com/lilgreenland/8f2a2c033fdf3d5546a0ca5d73a2ae11
todo:
can you render bullets a different color? // red?
maybe add the ability to put up shields to survive collisions?
maybe add durability regeneration
fix new mass spawn so that it will pick a new location if the first spawn location already has a mass
*/
function planetesimals() {
//pause n-gon
// if (!simulation.isChoosing && input.isPauseKeyReady && m.alive) {
// input.isPauseKeyReady = false
// setTimeout(function() {
// input.isPauseKeyReady = true
// }, 300);
// if (simulation.paused) {
// build.unPauseGrid()
// simulation.paused = false;
// // level.levelAnnounce();
// document.body.style.cursor = "none";
// requestAnimationFrame(cycle);
// } else {
// simulation.paused = true;
// build.pauseGrid()
// document.body.style.cursor = "auto";
// if (tech.isGunSwitchField || simulation.testing) {
// document.getElementById("pause-field").addEventListener("click", () => {
// const energy = m.energy
// m.setField((m.fieldMode === m.fieldUpgrades.length - 1) ? 1 : m.fieldMode + 1) //cycle to next field
// m.energy = energy
// document.getElementById("pause-field").innerHTML = `<div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[m.fieldMode].name}</div> ${m.fieldUpgrades[m.fieldMode].description}`
// });
// }
// }
// }
"use strict"; //strict mode to catch errors
//game objects values
var game = {
cycle: 0,
width: 0,
height: 0,
scale: 0.5,
gravity: 0.00011,
totalMass: 0,
massSize: 0,
level: 1,
startingMassValue: 0,
massSegment: 0,
clearThreshold: 0.2, // there must be less than this percent to move on to the next level
currentMass: 0,
explodeMin: 8000,
HUD: true,
};
function levelScaling() {
//game.gravity = 0.00011; // + 0.000012 * game.level;
game.width = 2000 * game.level; //shapes walls and spawn locations
game.height = 2000 * game.level; //shapes walls and spawn locations
game.scale = 1.2 / (Math.log(game.level + 1)); //0.6 + 1.0 / (game.level); //controls map zoom
game.totalMass = 3 + game.level * 1; //how many masses to spawn at start of level
game.massSize = 3 + game.level * 3; //adds the average length of a segment on a masses's vertices
game.massSegment = 0.1 + 0.1 / game.level;
}
//looks for key presses and logs them
var keys = [];
document.body.addEventListener("keydown", function(e) {
keys[e.keyCode] = true;
});
document.body.addEventListener("keyup", function(e) {
keys[e.keyCode] = false;
});
// module aliases
var Engine = Matter.Engine,
World = Matter.World,
Events = Matter.Events,
Composite = Matter.Composite,
Vertices = Matter.Vertices,
Body = Matter.Body,
Bodies = Matter.Bodies;
// create an engine
var engine = Engine.create();
//turn off gravity
engine.world.gravity.y = 0;
// run the engine
// Engine.run(engine);
Matter.Runner.run(engine)
function addWalls() {
//add the walls
var wallSettings = {
size: 200,
isStatic: true,
render: {
restitution: 0,
fillStyle: 'rgba(0, 0, 0, 0.0)',
strokeStyle: '#00ffff'
}
};
World.add(engine.world, [
Bodies.rectangle(game.width * 0.5, -wallSettings.size * 0.5, game.width, wallSettings.size, wallSettings), //top
Bodies.rectangle(game.width * 0.5, game.height + wallSettings.size * 0.5, game.width, wallSettings.size, wallSettings), //bottom
Bodies.rectangle(-wallSettings.size * 0.5, game.height * 0.5, wallSettings.size, game.height + wallSettings.size * 2, wallSettings), //left
Bodies.rectangle(game.width + wallSettings.size * 0.5, game.height * 0.5, wallSettings.size, game.height + wallSettings.size * 2, wallSettings) //right
]);
}
//add the masses
var mass = [];
function addPlayer() {
//add the player object as the first mass in the array
mass.push();
//var arrow = Vertices.fromPath('100 0 75 50 100 100 25 100 0 50 25 0');
var arrow = Vertices.fromPath('0 15 -10 -15 10 -15');
mass[0] = Matter.Bodies.fromVertices(Math.random() * game.width, Math.random() * game.height, arrow, {
//density: 0.001,
alive: true,
friction: 0,
frictionStatic: 0,
frictionAir: 0,
restitution: 0, //bounce 1 = 100% elastic
density: 0.003333,
thrust: 0.0004, //forward acceleration, if mass goes up this needs to go up
yaw: 0.00133, //angular acceleration, needs to be higher with larger mass
rotationLimit: 0.05, //max acceleration for player in radians/cycle
angularFriction: 0.98, // 1 = no friction, 0.9 = high friction
durability: 1,
fireCD: 0,
lastPlayerVelocity: { //for keeping track of damamge from too much acceleration
x: 0,
y: 0
},
});
World.add(engine.world, mass[0]);
}
function randomConvexPolygon(size) { //returns a string of vectors that make a convex polygon
var polyVector = '';
var x = 0;
var y = 0;
var r = 0;
var angle = 0;
for (var i = 1; i < 60; i++) {
angle += 0.1 + Math.random() * game.massSegment; //change in angle in radians
if (angle > 2 * Math.PI) {
break; //stop before it becomes convex
}
r = 2 + Math.random() * 2;
x = Math.round(x + r * Math.cos(angle));
y = Math.round(y + r * Math.sin(angle));
polyVector = polyVector.concat(x * size + ' ' + y * size + ' ');
}
return polyVector;
}
function addMassVector(x, y, Vx, Vy, size) {
var verticies = [];
var vector = Vertices.fromPath(randomConvexPolygon(size));
var i = mass.length;
mass.push();
mass[i] = Matter.Bodies.fromVertices(x, y, vector, { // x,y,vectors,{options}
friction: 0,
frictionStatic: 0,
frictionAir: 0,
restitution: 1,
angle: Math.random() * 2 * Math.PI
});
Matter.Body.setVelocity(mass[i], {
x: Vx,
y: Vy
});
Matter.Body.setAngularVelocity(mass[i], (Math.random() - 0.5) * 0.03);
World.add(engine.world, mass[i]);
}
function addMass(x, y, r, sides, Vx, Vy) {
var i = mass.length;
mass.push();
mass[i] = Bodies.polygon(x, y, sides, r, {
friction: 0,
frictionStatic: 0,
frictionAir: 0,
restitution: 1,
});
Matter.Body.setVelocity(mass[i], {
x: Vx,
y: Vy
});
Matter.Body.setAngularVelocity(mass[i], (Math.random() - 0.5) * 0.03);
World.add(engine.world, mass[i]);
}
function clearMasses() {
World.clear(engine.world, false);
console.log('clear')
mass = [];
}
function spawnSetup() {
//make the level indicator more clear on a new level
// document.getElementById("level").innerHTML = 'system ' + game.level;
// document.getElementById("level").style.color = 'white';
// document.getElementById("level").style.fontSize = '500%';
// document.getElementById("level").style.left = '40%';
// document.getElementById("level").style.position = 'absolute';
// setTimeout(levelFontSize, 3000);
//after 3 seconds return to normal style
// function levelFontSize(size) {
// document.getElementById("level").style.color = 'grey';
// document.getElementById("level").style.position = '';
// document.getElementById("level").style.left = '';
// document.getElementById("level").style.fontSize = '100%';
// }
levelScaling();
clearMasses();
addWalls();
addPlayer();
//add other masses
for (var j = 0; j < game.totalMass; j++) {
// addMassVector(x,y,Vx,Vy,size)
addMassVector(game.width * 0.2 + Math.random() * game.width * 0.6,
game.height * 0.2 + Math.random() * game.height * 0.6,
0, //(0.5 - Math.random()) * 4,
0,
Math.random() * 3 + game.massSize
);
}
//determine how much mass is in the game at the start
game.startingMassValue = 0;
for (var i = 0; i < mass.length; i++) {
game.startingMassValue += mass[i].mass;
}
game.currentMass = game.startingMassValue;
}
spawnSetup();
function repopulateMasses() {
game.currentMass = 0;
for (var i = 0; i < mass.length; i++) {
game.currentMass += mass[i].mass;
}
if (game.currentMass < game.startingMassValue * game.clearThreshold) {
game.level++;
spawnSetup();
mass[0].durability = 1;
}
}
var bullet = [];
function fireBullet() { //addMass(x, y, r, sides, Vx, Vy)
var i = bullet.length;
var angle = mass[0].angle + Math.PI * 0.5;
var speed = 9;
var playerDist = 25;
bullet.push();
bullet[i] = Bodies.polygon(
mass[0].position.x + playerDist * Math.cos(angle),
mass[0].position.y + playerDist * Math.sin(angle),
3, //sides
2, { //radius
angle: Math.random() * 6.28,
friction: 0,
frictionStatic: 0,
frictionAir: 0,
restitution: 1,
endCycle: game.cycle + 90, // life span for a bullet (60 per second)
});
Matter.Body.setVelocity(bullet[i], {
x: mass[0].velocity.x + speed * Math.cos(angle),
y: mass[0].velocity.y + speed * Math.sin(angle)
});
Matter.Body.setAngularVelocity(bullet[i], (Math.random() - 0.5) * 1);
World.add(engine.world, bullet[i]);
}
function bulletEndCycle() {
for (var i = 0; i < bullet.length; i++) {
if (bullet[i].endCycle < game.cycle) {
Matter.World.remove(engine.world, bullet[i]);
bullet.splice(i, 1);
}
}
}
function controls() {
if (mass[0].alive) {
if (keys[32] && mass[0].fireCD < game.cycle) {
mass[0].fireCD = game.cycle + 10; // ?/60 seconds of cooldown before you can fire
fireBullet();
}
if (keys[38] || keys[87]) { //forward thrust
mass[0].force.x += mass[0].thrust * Math.cos(mass[0].angle + Math.PI * 0.5);
mass[0].force.y += mass[0].thrust * Math.sin(mass[0].angle + Math.PI * 0.5);
thrustGraphic();
} else if (keys[40] || keys[83]) { //reverse thrust
mass[0].force = {
x: -mass[0].thrust * 0.5 * Math.cos(mass[0].angle + Math.PI * 0.5),
y: -mass[0].thrust * 0.5 * Math.sin(mass[0].angle + Math.PI * 0.5)
};
torqueGraphic(-1);
torqueGraphic(1);
}
//rotate left and right
if ((keys[37] || keys[65])) { //&& mass[0].angularVelocity > -mass[0].rotationLimit) {
mass[0].torque = -mass[0].yaw; //counter clockwise
torqueGraphic(-1);
} else if ((keys[39] || keys[68])) { //&& mass[0].angularVelocity < mass[0].rotationLimit) {
mass[0].torque = mass[0].yaw; //clockwise
torqueGraphic(1);
}
//angular friction if spinning too fast
if (Math.abs(mass[0].angularVelocity) > mass[0].rotationLimit) {
Matter.Body.setAngularVelocity(mass[0], mass[0].angularVelocity * mass[0].angularFriction);
}
}
}
function torqueGraphic(dir) { //thrust graphic when holding rotation keys
ctx.save();
//ctx.translate(0.5 * canvas.width, 0.5 * canvas.height)
ctx.rotate(mass[0].angle - Math.PI * 0.6 * dir);
ctx.translate(0, -23);
var grd = ctx.createLinearGradient(0, 0, 0, 15);
grd.addColorStop(0.1, 'rgba(0, 0, 0, 0)');
grd.addColorStop(1, 'rgba(160, 192, 255, 1)');
ctx.fillStyle = grd;
ctx.beginPath();
ctx.moveTo(dir * 6 * (Math.random() - 0.5) + 12 * dir, 6 * (Math.random() - 0.5));
ctx.lineTo(dir * 8, 14);
ctx.lineTo(dir * 12, 14);
ctx.fill();
ctx.restore();
}
function thrustGraphic() {
//ctx.fillStyle= "#90b0ff";
ctx.save();
//ctx.translate(0.5 * canvas.width, 0.5 * canvas.height)
ctx.rotate(mass[0].angle);
ctx.translate(0, -33);
var grd = ctx.createLinearGradient(0, 0, 0, 15);
grd.addColorStop(0, 'rgba(0, 0, 0, 0)');
grd.addColorStop(1, 'rgba(160, 192, 255, 1)');
ctx.fillStyle = grd;
ctx.beginPath();
ctx.moveTo(10 * (Math.random() - 0.5), 10 * (Math.random() - 0.5));
ctx.lineTo(7, 20);
ctx.lineTo(-7, 20);
ctx.fill();
ctx.restore();
}
function gravity() {
var length = mass.length;
var Dx = 0;
var Dy = 0;
var force = 0;
var angle = 0;
var i = 0;
var j = 0;
//gravity for array masses, but not player: mass[0]
for (i = 0; i < length; i++) {
for (j = 0; j < length; j++) {
if (i != j) {
Dx = mass[j].position.x - mass[i].position.x;
Dy = mass[j].position.y - mass[i].position.y;
force = game.gravity * mass[j].mass * mass[i].mass / (Math.sqrt(Dx * Dx + Dy * Dy));
angle = Math.atan2(Dy, Dx);
mass[i].force.x += force * Math.cos(angle);
mass[i].force.y += force * Math.sin(angle);
}
}
}
//gravity for bullets
var Blength = bullet.length;
for (i = 0; i < Blength; i++) {
for (j = 0; j < length; j++) { //bullets only feel gravity, they don't create it
Dx = mass[j].position.x - bullet[i].position.x;
Dy = mass[j].position.y - bullet[i].position.y;
force = game.gravity * mass[j].mass * bullet[i].mass / (Math.sqrt(Dx * Dx + Dy * Dy));
angle = Math.atan2(Dy, Dx);
bullet[i].force.x += force * Math.cos(angle);
bullet[i].force.y += force * Math.sin(angle);
}
}
}
function damage() { //changes player health if velocity changes too much
var limit2 = 9; //square of velocity damamge limit
var dX = Math.abs(mass[0].lastPlayerVelocity.x - mass[0].velocity.x);
var dY = Math.abs(mass[0].lastPlayerVelocity.y - mass[0].velocity.y);
var dV2 = dX * dX + dY * dY; //we are skipping the square root
if (dV2 > limit2) { //did velocity change enough to take damage
mass[0].durability -= Math.sqrt(dV2 - limit2) * 0.02; //player takes damage
if (mass[0].durability < 0 && mass[0].alive) { //player dead?
mass[0].alive = false;
//spawn player explosion debris
for (var j = 0; j < 10; j++) { //addMass(x, y, r, sides, Vx, Vy)
addMass(mass[0].position.x + 10 * (0.5 - Math.random()),
mass[0].position.y + 10 * (0.5 - Math.random()),
5,
3,
(0.5 - Math.random()) * 8 + mass[0].velocity.x,
(0.5 - Math.random()) * 8 + mass[0].velocity.y);
}
//shrink player to match debris size
Matter.Body.scale(mass[0], 0.4, 0.4);
//reset masses after a few seconds
window.setTimeout(spawnSetup, 6000);
}
}
//keep track of last player velocity to calculate changes in velocity
mass[0].lastPlayerVelocity.x = mass[0].velocity.x;
mass[0].lastPlayerVelocity.y = mass[0].velocity.y;
}
//bullet collision event
Events.on(engine, 'collisionStart', function(event) {
//slice the polygon up into sections
function slicePoly(m, start, end) { //cut a mass into two sectons
//build new string vector array that matches some of the reference mass
var polyVector = '';
for (var i = start; i < end; i++) {
polyVector = polyVector.concat(mass[m].vertices[i].x + ' ' + mass[m].vertices[i].y + ' ');
}
//buggy: making polygons noncolide. not sure why
//if (end = mass[m].vertices.length) { //catch the first vertices if the polygon hits the last
// polyVector = polyVector.concat(mass[m].vertices[0].x + ' ' + mass[m].vertices[0].y + ' '); }
var verticies = []; //build the polygon in matter.js
var vector = Vertices.fromPath(polyVector);
//add string vector array to game as a polygon
var len = mass.length;
mass.push();
mass[len] = Matter.Bodies.fromVertices(0, 0, vector, { // x,y,vectors,{options}
friction: 0,
frictionStatic: 0,
frictionAir: 0,
restitution: 1
});
World.add(engine.world, mass[len]);
//scale down the polygon a bit to help with collisions
Matter.Body.scale(mass[len], 0.9, 0.9);
//move polygon into position
var vectorPos = Matter.Vertices.centre(vector); //find the center of new polygon
Matter.Body.translate(mass[len], {
x: vectorPos.x,
y: vectorPos.y
});
//give a velocity pointed away from the old mass's center so it explodes
var angle = Math.atan2(mass[len].position.y - mass[m].position.y, mass[len].position.x - mass[m].position.x);
Matter.Body.setVelocity(mass[len], {
x: mass[m].velocity.x + 2 * Math.cos(angle),
y: mass[m].velocity.y + 2 * Math.sin(angle)
});
//add some spin
Matter.Body.setAngularVelocity(mass[len], (Math.random() - 0.5) * 0.1);
}
function hit(i, b, m) {
//match the collisions pair id to the mass
for (var j = 1; j < mass.length; j++) { //start at 1 to skip the player
if (mass[j].id === m.id) {
//remove bullet
Matter.World.remove(engine.world, bullet[i]);
bullet.splice(i, 1);
// explosion graphics
var driftSpeed = 1;
var length = mass[j].vertices.length - 1;
var dx = (mass[j].vertices[length].x - mass[j].position.x);
var dy = (mass[j].vertices[length].y - mass[j].position.y);
var r = Math.sqrt(dx * dx + dy * dy) * 1.5; // *1.5 give the explosion outward spread
var angle = Math.atan2(dy, dx);
boom.push({ //the line form the 1st and last vertex
x1: mass[j].vertices[length].x,
y1: mass[j].vertices[length].y,
x2: mass[j].vertices[0].x,
y2: mass[j].vertices[0].y,
alpha: 1,
driftVx: mass[j].velocity.x + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.cos(angle),
driftVy: mass[j].velocity.y + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.sin(angle),
});
for (var n = 0; n < length; n++) {
dx = (mass[j].vertices[n].x - mass[j].position.x);
dy = (mass[j].vertices[n].y - mass[j].position.y);
r = Math.sqrt(dx * dx + dy * dy);
angle = Math.atan2(dy, dx);
boom.push({
x1: mass[j].vertices[n].x,
y1: mass[j].vertices[n].y,
x2: mass[j].vertices[n + 1].x,
y2: mass[j].vertices[n + 1].y,
alpha: 1,
driftVx: mass[j].velocity.x + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.cos(angle),
driftVy: mass[j].velocity.y + (Math.random() - 0.5) * driftSpeed + r * mass[j].angularSpeed * Math.sin(angle),
});
}
//choose to slice
if (mass[j].vertices.length > 13) {
var cut = 6 + Math.floor(Math.random() * 4);
slicePoly(j, 0, cut);
//sliceChoices(mass.length - 1);
slicePoly(j, cut - 1, mass[j].vertices.length);
//sliceChoices(mass.length - 1);
Matter.World.remove(engine.world, mass[j]);
mass.splice(j, 1);
} else {
Matter.World.remove(engine.world, mass[j]);
mass.splice(j, 1);
}
return;
}
}
}
//check to see if one of the collisison pairs is a bullet
var pairs = event.pairs;
for (var i = 0, j = pairs.length; i != j; ++i) {
var pair = pairs[i];
for (var k = 0; k < bullet.length; k++) {
if (pair.bodyA === bullet[k]) {
hit(k, pair.bodyA, pair.bodyB);
repopulateMasses();
break;
} else if (pair.bodyB === bullet[k]) {
hit(k, pair.bodyB, pair.bodyA);
repopulateMasses();
break;
}
}
}
});
var boom = [];
function explosions() {
var i = boom.length;
ctx.lineWidth = 1.5;
while (i--) {
ctx.strokeStyle = 'rgba(255, 255, 255, ' + boom[i].alpha + ')';
//drift vector lines around
boom[i].x1 += boom[i].driftVx;
boom[i].y1 += boom[i].driftVy;
boom[i].x2 += boom[i].driftVx;
boom[i].y2 += boom[i].driftVy;
//draw vector lines
ctx.beginPath();
ctx.moveTo(boom[i].x1, boom[i].y1);
ctx.lineTo(boom[i].x2, boom[i].y2);
ctx.stroke();
//remove vector lines if they are too old
boom[i].alpha -= 0.03;
if (boom[i].alpha < 0.01) {
boom.splice(i, 1);
}
}
}
//set up render
var canvas = document.createElement('canvas'),
ctx = canvas.getContext('2d');
//make canvas fill window
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
document.body.appendChild(canvas);
window.onresize = function(event) {
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
starsMoveRandom();
};
(function cycle() { //render loop
game.cycle++;
//ctx.fillStyle = 'rgba(0, 0, 0, 0.2)'; //trails simulate a old arcade cathode look
//ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.clearRect(0, 0, canvas.width, canvas.height); //clear canvas for new cycle
bulletEndCycle();
damage();
gravity();
//background graphics
drawStars();
HUD();
ctx.save(); //move camera
ctx.translate(window.innerWidth * 0.5, window.innerHeight * 0.5);
ctx.scale(game.scale, game.scale);
controls();
ctx.translate(-mass[0].position.x, -mass[0].position.y);
//primary graphics
render();
drawVectors();
explosions();
ctx.restore(); //undo previous translation
//foreground graphics
miniMap();
completionBar();
durabilityBar();
window.requestAnimationFrame(cycle);
})();
function render() { //draw all the objects from matter.js physics engine
var bodies = Composite.allBodies(engine.world); //draw every object
//fill and stroke each body
ctx.lineWidth = 1.5;
ctx.strokeStyle = '#ffffff';
ctx.fillStyle = '#050505'; //'#111'; //'#0a0606';
ctx.beginPath();
for (var i = 0; i < bodies.length; i++) {
var vertices = bodies[i].vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (var j = 1; j < vertices.length; j++) {
ctx.lineTo(vertices[j].x, vertices[j].y);
}
ctx.lineTo(vertices[0].x, vertices[0].y);
}
ctx.fill();
ctx.stroke();
}
function drawVectors() { //render force and velocity vectors for each mass
if (game.HUD) {
var length = mass.length;
ctx.lineWidth = 1;
//velocity vector
//ctx.strokeStyle = 'rgba(0, 255, 255, 1)';
ctx.strokeStyle = '#00ffff';
ctx.beginPath();
for (var i = 0; i < length; i++) {
ctx.moveTo(mass[i].position.x, mass[i].position.y);
ctx.lineTo(mass[i].position.x + 10 * mass[i].velocity.x,
mass[i].position.y + 10 * mass[i].velocity.y);
}
ctx.stroke();
//force vector
//ctx.strokeStyle = 'rgba(255, 0, 255, 1)';
ctx.strokeStyle = '#ff00ff';
ctx.beginPath();
for (i = 0; i < length; i++) {
ctx.moveTo(mass[i].position.x, mass[i].position.y);
ctx.lineTo(mass[i].position.x + 600000 * mass[i].force.x / mass[i].mass,
mass[i].position.y + 600000 * mass[i].force.y / mass[i].mass);
}
ctx.stroke();
//angular motion vector
/* ctx.strokeStyle = 'rgba(255, 255, 00, 0.5)';//'#ff00ff';
ctx.beginPath();
if (mass[0].angularVelocity>0){
ctx.arc(mass[0].position.x,mass[0].position.y,20,Math.PI*0.5,53*mass[0].angularVelocity+Math.PI*0.5);
}else{
ctx.arc(mass[0].position.x,mass[0].position.y,20,53*mass[0].angularVelocity+Math.PI*0.5,Math.PI*0.5);
}
ctx.stroke(); */
}
}
function HUD() { //player data
// document.getElementById("level").innerHTML = 'system ' + game.level
if (game.HUD) { //testing and development data
document.getElementById("hud").innerHTML = '<table> ' +
//'<tr> <td>#:</td> <td>' + mass.length + '</td> </tr>' +
//'<tr> <td>level: </td> <td>' + game.level + '</td> </tr>' +
'<tr> <td>&nbsp;t:</td> <td>' + engine.timing.timestamp.toFixed(0) + '</td> </tr>' +
'<tr> <td style="color:#77f;">&nbsp;m:</td> <td>' + mass[0].mass.toFixed(2) + '</td> </tr>' +
'<tr> <td style="color:#77f;">&nbsp;θ:</td> <td>' + (Math.abs(mass[0].angle % (Math.PI * 2))).toFixed(2) + '</td> </tr>' +
'<tr> <td style="color:#77f;">dθ:</td> <td>' + mass[0].angularVelocity.toFixed(3) + '</td> </tr>' +
'<tr> <td style="color:#77f;">&nbsp;x:</td> <td>' + mass[0].position.x.toFixed(0) + '</td> </tr>' +
'<tr> <td style="color:#77f;">&nbsp;y:</td> <td>' + mass[0].position.y.toFixed(0) + '</td> </tr>' +
'<tr> <td style="color:#0dd;">Vx:</td> <td>' + mass[0].velocity.x.toFixed(2) + '</td> </tr>' +
'<tr> <td style="color:#0dd;">Vy:</td> <td>' + mass[0].velocity.y.toFixed(2) + '</td> </tr>' +
'<tr> <td style="color:#d0d;">Fx:</td> <td>' + mass[0].force.x.toFixed(6) + '</td> </tr>' +
'<tr> <td style="color:#d0d;">Fy:</td> <td>' + mass[0].force.y.toFixed(6) + '</td> </tr>' + '</table>';
} else {
document.getElementById("hud").innerHTML = "";
}
}
function durabilityBar() { // player health bar
var size = 200;
var x = 6;
var y = 6;
//ctx.lineWidth = 2;
//ctx.strokeStyle = '#999';
//ctx.strokeRect(x - 1, y - 1, size + 2, 12); //draw outline
//ctx.fillStyle = '#512';
ctx.fillStyle = 'rgba(255, 85, 119, 0.3)'
ctx.fillRect(x, y, size, 10); //draw bar
if (mass[0].alive) { //only draw bar if player is alive
ctx.fillStyle = 'rgba(255, 85, 119, 0.9)'
ctx.fillRect(x, y, size * mass[0].durability, 10); //draw bar
}
}
function completionBar() {
var size = 152;
var x = canvas.width - size - 4;
var y = 5;
//ctx.fillStyle = '#000007';
//ctx.fillRect(x, y, size, 5); //draw bar
ctx.fillStyle = 'rgba(85, 85, 170, 0.3)'
//ctx.fillStyle = '#55a';
ctx.fillRect(x, y, size, 5); //draw bar
//ctx.fillStyle = '#55a';
ctx.fillStyle = 'rgba(85, 85, 170, 0.9)'
ctx.fillRect(x, y, size * game.currentMass / game.startingMassValue, 5); //draw bar
//goal line
ctx.fillStyle = '#ffff00';
ctx.fillRect(x + size * game.clearThreshold, y, 1, 5); //draw bar
//outline of bar
//ctx.lineWidth = 1;
//ctx.strokeStyle = '#88f';
//ctx.strokeRect(x, y, size, 5); //draw outline
}
function miniMap() {
ctx.lineWidth = 1;
ctx.strokeStyle = '#88f';
ctx.beginPath();
var xOff = canvas.width - 5;
var yOff = 10;
var size = 150;
var scale = size / game.width;
ctx.fillStyle = 'rgba(0, 0, 50, 0.5)'
ctx.rect(xOff, yOff, -size, size);
ctx.stroke();
ctx.fill();
//draw dot for masses
ctx.fillStyle = '#aaf';
for (var i = 1; i < mass.length; i++) {
ctx.fillRect(mass[i].position.x * scale + xOff - size, mass[i].position.y * scale + yOff, 3, 3);
}
//draw player's dot
ctx.fillStyle = '#ffff00';
ctx.fillRect(mass[0].position.x * scale + xOff - size, mass[0].position.y * scale + yOff, 5, 5);
}
var star = [];
var totalStars = 100;
for (var i = 0; i < totalStars; i++) {
star.push({
x: Math.random() * window.innerWidth,
y: Math.random() * window.innerHeight
});
}
function starsMoveRandom() {
for (var i = 0; i < totalStars; i++) {
star[i].x = Math.random() * window.innerWidth;
star[i].y = Math.random() * window.innerHeight;
}
}
function drawStars() {
ctx.fillStyle = '#ffffff'; //'darkgrey'; //'rgba(255, 255, 255, 0.5)'
var parallax = 1;
var Vx = mass[0].velocity.x * game.scale;
var Vy = mass[0].velocity.y * game.scale;
var width = window.innerWidth;
var height = window.innerHeight;
for (var i = 0; i < totalStars; i++) {
star[i].x -= Vx;
star[i].y -= Vy;
ctx.fillRect(star[i].x, star[i].y, 1, 1);
if (star[i].x < 0) {
star[i].x = width;
star[i].y = Math.random() * height;
}
if (star[i].x > width) {
star[i].x = 0;
star[i].y = Math.random() * height;
}
if (star[i].y < 0) {
star[i].y = height;
star[i].x = Math.random() * width;
}
if (star[i].y > height) {
star[i].y = 0;
star[i].x = Math.random() * width;
}
}
}
}

View File

@@ -949,12 +949,12 @@ const m = {
},
setHoldDefaults() {
if (tech.isFreeWormHole && m.fieldUpgrades[m.fieldMode].name !== "wormhole") {
tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field
powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
const removed = tech.removeTech("charmed baryon") //neutronum can get player stuck so it has to be removed if player has wrong field
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
}
if (tech.isNeutronium && m.fieldUpgrades[m.fieldMode].name !== "negative mass") {
tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field
powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
const removed = tech.removeTech("neutronium") //neutronum can get player stuck so it has to be removed if player has wrong field
if (removed) powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
}
if (m.energy < m.maxEnergy) m.energy = m.maxEnergy;
m.fieldRegen = tech.energyRegen; //0.001

View File

@@ -357,7 +357,7 @@ const powerUps = {
currentRerollCount: 0,
use(type) { //runs when you actually research a list of selections, type can be field, gun, or tech
if (tech.isJunkResearch && powerUps.research.currentRerollCount < 3) {
tech.addJunkTechToPool(tech.junkResearchNumber)
tech.addJunkTechToPool(tech.junkResearchNumber * 0.01)
} else {
powerUps.research.changeRerolls(-1)
}

View File

@@ -111,7 +111,7 @@ const spawn = {
powerUps.research.changeRerolls(-4)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 4<br>${powerUps.research.count}`)
} else {
tech.addJunkTechToPool(49)
tech.addJunkTechToPool(0.49)
}
spawn.randomLevelBoss(x, y);
return true
@@ -2323,11 +2323,15 @@ const spawn = {
me.friction = 0;
me.memory = 240
me.seePlayerFreq = 60
me.delay = 25 + 30 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
me.blinkRange = 235
me.grenadeDelay = 35 + 60 * simulation.CDScale
me.pulseRadius = 2 * Math.min(550, 220 + simulation.difficulty * 4)
if (false && 0.5 < Math.random()) {
me.grenadeDelay = 260
} else {
me.grenadeDelay = 100
}
me.pulseRadius = 1.4 * Math.min(550, 220 + simulation.difficulty * 4)
me.delay = 30 + 35 * simulation.CDScale;
me.nextBlinkCycle = me.delay;
spawn.shield(me, x, y, 1);
me.onDamage = function() {
// this.cd = simulation.cycle + this.delay;

View File

@@ -53,8 +53,8 @@
}
const totalRemoved = tech.tech[index].count
simulation.makeTextLog(`<span class='color-var'>tech</span>.removeTech("<span class='color-text'>${tech.tech[index].name}</span>")`)
tech.tech[index].count = 0;
tech.tech[index].remove();
tech.tech[index].count = 0;
simulation.updateTechHUD();
tech.tech[index].isLost = true
simulation.updateTechHUD();
@@ -73,15 +73,40 @@
// if (tech.tech[i].isLore && tech.tech[i].count === 0) tech.tech.splice(i, 1)
// }
// },
addJunkTechToPool(num = 1) {
addJunkTechToPool(chance) { //chance is number between 0-1
// { //count JUNK
// let count = 0
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && tech.tech[i].isJunk && tech.tech[i].frequency > 0) count += tech.tech[i].frequency
// }
// console.log(count)
// }
// { //count not JUNK
// let count = 0
// for (let i = 0, len = tech.tech.length; i < len; i++) {
// if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk && tech.tech[i].frequency > 0) count++
// }
// console.log(count)
// }
// count total non junk tech
let count = 0
for (let i = 0, len = tech.tech.length; i < len; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].allowed() && !tech.tech[i].isJunk) count += tech.tech[i].frequency
}
//make an array for possible junk tech to add
let options = [];
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count < tech.tech[i].maxCount && tech.tech[i].isJunk) options.push(i);
}
//add random array options to tech pool
if (options.length) {
const num = chance * count //scale number added
for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
}
simulation.makeTextLog(`<span class='color-var'>tech</span>.tech.push(${num} <span class='color-text'>JUNK</span>)`)
return num
} else {
return 0
}
},
removeJunkTechFromPool(num = 1) {
for (let j = 0; j < num; j++) {
@@ -506,7 +531,7 @@
{
name: "desublimated ammunition",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Deposition_(phase_transition)' class="link">desublimated ammunition</a>`,
description: "every other <strong>crouched</strong> shot uses no <strong class='color-ammo'>ammo</strong><br><strong>+6</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "every other <strong>crouched</strong> shot uses no <strong class='color-ammo'>ammo</strong><br><strong>+6%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -517,32 +542,18 @@
requires: "",
effect() {
tech.isCrouchAmmo = true
tech.addJunkTechToPool(6)
this.refundAmount += tech.addJunkTechToPool(0.06)
},
refundAmount: 0,
remove() {
tech.isCrouchAmmo = false;
if (this.count > 0) tech.removeJunkTechFromPool(6)
tech.isExtraChoice = false;
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
// <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
// maxCount: 9,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return true
// },
// requires: "",
// effect() {
// tech.bonusEnergy += 0.6
// m.setMaxEnergy()
// tech.addJunkTechToPool(10)
// },
// remove() {
// tech.bonusEnergy = 0;
// m.setMaxEnergy()
// if (this.count > 0) tech.removeJunkTechFromPool(10)
// }
{
name: "gun turret",
description: "reduce <strong class='color-harm'>harm</strong> by <strong>55%</strong> when <strong>crouching</strong>",
@@ -2470,7 +2481,7 @@
},
{
name: "overcharge",
description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br><strong>+10</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br><strong>+10%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9,
count: 0,
frequency: 1,
@@ -2482,17 +2493,21 @@
effect() {
tech.bonusEnergy += 0.6
m.setMaxEnergy()
tech.addJunkTechToPool(10)
this.refundAmount += tech.addJunkTechToPool(0.1)
},
refundAmount: 0,
remove() {
tech.bonusEnergy = 0;
m.setMaxEnergy()
if (this.count > 0) tech.removeJunkTechFromPool(10)
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
name: "Maxwell's demon",
description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br><strong>+18</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br><strong>+18%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 2,
@@ -2503,11 +2518,15 @@
requires: "energy above your max",
effect() {
tech.overfillDrain = 0.85 //70% = 1-(1-0.75)/(1-0.15) //92% = 1-(1-0.75)/(1-0.87)
tech.addJunkTechToPool(18)
this.refundAmount += tech.addJunkTechToPool(0.18)
},
refundAmount: 0,
remove() {
tech.overfillDrain = 0.7
if (this.count > 0) tech.removeJunkTechFromPool(18)
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
@@ -3021,7 +3040,7 @@
},
{
name: "pseudoscience",
description: "<span style = 'font-size:94%;'>when <strong>selecting</strong> a power up, <strong class='color-r'>research</strong> <strong>3</strong> times</span><br>for <strong>free</strong>, but add <strong>0-3</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
description: "<span style = 'font-size:94%;'>when <strong>selecting</strong> a power up, <strong class='color-r'>research</strong> <strong>3</strong> times</span><br>for <strong>free</strong>, but add <strong>0-3%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3072,7 +3091,7 @@
},
{
name: "abiogenesis",
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
description: `at the start of a level spawn a 2nd <strong>boss</strong><br>use ${powerUps.orb.research(4)}or add <strong>49%</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool`,
maxCount: 1,
count: 0,
frequency: 2,
@@ -3114,9 +3133,9 @@
frequency: 1,
frequencyDefault: 1,
allowed() {
return tech.duplicateChance
return true
},
requires: "replication",
requires: "",
effect() {
tech.isMetaAnalysis = true
},
@@ -3126,7 +3145,7 @@
},
{
name: "replication",
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+30</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+30%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9,
count: 0,
frequency: 1,
@@ -3139,12 +3158,16 @@
tech.duplicateChance += 0.1
powerUps.setDupChance(); //needed after adjusting duplication chance
if (!build.isExperimentSelection) simulation.circleFlare(0.1);
tech.addJunkTechToPool(30)
this.refundAmount += tech.addJunkTechToPool(0.3)
},
refundAmount: 0,
remove() {
tech.duplicateChance = 0
powerUps.setDupChance(); //needed after adjusting duplication chance
if (this.count > 1) tech.removeJunkTechFromPool(30)
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
@@ -3515,11 +3538,15 @@
requires: "not determinism",
effect: () => {
tech.isExtraChoice = true;
tech.addJunkTechToPool(5)
this.refundAmount += tech.addJunkTechToPool(0.05)
},
refundAmount: 0,
remove() {
tech.isExtraChoice = false;
if (this.count > 0) tech.removeJunkTechFromPool(5)
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
@@ -3584,7 +3611,7 @@
},
{
name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+31%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3597,12 +3624,13 @@
level.difficultyDecrease(simulation.difficultyMode)
// simulation.difficulty<span class='color-symbol'>-=</span>
simulation.makeTextLog(`level.difficultyDecrease(simulation.difficultyMode)`)
tech.addJunkTechToPool(31)
this.refundAmount += tech.addJunkTechToPool(0.31)
// for (let i = 0; i < tech.junk.length; i++) tech.tech.push(tech.junk[i])
},
refundAmount: 0,
remove() {
if (this.count > 0) {
tech.removeJunkTechFromPool(31)
if (this.refundAmount > 0) tech.removeJunkTechFromPool(this.refundAmount)
level.difficultyIncrease(simulation.difficultyMode)
}
}
@@ -3734,9 +3762,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil
return tech.haveGunCheck("nail gun") && !tech.nailInstantFireRate && !tech.isIceCrystals && !tech.isRivets && !tech.nailRecoil && !tech.nailRecoil
},
requires: "nail gun, not ice crystal, rivets, or pneumatic actuator",
requires: "nail gun, not ice crystal, rivets, rotary cannon, or pneumatic actuator",
effect() {
tech.isNeedles = true
for (i = 0, len = b.guns.length; i < len; i++) { //find which gun
@@ -4582,7 +4610,7 @@
},
{
name: "booby trap",
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br><strong>+53</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br><strong>+53%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -4595,11 +4623,15 @@
effect() {
tech.isMineDrop = true;
if (tech.isMineDrop) b.mine(m.pos, { x: 0, y: 0 }, 0)
tech.addJunkTechToPool(53)
this.refundAmount += tech.addJunkTechToPool(0.53)
},
refundAmount: 0,
remove() {
tech.isMineDrop = false;
if (this.count > 0) tech.removeJunkTechFromPool(53)
if (this.count > 0 && this.refundAmount > 0) {
tech.removeJunkTechFromPool(this.refundAmount)
this.refundAmount = 0
}
}
},
{
@@ -6316,7 +6348,7 @@
},
{
name: "symbiosis",
description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>1</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1-2</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>",
description: "after a <strong>mob</strong> <strong>dies</strong>, lose <strong>1</strong> max <strong class='color-h'>health</strong><br><strong>bosses</strong> spawn <strong>1</strong> extra <strong class='color-m'>tech</strong> after they <strong>die</strong>",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -6890,6 +6922,43 @@
// },
// remove() {}
// },
{
name: "planetesimals",
description: `spawn a <strong class='color-m'>tech</strong> and play <strong>planetesimals</strong>,<br>an annoying asteroids game with Newtonian physics`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isExperimentHide: true,
isJunk: true,
allowed() {
return true
},
requires: "",
effect() {
window.open('../../planetesimals/index.html', '_blank')
powerUps.spawn(m.pos.x, m.pos.y, "tech");
},
remove() {}
},
{
name: "facsimile",
description: `inserts a copy of your current level into the level list`,
maxCount: 1,
count: 0,
frequency: 0,
isNonRefundable: true,
isExperimentHide: true,
isJunk: true,
allowed() {
return true
},
requires: "",
effect() {
level.levels.splice(level.onLevel, 0, level.levels[level.onLevel]);
},
remove() {}
},
{
name: "negative friction",
description: "when you touch walls you speed up instead of slowing down. It's kinda fun.",
@@ -7872,7 +7941,7 @@
},
{
name: "expert system",
description: "spawn a <strong class='color-m'>tech</strong> power up<br><strong>+64</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
description: "spawn a <strong class='color-m'>tech</strong> power up<br><strong>+64%</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9,
count: 0,
frequency: 0,
@@ -7885,7 +7954,7 @@
requires: "",
effect() {
powerUps.spawn(m.pos.x, m.pos.y, "tech");
tech.addJunkTechToPool(64)
tech.addJunkTechToPool(0.64)
},
remove() {}
},

View File

@@ -1,14 +1,34 @@
******************************************************** NEXT PATCH **************************************************
tech: neutronium - 90% harm reduce while field is active, 33% slower move speed
(requires negative mass field)
tech: charmed baryon - 0 cost wormhole, 33% slower move speed
harpoon tech: reticulum now always fires extra harpoons even if there are no targets
tech.removeTech() method has been improved
JUNK tech: facsimile - copy current level and insert into level queue
JUNK tech: planetesimals - spawn a tech, and play planetesimals, an annoying asteroids like game with realistic physics
tech that previously added 1 junk tech now adds 1% (of current non-JUNK tech options)
the percent values may seem like more but I actually lowered the JUNK chance about 10%
meta-analysis no longer requires replication - (if you choose a JUNK tech get a random tech and 3 research)
symbiosis: only gives 1 bonus tech (was 1 or 2)
blink boss rebalanced (it's easier, and has two modes)
bug fixes
******************************************************** TODO ********************************************************
fields weak in late game?
Pilot wave?
buff with cool tech options from other fields
buff with another damage scaling tech
stand wave and diamagnetism
buff end stage tech for these
tech perfect diamagnetism - holding the field makes the field slowly travel forward
could be base effect
make a field that just fires your first gun
if they have to share a cooldown give 50% shorter fire CD
bug - death while paused crashes game?
tech: aerodynamic heating - railgun rods super heat the air around it doing AoE damage