diff --git a/.DS_Store b/.DS_Store
index 461e335..2bf9398 100644
Binary files a/.DS_Store and b/.DS_Store differ
diff --git a/js/bullet.js b/js/bullet.js
index 0e117bd..73f5c09 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -2109,10 +2109,10 @@ const b = {
onEnd() {},
do() {
if (this.endCycle < simulation.cycle + 1) this.isWave = false
- if (Matter.Query.point(map, this.position).length) { //check if inside map
+ if (Matter.Query.point(map, this.position).length) { //check if inside map //|| Matter.Query.point(body, this.position).length
this.isBranch = true;
this.do = () => { if (this.endCycle < simulation.cycle + 1) this.isWave = false }
- } else { //check if inside a body
+ } else { //check if inside a mob
for (let i = 0, len = mob.length; i < len; i++) {
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position))
const radius = mob[i].radius + tech.extruderRange / 2
@@ -2387,14 +2387,14 @@ const b = {
}
if (tech.isLaserPush) { //push mobs away
const index = path.length - 1
- Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
- const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.006 * push * Math.min(6, best.who.mass))
+ Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.95, y: best.who.velocity.y * 0.95 });
+ const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.005 * push * Math.min(6, best.who.mass))
Matter.Body.applyForce(best.who, path[index], force)
}
} else if (tech.isLaserPush && best.who.classType === "body") {
const index = path.length - 1
- Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
- const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.006 * push * Math.min(6, best.who.mass))
+ Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.95, y: best.who.velocity.y * 0.95 });
+ const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.005 * push * Math.min(6, best.who.mass))
Matter.Body.applyForce(best.who, path[index], force)
}
};
@@ -6996,7 +6996,7 @@ const b = {
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
y: 7.5 * Math.sin(m.angle - Math.PI / 2)
}
- const dmg = 0.66 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
+ const dmg = 0.70 * tech.laserDamage // 3.5 * 0.55 = 200% more damage
const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
const eye = {
x: m.pos.x + 15 * Math.cos(m.angle),
diff --git a/js/engine.js b/js/engine.js
index 6129600..855a607 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -198,7 +198,7 @@ function collisionChecks(event) {
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
if (v > 9) {
if (tech.blockDmg) { //electricity
- console.log("hi")
+ // console.log("hi")
Matter.Body.setVelocity(mob[k], { x: 0.5 * mob[k].velocity.x, y: 0.5 * mob[k].velocity.y });
if (tech.isBlockRadiation && !mob[k].isShielded && !mob[k].isMobBullet) {
mobs.statusDoT(mob[k], tech.blockDmg * m.dmgScale * 4 / 12, 360) //200% increase -> x (1+2) //over 7s -> 360/30 = 12 half seconds -> 3/12
diff --git a/js/index.js b/js/index.js
index 89aa3e2..bbb4704 100644
--- a/js/index.js
+++ b/js/index.js
@@ -187,7 +187,7 @@ window.addEventListener('load', () => {
const canvas = document.getElementById("canvas");
//using "const" causes problems in safari when an ID shares the same name.
const ctx = canvas.getContext("2d");
-// const ctx = canvas.getContext('2d', { alpha: false }); //optimization, but doesn't work
+// const ctx = canvas.getContext('2d', { alpha: false }); //optimization, this works if you wipe with the background color of each level
document.body.style.backgroundColor = "#fff";
@@ -278,7 +278,7 @@ ${simulation.isCheating ? "
lore disabled": ""}
if (tech.tech[i].count > 0) {
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
if (tech.tech[i].isNonRefundable) {
- text += `
${tech.tech[i].link} ${techCountText}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
`
+ text += `${tech.tech[i].link} ${techCountText}
${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}
`
} else if (tech.tech[i].isFieldTech) {
text += `
diff --git a/js/level.js b/js/level.js
index b859f56..c7c8af0 100644
--- a/js/level.js
+++ b/js/level.js
@@ -17,10 +17,10 @@ const level = {
if (level.levelsCleared === 0) { //this code only runs on the first level
// // simulation.isHorizontalFlipped = true
// m.addHealth(Infinity)
- // m.setField("standing wave")
+ // m.setField("time dilation")
// b.giveGuns("nail gun")
// tech.giveTech("closed timelike curve")
- // tech.giveTech("irradiated nails")
+ // tech.giveTech("retrocausality")
// tech.giveTech("pneumatic actuator")
// tech.giveTech("6s half-life")
// for (let i = 0; i < 10; i++) tech.giveTech("replication")
@@ -36,8 +36,8 @@ const level = {
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
// simulation.enableConstructMode() //used to build maps in testing mode
// level.testing();
- // level.reactor(); //not in rotation, used for testing
- // spawn.timeBoss(1900, -500)
+ // spawn.snakeSpitBoss(1900, -500)
+ // level.reservoir(); //not in rotation, used for testing
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
// powerUps.research.changeRerolls(3000)
@@ -2681,7 +2681,7 @@ const level = {
// spawn.shieldingBoss(1700, -500)
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
- // for (let i = 0; i < 4; i++) spawn.starter(1900, -500)
+ for (let i = 0; i < 4; i++) spawn.starter(1900, -500)
// spawn.pulsar(1900, -500)
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
// mob[mob.length - 1].isShielded = true
@@ -3294,8 +3294,8 @@ const level = {
}
//2nd floor
- spawn.mapVertex(855, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
- spawn.mapVertex(-687, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
+ spawn.mapVertex(-687, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
+ spawn.mapVertex(855, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
//2nd floor right building
// spawn.mapRect(550, -3050, 600, 175);
@@ -3328,11 +3328,11 @@ const level = {
spawn.randomMob(950, -1725, 0.1);
spawn.randomMob(-725, -1775, 0.1);
spawn.randomMob(-200, -2075, 0);
+ spawn.randomMob(-550, -3500, -0.2);
spawn.randomMob(375, -2125, 0);
- spawn.randomMob(1025, -3200, 0);
- spawn.randomMob(-550, -3500, 0);
spawn.randomMob(-700, -2450, -0.1);
spawn.randomMob(-1175, -2775, -0.1);
+ spawn.randomMob(1025, -3200, -0.2);
spawn.randomMob(-525, -3750, -0.2);
spawn.randomMob(1350, -2075, -0.3);
spawn.randomMob(1775, 1000, -0.4);
diff --git a/js/mob.js b/js/mob.js
index 0197f71..e18a81f 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1119,7 +1119,7 @@ const mobs = {
if (tech.iceIXOnDeath && this.isSlowed) {
for (let i = 0, len = 2 * Math.sqrt(Math.min(this.mass, 25)) * tech.iceIXOnDeath; i < len; i++) b.iceIX(3, Math.random() * 2 * Math.PI, this.position)
}
- if (tech.deathSpawnsFromBoss || (tech.deathSpawns && this.isDropPowerUp)) {
+ if (tech.deathSpawnsFromBoss || tech.deathSpawns) {
const spawns = tech.deathSpawns + tech.deathSpawnsFromBoss
const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
for (let i = 0; i < len; i++) {
@@ -1130,6 +1130,22 @@ const mobs = {
});
}
}
+
+ if (tech.isDeathSkipTime && !m.isBodiesAsleep) {
+ requestAnimationFrame(() => {
+ simulation.timePlayerSkip(this.isBoss ? 45 : 25)
+ simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
+ }); //wrapping in animation frame prevents errors, probably
+
+ // if (tech.isFlipFlopOn) {
+ // m.rewind(this.isBoss ? 45 : 25)
+ // } else {
+ // requestAnimationFrame(() => {
+ // simulation.timePlayerSkip(this.isBoss ? 45 : 25)
+ // simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
+ // }); //wrapping in animation frame prevents errors, probably
+ // }
+ }
if (tech.isEnergyLoss) m.energy *= 0.75;
powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
diff --git a/js/player.js b/js/player.js
index 615ae94..dfd14f6 100644
--- a/js/player.js
+++ b/js/player.js
@@ -2529,6 +2529,25 @@ const m = {
this.rewindCount = 0
m.grabPowerUpRange2 = 300000
m.hold = function() {
+
+ m.grabPowerUp();
+
+ // //grab power ups
+ // for (let i = 0, len = powerUp.length; i < len; ++i) {
+ // if (
+ // Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
+ // !simulation.isChoosing &&
+ // (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
+ // ) {
+ // powerUps.onPickUp(powerUp[i]);
+ // powerUp[i].effect();
+ // Matter.Composite.remove(engine.world, powerUp[i]);
+ // powerUp.splice(i, 1);
+ // break; //because the array order is messed up after splice
+ // }
+ // }
+
+
if (m.isHolding) {
m.drawHold(m.holdingTarget);
m.holding();
@@ -2568,20 +2587,6 @@ const m = {
} else {
m.undoCrouch()
}
- //grab power ups
- for (let i = 0, len = powerUp.length; i < len; ++i) {
- if (
- Vector.magnitudeSquared(Vector.sub(m.pos, powerUp[i].position)) < 100000 &&
- !simulation.isChoosing &&
- (powerUp[i].name !== "heal" || m.health !== m.maxHealth || tech.isOverHeal)
- ) {
- powerUps.onPickUp(powerUp[i]);
- powerUp[i].effect();
- Matter.Composite.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
- break; //because the array order is messed up after splice
- }
- }
if (!(this.rewindCount % 30)) {
if (tech.isRewindBot) {
for (let i = 0; i < tech.isRewindBot; i++) {
@@ -2594,8 +2599,6 @@ const m = {
const who = bullet[bullet.length - 1]
who.endCycle = simulation.cycle + 60
}
-
-
}
}
}
@@ -2612,7 +2615,7 @@ const m = {
} else {
m.fieldFire = true;
m.isBodiesAsleep = false;
- m.drain = 0.003
+ m.drain = 0.0025
m.hold = function() {
if (m.isHolding) {
m.wakeCheck();
diff --git a/js/powerup.js b/js/powerup.js
index a726a19..b4eca9b 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -137,7 +137,7 @@ const powerUps = {
},
doDefault() {
//draw power ups
- ctx.globalAlpha = 0.4 * Math.sin(m.cycle * 0.15) + 0.6;
+ ctx.globalAlpha = 0.4 * Math.sin(simulation.cycle * 0.15) + 0.6;
for (let i = 0, len = powerUp.length; i < len; ++i) {
ctx.beginPath();
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
@@ -237,7 +237,6 @@ const powerUps = {
}
},
choose(type, index) {
- console.log('choose')
if (type === "gun") {
b.giveGuns(index)
let text = `b.giveGuns("${b.guns[index].name}")`
@@ -356,7 +355,7 @@ const powerUps = {
// document.body.style.overflow = "hidden"
// if (m.alive){}
if (simulation.paused) requestAnimationFrame(cycle);
- simulation.paused = false;
+ if (m.alive) simulation.paused = false;
simulation.isChoosing = false; //stops p from un pausing on key down
build.unPauseGrid()
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
@@ -1080,7 +1079,7 @@ const powerUps = {
},
pauseEjectTech(index) {
if ((tech.isPauseEjectTech || simulation.testing) && !simulation.isChoosing && !tech.tech[index].isNonRefundable) {
- if (Math.random() < 0.1 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
+ if (Math.random() < 0.16 || tech.tech[index].isFromAppliedScience || (tech.tech[index].bonusResearch !== undefined && tech.tech[index].bonusResearch > powerUps.research.count)) {
tech.removeTech(index)
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
} else {
diff --git a/js/simulation.js b/js/simulation.js
index 80ab6aa..9ef1c34 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -521,9 +521,7 @@ const simulation = {
}
}, len * swapPeriod);
},
- wipe() {
- ctx.clearRect(0, 0, canvas.width, canvas.height);
- },
+ wipe() {}, //set in simulation.startGame
gravity() {
function addGravity(bodies, magnitude) {
for (var i = 0; i < bodies.length; i++) {
@@ -1049,7 +1047,7 @@ const simulation = {
if (m.lastKillCycle + 300 > m.cycle) { //effects active for 5 seconds after killing a mob
if (tech.isEnergyRecovery && m.immuneCycle < m.cycle) m.energy += m.maxEnergy * 0.05
- if (tech.isHealthRecovery) m.addHealth(0.01 * m.maxHealth)
+ if (tech.isHealthRecovery) m.addHealth(0.005 * m.maxHealth)
}
if (!(m.cycle % 420)) { //once every 7 seconds
diff --git a/js/spawn.js b/js/spawn.js
index 8f12bd5..37f9ba8 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1,10 +1,11 @@
//main object for spawning things in a level
const spawn = {
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
- // other bosses: suckerBoss, laserBoss, tetherBoss, mantisBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool
- randomBossList: ["shieldingBoss", "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
- "powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
- "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss"
+ // other bosses: suckerBoss, laserBoss, tetherBoss, bounceBoss, sprayBoss //these need a particular level to work so they are not included in the random pool
+ randomBossList: [
+ "orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
+ "powerUpBoss", "powerUpBossBaby", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
+ "snakeBoss", "snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss", "shieldingBoss", "timeSkipBoss"
],
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
bossTypeSpawnIndex: 0, //increases as the boss type cycles
@@ -19,7 +20,7 @@ const spawn = {
pickList: ["starter", "starter"],
fullPickList: [
"hopper", "hopper", "hopper",
- "slasher", "slasher", "hopper",
+ "slasher", "slasher", "slasher",
"stabber", "stabber", "stabber",
"springer", "springer", "springer",
"shooter", "shooter",
@@ -2028,7 +2029,6 @@ const spawn = {
me.seePlayerFreq = 300;
const springStiffness = 0.00008; //simulation.difficulty
const springDampening = 0.01;
-
me.springTarget = {
x: me.position.x,
y: me.position.y
@@ -2055,11 +2055,9 @@ const spawn = {
Composite.add(engine.world, cons[cons.length - 1]);
cons[len2].length = 100 + 1.5 * radius;
me.cons2 = cons[len2];
-
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.invulnerabilityCountDown = 0
-
me.do = function() {
this.checkStatus();
this.gravity();
@@ -2069,7 +2067,6 @@ const spawn = {
ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
ctx.fillStyle = "#222";
ctx.fill();
-
this.seePlayerCheck()
// this.seePlayerByHistory()
if (this.isInvulnerable) {
@@ -2202,7 +2199,6 @@ const spawn = {
}
}
};
-
me.onDeath = function() {
this.removeCons();
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -2215,7 +2211,6 @@ const spawn = {
}
}
};
-
const sideLength = 80 // distance between each node mob
const nodes = 3
const angle = 2 * Math.PI / nodes
@@ -2255,7 +2250,6 @@ const spawn = {
}
};
}
-
const stiffness = 0.01
const damping = 0.1
for (let i = 1; i < nodes; ++i) { //attach to center mob
@@ -2287,88 +2281,86 @@ const spawn = {
}
spawn.allowShields = true;
},
- timeSkipBoss(x, y, radius = 55) {
- mobs.spawn(x, y, 6, radius, '#000');
- let me = mob[mob.length - 1];
- me.isBoss = true;
- // me.stroke = "transparent"; //used for drawSneaker
- me.timeSkipLastCycle = 0
- me.eventHorizon = 1800; //required for black hole
- me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
- me.accelMag = 0.0004 * simulation.accelScale;
- // me.frictionAir = 0.005;
- // me.memory = 1600;
- // Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
- Matter.Body.setDensity(me, 0.0005 + 0.00018 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
- spawn.shield(me, x, y, 1);
+ // timeSkipBoss(x, y, radius = 55) {
+ // mobs.spawn(x, y, 6, radius, '#000');
+ // let me = mob[mob.length - 1];
+ // me.isBoss = true;
+ // // me.stroke = "transparent"; //used for drawSneaker
+ // me.timeSkipLastCycle = 0
+ // me.eventHorizon = 1800; //required for black hole
+ // me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
+ // me.accelMag = 0.0004 * simulation.accelScale;
+ // // me.frictionAir = 0.005;
+ // // me.memory = 1600;
+ // // Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
+ // Matter.Body.setDensity(me, 0.0005 + 0.00018 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ // spawn.shield(me, x, y, 1);
+ // me.onDeath = function() {
+ // //applying forces to player doesn't seem to work inside this method, not sure why
+ // powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ // };
+ // me.do = function() {
+ // //keep it slow, to stop issues from explosion knock backs
+ // if (this.speed > 8) {
+ // Matter.Body.setVelocity(this, {
+ // x: this.velocity.x * 0.99,
+ // y: this.velocity.y * 0.99
+ // });
+ // }
+ // this.seePlayerCheck();
+ // this.checkStatus();
+ // this.attraction()
+ // if (!simulation.isTimeSkipping) {
+ // const compress = 1
+ // if (this.timeSkipLastCycle < simulation.cycle - compress &&
+ // Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
+ // this.timeSkipLastCycle = simulation.cycle
+ // simulation.timeSkip(compress)
+ // this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})`
+ // this.stroke = "#014"
+ // this.isShielded = false;
+ // this.isDropPowerUp = true;
+ // this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
- me.onDeath = function() {
- //applying forces to player doesn't seem to work inside this method, not sure why
- powerUps.spawnBossPowerUp(this.position.x, this.position.y)
- };
- me.do = function() {
- //keep it slow, to stop issues from explosion knock backs
- if (this.speed > 8) {
- Matter.Body.setVelocity(this, {
- x: this.velocity.x * 0.99,
- y: this.velocity.y * 0.99
- });
- }
- this.seePlayerCheck();
- this.checkStatus();
- this.attraction()
- if (!simulation.isTimeSkipping) {
- const compress = 1
- if (this.timeSkipLastCycle < simulation.cycle - compress &&
- Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
- this.timeSkipLastCycle = simulation.cycle
- simulation.timeSkip(compress)
+ // ctx.beginPath();
+ // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ // ctx.fillStyle = "#fff";
+ // ctx.globalCompositeOperation = "destination-in"; //in or atop
+ // ctx.fill();
+ // ctx.globalCompositeOperation = "source-over";
+ // ctx.beginPath();
+ // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ // ctx.clip();
- this.fill = `rgba(0,0,0,${0.4+0.6*Math.random()})`
- this.stroke = "#014"
- this.isShielded = false;
- this.isDropPowerUp = true;
- this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
+ // // ctx.beginPath();
+ // // ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
+ // // ctx.fillStyle = "#000";
+ // // ctx.fill();
+ // // ctx.strokeStyle = "#000";
+ // // ctx.stroke();
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
- ctx.fillStyle = "#fff";
- ctx.globalCompositeOperation = "destination-in"; //in or atop
- ctx.fill();
- ctx.globalCompositeOperation = "source-over";
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
- ctx.clip();
-
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
- // ctx.fillStyle = "#000";
- // ctx.fill();
- // ctx.strokeStyle = "#000";
- // ctx.stroke();
-
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
- // ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
- // ctx.fill();
- // ctx.strokeStyle = "#000";
- // ctx.stroke();
- } else {
- this.isShielded = true;
- this.isDropPowerUp = false;
- this.seePlayer.recall = false
- this.fill = "transparent"
- this.stroke = "transparent"
- this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob; //can't touch bullets
- ctx.beginPath();
- ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
- ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
- ctx.fill();
- }
- }
- }
- },
+ // // ctx.beginPath();
+ // // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ // // ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
+ // // ctx.fill();
+ // // ctx.strokeStyle = "#000";
+ // // ctx.stroke();
+ // } else {
+ // this.isShielded = true;
+ // this.isDropPowerUp = false;
+ // this.seePlayer.recall = false
+ // this.fill = "transparent"
+ // this.stroke = "transparent"
+ // this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob; //can't touch bullets
+ // ctx.beginPath();
+ // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ // ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
+ // ctx.fill();
+ // }
+ // }
+ // }
+ // },
beamer(x, y, radius = 15 + Math.ceil(Math.random() * 15)) {
mobs.spawn(x, y, 4, radius, "rgb(255,0,190)");
let me = mob[mob.length - 1];
@@ -3931,7 +3923,7 @@ const spawn = {
me.isBoss = true;
Matter.Body.setDensity(me, 0.001); //normal is 0.001
me.inertia = Infinity;
- me.damageReduction = 0.04 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0.06 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false
me.frictionAir = 0.01
@@ -3974,8 +3966,8 @@ const spawn = {
const unit = Vector.sub(player.position, this.position)
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(unit), 0.1));
} else {
- if (Math.abs(this.velocity.y) < 9) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.02 });
- if (Math.abs(this.velocity.x) < 6.5) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.02, y: this.velocity.y });
+ if (Math.abs(this.velocity.y) < 10) Matter.Body.setVelocity(this, { x: this.velocity.x, y: this.velocity.y * 1.02 });
+ if (Math.abs(this.velocity.x) < 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.02, y: this.velocity.y });
}
if (this.isInvulnerable) {
@@ -5138,7 +5130,7 @@ const spawn = {
me.maxCycles = 110;
me.frictionStatic = 0;
me.friction = 0;
- me.frictionAir = 0.5;
+ me.frictionAir = 1;
// me.homePosition = { x: x, y: y };
spawn.shield(me, x, y, 1);
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
@@ -5153,7 +5145,7 @@ const spawn = {
};
me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
- // this.armor();
+ Matter.Body.rotate(this, 0.003) //gently spin around
this.checkStatus();
ctx.beginPath(); //draw cycle timer
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
@@ -5186,6 +5178,73 @@ const spawn = {
}
};
},
+ timeSkipBoss(x, y, radius = 50) {
+ mobs.spawn(x, y, 15, radius, "rgb(150, 150, 255)");
+ let me = mob[mob.length - 1];
+ me.isBoss = true;
+ me.eventHorizon = 0; //set in mob loop
+ me.frictionStatic = 0;
+ me.friction = 0;
+ me.frictionAir = 0.004;
+ me.accelMag = 0.0001 + 0.00003 * simulation.accelScale
+ spawn.shield(me, x, y, 1);
+ spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random(), true)
+
+ Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger
+ me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.startingDamageReduction = me.damageReduction
+ me.isInvulnerable = false
+ me.onDeath = function() {
+ powerUps.spawnBossPowerUp(this.position.x, this.position.y)
+ // requestAnimationFrame(() => { simulation.timePlayerSkip(120) }); //wrapping in animation frame prevents errors, probably
+ };
+ me.onDamage = function() {
+ //find side of mob closest to player
+ //causes lag for foam,laser too many seekers //maybe scale chance with dmg
+ // const where = Vector.add(this.position, Vector.mult(Vector.normalise(Vector.sub(m.pos, this.position)), this.radius + 10))
+ // spawn.seeker(where.x, where.y); //give the bullet a rotational velocity as if they were attached to a vertex
+ };
+ me.do = function() {
+ this.seePlayerByHistory();
+ this.attraction();
+ this.checkStatus();
+ this.eventHorizon = 950 + 170 * Math.sin(simulation.cycle * 0.005)
+ if (!simulation.isTimeSkipping) {
+ if (Vector.magnitude(Vector.sub(this.position, m.pos)) < this.eventHorizon) {
+ this.attraction();
+ this.damageReduction = this.startingDamageReduction
+ this.isInvulnerable = false
+ if (!(simulation.cycle % 15)) requestAnimationFrame(() => {
+ simulation.timePlayerSkip(8)
+ simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations
+ }); //wrapping in animation frame prevents errors, probably
+
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ ctx.fillStyle = "#fff";
+ ctx.globalCompositeOperation = "destination-in"; //in or atop
+ ctx.fill();
+ ctx.globalCompositeOperation = "source-over";
+ ctx.beginPath();
+ ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
+ // ctx.stroke();
+ ctx.clip();
+ } else {
+ this.damageReduction = 0
+ this.isInvulnerable = true
+ //prevents other things from being drawn later on in the draw cycle
+ requestAnimationFrame(() => {
+ simulation.camera();
+ ctx.beginPath(); //gets rid of already draw shapes
+ ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI, false); //part you can't see
+ ctx.fillStyle = color.background;
+ ctx.fill();
+ ctx.restore();
+ })
+ }
+ }
+ };
+ },
streamBoss(x, y, radius = 110) {
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
let me = mob[mob.length - 1];
@@ -5412,10 +5471,14 @@ const spawn = {
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1];
me.isBoss = true;
- me.accelMag = 0.0001 + 0.0002 * Math.sqrt(simulation.accelScale)
+ me.accelMag = 0.0003 + 0.0002 * Math.sqrt(simulation.accelScale)
me.memory = 250;
me.laserRange = 500;
Matter.Body.setDensity(me, 0.0022 + 0.00022 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.startingDamageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0
+ me.isInvulnerable = true
+
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
@@ -5428,9 +5491,7 @@ const spawn = {
};
me.canFire = false;
me.closestVertex1 = 0;
- // me.closestVertex2 = 1;
me.cycle = 0
- me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
// this.armor();
this.seePlayerByHistory()
@@ -5439,7 +5500,7 @@ const spawn = {
this.cycle++
if (this.seePlayer.recall && ((this.cycle % 10) === 0)) {
if (this.canFire) {
- if (this.cycle > 120) {
+ if (this.cycle > 100) {
this.cycle = 0
this.canFire = false
// Matter.Body.setAngularVelocity(this, 0.1)
@@ -5450,7 +5511,7 @@ const spawn = {
}
spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 6)
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
- const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10)
+ const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -13)
Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + velocity.x,
y: this.velocity.y + velocity.y
@@ -5482,14 +5543,29 @@ const spawn = {
// }
}
}
+ if (this.isInvulnerable) {
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(255,255,255,0.7)";
+ ctx.stroke();
+ }
};
//extra space to give head room
angle -= 0.1
mag -= 10
+ let previousTailID = 0
+
for (let i = 0; i < nodes; ++i) {
angle -= 0.15 + i * 0.008
mag -= 5
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
+ if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
+ mob[mob.length - 1].previousTailID = previousTailID
+ previousTailID = mob[mob.length - 1].id
}
this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01);
@@ -5530,36 +5606,46 @@ const spawn = {
mobs.spawn(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 8, radius, color1); //"rgb(55,170,170)"
let me = mob[mob.length - 1];
me.isBoss = true;
- me.accelMag = 0.00077 * simulation.accelScale;
+ me.accelMag = 0.0004 + 0.0003 * Math.sqrt(simulation.accelScale)
me.memory = 250;
me.laserRange = 500;
Matter.Body.setDensity(me, 0.00165 + 0.00011 * Math.sqrt(simulation.difficulty)); //extra dense //normal is 0.001 //makes effective life much larger
+ me.startingDamageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0
+ me.isInvulnerable = true
+
me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
- for (let i = 0; i < mob.length; i++) { //wake up tail mobs
- if (mob[i].isSnakeTail && mob[i].alive) {
- mob[i].isSnakeTail = false;
- mob[i].do = mob[i].doActive
- // mob[i].removeConsBB();
- }
- }
};
- me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.do = function() {
- // this.armor();
this.seePlayerByHistory()
this.checkStatus();
this.attraction();
this.harmZone();
+ if (this.isInvulnerable) {
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 20;
+ ctx.strokeStyle = "rgba(255,255,255,0.7)";
+ ctx.stroke();
+ }
};
//extra space to give head room
angle -= 0.1
mag -= 10
+ let previousTailID = 0
for (let i = 0; i < nodes; ++i) {
angle -= 0.15 + i * 0.008
mag -= 5
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
+ if (i === 0) mob[mob.length - 1].snakeHeadID = me.id
+ mob[mob.length - 1].previousTailID = previousTailID
+ previousTailID = mob[mob.length - 1].id
}
+
this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01);
for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors
@@ -5595,23 +5681,23 @@ const spawn = {
let me = mob[mob.length - 1];
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
me.accelMag = 0.0006 * simulation.accelScale;
- me.leaveBody = false;
+ me.leaveBody = Math.random() < 0.33 ? true : false;
me.showHealthBar = false;
me.isDropPowerUp = false;
- // Matter.Body.setDensity(me, 0.00004); //normal is 0.001
+ Matter.Body.setDensity(me, 0.003); //normal is 0.001
me.frictionAir = 0.015;
me.isSnakeTail = true;
me.stroke = "transparent"
me.onDeath = function() {
- // if (this.isSnakeTail) { //wake up tail mobs
- // for (let i = 0; i < mob.length; i++) {
- // if (mob[i].isSnakeTail && mob[i].alive) {
- // mob[i].isSnakeTail = false;
- // mob[i].do = mob[i].doActive
- // mob[i].removeConsBB();
- // }
- // }
- // }
+ setTimeout(() => {
+ for (let i = 0, len = mob.length; i < len; i++) {
+ if (this.id === mob[i].previousTailID && mob[i].alive) mob[i].death()
+ if (this.snakeHeadID === mob[i].id) {
+ mob[i].isInvulnerable = false
+ mob[i].damageReduction = mob[i].startingDamageReduction
+ }
+ }
+ }, 150);
};
me.do = function() {
this.checkStatus();
@@ -5666,7 +5752,7 @@ const spawn = {
me.stroke = "rgb(220,220,255)";
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
me.shield = true;
- me.damageReduction = 0.075 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
diff --git a/js/tech.js b/js/tech.js
index da34755..756e796 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -221,7 +221,8 @@ const tech = {
},
damageFromTech() {
let dmg = 1 //m.fieldDamage
- if (tech.isNoDraftPause) dmg *= 1.5
+ if (tech.isDeathSkipTime) dmg *= 1.67
+ if (tech.isNoDraftPause) dmg *= 1.4
if (tech.isTechDebt) dmg *= Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount)
if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
if (tech.OccamDamage) dmg *= tech.OccamDamage
@@ -556,7 +557,7 @@ const tech = {
{
name: "cache",
link: `cache`,
- description: `${powerUps.orb.ammo()} give 16x more ammo, but
you can't store any more ammo than that`,
+ description: `${powerUps.orb.ammo()} give 1600% more ammo, but
you can't store any more ammo than that`,
// ammo powerups always max out your gun,
// but the maximum ammo ti limited
// description: `${powerUps.orb.ammo()} give 13x more ammo, but
you can't store any more ammo than that`,
@@ -936,7 +937,7 @@ const tech = {
},
{
name: "reaction inhibitor",
- description: "mobs spawn with 11% less health",
+ description: "mobs spawn with 13% less health",
maxCount: 3,
count: 0,
frequency: 1,
@@ -946,7 +947,7 @@ const tech = {
},
requires: "", //"any mob death tech",
effect: () => {
- tech.mobSpawnWithHealth *= 0.89
+ tech.mobSpawnWithHealth *= 0.87
//set all mobs at full health to 0.85
for (let i = 0; i < mob.length; i++) {
@@ -957,6 +958,24 @@ const tech = {
tech.mobSpawnWithHealth = 1;
}
},
+ {
+ name: "propagator",
+ description: "increase damage by 67%, but after
mobs die lose 0.5 seconds of time",
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ tech.isDeathSkipTime = true
+ },
+ remove() {
+ tech.isDeathSkipTime = false
+ }
+ },
{
name: "decorrelation",
description: "reduce harm by 70% after not activating
your gun or field for 2 seconds",
@@ -1772,6 +1791,24 @@ const tech = {
m.eyeFillColor = 'transparent'
}
},
+ // {
+ // name: "spacetime interval",
+ // description: "increase damage by 93%, but after mobs die
move into the past / future while ON / OFF",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 4,
+ // frequencyDefault: 4,
+ // allowed() {
+ // return tech.isFlipFlop || tech.isRelay
+ // },
+ // requires: "ON/OFF tech",
+ // effect() {
+ // tech.isDeathSkipTime = true
+ // },
+ // remove() {
+ // tech.isDeathSkipTime = false
+ // }
+ // },
{
name: "NAND gate",
description: "if in the ON state
do 55.5% more damage",
@@ -2479,7 +2516,7 @@ const tech = {
},
{
name: "recycling",
- description: "if a mob has died in the last 5 seconds
regain 1% of max health every second",
+ description: "if a mob has died in the last 5 seconds
regain 0.5% of max health every second",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3172,7 +3209,7 @@ const tech = {
{
name: "paradigm shift",
- description: `clicking tech while paused ejects them
10% chance to convert that tech into ${powerUps.orb.research(1)}`,
+ description: `clicking tech while paused ejects them
16% chance to convert that tech into ${powerUps.orb.research(1)}`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -3191,7 +3228,7 @@ const tech = {
{
name: "eternalism",
// description: `increase damage by 60%, but time doesn't pause
while choosing a choosing a field, tech, or gun`, //${powerUps.orb.heal()} or
- description: "increase damage by 50%, but
time can't be paused (time dilation still works)",
+ description: "increase damage by 40%, but
time can't be paused (time dilation still works)",
maxCount: 1,
count: 0,
frequency: 1,
@@ -3556,19 +3593,19 @@ const tech = {
// return `randomly remove ${this.removePercent * 100}% of your tech
for each removed gain ${this.damagePerRemoved * 100}% damage`
// },
descriptionFunction() {
- return `randomly remove half your tech
for each removed gain ${this.damagePerRemoved * 100}% damage (~${this.damagePerRemoved * 50 * tech.totalCount}%)`
+ return `randomly remove half your tech
for each removed gain ${this.damagePerRemoved * 100 }% damage (~${(this.count === 0) ? this.damagePerRemoved * 50 * tech.totalCount : tech.OccamDamage*100}%)`
},
maxCount: 1,
count: 0,
- frequency: 1,
+ frequency: 199,
frequencyDefault: 1,
isNonRefundable: true,
isBadRandomOption: true,
allowed() {
return (tech.totalCount > 6)
},
- requires: "NOT EXPERIMENT MODE, more than 6 tech",
- removePercent: 0.5,
+ requires: "more than 6 tech",
+ // removePercent: 0.5,
damagePerRemoved: 0.5,
effect() {
let pool = []
@@ -3577,7 +3614,7 @@ const tech = {
}
pool = shuffle(pool); //shuffles order of maps
let removeCount = 0
- for (let i = 0, len = pool.length * this.removePercent; i < len; i++) removeCount += tech.removeTech(pool[i])
+ for (let i = 0, len = pool.length * this.damagePerRemoved; i < len; i++) removeCount += tech.removeTech(pool[i])
tech.OccamDamage = 1 + this.damagePerRemoved * removeCount
// tech.OccamDamage = Math.pow(1.25, removeCount)
},
@@ -5713,8 +5750,8 @@ const tech = {
simulation.updateGunHUD()
},
remove() {
+ b.guns[8].ammoPack = 24
if (this.count) {
- b.guns[8].ammoPack = 24
b.guns[8].ammo += this.ammoLost
simulation.updateGunHUD()
}
@@ -6110,7 +6147,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.17
+ return (tech.haveGunCheck("laser") || tech.isLaserBotUpgrade || tech.isLaserMine) && tech.laserDamage === 0.18
},
requires: "laser, not free-electron",
effect() {
@@ -6138,13 +6175,13 @@ const tech = {
requires: "laser, not pulse, diodes",
effect() {
tech.laserFieldDrain = 0.007 //base is 0.002
- tech.laserDamage = 0.51; //base is 0.16
+ tech.laserDamage = 0.54; //base is 0.18
tech.laserColor = "#83f"
tech.laserColorAlpha = "rgba(136, 51, 255,0.5)"
},
remove() {
tech.laserFieldDrain = 0.002;
- tech.laserDamage = 0.17; //used in check on pulse and diode: tech.laserDamage === 0.16
+ tech.laserDamage = 0.18; //used in check on pulse and diode: tech.laserDamage === 0.16
tech.laserColor = "#f00"
tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
}
@@ -6217,7 +6254,7 @@ const tech = {
{
name: "diffuse beam",
link: `diffuse beam`,
- description: "laser beam is wider and doesn't reflect
increase full beam damage by 200%",
+ description: "laser beam is wider and doesn't reflect
increase full beam damage by 220%",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -6311,7 +6348,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.17 && !tech.isStuckOn
+ return tech.haveGunCheck("laser") && tech.laserReflections < 3 && !tech.isWideLaser && tech.laserDamage === 0.18 && !tech.isStuckOn
},
requires: "laser gun, not specular reflection, diffuse, free-electron laser, optical amplifier",
effect() {
@@ -7049,7 +7086,7 @@ const tech = {
},
requires: "extruder",
effect() {
- tech.extruderRange += 60
+ tech.extruderRange += 55
},
remove() {
tech.extruderRange = 15
@@ -7895,6 +7932,51 @@ const tech = {
},
remove() {}
},
+ {
+ name: "translate",
+ description: "translate n-gon into a random language",
+ maxCount: 1,
+ count: 0,
+ frequency: 0,
+ isJunk: true,
+ isNonRefundable: true,
+ allowed() {
+ return true
+ },
+ requires: "",
+ effect() {
+ // generate a container
+ const gtElem = document.createElement('div')
+ gtElem.id = "gtElem"
+ gtElem.style.visibility = 'hidden' // make it invisible
+ document.body.append(gtElem)
+
+ // generate a script to run after creation
+ function initGT() {
+ // create a new translate element
+ new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem')
+ // ok now since it's loaded perform a funny hack to make it work
+ const langSelect = document.getElementsByClassName("goog-te-combo")[0]
+ // select a random language. It takes a second for all langauges to load, so wait a second.
+ setTimeout(() => {
+ langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random())
+ // simulate a click
+ langSelect.dispatchEvent(new Event('change'))
+ // now make it go away
+ const bar = document.getElementById(':1.container')
+ bar.style.display = 'none'
+ bar.style.visibility = 'hidden'
+ }, 1000)
+
+ }
+
+ // add the google translate script
+ const translateScript = document.createElement('script')
+ translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT'
+ document.body.append(translateScript)
+ },
+ remove() {}
+ },
{
name: "discount",
description: "get 3 random JUNK tech for the price of 1!",
@@ -10223,4 +10305,5 @@ const tech = {
isClusterExplode: null,
isCircleExplode: null,
isPetalsExplode: null,
+ isDeathSkipTime: null
}
\ No newline at end of file
diff --git a/todo.txt b/todo.txt
index 8f983c2..904ec56 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,14 +1,43 @@
******************************************************** NEXT PATCH **************************************************
-new reactor boss: timeBoss - after taking some damage it speeds up the passage of time
-reactor level has big doors
+tech: propagator - 67% damage, lose 1/2 second of time when a mob dies
-nonrefundable tech show up in the pause menu
-time dilation field - move, jump, and fire 25% faster
-JUNK tech: closed timelike curve - spawn 5 field power ups, but every 12 seconds teleport a second into your future
+timeSkipBoss is back, maybe it will not cause bugs this time
+ immune to harm unless player is inside horizon
+ player loses time when inside horizon
+
+snake bosses are immune to harm until your remove their tail
+
+mob shields are 30% stronger
+time dilation: retrocausality automatically grabs power ups
+eternalism 50->40% damage
+paradigm shift 10->16% chance to get a research when ejecting tech
+reaction inhibitor 11->13% mob health reduction
+recycling 1->0.5% health for 5 seconds
+ up to 2.5% per mob kill at normal max health
+
+bug fixes
******************************************************** TODO ********************************************************
+make targeting skip invulnerable mobs
+ drones, spores, harpoon, missiles?, mines, nail on death
+ this helps beat snake boss
+ spores are biggest issue
+
+let blocking instantly destroy the red orbitals? since they can't be deflected
+ also mines on reactor level?
+ also any bullet?
+
+BUG time skip probably led to player being able to move, and game not being paused for a few seconds while the death screen faded in
+ also small chance it happened with rewind instead, but unlikely
+
+make one value to track all the +dmg effects that don't need dynamic calculations
+ update it with a set damage function
+
+block manufacturing - molecular assembler tech
+Holding r-click will create a slowly increasing in size block, which will be thrown on release
+
if a mob dies in skiptime it doesn't register?
is this only for the ondeath event?
so far, but needs more tests
@@ -19,23 +48,9 @@ make MEE work with harm reduction
how to nerf MEE
maybe harm reduction could also reduce energy regen
-timeSkipBoss
- sends out waves of 60s time skip every 5 seconds?
- or 1 cycle skip every other cycle
- only active when player is inside range
- immune to harm outside range?
-
simulation.timeSkip(60)
- skip every other cycle inside black holes?
- maybe run simulation.timeSkip(60) in a map
- in labs?
- reactor boss
+ maybe run simulation.timeSkip(60) in a room in labs
mob fires laser/bullets that timeSkip player
- maybe an effect when in range of the historyBoss
- JUNK tech simulation.timeSkip(60)
- add CPT graphics to simulation.timeSkip(60)
- for player
- tech requires eternalism - 2x time while choosing, gain more damage
Currently, the mob just deals higher damage on impact, which is annoying although not hard to compete with nor unique
By "redesign" I mean replacing instances of the regular mob, since the same code is used for the tiny red projectiles (I think) just add a new mob and remove the old one from the rotation
@@ -51,7 +66,6 @@ About to explode: animation to dark red
Exploding: several shockwaves from the explosion points and tiny trails given to the shrapnel for a second or two until they deaccelerate
-
make laser gain damage and energy drain from fire delay tech
wording? put it in the gun description
@@ -62,8 +76,6 @@ pause time like invariant for other things...
charging railgun
charging anything?
-give retrocausality a short delay before it rewinds, so you can pick up powerups without going back
-
tech expansion: should also make other fields do things
how to make the description work
change description based on your current field?
@@ -733,23 +745,13 @@ possible names for tech
nuclear pasta - hard matter in neutron star
nonlocal
fine-tuned universe
- eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)
- axial motor
hall effect thrusters
spaghettification
particle accelerator
superluminal signalling
NP-complete
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
-
-a tutorial / lore intro
- needs to be optional so it doesn't slow experienced players
- put something on the intro map
- maybe a button triggers something
-
-rename ?
- health -> integrity, unity
- heal -> also integrity, unity
+ p-zombie
plot script: