abiogenesis

tech: abiogenesis - spawn a second level boss on each level, but costs 5 research or if you don't have the research add 49 JUNK tech to the pool
  note to level builders I rewrote the add duplicate boss code in all levels: spawn.secondaryBossChance(x,y)

foam tech: uncertainty principle - foam bullets change position randomly, increase foam damage by 66%

throwing blocks now charges faster with reduced fire cooldown
tech renormalization now has a 40% chance to refund a research  (was 37%)
performance- now precalculate player gradient fill
This commit is contained in:
landgreen
2021-06-30 06:40:37 -07:00
parent 5d4ef1994c
commit a2b56d1f7e
9 changed files with 338 additions and 342 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -216,18 +216,18 @@ const b = {
} }
}, },
fireProps(cd, speed, dir, me) { fireProps(cd, speed, dir, me) {
m.fireCDcycle = m.cycle + Math.floor(cd * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(cd * b.fireCDscale); // cool down
Matter.Body.setVelocity(bullet[me], { Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(dir), x: m.Vx / 2 + speed * Math.cos(dir),
y: m.Vy / 2 + speed * Math.sin(dir) y: m.Vy / 2 + speed * Math.sin(dir)
}); });
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
}, },
fireCD: 1, fireCDscale: 1,
setFireCD() { setFireCD() {
b.fireCD = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage / tech.fastTime b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage / tech.fastTime
if (tech.isFireRateForGuns) b.fireCD *= Math.pow(0.86, b.inventory.length) if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.86, b.inventory.length)
if (tech.isFireMoveLock) b.fireCD *= 0.5 if (tech.isFireMoveLock) b.fireCDscale *= 0.5
}, },
fireAttributes(dir, rotate = true) { fireAttributes(dir, rotate = true) {
if (rotate) { if (rotate) {
@@ -2435,7 +2435,7 @@ const b = {
// friction: 0.2, // friction: 0.2,
// restitution: 0.2, // restitution: 0.2,
dmg: 0, //damage on impact dmg: 0, //damage on impact
damage: tech.isFastFoam ? 0.048 : 0.012, //damage done over time damage: (tech.isFastFoam ? 0.048 : 0.012) * (tech.isFoamTeleport ? 1.66 : 1), //damage done over time
scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.6 : 1), scale: 1 - 0.006 / tech.isBulletsLastLonger * (tech.isFastFoam ? 1.6 : 1),
classType: "bullet", classType: "bullet",
collisionFilter: { collisionFilter: {
@@ -2449,6 +2449,8 @@ const b = {
target: null, target: null,
targetVertex: null, targetVertex: null,
targetRelativePosition: null, targetRelativePosition: null,
portFrequency: 5 + Math.floor(5 * Math.random()),
nextPortCycle: Infinity, //disabled unless you have the teleport tech
beforeDmg(who) { beforeDmg(who) {
if (!this.target && who.alive) { if (!this.target && who.alive) {
this.target = who; this.target = who;
@@ -2494,6 +2496,8 @@ const b = {
if (this.radius < 8) this.endCycle = 0; if (this.radius < 8) this.endCycle = 0;
} }
if (this.target && this.target.alive) { //if stuck to a target if (this.target && this.target.alive) { //if stuck to a target
const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
if (this.target.isVerticesChange) { if (this.target.isVerticesChange) {
@@ -2577,9 +2581,15 @@ const b = {
} }
} }
} }
if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isFoamTeleport
this.nextPortCycle = simulation.cycle + this.portFrequency
const range = 10 * Math.sqrt(this.radius) * Math.random()
Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
}
} }
} }
}); });
if (tech.isFoamTeleport) bullet[me].nextPortCycle = simulation.cycle + bullet[me].portFrequency
World.add(engine.world, bullet[me]); //add bullet to world World.add(engine.world, bullet[me]); //add bullet to world
Matter.Body.setVelocity(bullet[me], velocity); Matter.Body.setVelocity(bullet[me], velocity);
}, },
@@ -3502,9 +3512,9 @@ const b = {
fireNormal() { fireNormal() {
if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
const CD = Math.max(11 - 0.06 * (m.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down const CD = Math.max(11 - 0.06 * (m.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
this.nextFireCycle = m.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down this.nextFireCycle = m.cycle + CD * b.fireCDscale //predict next fire cycle if the fire button is held down
m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCDscale); // cool down
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD) this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD)
}, },
fireNeedles() { fireNeedles() {
@@ -3575,13 +3585,13 @@ const b = {
} }
if (m.crouch) { if (m.crouch) {
m.fireCDcycle = m.cycle + 45 * b.fireCD; // cool down m.fireCDcycle = m.cycle + 45 * b.fireCDscale; // cool down
makeNeedle() makeNeedle()
for (let i = 1; i < 4; i++) { //4 total needles for (let i = 1; i < 4; i++) { //4 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
} }
} else { } else {
m.fireCDcycle = m.cycle + 25 * b.fireCD; // cool down m.fireCDcycle = m.cycle + 25 * b.fireCDscale; // cool down
makeNeedle() makeNeedle()
for (let i = 1; i < 3; i++) { //3 total needles for (let i = 1; i < 3; i++) { //3 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i); setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
@@ -3595,7 +3605,7 @@ const b = {
// makeNeedle(m.angle - spread) // makeNeedle(m.angle - spread)
}, },
fireRivets() { fireRivets() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 25 : 17) * b.fireCDscale); // cool down
const me = bullet.length; const me = bullet.length;
const size = tech.rivetSize * 7.5 const size = tech.rivetSize * 7.5
@@ -3640,13 +3650,13 @@ const b = {
fireNailFireRate() { fireNailFireRate() {
if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing if (this.nextFireCycle + 1 < m.cycle) this.startingHoldCycle = m.cycle //reset if not constantly firing
const CD = Math.max(7.5 - 0.06 * (m.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down const CD = Math.max(7.5 - 0.06 * (m.cycle - this.startingHoldCycle), 2) //CD scales with cycles fire is held down
this.nextFireCycle = m.cycle + CD * b.fireCD //predict next fire cycle if the fire button is held down this.nextFireCycle = m.cycle + CD * b.fireCDscale //predict next fire cycle if the fire button is held down
m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(CD * b.fireCDscale); // cool down
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD) this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / CD)
}, },
fireInstantFireRate() { fireInstantFireRate() {
m.fireCDcycle = m.cycle + Math.floor(2 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(2 * b.fireCDscale); // cool down
this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / 2) this.baseFire(m.angle + (Math.random() - 0.5) * (Math.random() - 0.5) * (m.crouch ? 1.35 : 3.2) / 2)
}, },
baseFire(angle) { baseFire(angle) {
@@ -3685,18 +3695,18 @@ const b = {
let knock, spread let knock, spread
if (m.crouch) { if (m.crouch) {
spread = 0.65 spread = 0.65
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCD)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCD); //player is immune to damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(58 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(58 * b.fireCDscale); //player is immune to damage for 30 cycles
knock = 0.01 knock = 0.01
} else { } else {
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale); // cool down
if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCD)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCD); //player is immune to damage for 30 cycles if (tech.isShotgunImmune && m.immuneCycle < m.cycle + Math.floor(47 * b.fireCDscale)) m.immuneCycle = m.cycle + Math.floor(47 * b.fireCDscale); //player is immune to damage for 30 cycles
spread = 1.3 spread = 1.3
knock = 0.1 knock = 0.1
} }
if (tech.isShotgunRecoil) { if (tech.isShotgunRecoil) {
m.fireCDcycle -= 0.66 * (45 * b.fireCD) m.fireCDcycle -= 0.66 * (45 * b.fireCDscale)
player.force.x -= 2 * knock * Math.cos(m.angle) player.force.x -= 2 * knock * Math.cos(m.angle)
player.force.y -= 2 * knock * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps player.force.y -= 2 * knock * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
} else { } else {
@@ -3848,7 +3858,7 @@ const b = {
do() {}, do() {},
fireOne() { fireOne() {
const SPEED = m.crouch ? 43 : 36 const SPEED = m.crouch ? 43 : 36
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCDscale); // cool down
let dir = m.angle let dir = m.angle
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.polygon(m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle), 12, 21 * tech.bulletSize, b.fireAttributes(dir, false)); bullet[me] = Bodies.polygon(m.pos.x + 30 * Math.cos(m.angle), m.pos.y + 30 * Math.sin(m.angle), 12, 21 * tech.bulletSize, b.fireAttributes(dir, false));
@@ -3875,7 +3885,7 @@ const b = {
}, },
fireMulti() { fireMulti() {
const SPEED = m.crouch ? 43 : 36 const SPEED = m.crouch ? 43 : 36
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCDscale); // cool down
const SPREAD = m.crouch ? 0.08 : 0.13 const SPREAD = m.crouch ? 0.08 : 0.13
let dir = m.angle - SPREAD * (tech.superBallNumber - 1) / 2; let dir = m.angle - SPREAD * (tech.superBallNumber - 1) / 2;
for (let i = 0; i < tech.superBallNumber; i++) { for (let i = 0; i < tech.superBallNumber; i++) {
@@ -3908,7 +3918,7 @@ const b = {
const dir = m.angle const dir = m.angle
const x = m.pos.x + 30 * Math.cos(m.angle) const x = m.pos.x + 30 * Math.cos(m.angle)
const y = m.pos.y + 30 * Math.sin(m.angle) const y = m.pos.y + 30 * Math.sin(m.angle)
const delay = Math.floor((m.crouch ? 18 : 12) * b.fireCD) const delay = Math.floor((m.crouch ? 18 : 12) * b.fireCDscale)
m.fireCDcycle = m.cycle + delay; // cool down m.fireCDcycle = m.cycle + delay; // cool down
for (let i = 0; i < tech.superBallNumber; i++) { for (let i = 0; i < tech.superBallNumber; i++) {
@@ -3960,7 +3970,7 @@ const b = {
do() { do() {
if (this.wavePacketCycle && !input.fire) { if (this.wavePacketCycle && !input.fire) {
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
} }
}, },
damage: 1, damage: 1,
@@ -4060,7 +4070,7 @@ const b = {
//fire a packet of bullets then delay for a while //fire a packet of bullets then delay for a while
this.wavePacketCycle++ this.wavePacketCycle++
if (this.wavePacketCycle > tech.wavePacketLength) { if (this.wavePacketCycle > tech.wavePacketLength) {
m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(this.delay * b.fireCDscale); // cool down
this.wavePacketCycle = 0; this.wavePacketCycle = 0;
} }
} }
@@ -4076,7 +4086,7 @@ const b = {
fire() { fire() {
const countReduction = Math.pow(0.9, tech.missileCount) const countReduction = Math.pow(0.9, tech.missileCount)
if (m.crouch) { if (m.crouch) {
m.fireCDcycle = m.cycle + 10 * b.fireCD / countReduction; // cool down m.fireCDcycle = m.cycle + 10 * b.fireCDscale / countReduction; // cool down
// for (let i = 0; i < tech.missileCount; i++) { // for (let i = 0; i < tech.missileCount; i++) {
// b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5) * Math.sqrt(tech.missileCount), -2, Math.sqrt(countReduction)) // b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5) * Math.sqrt(tech.missileCount), -2, Math.sqrt(countReduction))
@@ -4102,7 +4112,7 @@ const b = {
b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5), -2) b.missile(where, -Math.PI / 2 + 0.2 * (Math.random() - 0.5), -2)
} }
} else { } else {
m.fireCDcycle = m.cycle + 50 * b.fireCD / countReduction; // cool down m.fireCDcycle = m.cycle + 50 * b.fireCDscale / countReduction; // cool down
const direction = { const direction = {
x: Math.cos(m.angle), x: Math.cos(m.angle),
y: Math.sin(m.angle) y: Math.sin(m.angle)
@@ -4147,7 +4157,7 @@ const b = {
// bullet[bullet.length - 1].force.x -= 0.015 * (i - 1); // bullet[bullet.length - 1].force.x -= 0.015 * (i - 1);
// } // }
// } else { // } else {
// m.fireCDcycle = m.cycle + 80 * b.fireCD; // cool down // m.fireCDcycle = m.cycle + 80 * b.fireCDscale; // cool down
// const direction = { // const direction = {
// x: Math.cos(m.angle), // x: Math.cos(m.angle),
// y: Math.sin(m.angle) // y: Math.sin(m.angle)
@@ -4164,7 +4174,7 @@ const b = {
// } // }
// } else { // } else {
// if (m.crouch) { // if (m.crouch) {
// m.fireCDcycle = m.cycle + 10 * b.fireCD; // cool down // m.fireCDcycle = m.cycle + 10 * b.fireCDscale; // cool down
// const off = Math.random() - 0.5 // const off = Math.random() - 0.5
// b.missile({ // b.missile({
// x: m.pos.x, // x: m.pos.x,
@@ -4174,7 +4184,7 @@ const b = {
// bullet[bullet.length - 1].force.x += off * 0.03; // bullet[bullet.length - 1].force.x += off * 0.03;
// // bullet[bullet.length - 1].force.y += push.y * (i - 1); // // bullet[bullet.length - 1].force.y += push.y * (i - 1);
// } else { // } else {
// m.fireCDcycle = m.cycle + 55 * b.fireCD; // cool down // m.fireCDcycle = m.cycle + 55 * b.fireCDscale; // cool down
// // bullet[bullet.length - 1].force.y += 0.01; //a small push down at first to make it seem like the missile is briefly falling // // bullet[bullet.length - 1].force.y += 0.01; //a small push down at first to make it seem like the missile is briefly falling
// } // }
@@ -4189,7 +4199,7 @@ const b = {
have: false, have: false,
do() {}, do() {},
fire() { fire() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 40 : 30) * b.fireCDscale); // cool down
b.grenade() b.grenade()
}, },
}, { }, {
@@ -4218,7 +4228,7 @@ const b = {
y: speed * Math.sin(m.angle) y: speed * Math.sin(m.angle)
}, 0, tech.isMineAmmoBack) }, 0, tech.isMineAmmoBack)
} }
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 50 : 25) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 50 : 25) * b.fireCDscale); // cool down
} }
}, { }, {
name: "spores", name: "spores",
@@ -4362,18 +4372,18 @@ const b = {
if (tech.isDroneRadioactive) { if (tech.isDroneRadioactive) {
if (m.crouch) { if (m.crouch) {
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45) b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
m.fireCDcycle = m.cycle + Math.floor(5 * 13 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(5 * 13 * b.fireCDscale); // cool down
} else { } else {
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 10) b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 10)
m.fireCDcycle = m.cycle + Math.floor(5 * 6 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(5 * 6 * b.fireCDscale); // cool down
} }
} else { } else {
if (m.crouch) { if (m.crouch) {
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45) b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCDscale); // cool down
} else { } else {
b.drone() b.drone()
m.fireCDcycle = m.cycle + Math.floor(6 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(6 * b.fireCDscale); // cool down
} }
} }
} }
@@ -4388,10 +4398,10 @@ const b = {
// fire() { // fire() {
// if (m.crouch) { // if (m.crouch) {
// b.iceIX(10, 0.3) // b.iceIX(10, 0.3)
// m.fireCDcycle = m.cycle + Math.floor(8 * b.fireCD); // cool down // m.fireCDcycle = m.cycle + Math.floor(8 * b.fireCDscale); // cool down
// } else { // } else {
// b.iceIX(2) // b.iceIX(2)
// m.fireCDcycle = m.cycle + Math.floor(3 * b.fireCD); // cool down // m.fireCDcycle = m.cycle + Math.floor(3 * b.fireCDscale); // cool down
// } // }
// } // }
@@ -4427,7 +4437,7 @@ const b = {
}, },
fire() { fire() {
this.charge++ this.charge++
m.fireCDcycle = m.cycle + Math.floor((1 + 0.35 * this.charge) * b.fireCD); m.fireCDcycle = m.cycle + Math.floor((1 + 0.35 * this.charge) * b.fireCDscale);
}, },
fireFoam() { fireFoam() {
const spread = (m.crouch ? 0.05 : 0.6) * (Math.random() - 0.5) const spread = (m.crouch ? 0.05 : 0.6) * (Math.random() - 0.5)
@@ -4517,7 +4527,7 @@ const b = {
if (tech.isCapacitor) { if (tech.isCapacitor) {
if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1) m.energy += 0.16 * (tech.isRailEnergyGain ? 6 : -1)
m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCD); m.fireCDcycle = m.cycle + Math.floor(30 * b.fireCDscale);
const me = bullet.length; const me = bullet.length;
bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, { bullet[me] = Bodies.rectangle(m.pos.x + 50 * Math.cos(m.angle), m.pos.y + 50 * Math.sin(m.angle), 60, 14, {
density: 0.005, //0.001 is normal density: 0.005, //0.001 is normal
@@ -4552,7 +4562,7 @@ const b = {
} }
}, },
onEnd() {}, onEnd() {},
drawCycle: Math.floor(10 * b.fireCD), drawCycle: Math.floor(10 * b.fireCDscale),
do() { do() {
this.force.y += this.mass * 0.0003; // low gravity that scales with charge this.force.y += this.mass * 0.0003; // low gravity that scales with charge
if (this.drawCycle > 0) { if (this.drawCycle > 0) {
@@ -4693,7 +4703,7 @@ const b = {
m.fireCDcycle = Infinity //can't fire until mouse is released m.fireCDcycle = Infinity //can't fire until mouse is released
const previousCharge = this.charge const previousCharge = this.charge
let smoothRate = 0.98 * (m.crouch ? 0.99 : 1) * (0.98 + 0.02 * b.fireCD) //small b.fireCD = faster shots, b.fireCD=1 = normal shot, big b.fireCD = slower chot let smoothRate = 0.98 * (m.crouch ? 0.99 : 1) * (0.98 + 0.02 * b.fireCDscale) //small b.fireCDscale = faster shots, b.fireCDscale=1 = normal shot, big b.fireCDscale = slower chot
this.charge = this.charge * smoothRate + 1 * (1 - smoothRate) this.charge = this.charge * smoothRate + 1 * (1 - smoothRate)
if (tech.isRailEnergyGain) { if (tech.isRailEnergyGain) {
if (m.immuneCycle < m.cycle) m.energy += (this.charge - previousCharge) * 2 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen if (m.immuneCycle < m.cycle) m.energy += (this.charge - previousCharge) * 2 //energy drain is proportional to charge gained, but doesn't stop normal m.fieldRegen
@@ -4827,12 +4837,12 @@ const b = {
this.do = () => {}; this.do = () => {};
if (tech.isPulseLaser) { if (tech.isPulseLaser) {
this.fire = () => { this.fire = () => {
const drain = 0.01 * tech.isLaserDiode / b.fireCD const drain = 0.01 * tech.isLaserDiode / b.fireCDscale
if (m.energy > drain) { if (m.energy > drain) {
m.energy -= m.fieldRegen m.energy -= m.fieldRegen
if (this.charge < 50 * m.maxEnergy) { if (this.charge < 50 * m.maxEnergy) {
m.energy -= drain m.energy -= drain
this.charge += 1 / b.fireCD this.charge += 1 / b.fireCDscale
} }
} }
} }
@@ -4905,7 +4915,7 @@ const b = {
// this.fire = this.firePhoton // this.fire = this.firePhoton
}, },
// firePhoton() { // firePhoton() {
// m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down // m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCDscale); // cool down
// b.photon({ x: m.pos.x + 23 * Math.cos(m.angle), y: m.pos.y + 23 * Math.sin(m.angle) }, m.angle) // b.photon({ x: m.pos.x + 23 * Math.cos(m.angle), y: m.pos.y + 23 * Math.sin(m.angle) }, m.angle)
// }, // },
fireLaser() { fireLaser() {
@@ -5041,7 +5051,7 @@ const b = {
} }
}, },
// firePulse() { // firePulse() {
// m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCD); // cool down // m.fireCDcycle = m.cycle + Math.floor((tech.isPulseAim ? 25 : 50) * b.fireCDscale); // cool down
// let energy = 0.3 * Math.min(m.energy, 1.5) // let energy = 0.3 * Math.min(m.energy, 1.5)
// m.energy -= energy * tech.isLaserDiode // m.energy -= energy * tech.isLaserDiode
// if (tech.beamSplitter) { // if (tech.beamSplitter) {
@@ -5082,7 +5092,7 @@ const b = {
if (this.rewindCount > 599 || m.energy < DRAIN || history.activeGun !== this.activeGunIndex) { if (this.rewindCount > 599 || m.energy < DRAIN || history.activeGun !== this.activeGunIndex) {
this.rewindCount = 0; this.rewindCount = 0;
m.resetHistory(); m.resetHistory();
m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor(120 * b.fireCDscale); // cool down
} else { } else {
m.energy -= DRAIN m.energy -= DRAIN
if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 5 cycles if (m.immuneCycle < m.cycle + 30) m.immuneCycle = m.cycle + 30; //player is immune to damage for 5 cycles

View File

@@ -119,6 +119,8 @@ 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
document.body.style.backgroundColor = "#fff"; document.body.style.backgroundColor = "#fff";
//disable pop up menu on right click //disable pop up menu on right click
@@ -195,7 +197,7 @@ const build = {
${simulation.isCheating? "<em>lore disabled</em><br><br>": ""} ${simulation.isCheating? "<em>lore disabled</em><br><br>": ""}
<strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}% <strong class='color-d'>damage</strong> increase: ${((tech.damageFromTech()-1)*100).toFixed(0)}%
<br><strong class='color-harm'>harm</strong> reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}% <br><strong class='color-harm'>harm</strong> reduction: ${harm.toFixed(harm > 90 ? 2 : 0)}%
<br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCD)*100).toFixed(b.fireCD < 0.1 ? 2 : 0)}% <br><strong><em>fire delay</em></strong> decrease: ${((1-b.fireCDscale)*100).toFixed(b.fireCDscale < 0.1 ? 2 : 0)}%
<br><strong class='color-dup'>duplication</strong> chance: ${(Math.min(1,tech.duplicationChance())*100).toFixed(0)}% <br><strong class='color-dup'>duplication</strong> chance: ${(Math.min(1,tech.duplicationChance())*100).toFixed(0)}%
${botText} ${botText}
<br> <br>

View File

@@ -15,9 +15,9 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode // simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(30) // level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
// m.setField("time dilation") // m.setField("metamaterial cloaking")
// b.giveGuns("grenades") // b.giveGuns("foam")
// tech.giveTech("neutron bomb") // tech.giveTech("uncertainty principle")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics") // for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// tech.giveTech("supertemporal") // tech.giveTech("supertemporal")
// for (let i = 0; i < 3; i++) tech.giveTech("packet length") // for (let i = 0; i < 3; i++) tech.giveTech("packet length")
@@ -1273,7 +1273,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 2000 - 650, y + -875);
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1281,6 +1280,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity); spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 2000 - 650, y + -875)
} else { } else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400); powerUps.spawnStartingPowerUps(x + 1650, y + -400);
spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall
@@ -1305,7 +1305,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875);
spawn.randomMob(x + 1600, y + -425, Infinity); spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity); spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity); spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1313,6 +1312,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity); spawn.randomMob(x + 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y + -875)
} }
}, },
(x = offset.x, y = offset.y) => { //spawn block and fire it (x = offset.x, y = offset.y) => { //spawn block and fire it
@@ -1365,7 +1365,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875);
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1373,6 +1372,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity); spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y + -875)
} else { } else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400); powerUps.spawnStartingPowerUps(x + 1650, y + -400);
spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall
@@ -1422,7 +1422,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875);
spawn.randomMob(x + 1600, y + -425, Infinity); spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity); spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity); spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1430,6 +1429,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity); spawn.randomMob(x + 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
} }
}, },
(x = offset.x, y = offset.y) => { //fire an "ammo clip" of blocks (x = offset.x, y = offset.y) => { //fire an "ammo clip" of blocks
@@ -1493,7 +1493,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875);
spawn.randomMob(x + 2000 - 1600, y + -425, Infinity); spawn.randomMob(x + 2000 - 1600, y + -425, Infinity);
spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity); spawn.randomMob(x + 2000 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity); spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1501,6 +1500,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity); spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 2000 - 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
} else { } else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400); powerUps.spawnStartingPowerUps(x + 1650, y + -400);
spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall spawn.mapRect(x + 1575, y + -625, 25, 375); //wall on top of wall
@@ -1561,7 +1561,6 @@ const level = {
} }
} }
) )
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(x + 650, y + -875);
spawn.randomMob(x + 1600, y + -425, Infinity); spawn.randomMob(x + 1600, y + -425, Infinity);
spawn.randomMob(x + 1725, y + -1250, Infinity); spawn.randomMob(x + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity); spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1569,6 +1568,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity); spawn.randomMob(x + 800, y + -125, Infinity);
let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)]; let pick = spawn.pickList[Math.floor(Math.random() * spawn.pickList.length)];
spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob spawn[pick](x + 1275, y + -150, 90 + Math.random() * 40); //one extra large mob
spawn.secondaryBossChance(x + 650, y - 875)
} }
} }
] ]
@@ -2169,7 +2169,6 @@ const level = {
// spawn.randomGroup(1700, -900, 0.4); // spawn.randomGroup(1700, -900, 0.4);
// if (simulation.difficulty > 3) spawn.randomLevelBoss(2200, -1300); // if (simulation.difficulty > 3) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
// if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(4800, -500);
}, },
final() { final() {
level.custom = () => { level.custom = () => {
@@ -2219,7 +2218,7 @@ const level = {
spawn.mapRect(5700, -3300, 1800, 5100); //right wall spawn.mapRect(5700, -3300, 1800, 5100); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
spawn.mapRect(5425, -650, 375, 450); //blocking exit spawn.mapRect(5425, -650, 375, 450); //blocking exit
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(4800, -500); spawn.secondaryBossChance(4800, -500)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -2289,7 +2288,7 @@ const level = {
if (simulation.difficulty * Math.random() > 7 * i) spawn.randomGroup(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity); if (simulation.difficulty * Math.random() > 7 * i) spawn.randomGroup(5000 + 500 * (Math.random() - 0.5), -800 + 200 * (Math.random() - 0.5), Infinity);
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(4125, -350); spawn.secondaryBossChance(4125, -350)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -2509,7 +2508,6 @@ const level = {
} }
} }
powerUps.spawnStartingPowerUps(2300, -150); powerUps.spawnStartingPowerUps(2300, -150);
// if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(1900, -675);
}, },
testChamber() { testChamber() {
level.setPosToSpawn(0, -50); //lower start level.setPosToSpawn(0, -50); //lower start
@@ -2705,8 +2703,7 @@ const level = {
} }
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(1925, -1250); spawn.secondaryBossChance(1925, -1250)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -2913,8 +2910,7 @@ const level = {
spawn.randomMob(2825, 400, 0.9); spawn.randomMob(2825, 400, 0.9);
if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "historyBoss", "orbitalBoss", "shieldingBoss"]); if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "historyBoss", "orbitalBoss", "shieldingBoss"]);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275); spawn.secondaryBossChance(7725, 2275)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3101,7 +3097,7 @@ const level = {
} }
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850); spawn.secondaryBossChance(3950, -850)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3272,7 +3268,7 @@ const level = {
spawn.randomGroup(4900, -1200, 0); spawn.randomGroup(4900, -1200, 0);
if (simulation.difficulty > 3) spawn.randomLevelBoss(3200, -1900); if (simulation.difficulty > 3) spawn.randomLevelBoss(3200, -1900);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(2175, -2425); spawn.secondaryBossChance(2175, -2425)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3489,7 +3485,7 @@ const level = {
} }
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(5350, -325); spawn.secondaryBossChance(5350, -325)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3657,7 +3653,7 @@ const level = {
spawn.randomGroup(1700, -900, 0.4); spawn.randomGroup(1700, -900, 0.4);
if (simulation.difficulty > 3) spawn.randomLevelBoss(2600, -2300); if (simulation.difficulty > 3) spawn.randomLevelBoss(2600, -2300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3075, -2050); spawn.secondaryBossChance(3075, -2050)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3899,7 +3895,7 @@ const level = {
if (simulation.difficulty > 3) spawn.randomLevelBoss(-2400, -2650); if (simulation.difficulty > 3) spawn.randomLevelBoss(-2400, -2650);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(-1825, -1975); spawn.secondaryBossChance(-1825, -1975)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -4206,8 +4202,8 @@ const level = {
spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head spawn.snakeBoss(-1000 + Math.random() * 2500, -1300); //boss snake with head
} }
} }
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(300, -800);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(300, -800)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -4438,7 +4434,7 @@ const level = {
} }
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(1875, -675); spawn.secondaryBossChance(1875, -675)
if (simulation.isHorizontalFlipped) { //flip the map horizontally if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -5920,7 +5916,7 @@ const level = {
} }
} }
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275); spawn.secondaryBossChance(7725, 2275)
}, },
coliseum() { coliseum() {
level.custom = () => { level.custom = () => {
@@ -6070,8 +6066,7 @@ const level = {
powerUps.spawn(200, 50, "ammo"); powerUps.spawn(200, 50, "ammo");
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(6600, 600)
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(6600, 600, ["historyBoss", "powerUpBoss", "pulsarBoss", "orbitalBoss"]);
}, },
crossfire() { crossfire() {
//*1.5 //*1.5
@@ -6179,12 +6174,8 @@ const level = {
// spawn.randomGroup(7700, -1100, 0.5); // spawn.randomGroup(7700, -1100, 0.5);
spawn.randomGroup(9800, -1100, 0.5); spawn.randomGroup(9800, -1100, 0.5);
if (simulation.difficulty > 10) { if (simulation.difficulty > 10) spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "snakeBoss", "spiderBoss", "historyBoss"])
spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "snakeBoss", "spiderBoss", "historyBoss"]); spawn.secondaryBossChance(7900, -400)
}
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) {
spawn.randomLevelBoss(7900, -400, ["powerUpBoss", "spiderBoss", "historyBoss"]);
}
//Boss Spawning //Boss Spawning
if (simulation.difficulty > 10) { if (simulation.difficulty > 10) {
@@ -6422,7 +6413,7 @@ const level = {
} else { } else {
exitDoor.isOpen = false; exitDoor.isOpen = false;
} }
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(800, -800); spawn.secondaryBossChance(800, -800)
powerUps.spawn(4450, 1050, "heal"); powerUps.spawn(4450, 1050, "heal");
if (Math.random() > (0.2 + (simulation.difficulty / 60))) { if (Math.random() > (0.2 + (simulation.difficulty / 60))) {
@@ -6933,15 +6924,7 @@ const level = {
spawn.randomLevelBoss(850 + Math.random() * 250, -1100 + Math.random() * 200, bosses); spawn.randomLevelBoss(850 + Math.random() * 250, -1100 + Math.random() * 200, bosses);
} }
} }
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) { spawn.secondaryBossChance(850 + Math.random() * 250, -1100 + Math.random() * 200)
if (abc < 0.6 * 5 / 8 || abc >= 1 - 0.15 * 5 / 17) {
spawn.laserBoss(-350 + Math.random() * 300, -600 + Math.random() * 200);
} else if (abc < 0.65) {
spawn.randomLevelBoss(850 + Math.random() * 250, -1100 + Math.random() * 200, bosses);
} else {
spawn.randomLevelBoss(-1500 + Math.random() * 250, -1100 + Math.random() * 200, bosses);
}
}
//draw leg for statue //draw leg for statue
function statueLeg(shift, color) { function statueLeg(shift, color) {

View File

@@ -49,6 +49,7 @@ const m = {
eyeFillColor: null, eyeFillColor: null,
fillColor: null, //set by setFillColors fillColor: null, //set by setFillColors
fillColorDark: null, //set by setFillColors fillColorDark: null, //set by setFillColors
bodyGradient: null, //set by setFillColors
color: { color: {
hue: 0, hue: 0,
sat: 0, sat: 0,
@@ -57,6 +58,10 @@ const m = {
setFillColors() { setFillColors() {
this.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)` this.fillColor = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light}%)`
this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light-25}%)` this.fillColorDark = `hsl(${m.color.hue},${m.color.sat}%,${m.color.light-25}%)`
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
this.bodyGradient = grd
}, },
height: 42, height: 42,
yOffWhen: { yOffWhen: {
@@ -803,10 +808,7 @@ const m = {
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient;
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
@@ -838,10 +840,7 @@ const m = {
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
@@ -873,10 +872,7 @@ const m = {
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
@@ -1091,8 +1087,8 @@ const m = {
if (input.field) { if (input.field) {
if (m.energy > 0.001) { if (m.energy > 0.001) {
if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle if (m.fireCDcycle < m.cycle) m.fireCDcycle = m.cycle
m.energy -= 0.001 / tech.throwChargeRate; m.throwCharge += 0.5 * (tech.throwChargeRate / b.fireCDscale + 2 * tech.isAddBlockMass) / m.holdingTarget.mass
m.throwCharge += 0.5 * (tech.throwChargeRate + 2 * tech.isAddBlockMass) / m.holdingTarget.mass if (m.throwCharge < 6) m.energy -= 0.001 / tech.throwChargeRate / b.fireCDscale; // m.throwCharge caps at 5
//draw charge //draw charge
const x = m.pos.x + 15 * Math.cos(m.angle); const x = m.pos.x + 15 * Math.cos(m.angle);
const y = m.pos.y + 15 * Math.sin(m.angle); const y = m.pos.y + 15 * Math.sin(m.angle);
@@ -2996,10 +2992,7 @@ const m = {
//body //body
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";

View File

@@ -223,7 +223,7 @@ const powerUps = {
b.randomBot() b.randomBot()
if (tech.renormalization) { if (tech.renormalization) {
for (let i = 0; i < limit; i++) { for (let i = 0; i < limit; i++) {
if (Math.random() < 0.37) { if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30; m.fieldCDcycle = m.cycle + 30;
powerUps.spawn(m.pos.x, m.pos.y, "research"); powerUps.spawn(m.pos.x, m.pos.y, "research");
} }
@@ -234,7 +234,7 @@ const powerUps = {
if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) { if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) {
document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}` document.getElementById("tech-anthropic").innerHTML = `-${powerUps.research.count}`
} }
if (tech.renormalization && Math.random() < 0.37 && amount < 0) { if (tech.renormalization && Math.random() < 0.4 && amount < 0) {
for (let i = 0, len = -amount; i < len; i++) powerUps.spawn(m.pos.x, m.pos.y, "research"); for (let i = 0, len = -amount; i < len; i++) powerUps.spawn(m.pos.x, m.pos.y, "research");
} }
if (tech.isRerollHaste) { if (tech.isRerollHaste) {

View File

@@ -87,6 +87,19 @@ const spawn = {
// other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool // other bosses: suckerBoss, laserBoss, tetherBoss, //these need a particular level to work so they are not included in the random pool
spawn[options[Math.floor(Math.random() * options.length)]](x, y) spawn[options[Math.floor(Math.random() * options.length)]](x, y)
}, },
secondaryBossChance(x, y) {
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) {
spawn.randomLevelBoss(x, y);
} else if (tech.isResearchBoss) {
if (powerUps.research.count > 4) {
powerUps.research.changeRerolls(-5)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>-=</span> 5<br>${powerUps.research.count}`)
} else {
tech.addJunkTechToPool(49)
}
spawn.randomLevelBoss(x, y);
}
},
//mob templates ********************************************************************************************* //mob templates *********************************************************************************************
//*********************************************************************************************************** //***********************************************************************************************************
MACHO(x = m.pos.x, y = m.pos.y) { //immortal mob that follows player //if you have the tech it spawns at start of every level at the player MACHO(x = m.pos.x, y = m.pos.y) { //immortal mob that follows player //if you have the tech it spawns at start of every level at the player

View File

@@ -66,6 +66,7 @@
if (options.length) { if (options.length) {
for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++ for (let i = 0; i < num; i++) tech.tech[options[Math.floor(Math.random() * options.length)]].frequency++
} }
simulation.makeTextLog(`<span class='color-var'>tech</span>.tech.push(${num} <span class='color-text'>JUNK</span>)`)
}, },
removeJunkTechFromPool(num = 1) { removeJunkTechFromPool(num = 1) {
for (let j = 0; j < num; j++) { for (let j = 0; j < num; j++) {
@@ -77,11 +78,6 @@
} }
} }
}, },
// removeJunkTechFromPool() {
// for (let i = tech.tech.length - 1; i > 0; i--) {
// if (tech.tech[i].isJunk && tech.tech[i].count === 0) tech.tech.splice(i, 1)
// }
// },
giveTech(index = 'random') { giveTech(index = 'random') {
if (index === 'random') { if (index === 'random') {
let options = []; let options = [];
@@ -93,7 +89,6 @@
let newTech = options[Math.floor(Math.random() * options.length)] let newTech = options[Math.floor(Math.random() * options.length)]
tech.giveTech(newTech) tech.giveTech(newTech)
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[newTech].name}</span>")<em> //random tech</em>`); simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[newTech].name}</span>")<em> //random tech</em>`);
} }
} else { } else {
if (isNaN(index)) { //find index by name if (isNaN(index)) { //find index by name
@@ -704,6 +699,24 @@
tech.isRadioactive = false tech.isRadioactive = false
} }
}, },
{
name: "water shielding",
description: "<strong class='color-p'>radioactive</strong> effects on you are reduced by 75%<br><em>neutron bomb, drones, explosions, slime</em>",
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isNeutronBomb || tech.isDroneRadioactive || tech.isExplodeRadio
},
requires: "neutron bomb or irradiated drones or iridium-192",
effect() {
tech.isRadioactiveResistance = true
},
remove() {
tech.isRadioactiveResistance = false
}
},
{ {
name: "iridium-192", name: "iridium-192",
description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>100%</strong> more <strong class='color-d'>damage</strong>, but over 4 seconds", description: "<strong class='color-e'>explosions</strong> release <strong class='color-p'>gamma radiation</strong><br><strong>100%</strong> more <strong class='color-d'>damage</strong>, but over 4 seconds",
@@ -951,15 +964,15 @@
}, },
{ {
name: "decorrelation", name: "decorrelation",
description: "reduce <strong class='color-harm'>harm</strong> by <strong>66%</strong><br>after not using 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>66%</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",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (b.totalBots() > 1 || tech.haveGunCheck("mine") || tech.haveGunCheck("spores") || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing") && !tech.isEnergyHealth return ((m.fieldUpgrades[m.fieldMode].name === "standing wave harmonics" && (tech.blockingIce !== 0 || tech.blockDmg !== 0)) || b.totalBots() > 1 || tech.haveGunCheck("mine") || tech.haveGunCheck("spores") || m.fieldUpgrades[m.fieldMode].name === "nano-scale manufacturing") && !tech.isEnergyHealth
}, },
requires: "drones, spores, mines, or bots", requires: "drones, spores, mines, or bots, ",
effect() { effect() {
tech.isNoFireDefense = true tech.isNoFireDefense = true
}, },
@@ -2244,7 +2257,7 @@
}, },
{ {
name: "overcharge", name: "overcharge",
description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br>add <strong>10</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "increase your <strong>maximum</strong> <strong class='color-f'>energy</strong> by <strong>60</strong><br><strong>+10</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2266,7 +2279,7 @@
}, },
{ {
name: "Maxwell's demon", name: "Maxwell's demon",
description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br>add <strong>18</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "<strong class='color-f'>energy</strong> above your max decays <strong>92%</strong> slower<br><strong>+18</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -2712,7 +2725,7 @@
}, },
{ {
name: "renormalization", name: "renormalization",
description: "using a <strong class='color-r'>research</strong> for <strong>any</strong> purpose<br>has a <strong>37%</strong> chance to spawn a <strong class='color-r'>research</strong>", description: "using a <strong class='color-r'>research</strong> for <strong>any</strong> purpose<br>has a <strong>40%</strong> chance to spawn a <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -2819,6 +2832,24 @@
}, },
remove() {} remove() {}
}, },
{
name: "abiogenesis",
description: "at the start of a level spawn a 2nd <strong>boss</strong> for<br><strong>5</strong> <strong class='color-r'>research</strong> or <strong>+49</strong> <strong class='color-j'>JUNK</strong> to the <strong class='color-m'>tech</strong> pool",
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return (build.isExperimentSelection || powerUps.research.count > 4) && !tech.isDuplicateBoss
},
requires: "at least 5 research and not parthenogenesis",
effect() {
tech.isResearchBoss = true; //abiogenesis
},
remove() {
tech.isResearchBoss = false;
}
},
{ {
name: "bubble fusion", name: "bubble fusion",
description: "after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>", description: "after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> <strong class='color-h'>heals</strong>, <strong class='color-g'>ammo</strong>, or <strong class='color-r'>research</strong>",
@@ -2857,7 +2888,7 @@
}, },
{ {
name: "replication", name: "replication",
description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>18</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "<strong>10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+18</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2983,9 +3014,9 @@
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.duplicationChance() > 0 return tech.duplicationChance() > 0 && !tech.isResearchBoss
}, },
requires: "some duplication chance", requires: "some duplication chance, not abiogenesis",
effect() { effect() {
tech.isDuplicateBoss = true; tech.isDuplicateBoss = true;
}, },
@@ -3259,7 +3290,7 @@
}, },
{ {
name: "dark patterns", name: "dark patterns",
description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br>add <strong>21</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "reduce combat <strong>difficulty</strong> by <strong>1 level</strong><br><strong>+21</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -4058,25 +4089,6 @@
b.setGrenadeMode() b.setGrenadeMode()
} }
}, },
{
name: "water shielding",
description: "<strong class='color-p'>radioactive</strong> effects on you are reduced by 75%<br><em>neutron bomb, drones, explosions, slime</em>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.isNeutronBomb || tech.isDroneRadioactive || tech.isExplodeRadio
},
requires: "neutron bomb or irradiated drones or iridium-192",
effect() {
tech.isRadioactiveResistance = true
},
remove() {
tech.isRadioactiveResistance = false
}
},
{ {
name: "vacuum permittivity", name: "vacuum permittivity",
description: "increase <strong class='color-p'>radioactive</strong> range by <strong>20%</strong><br>objects in range of the bomb are <strong>slowed</strong>", description: "increase <strong class='color-p'>radioactive</strong> range by <strong>20%</strong><br>objects in range of the bomb are <strong>slowed</strong>",
@@ -4155,7 +4167,7 @@
}, },
{ {
name: "booby trap", name: "booby trap",
description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br>add <strong>13</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "drop a <strong>mine</strong> after picking up a <strong>power up</strong><br><strong>+13</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 2, frequency: 2,
@@ -4410,6 +4422,25 @@
tech.droneRadioDamage = 1 tech.droneRadioDamage = 1
} }
}, },
{
name: "uncertainty principle",
description: "<strong>foam</strong> bubbles randomly change <strong>position</strong><br>increase <strong>foam</strong> <strong class='color-d'>damage</strong> per second by <strong>66%</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isFoamAttract && (tech.haveGunCheck("foam") || tech.foamBotCount > 1)
},
requires: "foam, not electrostatic induction",
effect() {
tech.isFoamTeleport = true
},
remove() {
tech.isFoamTeleport = false;
}
},
{ {
name: "necrophoresis", name: "necrophoresis",
description: "<strong>foam</strong> bubbles grow and split into 3 <strong>copies</strong><br> when the mob they are stuck to <strong>dies</strong>", description: "<strong>foam</strong> bubbles grow and split into 3 <strong>copies</strong><br> when the mob they are stuck to <strong>dies</strong>",
@@ -4450,25 +4481,6 @@
tech.foamGravity = 0.00008 tech.foamGravity = 0.00008
} }
}, },
{
name: "electrostatic induction",
description: "<strong>foam</strong> bullets are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.haveGunCheck("foam") || tech.foamBotCount > 1
},
requires: "foam",
effect() {
tech.isFoamAttract = true
},
remove() {
tech.isFoamAttract = false
}
},
{ {
name: "quantum foam", name: "quantum foam",
description: "<strong>foam</strong> gun fires <strong>0.30</strong> seconds into the <strong>future</strong><br>increase <strong>foam</strong> gun <strong class='color-d'>damage</strong> by <strong>90%</strong>", description: "<strong>foam</strong> gun fires <strong>0.30</strong> seconds into the <strong>future</strong><br>increase <strong>foam</strong> gun <strong class='color-d'>damage</strong> by <strong>90%</strong>",
@@ -4507,6 +4519,25 @@
tech.isAmmoFoamSize = false; tech.isAmmoFoamSize = false;
} }
}, },
{
name: "electrostatic induction",
description: "<strong>foam</strong> bullets are electrically charged<br>causing <strong>attraction</strong> to nearby <strong>mobs</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return !tech.isFoamTeleport && (tech.haveGunCheck("foam") || tech.foamBotCount > 1)
},
requires: "foam, not uncertainty",
effect() {
tech.isFoamAttract = true
},
remove() {
tech.isFoamAttract = false
}
},
{ {
name: "half-wave rectifier", name: "half-wave rectifier",
description: "charging the <strong>rail gun</strong> gives you <strong class='color-f'>energy</strong><br><em>instead of draining it</em>", description: "charging the <strong>rail gun</strong> gives you <strong class='color-f'>energy</strong><br><em>instead of draining it</em>",
@@ -6454,7 +6485,7 @@
}, },
{ {
name: "expert system", name: "expert system",
description: "spawn a <strong class='color-m'>tech</strong> power up<br>add <strong>64</strong> <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> to the potential pool", description: "spawn a <strong class='color-m'>tech</strong> power up<br><strong>+64</strong> <strong class='color-j'>JUNK</strong> to the potential <strong class='color-m'>tech</strong> pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -6604,10 +6635,7 @@
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
@@ -6652,10 +6680,7 @@
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI); ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
@@ -6694,10 +6719,7 @@
ctx.rotate(m.angle); ctx.rotate(m.angle);
ctx.beginPath(); ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI); ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0); ctx.fillStyle = this.bodyGradient
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fill(); ctx.fill();
ctx.strokeStyle = "#333"; ctx.strokeStyle = "#333";
ctx.lineWidth = 2; ctx.lineWidth = 2;
@@ -6909,7 +6931,7 @@
}, },
{ {
name: "quantum black hole", name: "quantum black hole",
description: "use all your <strong class='color-f'>energy</strong> to <strong>spawn</strong><br>inside the event horizon of a huge <strong>black hole</strong>", description: "use your <strong class='color-f'>energy</strong> and <strong>1</strong> <strong class='color-r'>research</strong> to <strong>spawn</strong><br>inside the event horizon of a huge <strong>black hole</strong>",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
frequency: 0, frequency: 0,
@@ -6917,12 +6939,14 @@
isExperimentHide: true, isExperimentHide: true,
isJunk: true, isJunk: true,
allowed() { allowed() {
return true return powerUps.research.count > 0
}, },
requires: "", requires: "at least 1 research",
effect() { effect() {
m.energy = 0 m.energy = 0
spawn.suckerBoss(m.pos.x, m.pos.y - 1000) spawn.suckerBoss(m.pos.x, m.pos.y - 1000)
powerUps.research.changeRerolls(-1)
simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-r'>research</span> <span class='color-symbol'>--</span><br>${powerUps.research.count}`)
}, },
remove() {} remove() {}
}, },
@@ -7267,5 +7291,7 @@
isBlockExplode: null, isBlockExplode: null,
isOverHeal: null, isOverHeal: null,
isDroneRadioactive: null, isDroneRadioactive: null,
droneRadioDamage: null droneRadioDamage: null,
isFoamTeleport: null,
isResearchBoss: null
} }

289
todo.txt
View File

@@ -1,170 +1,19 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
irradiated drones tech: abiogenesis - spawn a second level boss on each level, but costs 5 research or if you don't have the research add 49 JUNK tech to the pool
new tech: beta radiation - double damage and half lifespan note to level builders I rewrote the add duplicate boss code in all levels: spawn.secondaryBossChance(x,y)
now don't clump as often, to make the graphics look better
effective radius now includes edges of mobs, not just centers
so they work better on large radius mobs
do 50% more damage, but have a 10% smaller radius and last 3 second shorter time and 80% less ammo (was 75%)
irradiated drones can't get a slowing effect anymore
it was just too annoying
nano-scale can now unlock irradiated drone tech properly
nano-scale now drains more energy per irradiated drone, to scale with the higher ammo costs
time dilation field is now just called "time dilation" foam tech: uncertainty principle - foam bullets change position randomly, increase foam damage by 66%
constraints under time dilation is less buggy, but still a bit buggy
******************************************************** BUGS ******************************************************** throwing blocks now charges faster with reduced fire cooldown
tech renormalization now has a 40% chance to refund a research (was 37%)
player can become crouched while not touching the ground if they exit the ground while crouched performance- now precalculate player gradient fill
a couple times people have reported the final boss dropping extra bodies on death
Why does micro-extruder lag so much
blue triangle boss can move backwards and aim away from you if set up properly
issues with dot product probably, but might not be worth fixing
mouse event e.which is deprecated
fix door.isOpen actually meaning isClosed?
make it so that when you are immune to harm you can either jump on mobs or you pass through them
is there a way to check if the player is stuck inside the map or block
trigger a short term non-collide if that occurs
(intermittent, but almost every time) bug - capping the fps causes random slow downs, that can be fixed with pause
******************************************************** LEVELS ********************************************************
labs - procedural generation
bugs
mob spawns shouldn't be based on probability?
style
graphics look too bright?
add shadows and lighting and graphic details?
what about performance?
with the mobs staggered spawning it should be fine
feel
disrupt the flat ground
less platforming / easier platforming
the spinners on exit are still too hard...
make combat more interesting
is it laggy?
in loot room, spawn mobs after power up is grabbed
more background graphics, better colors
loot room:
make it more interesting to get the power up
slow player and reduce damage in region
increase the size of the region
don't have space for much
make graphics more unique
push player away, so that normal pick up methods don't work, but add a button to disable region
room ideas -
portal room
endlessly falling blocks down a slide, that the player has to climb up
portal + rotor + falling blocks = perpetual motion
slime room
sound room, with buttons to control sound
color room with r,g,b buttons to control color
mob buff zone: Map element: "Orbital Pickup Zone": Mobs that enter a specific area of the map gain +1 orbital per second, or a shield
could put in the loot room
buttons can now on/off boosts
repeat map in vertical when you fall teleport to above the mab, as if the map repeats
camera looks strange when you teleport player with a high velocity
map element - player rotates a rotor that makes a platform go up or down
level element: a zone with wind, anti-gravity, extra gravity
control with button
map: observatory
button controls rotation of telescope
laser beam shoots out of telescope
button opens the dome
******************************************************** MOBS ********************************************************
mob mechanics
use the force at a location effect, like the plasma field
Matter.Body.applyForce(who, path[1], force)
mob - after taking damage
release seekers
teleports
hop boss:
AoE damage when landing
pull in player? and blocks?
extra gravity on falling?
immune to damage while falling?
mob: molecule shapes - 2 separate mobs joined by a bond
use constraints: just spawn 2x or 3x groupings
low friction so they can spin around
spin when attacking player?
increase constraint length when attacking
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
write find in spawn undo exploder, but commented out
Mob: "Tentacle": Sits on wall. Is a black blob. When you get near it, reaches out and grabs you, similar to wires. Does not deal damage.
maybe it could be immune to damage? but it is spawned by an actual mob
level Boss: fractal Sierpiński triangle
https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle
spawns a 1/2 size version of the boss, this version can also spawn a smaller version, but it is capped at some size level
they spawn once at the start of the level
if a version dies, one can be replaced every ten seconds by the largest version
give mobs more animal-like behaviors like rain world
mobs play, look for food, explore
mobs some times aren't aggressive
when low on life or after taking a large hit
mobs can fight each other
this might be hard to code
isolated mobs try to group up
mob: wall mounted guns / lasers
not part of randomized mob pool, customized to each level
level boss: fires a line intersection in a random direction every few seconds.
the last two intersections have a destructive laser between them.
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
tech - shorter cloaking delay
irradiated drones, get annoying when they go after mobs near the player...
should they only follow mouse? or at least show a preference for targets near mouse, not near player
tech - 1/2 your drone ammo/efficiency double the damage?
tech foam teleports around, like a quantum wave function collapse
should ammo apply to all guns, or just one of your guns? should ammo apply to all guns, or just one of your guns?
if one gun only, it would make multi-gun builds weaker if one gun only, it would make multi-gun builds weaker
nail bots should benefit from nail gun tech
tech: picking up heal power ups at max health does harm, but increases max health
scales with heal value
let standing wave harmonics get tech decorrelation
tech: cloaking field - decrease/increase cooldown on sneak attack?
decrease/increase damage bonus?
decrease/increase visual radius?
have throw charge scale with fire delay
in testing mode console log the body you click on in testing mode console log the body you click on
throwing a block removes the block and rewinds time 10 seconds (including health and energy) throwing a block removes the block and rewinds time 10 seconds (including health and energy)
@@ -174,8 +23,6 @@ tech plasma : plasma length increases then decreases as you hold down the field
grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again grows to 1.5 longer after 0.3 seconds, then returns to normal length over 1 second, until field is pressed again
extra energy is drained when field is longer extra energy is drained when field is longer
tech: at the start of a new level remove 5 research and spawn a second boss
energy conservation 6% damage recovered as energy energy conservation 6% damage recovered as energy
add a negative effect: add a negative effect:
junk tech junk tech
@@ -335,6 +182,129 @@ n-gon outreach ideas
hacker news - show hacker news post hacker news - show hacker news post
twitch - lets play twitch - lets play
******************************************************** BUGS ********************************************************
player can become crouched while not touching the ground if they exit the ground while crouched
a couple times people have reported the final boss dropping extra bodies on death
Why does micro-extruder lag so much
blue triangle boss can move backwards and aim away from you if set up properly
issues with dot product probably, but might not be worth fixing
mouse event e.which is deprecated
fix door.isOpen actually meaning isClosed?
make it so that when you are immune to harm you can either jump on mobs or you pass through them
is there a way to check if the player is stuck inside the map or block
trigger a short term non-collide if that occurs
(intermittent, but almost every time) bug - capping the fps causes random slow downs, that can be fixed with pause
******************************************************** LEVELS ********************************************************
labs - procedural generation
bugs
mob spawns shouldn't be based on probability?
style
graphics look too bright?
add shadows and lighting and graphic details?
what about performance?
with the mobs staggered spawning it should be fine
feel
disrupt the flat ground
less platforming / easier platforming
the spinners on exit are still too hard...
make combat more interesting
is it laggy?
in loot room, spawn mobs after power up is grabbed
more background graphics, better colors
loot room:
make it more interesting to get the power up
slow player and reduce damage in region
increase the size of the region
don't have space for much
make graphics more unique
push player away, so that normal pick up methods don't work, but add a button to disable region
room ideas -
portal room
endlessly falling blocks down a slide, that the player has to climb up
portal + rotor + falling blocks = perpetual motion
slime room
sound room, with buttons to control sound
color room with r,g,b buttons to control color
mob buff zone: Map element: "Orbital Pickup Zone": Mobs that enter a specific area of the map gain +1 orbital per second, or a shield
could put in the loot room
buttons can now on/off boosts
repeat map in vertical when you fall teleport to above the mab, as if the map repeats
camera looks strange when you teleport player with a high velocity
map element - player rotates a rotor that makes a platform go up or down
level element: a zone with wind, anti-gravity, extra gravity
control with button
map: observatory
button controls rotation of telescope
laser beam shoots out of telescope
button opens the dome
******************************************************** MOBS ********************************************************
mob mechanics
use the force at a location effect, like the plasma field
Matter.Body.applyForce(who, path[1], force)
mob - after taking damage
release seekers
teleports
hop boss:
AoE damage when landing
pull in player? and blocks?
extra gravity on falling?
immune to damage while falling?
mob: molecule shapes - 2 separate mobs joined by a bond
use constraints: just spawn 2x or 3x groupings
low friction so they can spin around
spin when attacking player?
increase constraint length when attacking
mob vision: look at player history
build a new type of attraction for mobs
if mobs can't see player, they check to see if they can see where the player was in the history
if mobs can't see player, they could check to see if they can find player in the past
https://abitawake.com/news/articles/enemy-ai-chasing-a-player-without-navigation2d-or-a-star-pathfinding
write find in spawn undo exploder, but commented out
Mob: "Tentacle": Sits on wall. Is a black blob. When you get near it, reaches out and grabs you, similar to wires. Does not deal damage.
maybe it could be immune to damage? but it is spawned by an actual mob
level Boss: fractal Sierpiński triangle
https://en.wikipedia.org/wiki/Sierpi%C5%84ski_triangle
spawns a 1/2 size version of the boss, this version can also spawn a smaller version, but it is capped at some size level
they spawn once at the start of the level
if a version dies, one can be replaced every ten seconds by the largest version
give mobs more animal-like behaviors like rain world
mobs play, look for food, explore
mobs some times aren't aggressive
when low on life or after taking a large hit
mobs can fight each other
this might be hard to code
isolated mobs try to group up
mob: wall mounted guns / lasers
not part of randomized mob pool, customized to each level
level boss: fires a line intersection in a random direction every few seconds.
the last two intersections have a destructive laser between them.
******************************************************** LORE ******************************************************** ******************************************************** LORE ********************************************************
@@ -342,7 +312,6 @@ possible names for tech
strange loop strange loop
holonomy - parallel transport of a vector leads to movement (applies to curved space) holonomy - parallel transport of a vector leads to movement (applies to curved space)
hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other. hypergolic - A hypergolic propellant combination used in a rocket engine is one whose components spontaneously ignite when they come into contact with each other.
uncertainty principle
swarm intelligence - for a drone tech swarm intelligence - for a drone tech
genetic algorithm genetic algorithm
metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity metaheuristic - is a higher-level procedure or heuristic designed to find, generate, or select a heuristic (partial search algorithm) that may provide a sufficiently good solution to an optimization problem, especially with incomplete or imperfect information or limited computation capacity