propagator
tech: propagator - 67% damage, lose 1/2 second of time when a mob dies 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
This commit is contained in:
14
js/bullet.js
14
js/bullet.js
@@ -2109,10 +2109,10 @@ const b = {
|
|||||||
onEnd() {},
|
onEnd() {},
|
||||||
do() {
|
do() {
|
||||||
if (this.endCycle < simulation.cycle + 1) this.isWave = false
|
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.isBranch = true;
|
||||||
this.do = () => { if (this.endCycle < simulation.cycle + 1) this.isWave = false }
|
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++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position))
|
const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position))
|
||||||
const radius = mob[i].radius + tech.extruderRange / 2
|
const radius = mob[i].radius + tech.extruderRange / 2
|
||||||
@@ -2387,14 +2387,14 @@ const b = {
|
|||||||
}
|
}
|
||||||
if (tech.isLaserPush) { //push mobs away
|
if (tech.isLaserPush) { //push mobs away
|
||||||
const index = path.length - 1
|
const index = path.length - 1
|
||||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
|
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.006 * push * Math.min(6, best.who.mass))
|
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)
|
Matter.Body.applyForce(best.who, path[index], force)
|
||||||
}
|
}
|
||||||
} else if (tech.isLaserPush && best.who.classType === "body") {
|
} else if (tech.isLaserPush && best.who.classType === "body") {
|
||||||
const index = path.length - 1
|
const index = path.length - 1
|
||||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
|
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.006 * push * Math.min(6, best.who.mass))
|
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)
|
Matter.Body.applyForce(best.who, path[index], force)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -6996,7 +6996,7 @@ const b = {
|
|||||||
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
|
x: 7.5 * Math.cos(m.angle - Math.PI / 2),
|
||||||
y: 7.5 * Math.sin(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 where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
|
||||||
const eye = {
|
const eye = {
|
||||||
x: m.pos.x + 15 * Math.cos(m.angle),
|
x: m.pos.x + 15 * Math.cos(m.angle),
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ function collisionChecks(event) {
|
|||||||
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
|
const v = Vector.magnitude(Vector.sub(mob[k].velocity, obj.velocity));
|
||||||
if (v > 9) {
|
if (v > 9) {
|
||||||
if (tech.blockDmg) { //electricity
|
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 });
|
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) {
|
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
|
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
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ window.addEventListener('load', () => {
|
|||||||
const canvas = document.getElementById("canvas");
|
const canvas = document.getElementById("canvas");
|
||||||
//using "const" causes problems in safari when an ID shares the same name.
|
//using "const" causes problems in safari when an ID shares the same name.
|
||||||
const ctx = canvas.getContext("2d");
|
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";
|
document.body.style.backgroundColor = "#fff";
|
||||||
|
|
||||||
@@ -278,7 +278,7 @@ ${simulation.isCheating ? "<br><br><em>lore disabled</em>": ""}
|
|||||||
if (tech.tech[i].count > 0) {
|
if (tech.tech[i].count > 0) {
|
||||||
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
|
const techCountText = tech.tech[i].count > 1 ? `(${tech.tech[i].count}x)` : "";
|
||||||
if (tech.tech[i].isNonRefundable) {
|
if (tech.tech[i].isNonRefundable) {
|
||||||
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
|
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" style = "border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[i].link} ${techCountText}</div>${tech.tech[i].descriptionFunction ? tech.tech[i].descriptionFunction() :tech.tech[i].description}</div></div>`
|
||||||
} else if (tech.tech[i].isFieldTech) {
|
} else if (tech.tech[i].isFieldTech) {
|
||||||
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
|
text += `<div class="pause-grid-module" id ="${i}-pause-tech" onclick="powerUps.pauseEjectTech(${i})" ${style}><div class="grid-title">
|
||||||
<span style="position:relative;">
|
<span style="position:relative;">
|
||||||
|
|||||||
18
js/level.js
18
js/level.js
@@ -17,10 +17,10 @@ const level = {
|
|||||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||||
// // simulation.isHorizontalFlipped = true
|
// // simulation.isHorizontalFlipped = true
|
||||||
// m.addHealth(Infinity)
|
// m.addHealth(Infinity)
|
||||||
// m.setField("standing wave")
|
// m.setField("time dilation")
|
||||||
// b.giveGuns("nail gun")
|
// b.giveGuns("nail gun")
|
||||||
// tech.giveTech("closed timelike curve")
|
// tech.giveTech("closed timelike curve")
|
||||||
// tech.giveTech("irradiated nails")
|
// tech.giveTech("retrocausality")
|
||||||
// tech.giveTech("pneumatic actuator")
|
// tech.giveTech("pneumatic actuator")
|
||||||
// tech.giveTech("6s half-life")
|
// tech.giveTech("6s half-life")
|
||||||
// for (let i = 0; i < 10; i++) tech.giveTech("replication")
|
// 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
|
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||||
// simulation.enableConstructMode() //used to build maps in testing mode
|
// simulation.enableConstructMode() //used to build maps in testing mode
|
||||||
// level.testing();
|
// level.testing();
|
||||||
// level.reactor(); //not in rotation, used for testing
|
// spawn.snakeSpitBoss(1900, -500)
|
||||||
// spawn.timeBoss(1900, -500)
|
// level.reservoir(); //not in rotation, used for testing
|
||||||
|
|
||||||
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
|
if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************
|
||||||
// powerUps.research.changeRerolls(3000)
|
// powerUps.research.changeRerolls(3000)
|
||||||
@@ -2681,7 +2681,7 @@ const level = {
|
|||||||
// spawn.shieldingBoss(1700, -500)
|
// spawn.shieldingBoss(1700, -500)
|
||||||
|
|
||||||
// for (let i = 0; i < 10; ++i) spawn.bodyRect(1600 + 5, -500, 30, 40);
|
// 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.pulsar(1900, -500)
|
||||||
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
// spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
||||||
// mob[mob.length - 1].isShielded = true
|
// mob[mob.length - 1].isShielded = true
|
||||||
@@ -3294,8 +3294,8 @@ const level = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//2nd floor
|
//2nd floor
|
||||||
spawn.mapVertex(855, -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(-687, -1936, "-612 50 0 100 612 50 612 -50 -612 -50");
|
spawn.mapVertex(855, -1936, "-625 50 0 100 625 50 625 -50 -625 -50");
|
||||||
|
|
||||||
//2nd floor right building
|
//2nd floor right building
|
||||||
// spawn.mapRect(550, -3050, 600, 175);
|
// spawn.mapRect(550, -3050, 600, 175);
|
||||||
@@ -3328,11 +3328,11 @@ const level = {
|
|||||||
spawn.randomMob(950, -1725, 0.1);
|
spawn.randomMob(950, -1725, 0.1);
|
||||||
spawn.randomMob(-725, -1775, 0.1);
|
spawn.randomMob(-725, -1775, 0.1);
|
||||||
spawn.randomMob(-200, -2075, 0);
|
spawn.randomMob(-200, -2075, 0);
|
||||||
|
spawn.randomMob(-550, -3500, -0.2);
|
||||||
spawn.randomMob(375, -2125, 0);
|
spawn.randomMob(375, -2125, 0);
|
||||||
spawn.randomMob(1025, -3200, 0);
|
|
||||||
spawn.randomMob(-550, -3500, 0);
|
|
||||||
spawn.randomMob(-700, -2450, -0.1);
|
spawn.randomMob(-700, -2450, -0.1);
|
||||||
spawn.randomMob(-1175, -2775, -0.1);
|
spawn.randomMob(-1175, -2775, -0.1);
|
||||||
|
spawn.randomMob(1025, -3200, -0.2);
|
||||||
spawn.randomMob(-525, -3750, -0.2);
|
spawn.randomMob(-525, -3750, -0.2);
|
||||||
spawn.randomMob(1350, -2075, -0.3);
|
spawn.randomMob(1350, -2075, -0.3);
|
||||||
spawn.randomMob(1775, 1000, -0.4);
|
spawn.randomMob(1775, 1000, -0.4);
|
||||||
|
|||||||
18
js/mob.js
18
js/mob.js
@@ -1119,7 +1119,7 @@ const mobs = {
|
|||||||
if (tech.iceIXOnDeath && this.isSlowed) {
|
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)
|
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 spawns = tech.deathSpawns + tech.deathSpawnsFromBoss
|
||||||
const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
|
const len = Math.min(12, spawns * Math.ceil(Math.random() * simulation.difficulty * spawns))
|
||||||
for (let i = 0; i < len; i++) {
|
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;
|
if (tech.isEnergyLoss) m.energy *= 0.75;
|
||||||
powerUps.spawnRandomPowerUp(this.position.x, this.position.y);
|
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()
|
m.lastKillCycle = m.cycle; //tracks the last time a kill was made, mostly used in simulation.checks()
|
||||||
|
|||||||
37
js/player.js
37
js/player.js
@@ -2529,6 +2529,25 @@ const m = {
|
|||||||
this.rewindCount = 0
|
this.rewindCount = 0
|
||||||
m.grabPowerUpRange2 = 300000
|
m.grabPowerUpRange2 = 300000
|
||||||
m.hold = function() {
|
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) {
|
if (m.isHolding) {
|
||||||
m.drawHold(m.holdingTarget);
|
m.drawHold(m.holdingTarget);
|
||||||
m.holding();
|
m.holding();
|
||||||
@@ -2568,20 +2587,6 @@ const m = {
|
|||||||
} else {
|
} else {
|
||||||
m.undoCrouch()
|
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 (!(this.rewindCount % 30)) {
|
||||||
if (tech.isRewindBot) {
|
if (tech.isRewindBot) {
|
||||||
for (let i = 0; i < tech.isRewindBot; i++) {
|
for (let i = 0; i < tech.isRewindBot; i++) {
|
||||||
@@ -2594,8 +2599,6 @@ const m = {
|
|||||||
const who = bullet[bullet.length - 1]
|
const who = bullet[bullet.length - 1]
|
||||||
who.endCycle = simulation.cycle + 60
|
who.endCycle = simulation.cycle + 60
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2612,7 +2615,7 @@ const m = {
|
|||||||
} else {
|
} else {
|
||||||
m.fieldFire = true;
|
m.fieldFire = true;
|
||||||
m.isBodiesAsleep = false;
|
m.isBodiesAsleep = false;
|
||||||
m.drain = 0.003
|
m.drain = 0.0025
|
||||||
m.hold = function() {
|
m.hold = function() {
|
||||||
if (m.isHolding) {
|
if (m.isHolding) {
|
||||||
m.wakeCheck();
|
m.wakeCheck();
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ const powerUps = {
|
|||||||
},
|
},
|
||||||
doDefault() {
|
doDefault() {
|
||||||
//draw power ups
|
//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) {
|
for (let i = 0, len = powerUp.length; i < len; ++i) {
|
||||||
ctx.beginPath();
|
ctx.beginPath();
|
||||||
ctx.arc(powerUp[i].position.x, powerUp[i].position.y, powerUp[i].size, 0, 2 * Math.PI);
|
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) {
|
choose(type, index) {
|
||||||
console.log('choose')
|
|
||||||
if (type === "gun") {
|
if (type === "gun") {
|
||||||
b.giveGuns(index)
|
b.giveGuns(index)
|
||||||
let text = `b.giveGuns("<span class='color-text'>${b.guns[index].name}</span>")`
|
let text = `b.giveGuns("<span class='color-text'>${b.guns[index].name}</span>")`
|
||||||
@@ -356,7 +355,7 @@ const powerUps = {
|
|||||||
// document.body.style.overflow = "hidden"
|
// document.body.style.overflow = "hidden"
|
||||||
// if (m.alive){}
|
// if (m.alive){}
|
||||||
if (simulation.paused) requestAnimationFrame(cycle);
|
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
|
simulation.isChoosing = false; //stops p from un pausing on key down
|
||||||
build.unPauseGrid()
|
build.unPauseGrid()
|
||||||
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 30 cycles
|
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) {
|
pauseEjectTech(index) {
|
||||||
if ((tech.isPauseEjectTech || simulation.testing) && !simulation.isChoosing && !tech.tech[index].isNonRefundable) {
|
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)
|
tech.removeTech(index)
|
||||||
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -521,9 +521,7 @@ const simulation = {
|
|||||||
}
|
}
|
||||||
}, len * swapPeriod);
|
}, len * swapPeriod);
|
||||||
},
|
},
|
||||||
wipe() {
|
wipe() {}, //set in simulation.startGame
|
||||||
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
||||||
},
|
|
||||||
gravity() {
|
gravity() {
|
||||||
function addGravity(bodies, magnitude) {
|
function addGravity(bodies, magnitude) {
|
||||||
for (var i = 0; i < bodies.length; i++) {
|
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 (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.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
|
if (!(m.cycle % 420)) { //once every 7 seconds
|
||||||
|
|||||||
330
js/spawn.js
330
js/spawn.js
@@ -1,10 +1,11 @@
|
|||||||
//main object for spawning things in a level
|
//main object for spawning things in a level
|
||||||
const spawn = {
|
const spawn = {
|
||||||
nonCollideBossList: ["cellBossCulture", "bomberBoss", "powerUpBoss", "growBossCulture"],
|
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
|
// other bosses: suckerBoss, laserBoss, tetherBoss, 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",
|
randomBossList: [
|
||||||
"powerUpBoss", "powerUpBossBaby", "snakeBoss", "streamBoss", "pulsarBoss", "spawnerBossCulture", "grenadierBoss", "growBossCulture", "blinkBoss",
|
"orbitalBoss", "historyBoss", "shooterBoss", "cellBossCulture", "bomberBoss", "spiderBoss", "launcherBoss", "laserTargetingBoss",
|
||||||
"snakeSpitBoss", "laserBombingBoss", "blockBoss", "revolutionBoss", "slashBoss"
|
"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
|
bossTypeSpawnOrder: [], //preset list of boss names calculated at the start of a run by the randomSeed
|
||||||
bossTypeSpawnIndex: 0, //increases as the boss type cycles
|
bossTypeSpawnIndex: 0, //increases as the boss type cycles
|
||||||
@@ -19,7 +20,7 @@ const spawn = {
|
|||||||
pickList: ["starter", "starter"],
|
pickList: ["starter", "starter"],
|
||||||
fullPickList: [
|
fullPickList: [
|
||||||
"hopper", "hopper", "hopper",
|
"hopper", "hopper", "hopper",
|
||||||
"slasher", "slasher", "hopper",
|
"slasher", "slasher", "slasher",
|
||||||
"stabber", "stabber", "stabber",
|
"stabber", "stabber", "stabber",
|
||||||
"springer", "springer", "springer",
|
"springer", "springer", "springer",
|
||||||
"shooter", "shooter",
|
"shooter", "shooter",
|
||||||
@@ -2028,7 +2029,6 @@ const spawn = {
|
|||||||
me.seePlayerFreq = 300;
|
me.seePlayerFreq = 300;
|
||||||
const springStiffness = 0.00008; //simulation.difficulty
|
const springStiffness = 0.00008; //simulation.difficulty
|
||||||
const springDampening = 0.01;
|
const springDampening = 0.01;
|
||||||
|
|
||||||
me.springTarget = {
|
me.springTarget = {
|
||||||
x: me.position.x,
|
x: me.position.x,
|
||||||
y: me.position.y
|
y: me.position.y
|
||||||
@@ -2055,11 +2055,9 @@ const spawn = {
|
|||||||
Composite.add(engine.world, cons[cons.length - 1]);
|
Composite.add(engine.world, cons[cons.length - 1]);
|
||||||
cons[len2].length = 100 + 1.5 * radius;
|
cons[len2].length = 100 + 1.5 * radius;
|
||||||
me.cons2 = cons[len2];
|
me.cons2 = cons[len2];
|
||||||
|
|
||||||
me.startingDamageReduction = me.damageReduction
|
me.startingDamageReduction = me.damageReduction
|
||||||
me.isInvulnerable = false
|
me.isInvulnerable = false
|
||||||
me.invulnerabilityCountDown = 0
|
me.invulnerabilityCountDown = 0
|
||||||
|
|
||||||
me.do = function() {
|
me.do = function() {
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
this.gravity();
|
this.gravity();
|
||||||
@@ -2069,7 +2067,6 @@ const spawn = {
|
|||||||
ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
|
ctx.arc(this.cons2.pointA.x, this.cons2.pointA.y, 6, 0, 2 * Math.PI);
|
||||||
ctx.fillStyle = "#222";
|
ctx.fillStyle = "#222";
|
||||||
ctx.fill();
|
ctx.fill();
|
||||||
|
|
||||||
this.seePlayerCheck()
|
this.seePlayerCheck()
|
||||||
// this.seePlayerByHistory()
|
// this.seePlayerByHistory()
|
||||||
if (this.isInvulnerable) {
|
if (this.isInvulnerable) {
|
||||||
@@ -2202,7 +2199,6 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
me.onDeath = function() {
|
me.onDeath = function() {
|
||||||
this.removeCons();
|
this.removeCons();
|
||||||
if (isSpawnBossPowerUp) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
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 sideLength = 80 // distance between each node mob
|
||||||
const nodes = 3
|
const nodes = 3
|
||||||
const angle = 2 * Math.PI / nodes
|
const angle = 2 * Math.PI / nodes
|
||||||
@@ -2255,7 +2250,6 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const stiffness = 0.01
|
const stiffness = 0.01
|
||||||
const damping = 0.1
|
const damping = 0.1
|
||||||
for (let i = 1; i < nodes; ++i) { //attach to center mob
|
for (let i = 1; i < nodes; ++i) { //attach to center mob
|
||||||
@@ -2287,88 +2281,86 @@ const spawn = {
|
|||||||
}
|
}
|
||||||
spawn.allowShields = true;
|
spawn.allowShields = true;
|
||||||
},
|
},
|
||||||
timeSkipBoss(x, y, radius = 55) {
|
// timeSkipBoss(x, y, radius = 55) {
|
||||||
mobs.spawn(x, y, 6, radius, '#000');
|
// mobs.spawn(x, y, 6, radius, '#000');
|
||||||
let me = mob[mob.length - 1];
|
// let me = mob[mob.length - 1];
|
||||||
me.isBoss = true;
|
// me.isBoss = true;
|
||||||
// me.stroke = "transparent"; //used for drawSneaker
|
// // me.stroke = "transparent"; //used for drawSneaker
|
||||||
me.timeSkipLastCycle = 0
|
// me.timeSkipLastCycle = 0
|
||||||
me.eventHorizon = 1800; //required for black hole
|
// me.eventHorizon = 1800; //required for black hole
|
||||||
me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
|
// me.seeAtDistance2 = (me.eventHorizon + 2000) * (me.eventHorizon + 2000); //vision limit is event horizon + 2000
|
||||||
me.accelMag = 0.0004 * simulation.accelScale;
|
// me.accelMag = 0.0004 * simulation.accelScale;
|
||||||
// me.frictionAir = 0.005;
|
// // me.frictionAir = 0.005;
|
||||||
// me.memory = 1600;
|
// // 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.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
|
// 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);
|
// 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() {
|
// ctx.beginPath();
|
||||||
//applying forces to player doesn't seem to work inside this method, not sure why
|
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
// ctx.fillStyle = "#fff";
|
||||||
};
|
// ctx.globalCompositeOperation = "destination-in"; //in or atop
|
||||||
me.do = function() {
|
// ctx.fill();
|
||||||
//keep it slow, to stop issues from explosion knock backs
|
// ctx.globalCompositeOperation = "source-over";
|
||||||
if (this.speed > 8) {
|
// ctx.beginPath();
|
||||||
Matter.Body.setVelocity(this, {
|
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||||
x: this.velocity.x * 0.99,
|
// ctx.clip();
|
||||||
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()})`
|
// // ctx.beginPath();
|
||||||
this.stroke = "#014"
|
// // ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
|
||||||
this.isShielded = false;
|
// // ctx.fillStyle = "#000";
|
||||||
this.isDropPowerUp = true;
|
// // ctx.fill();
|
||||||
this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob; //can't touch bullets
|
// // ctx.strokeStyle = "#000";
|
||||||
|
// // ctx.stroke();
|
||||||
|
|
||||||
ctx.beginPath();
|
// // ctx.beginPath();
|
||||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
// // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||||
ctx.fillStyle = "#fff";
|
// // ctx.fillStyle = `rgba(0,0,0,${0.05*Math.random()})`;
|
||||||
ctx.globalCompositeOperation = "destination-in"; //in or atop
|
// // ctx.fill();
|
||||||
ctx.fill();
|
// // ctx.strokeStyle = "#000";
|
||||||
ctx.globalCompositeOperation = "source-over";
|
// // ctx.stroke();
|
||||||
ctx.beginPath();
|
// } else {
|
||||||
ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
// this.isShielded = true;
|
||||||
ctx.clip();
|
// this.isDropPowerUp = false;
|
||||||
|
// this.seePlayer.recall = false
|
||||||
// ctx.beginPath();
|
// this.fill = "transparent"
|
||||||
// ctx.arc(this.position.x, this.position.y, 9999, 0, 2 * Math.PI);
|
// this.stroke = "transparent"
|
||||||
// ctx.fillStyle = "#000";
|
// this.collisionFilter.mask = cat.player | cat.map | cat.body | cat.mob; //can't touch bullets
|
||||||
// ctx.fill();
|
// ctx.beginPath();
|
||||||
// ctx.strokeStyle = "#000";
|
// ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
|
||||||
// ctx.stroke();
|
// 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)) {
|
beamer(x, y, radius = 15 + Math.ceil(Math.random() * 15)) {
|
||||||
mobs.spawn(x, y, 4, radius, "rgb(255,0,190)");
|
mobs.spawn(x, y, 4, radius, "rgb(255,0,190)");
|
||||||
let me = mob[mob.length - 1];
|
let me = mob[mob.length - 1];
|
||||||
@@ -3931,7 +3923,7 @@ const spawn = {
|
|||||||
me.isBoss = true;
|
me.isBoss = true;
|
||||||
Matter.Body.setDensity(me, 0.001); //normal is 0.001
|
Matter.Body.setDensity(me, 0.001); //normal is 0.001
|
||||||
me.inertia = Infinity;
|
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.startingDamageReduction = me.damageReduction
|
||||||
me.isInvulnerable = false
|
me.isInvulnerable = false
|
||||||
me.frictionAir = 0.01
|
me.frictionAir = 0.01
|
||||||
@@ -3974,8 +3966,8 @@ const spawn = {
|
|||||||
const unit = Vector.sub(player.position, this.position)
|
const unit = Vector.sub(player.position, this.position)
|
||||||
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(unit), 0.1));
|
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(unit), 0.1));
|
||||||
} else {
|
} 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.y) < 10) 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.x) < 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 1.02, y: this.velocity.y });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isInvulnerable) {
|
if (this.isInvulnerable) {
|
||||||
@@ -5138,7 +5130,7 @@ const spawn = {
|
|||||||
me.maxCycles = 110;
|
me.maxCycles = 110;
|
||||||
me.frictionStatic = 0;
|
me.frictionStatic = 0;
|
||||||
me.friction = 0;
|
me.friction = 0;
|
||||||
me.frictionAir = 0.5;
|
me.frictionAir = 1;
|
||||||
// me.homePosition = { x: x, y: y };
|
// me.homePosition = { x: x, y: y };
|
||||||
spawn.shield(me, x, y, 1);
|
spawn.shield(me, x, y, 1);
|
||||||
spawn.spawnOrbitals(me, radius + 50 + 200 * Math.random())
|
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.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
||||||
me.do = function() {
|
me.do = function() {
|
||||||
// this.armor();
|
Matter.Body.rotate(this, 0.003) //gently spin around
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
ctx.beginPath(); //draw cycle timer
|
ctx.beginPath(); //draw cycle timer
|
||||||
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
|
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) {
|
streamBoss(x, y, radius = 110) {
|
||||||
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
|
mobs.spawn(x, y, 5, radius, "rgb(245,180,255)");
|
||||||
let me = mob[mob.length - 1];
|
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)"
|
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];
|
let me = mob[mob.length - 1];
|
||||||
me.isBoss = true;
|
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.memory = 250;
|
||||||
me.laserRange = 500;
|
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
|
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() {
|
me.onDeath = function() {
|
||||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
||||||
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
|
for (let i = 0; i < mob.length; i++) { //wake up tail mobs
|
||||||
@@ -5428,9 +5491,7 @@ const spawn = {
|
|||||||
};
|
};
|
||||||
me.canFire = false;
|
me.canFire = false;
|
||||||
me.closestVertex1 = 0;
|
me.closestVertex1 = 0;
|
||||||
// me.closestVertex2 = 1;
|
|
||||||
me.cycle = 0
|
me.cycle = 0
|
||||||
me.damageReduction = 0.2 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
|
|
||||||
me.do = function() {
|
me.do = function() {
|
||||||
// this.armor();
|
// this.armor();
|
||||||
this.seePlayerByHistory()
|
this.seePlayerByHistory()
|
||||||
@@ -5439,7 +5500,7 @@ const spawn = {
|
|||||||
this.cycle++
|
this.cycle++
|
||||||
if (this.seePlayer.recall && ((this.cycle % 10) === 0)) {
|
if (this.seePlayer.recall && ((this.cycle % 10) === 0)) {
|
||||||
if (this.canFire) {
|
if (this.canFire) {
|
||||||
if (this.cycle > 120) {
|
if (this.cycle > 100) {
|
||||||
this.cycle = 0
|
this.cycle = 0
|
||||||
this.canFire = false
|
this.canFire = false
|
||||||
// Matter.Body.setAngularVelocity(this, 0.1)
|
// 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)
|
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
|
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], {
|
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||||
x: this.velocity.x + velocity.x,
|
x: this.velocity.x + velocity.x,
|
||||||
y: this.velocity.y + velocity.y
|
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
|
//extra space to give head room
|
||||||
angle -= 0.1
|
angle -= 0.1
|
||||||
mag -= 10
|
mag -= 10
|
||||||
|
let previousTailID = 0
|
||||||
|
|
||||||
for (let i = 0; i < nodes; ++i) {
|
for (let i = 0; i < nodes; ++i) {
|
||||||
angle -= 0.15 + i * 0.008
|
angle -= 0.15 + i * 0.008
|
||||||
mag -= 5
|
mag -= 5
|
||||||
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
|
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);
|
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)"
|
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];
|
let me = mob[mob.length - 1];
|
||||||
me.isBoss = true;
|
me.isBoss = true;
|
||||||
me.accelMag = 0.00077 * simulation.accelScale;
|
me.accelMag = 0.0004 + 0.0003 * Math.sqrt(simulation.accelScale)
|
||||||
me.memory = 250;
|
me.memory = 250;
|
||||||
me.laserRange = 500;
|
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
|
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() {
|
me.onDeath = function() {
|
||||||
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
|
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() {
|
me.do = function() {
|
||||||
// this.armor();
|
|
||||||
this.seePlayerByHistory()
|
this.seePlayerByHistory()
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
this.attraction();
|
this.attraction();
|
||||||
this.harmZone();
|
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
|
//extra space to give head room
|
||||||
angle -= 0.1
|
angle -= 0.1
|
||||||
mag -= 10
|
mag -= 10
|
||||||
|
let previousTailID = 0
|
||||||
for (let i = 0; i < nodes; ++i) {
|
for (let i = 0; i < nodes; ++i) {
|
||||||
angle -= 0.15 + i * 0.008
|
angle -= 0.15 + i * 0.008
|
||||||
mag -= 5
|
mag -= 5
|
||||||
spawn.snakeBody(x + mag * Math.cos(angle), y + mag * Math.sin(angle), 20);
|
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);
|
this.constrain2AdjacentMobs(nodes, Math.random() * 0.06 + 0.01);
|
||||||
|
|
||||||
for (let i = mob.length - 1, len = i - nodes; i > len; i--) { //set alternating colors
|
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];
|
let me = mob[mob.length - 1];
|
||||||
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
|
me.collisionFilter.mask = cat.bullet | cat.player | cat.mob //| cat.body
|
||||||
me.accelMag = 0.0006 * simulation.accelScale;
|
me.accelMag = 0.0006 * simulation.accelScale;
|
||||||
me.leaveBody = false;
|
me.leaveBody = Math.random() < 0.33 ? true : false;
|
||||||
me.showHealthBar = false;
|
me.showHealthBar = false;
|
||||||
me.isDropPowerUp = 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.frictionAir = 0.015;
|
||||||
me.isSnakeTail = true;
|
me.isSnakeTail = true;
|
||||||
me.stroke = "transparent"
|
me.stroke = "transparent"
|
||||||
me.onDeath = function() {
|
me.onDeath = function() {
|
||||||
// if (this.isSnakeTail) { //wake up tail mobs
|
setTimeout(() => {
|
||||||
// for (let i = 0; i < mob.length; i++) {
|
for (let i = 0, len = mob.length; i < len; i++) {
|
||||||
// if (mob[i].isSnakeTail && mob[i].alive) {
|
if (this.id === mob[i].previousTailID && mob[i].alive) mob[i].death()
|
||||||
// mob[i].isSnakeTail = false;
|
if (this.snakeHeadID === mob[i].id) {
|
||||||
// mob[i].do = mob[i].doActive
|
mob[i].isInvulnerable = false
|
||||||
// mob[i].removeConsBB();
|
mob[i].damageReduction = mob[i].startingDamageReduction
|
||||||
// }
|
}
|
||||||
// }
|
}
|
||||||
// }
|
}, 150);
|
||||||
};
|
};
|
||||||
me.do = function() {
|
me.do = function() {
|
||||||
this.checkStatus();
|
this.checkStatus();
|
||||||
@@ -5666,7 +5752,7 @@ const spawn = {
|
|||||||
me.stroke = "rgb(220,220,255)";
|
me.stroke = "rgb(220,220,255)";
|
||||||
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
|
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
|
||||||
me.shield = true;
|
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.isUnblockable = true
|
||||||
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
|
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
|
||||||
me.collisionFilter.category = cat.mobShield
|
me.collisionFilter.category = cat.mobShield
|
||||||
|
|||||||
121
js/tech.js
121
js/tech.js
@@ -221,7 +221,8 @@ const tech = {
|
|||||||
},
|
},
|
||||||
damageFromTech() {
|
damageFromTech() {
|
||||||
let dmg = 1 //m.fieldDamage
|
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.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.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction())
|
||||||
if (tech.OccamDamage) dmg *= tech.OccamDamage
|
if (tech.OccamDamage) dmg *= tech.OccamDamage
|
||||||
@@ -556,7 +557,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "cache",
|
name: "cache",
|
||||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`,
|
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Cache_(computing)' class="link">cache</a>`,
|
||||||
description: `${powerUps.orb.ammo()} give <strong>16x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
description: `${powerUps.orb.ammo()} give <strong>1600%</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
||||||
// ammo powerups always max out your gun,
|
// ammo powerups always max out your gun,
|
||||||
// but the maximum ammo ti limited
|
// but the maximum ammo ti limited
|
||||||
// description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
// description: `${powerUps.orb.ammo()} give <strong>13x</strong> more <strong class='color-ammo'>ammo</strong>, but<br>you can't <strong>store</strong> any more <strong class='color-ammo'>ammo</strong> than that`,
|
||||||
@@ -936,7 +937,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "reaction inhibitor",
|
name: "reaction inhibitor",
|
||||||
description: "mobs spawn with <strong>11%</strong> less <strong>health</strong>",
|
description: "mobs spawn with <strong>13%</strong> less <strong>health</strong>",
|
||||||
maxCount: 3,
|
maxCount: 3,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -946,7 +947,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
requires: "", //"any mob death tech",
|
requires: "", //"any mob death tech",
|
||||||
effect: () => {
|
effect: () => {
|
||||||
tech.mobSpawnWithHealth *= 0.89
|
tech.mobSpawnWithHealth *= 0.87
|
||||||
|
|
||||||
//set all mobs at full health to 0.85
|
//set all mobs at full health to 0.85
|
||||||
for (let i = 0; i < mob.length; i++) {
|
for (let i = 0; i < mob.length; i++) {
|
||||||
@@ -957,6 +958,24 @@ const tech = {
|
|||||||
tech.mobSpawnWithHealth = 1;
|
tech.mobSpawnWithHealth = 1;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "propagator",
|
||||||
|
description: "increase <strong class='color-d'>damage</strong> by <strong>67%</strong>, but after<br>mobs <strong>die</strong> lose <strong>0.5</strong> seconds of <strong>time</strong>",
|
||||||
|
maxCount: 1,
|
||||||
|
count: 0,
|
||||||
|
frequency: 1,
|
||||||
|
frequencyDefault: 1,
|
||||||
|
allowed() {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
requires: "",
|
||||||
|
effect() {
|
||||||
|
tech.isDeathSkipTime = true
|
||||||
|
},
|
||||||
|
remove() {
|
||||||
|
tech.isDeathSkipTime = false
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "decorrelation",
|
name: "decorrelation",
|
||||||
description: "reduce <strong class='color-harm'>harm</strong> by <strong>70%</strong> after not <strong>activating</strong><br>your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> for <strong>2</strong> seconds",
|
description: "reduce <strong class='color-harm'>harm</strong> by <strong>70%</strong> after not <strong>activating</strong><br>your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> for <strong>2</strong> seconds",
|
||||||
@@ -1772,6 +1791,24 @@ const tech = {
|
|||||||
m.eyeFillColor = 'transparent'
|
m.eyeFillColor = 'transparent'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
// {
|
||||||
|
// name: "spacetime interval",
|
||||||
|
// description: "increase <strong class='color-d'>damage</strong> by <strong>93%</strong>, but after mobs <strong>die</strong><br>move into the <strong>past</strong> / <strong>future</strong> while <strong class='color-flop'>ON</strong> / <strong class='color-flop'>OFF</strong>",
|
||||||
|
// 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",
|
name: "NAND gate",
|
||||||
description: "if in the <strong class='color-flop'>ON</strong> state<br>do <strong>55.5%</strong> more <strong class='color-d'>damage</strong>",
|
description: "if in the <strong class='color-flop'>ON</strong> state<br>do <strong>55.5%</strong> more <strong class='color-d'>damage</strong>",
|
||||||
@@ -2479,7 +2516,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "recycling",
|
name: "recycling",
|
||||||
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>regain <strong>1%</strong> of max <strong class='color-h'>health</strong> every second",
|
description: "if a mob has <strong>died</strong> in the last <strong>5 seconds</strong><br>regain <strong>0.5%</strong> of max <strong class='color-h'>health</strong> every second",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3172,7 +3209,7 @@ const tech = {
|
|||||||
|
|
||||||
{
|
{
|
||||||
name: "paradigm shift",
|
name: "paradigm shift",
|
||||||
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>10%</strong> chance to convert that <strong class='color-m'>tech</strong> into ${powerUps.orb.research(1)}`,
|
description: `<strong>clicking</strong> <strong class='color-m'>tech</strong> while paused <strong>ejects</strong> them<br><strong>16%</strong> chance to convert that <strong class='color-m'>tech</strong> into ${powerUps.orb.research(1)}`,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3191,7 +3228,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "eternalism",
|
name: "eternalism",
|
||||||
// description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but <strong>time</strong> doesn't <strong>pause</strong><br>while choosing a choosing a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong>`, //${powerUps.orb.heal()} or
|
// description: `increase <strong class='color-d'>damage</strong> by <strong>60%</strong>, but <strong>time</strong> doesn't <strong>pause</strong><br>while choosing a choosing a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong>`, //${powerUps.orb.heal()} or
|
||||||
description: "increase <strong class='color-d'>damage</strong> by <strong>50%</strong>, but<br><strong>time</strong> can't be <strong>paused</strong> <em>(time dilation still works)</em>",
|
description: "increase <strong class='color-d'>damage</strong> by <strong>40%</strong>, but<br><strong>time</strong> can't be <strong>paused</strong> <em>(time dilation still works)</em>",
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 1,
|
||||||
@@ -3556,19 +3593,19 @@ const tech = {
|
|||||||
// return `randomly remove <strong>${this.removePercent * 100}%</strong> of your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong>`
|
// return `randomly remove <strong>${this.removePercent * 100}%</strong> of your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong>`
|
||||||
// },
|
// },
|
||||||
descriptionFunction() {
|
descriptionFunction() {
|
||||||
return `randomly remove <strong>half</strong> your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100}%</strong> <strong class='color-d'>damage</strong> <em>(~${this.damagePerRemoved * 50 * tech.totalCount}%)</em>`
|
return `randomly remove <strong>half</strong> your <strong class='color-m'>tech</strong><br>for each removed gain <strong>${this.damagePerRemoved * 100 }%</strong> <strong class='color-d'>damage</strong> <em>(~${(this.count === 0) ? this.damagePerRemoved * 50 * tech.totalCount : tech.OccamDamage*100}%)</em>`
|
||||||
},
|
},
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
frequency: 1,
|
frequency: 199,
|
||||||
frequencyDefault: 1,
|
frequencyDefault: 1,
|
||||||
isNonRefundable: true,
|
isNonRefundable: true,
|
||||||
isBadRandomOption: true,
|
isBadRandomOption: true,
|
||||||
allowed() {
|
allowed() {
|
||||||
return (tech.totalCount > 6)
|
return (tech.totalCount > 6)
|
||||||
},
|
},
|
||||||
requires: "NOT EXPERIMENT MODE, more than 6 tech",
|
requires: "more than 6 tech",
|
||||||
removePercent: 0.5,
|
// removePercent: 0.5,
|
||||||
damagePerRemoved: 0.5,
|
damagePerRemoved: 0.5,
|
||||||
effect() {
|
effect() {
|
||||||
let pool = []
|
let pool = []
|
||||||
@@ -3577,7 +3614,7 @@ const tech = {
|
|||||||
}
|
}
|
||||||
pool = shuffle(pool); //shuffles order of maps
|
pool = shuffle(pool); //shuffles order of maps
|
||||||
let removeCount = 0
|
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 = 1 + this.damagePerRemoved * removeCount
|
||||||
// tech.OccamDamage = Math.pow(1.25, removeCount)
|
// tech.OccamDamage = Math.pow(1.25, removeCount)
|
||||||
},
|
},
|
||||||
@@ -5713,8 +5750,8 @@ const tech = {
|
|||||||
simulation.updateGunHUD()
|
simulation.updateGunHUD()
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
|
b.guns[8].ammoPack = 24
|
||||||
if (this.count) {
|
if (this.count) {
|
||||||
b.guns[8].ammoPack = 24
|
|
||||||
b.guns[8].ammo += this.ammoLost
|
b.guns[8].ammo += this.ammoLost
|
||||||
simulation.updateGunHUD()
|
simulation.updateGunHUD()
|
||||||
}
|
}
|
||||||
@@ -6110,7 +6147,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
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",
|
requires: "laser, not free-electron",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -6138,13 +6175,13 @@ const tech = {
|
|||||||
requires: "laser, not pulse, diodes",
|
requires: "laser, not pulse, diodes",
|
||||||
effect() {
|
effect() {
|
||||||
tech.laserFieldDrain = 0.007 //base is 0.002
|
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.laserColor = "#83f"
|
||||||
tech.laserColorAlpha = "rgba(136, 51, 255,0.5)"
|
tech.laserColorAlpha = "rgba(136, 51, 255,0.5)"
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
tech.laserFieldDrain = 0.002;
|
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.laserColor = "#f00"
|
||||||
tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
|
tech.laserColorAlpha = "rgba(255, 0, 0, 0.5)"
|
||||||
}
|
}
|
||||||
@@ -6217,7 +6254,7 @@ const tech = {
|
|||||||
{
|
{
|
||||||
name: "diffuse beam",
|
name: "diffuse beam",
|
||||||
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Diffuser_(optics)' class="link">diffuse beam</a>`,
|
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Diffuser_(optics)' class="link">diffuse beam</a>`,
|
||||||
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>200%</strong>",
|
description: "<strong class='color-laser'>laser</strong> beam is <strong>wider</strong> and doesn't <strong>reflect</strong><br>increase full beam <strong class='color-d'>damage</strong> by <strong>220%</strong>",
|
||||||
isGunTech: true,
|
isGunTech: true,
|
||||||
maxCount: 1,
|
maxCount: 1,
|
||||||
count: 0,
|
count: 0,
|
||||||
@@ -6311,7 +6348,7 @@ const tech = {
|
|||||||
frequency: 2,
|
frequency: 2,
|
||||||
frequencyDefault: 2,
|
frequencyDefault: 2,
|
||||||
allowed() {
|
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",
|
requires: "laser gun, not specular reflection, diffuse, free-electron laser, optical amplifier",
|
||||||
effect() {
|
effect() {
|
||||||
@@ -7049,7 +7086,7 @@ const tech = {
|
|||||||
},
|
},
|
||||||
requires: "extruder",
|
requires: "extruder",
|
||||||
effect() {
|
effect() {
|
||||||
tech.extruderRange += 60
|
tech.extruderRange += 55
|
||||||
},
|
},
|
||||||
remove() {
|
remove() {
|
||||||
tech.extruderRange = 15
|
tech.extruderRange = 15
|
||||||
@@ -7895,6 +7932,51 @@ const tech = {
|
|||||||
},
|
},
|
||||||
remove() {}
|
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",
|
name: "discount",
|
||||||
description: "get 3 random <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> for the price of 1!",
|
description: "get 3 random <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> for the price of 1!",
|
||||||
@@ -10223,4 +10305,5 @@ const tech = {
|
|||||||
isClusterExplode: null,
|
isClusterExplode: null,
|
||||||
isCircleExplode: null,
|
isCircleExplode: null,
|
||||||
isPetalsExplode: null,
|
isPetalsExplode: null,
|
||||||
|
isDeathSkipTime: null
|
||||||
}
|
}
|
||||||
70
todo.txt
70
todo.txt
@@ -1,14 +1,43 @@
|
|||||||
******************************************************** NEXT PATCH **************************************************
|
******************************************************** NEXT PATCH **************************************************
|
||||||
|
|
||||||
new reactor boss: timeBoss - after taking some damage it speeds up the passage of time
|
tech: propagator - 67% damage, lose 1/2 second of time when a mob dies
|
||||||
reactor level has big doors
|
|
||||||
|
|
||||||
nonrefundable tech show up in the pause menu
|
timeSkipBoss is back, maybe it will not cause bugs this time
|
||||||
time dilation field - move, jump, and fire 25% faster
|
immune to harm unless player is inside horizon
|
||||||
JUNK tech: closed timelike curve - spawn 5 field power ups, but every 12 seconds teleport a second into your future
|
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 ********************************************************
|
******************************************************** 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?
|
if a mob dies in skiptime it doesn't register?
|
||||||
is this only for the ondeath event?
|
is this only for the ondeath event?
|
||||||
so far, but needs more tests
|
so far, but needs more tests
|
||||||
@@ -19,23 +48,9 @@ make MEE work with harm reduction
|
|||||||
how to nerf MEE
|
how to nerf MEE
|
||||||
maybe harm reduction could also reduce energy regen
|
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)
|
simulation.timeSkip(60)
|
||||||
skip every other cycle inside black holes?
|
maybe run simulation.timeSkip(60) in a room in labs
|
||||||
maybe run simulation.timeSkip(60) in a map
|
|
||||||
in labs?
|
|
||||||
reactor boss
|
|
||||||
mob fires laser/bullets that timeSkip player
|
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
|
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
|
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
|
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
|
make laser gain damage and energy drain from fire delay tech
|
||||||
wording? put it in the gun description
|
wording? put it in the gun description
|
||||||
|
|
||||||
@@ -62,8 +76,6 @@ pause time like invariant for other things...
|
|||||||
charging railgun
|
charging railgun
|
||||||
charging anything?
|
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
|
tech expansion: should also make other fields do things
|
||||||
how to make the description work
|
how to make the description work
|
||||||
change description based on your current field?
|
change description based on your current field?
|
||||||
@@ -733,23 +745,13 @@ possible names for tech
|
|||||||
nuclear pasta - hard matter in neutron star
|
nuclear pasta - hard matter in neutron star
|
||||||
nonlocal
|
nonlocal
|
||||||
fine-tuned universe
|
fine-tuned universe
|
||||||
eternalism https://en.wikipedia.org/wiki/Eternalism_(philosophy_of_time)
|
|
||||||
axial motor
|
|
||||||
hall effect thrusters
|
hall effect thrusters
|
||||||
spaghettification
|
spaghettification
|
||||||
particle accelerator
|
particle accelerator
|
||||||
superluminal signalling
|
superluminal signalling
|
||||||
NP-complete
|
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.
|
lenticular lens: is an array of lenses, designed so that when viewed from slightly different angles, different parts of the image underneath are shown.
|
||||||
|
p-zombie
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
plot script:
|
plot script:
|
||||||
|
|||||||
Reference in New Issue
Block a user