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) {
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], {
x: m.Vx / 2 + speed * Math.cos(dir),
y: m.Vy / 2 + speed * Math.sin(dir)
});
World.add(engine.world, bullet[me]); //add bullet to world
},
fireCD: 1,
fireCDscale: 1,
setFireCD() {
b.fireCD = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage / tech.fastTime
if (tech.isFireRateForGuns) b.fireCD *= Math.pow(0.86, b.inventory.length)
if (tech.isFireMoveLock) b.fireCD *= 0.5
b.fireCDscale = tech.fireRate * tech.slowFire * tech.researchHaste * tech.aimDamage / tech.fastTime
if (tech.isFireRateForGuns) b.fireCDscale *= Math.pow(0.86, b.inventory.length)
if (tech.isFireMoveLock) b.fireCDscale *= 0.5
},
fireAttributes(dir, rotate = true) {
if (rotate) {
@@ -2435,7 +2435,7 @@ const b = {
// friction: 0.2,
// restitution: 0.2,
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),
classType: "bullet",
collisionFilter: {
@@ -2449,6 +2449,8 @@ const b = {
target: null,
targetVertex: null,
targetRelativePosition: null,
portFrequency: 5 + Math.floor(5 * Math.random()),
nextPortCycle: Infinity, //disabled unless you have the teleport tech
beforeDmg(who) {
if (!this.target && who.alive) {
this.target = who;
@@ -2494,6 +2496,8 @@ const b = {
if (this.radius < 8) this.endCycle = 0;
}
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
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
Matter.Body.setVelocity(bullet[me], velocity);
},
@@ -3502,9 +3512,9 @@ const b = {
fireNormal() {
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
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)
},
fireNeedles() {
@@ -3575,13 +3585,13 @@ const b = {
}
if (m.crouch) {
m.fireCDcycle = m.cycle + 45 * b.fireCD; // cool down
m.fireCDcycle = m.cycle + 45 * b.fireCDscale; // cool down
makeNeedle()
for (let i = 1; i < 4; i++) { //4 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
}
} else {
m.fireCDcycle = m.cycle + 25 * b.fireCD; // cool down
m.fireCDcycle = m.cycle + 25 * b.fireCDscale; // cool down
makeNeedle()
for (let i = 1; i < 3; i++) { //3 total needles
setTimeout(() => { if (!simulation.paused) makeNeedle() }, 60 * i);
@@ -3595,7 +3605,7 @@ const b = {
// makeNeedle(m.angle - spread)
},
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 size = tech.rivetSize * 7.5
@@ -3640,13 +3650,13 @@ const b = {
fireNailFireRate() {
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
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)
},
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)
},
baseFire(angle) {
@@ -3685,18 +3695,18 @@ const b = {
let knock, spread
if (m.crouch) {
spread = 0.65
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCD); // 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
m.fireCDcycle = m.cycle + Math.floor(55 * b.fireCDscale); // cool down
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
} else {
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCD); // 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
m.fireCDcycle = m.cycle + Math.floor(45 * b.fireCDscale); // cool down
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
knock = 0.1
}
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.y -= 2 * knock * Math.sin(m.angle) //reduce knock back in vertical direction to stop super jumps
} else {
@@ -3848,7 +3858,7 @@ const b = {
do() {},
fireOne() {
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
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));
@@ -3875,7 +3885,7 @@ const b = {
},
fireMulti() {
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
let dir = m.angle - SPREAD * (tech.superBallNumber - 1) / 2;
for (let i = 0; i < tech.superBallNumber; i++) {
@@ -3908,7 +3918,7 @@ const b = {
const dir = m.angle
const x = m.pos.x + 30 * Math.cos(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
for (let i = 0; i < tech.superBallNumber; i++) {
@@ -3960,7 +3970,7 @@ const b = {
do() {
if (this.wavePacketCycle && !input.fire) {
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,
@@ -4060,7 +4070,7 @@ const b = {
//fire a packet of bullets then delay for a while
this.wavePacketCycle++
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;
}
}
@@ -4076,7 +4086,7 @@ const b = {
fire() {
const countReduction = Math.pow(0.9, tech.missileCount)
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++) {
// 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)
}
} else {
m.fireCDcycle = m.cycle + 50 * b.fireCD / countReduction; // cool down
m.fireCDcycle = m.cycle + 50 * b.fireCDscale / countReduction; // cool down
const direction = {
x: Math.cos(m.angle),
y: Math.sin(m.angle)
@@ -4147,7 +4157,7 @@ const b = {
// bullet[bullet.length - 1].force.x -= 0.015 * (i - 1);
// }
// } else {
// m.fireCDcycle = m.cycle + 80 * b.fireCD; // cool down
// m.fireCDcycle = m.cycle + 80 * b.fireCDscale; // cool down
// const direction = {
// x: Math.cos(m.angle),
// y: Math.sin(m.angle)
@@ -4164,7 +4174,7 @@ const b = {
// }
// } else {
// 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
// b.missile({
// x: m.pos.x,
@@ -4174,7 +4184,7 @@ const b = {
// bullet[bullet.length - 1].force.x += off * 0.03;
// // bullet[bullet.length - 1].force.y += push.y * (i - 1);
// } 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
// }
@@ -4189,7 +4199,7 @@ const b = {
have: false,
do() {},
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()
},
}, {
@@ -4218,7 +4228,7 @@ const b = {
y: speed * Math.sin(m.angle)
}, 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",
@@ -4362,18 +4372,18 @@ const b = {
if (tech.isDroneRadioactive) {
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)
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 {
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 {
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)
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCD); // cool down
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCDscale); // cool down
} else {
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() {
// if (m.crouch) {
// 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 {
// 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() {
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() {
const spread = (m.crouch ? 0.05 : 0.6) * (Math.random() - 0.5)
@@ -4517,7 +4527,7 @@ const b = {
if (tech.isCapacitor) {
if ((m.energy > 0.16 || tech.isRailEnergyGain)) { //&& m.immuneCycle < m.cycle
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;
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
@@ -4552,7 +4562,7 @@ const b = {
}
},
onEnd() {},
drawCycle: Math.floor(10 * b.fireCD),
drawCycle: Math.floor(10 * b.fireCDscale),
do() {
this.force.y += this.mass * 0.0003; // low gravity that scales with charge
if (this.drawCycle > 0) {
@@ -4693,7 +4703,7 @@ const b = {
m.fireCDcycle = Infinity //can't fire until mouse is released
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)
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
@@ -4827,12 +4837,12 @@ const b = {
this.do = () => {};
if (tech.isPulseLaser) {
this.fire = () => {
const drain = 0.01 * tech.isLaserDiode / b.fireCD
const drain = 0.01 * tech.isLaserDiode / b.fireCDscale
if (m.energy > drain) {
m.energy -= m.fieldRegen
if (this.charge < 50 * m.maxEnergy) {
m.energy -= drain
this.charge += 1 / b.fireCD
this.charge += 1 / b.fireCDscale
}
}
}
@@ -4905,7 +4915,7 @@ const b = {
// this.fire = this.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)
// },
fireLaser() {
@@ -5041,7 +5051,7 @@ const b = {
}
},
// 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)
// m.energy -= energy * tech.isLaserDiode
// if (tech.beamSplitter) {
@@ -5082,7 +5092,7 @@ const b = {
if (this.rewindCount > 599 || m.energy < DRAIN || history.activeGun !== this.activeGunIndex) {
this.rewindCount = 0;
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 {
m.energy -= DRAIN
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");
//using "const" causes problems in safari when an ID shares the same name.
const ctx = canvas.getContext("2d");
// const ctx = canvas.getContext('2d', { alpha: false }); //optimization, but doesn't work
document.body.style.backgroundColor = "#fff";
//disable pop up menu on right click
@@ -195,7 +197,7 @@ const build = {
${simulation.isCheating? "<em>lore disabled</em><br><br>": ""}
<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><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)}%
${botText}
<br>

View File

@@ -15,9 +15,9 @@ const level = {
// simulation.enableConstructMode() //used to build maps in testing mode
// level.difficultyIncrease(30)
// simulation.isHorizontalFlipped = true
// m.setField("time dilation")
// b.giveGuns("grenades")
// tech.giveTech("neutron bomb")
// m.setField("metamaterial cloaking")
// b.giveGuns("foam")
// tech.giveTech("uncertainty principle")
// for (let i = 0; i < 9; i++) tech.giveTech("spherical harmonics")
// tech.giveTech("supertemporal")
// 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 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1281,6 +1280,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
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.secondaryBossChance(x + 2000 - 650, y + -875)
} else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400);
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 + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1313,6 +1312,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity);
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.secondaryBossChance(x + 650, y + -875)
}
},
(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 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1373,6 +1372,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
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.secondaryBossChance(x + 650, y + -875)
} else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400);
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 + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1430,6 +1429,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity);
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.secondaryBossChance(x + 650, y - 875)
}
},
(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 - 1725, y + -1250, Infinity);
spawn.randomMob(x + 2000 - 1250, y + -1200, Infinity);
@@ -1501,6 +1500,7 @@ const level = {
spawn.randomMob(x + 2000 - 800, y + -125, Infinity);
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.secondaryBossChance(x + 650, y - 875)
} else {
powerUps.spawnStartingPowerUps(x + 1650, y + -400);
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 + 1725, y + -1250, Infinity);
spawn.randomMob(x + 1250, y + -1200, Infinity);
@@ -1569,6 +1568,7 @@ const level = {
spawn.randomMob(x + 800, y + -125, Infinity);
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.secondaryBossChance(x + 650, y - 875)
}
}
]
@@ -2169,7 +2169,6 @@ const level = {
// spawn.randomGroup(1700, -900, 0.4);
// if (simulation.difficulty > 3) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
// if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(4800, -500);
},
final() {
level.custom = () => {
@@ -2219,7 +2218,7 @@ const level = {
spawn.mapRect(5700, -3300, 1800, 5100); //right wall
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 100); //exit bump
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
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);
}
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
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -2509,7 +2508,6 @@ const level = {
}
}
powerUps.spawnStartingPowerUps(2300, -150);
// if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(1900, -675);
},
testChamber() {
level.setPosToSpawn(0, -50); //lower start
@@ -2705,8 +2703,7 @@ const level = {
}
}
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
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -2913,8 +2910,7 @@ const level = {
spawn.randomMob(2825, 400, 0.9);
if (simulation.difficulty > 3) spawn.randomLevelBoss(6000, 2300, ["spiderBoss", "launcherBoss", "laserTargetingBoss", "streamBoss", "historyBoss", "orbitalBoss", "shieldingBoss"]);
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
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
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(3950, -850);
spawn.secondaryBossChance(3950, -850)
if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3272,7 +3268,7 @@ const level = {
spawn.randomGroup(4900, -1200, 0);
if (simulation.difficulty > 3) spawn.randomLevelBoss(3200, -1900);
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
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
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(5350, -325);
spawn.secondaryBossChance(5350, -325)
if (simulation.isHorizontalFlipped) { //flip the map horizontally
level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit
@@ -3657,7 +3653,7 @@ const level = {
spawn.randomGroup(1700, -900, 0.4);
if (simulation.difficulty > 3) spawn.randomLevelBoss(2600, -2300);
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
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);
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
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
}
}
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(300, -800);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
spawn.secondaryBossChance(300, -800)
if (simulation.isHorizontalFlipped) { //flip the map horizontally
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
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(1875, -675);
spawn.secondaryBossChance(1875, -675)
if (simulation.isHorizontalFlipped) { //flip the map horizontally
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
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(7725, 2275);
spawn.secondaryBossChance(7725, 2275)
},
coliseum() {
level.custom = () => {
@@ -6070,8 +6066,7 @@ const level = {
powerUps.spawn(200, 50, "ammo");
powerUps.addResearchToLevel() //needs to run after mobs are spawned
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(6600, 600, ["historyBoss", "powerUpBoss", "pulsarBoss", "orbitalBoss"]);
spawn.secondaryBossChance(6600, 600)
},
crossfire() {
//*1.5
@@ -6179,12 +6174,8 @@ const level = {
// spawn.randomGroup(7700, -1100, 0.5);
spawn.randomGroup(9800, -1100, 0.5);
if (simulation.difficulty > 10) {
spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "snakeBoss", "spiderBoss", "historyBoss"]);
}
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) {
spawn.randomLevelBoss(7900, -400, ["powerUpBoss", "spiderBoss", "historyBoss"]);
}
if (simulation.difficulty > 10) spawn.randomLevelBoss(8600, -600, ["powerUpBoss", "bomberBoss", "snakeBoss", "spiderBoss", "historyBoss"])
spawn.secondaryBossChance(7900, -400)
//Boss Spawning
if (simulation.difficulty > 10) {
@@ -6422,7 +6413,7 @@ const level = {
} else {
exitDoor.isOpen = false;
}
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) spawn.randomLevelBoss(800, -800);
spawn.secondaryBossChance(800, -800)
powerUps.spawn(4450, 1050, "heal");
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);
}
}
if (tech.isDuplicateBoss && Math.random() < 2 * tech.duplicationChance()) {
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);
}
}
spawn.secondaryBossChance(850 + Math.random() * 250, -1100 + Math.random() * 200)
//draw leg for statue
function statueLeg(shift, color) {

View File

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

View File

@@ -223,7 +223,7 @@ const powerUps = {
b.randomBot()
if (tech.renormalization) {
for (let i = 0; i < limit; i++) {
if (Math.random() < 0.37) {
if (Math.random() < 0.4) {
m.fieldCDcycle = m.cycle + 30;
powerUps.spawn(m.pos.x, m.pos.y, "research");
}
@@ -234,7 +234,7 @@ const powerUps = {
if (tech.isDeathAvoid && document.getElementById("tech-anthropic")) {
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");
}
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
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 *********************************************************************************************
//***********************************************************************************************************
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) {
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) {
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') {
if (index === 'random') {
let options = [];
@@ -93,7 +89,6 @@
let newTech = options[Math.floor(Math.random() * options.length)]
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>`);
}
} else {
if (isNaN(index)) { //find index by name
@@ -704,6 +699,24 @@
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",
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",
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,
count: 0,
frequency: 2,
frequencyDefault: 2,
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() {
tech.isNoFireDefense = true
},
@@ -2244,7 +2257,7 @@
},
{
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,
count: 0,
frequency: 1,
@@ -2266,7 +2279,7 @@
},
{
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,
count: 0,
frequency: 2,
@@ -2712,7 +2725,7 @@
},
{
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,
count: 0,
frequency: 2,
@@ -2819,6 +2832,24 @@
},
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",
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",
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,
count: 0,
frequency: 1,
@@ -2983,9 +3014,9 @@
frequency: 2,
frequencyDefault: 2,
allowed() {
return tech.duplicationChance() > 0
return tech.duplicationChance() > 0 && !tech.isResearchBoss
},
requires: "some duplication chance",
requires: "some duplication chance, not abiogenesis",
effect() {
tech.isDuplicateBoss = true;
},
@@ -3259,7 +3290,7 @@
},
{
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,
count: 0,
frequency: 1,
@@ -4058,25 +4089,6 @@
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",
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",
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,
count: 0,
frequency: 2,
@@ -4410,6 +4422,25 @@
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",
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
}
},
{
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",
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;
}
},
{
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",
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",
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,
count: 0,
frequency: 0,
@@ -6604,10 +6635,7 @@
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fillStyle = this.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
@@ -6652,10 +6680,7 @@
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fillStyle = this.bodyGradient
ctx.fill();
ctx.arc(15, 0, 4, 0, 2 * Math.PI);
ctx.strokeStyle = "#333";
@@ -6694,10 +6719,7 @@
ctx.rotate(m.angle);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, 2 * Math.PI);
let grd = ctx.createLinearGradient(-30, 0, 30, 0);
grd.addColorStop(0, m.fillColorDark);
grd.addColorStop(1, m.fillColor);
ctx.fillStyle = grd;
ctx.fillStyle = this.bodyGradient
ctx.fill();
ctx.strokeStyle = "#333";
ctx.lineWidth = 2;
@@ -6909,7 +6931,7 @@
},
{
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,
count: 0,
frequency: 0,
@@ -6917,12 +6939,14 @@
isExperimentHide: true,
isJunk: true,
allowed() {
return true
return powerUps.research.count > 0
},
requires: "",
requires: "at least 1 research",
effect() {
m.energy = 0
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() {}
},
@@ -7267,5 +7291,7 @@
isBlockExplode: null,
isOverHeal: null,
isDroneRadioactive: null,
droneRadioDamage: null
droneRadioDamage: null,
isFoamTeleport: null,
isResearchBoss: null
}

289
todo.txt
View File

@@ -1,170 +1,19 @@
******************************************************** NEXT PATCH ********************************************************
irradiated drones
new tech: beta radiation - double damage and half lifespan
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
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)
time dilation field is now just called "time dilation"
constraints under time dilation is less buggy, but still a bit buggy
foam tech: uncertainty principle - foam bullets change position randomly, increase foam damage by 66%
******************************************************** 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.
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
******************************************************** 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?
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
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
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
add a negative effect:
junk tech
@@ -335,6 +182,129 @@ n-gon outreach ideas
hacker news - show hacker news post
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 ********************************************************
@@ -342,7 +312,6 @@ possible names for tech
strange loop
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.
uncertainty principle
swarm intelligence - for a drone tech
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