quantum foam

all mobs that move through walls and blocks now have a transparent fill
player and power ups float in hazards

tech: apomixis - after reaching 100% duplication spawn 4 level bosses
tech: quantum foam - +153% foam damage, fire 0.35s into the future
bullets are bigger, and  easier to see
This commit is contained in:
landgreen
2021-02-12 06:02:34 -08:00
parent 045039171e
commit 5aa7233bc8
9 changed files with 254 additions and 103 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -3017,7 +3017,7 @@ const b = {
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() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 35 : 20) * b.fireCD); // cool down m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 33 : 16) * b.fireCD); // cool down
function makeNeedle(angle = m.angle) { function makeNeedle(angle = m.angle) {
const me = bullet.length; const me = bullet.length;
@@ -3047,7 +3047,7 @@ const b = {
if (tech.isNailRadiation) { if (tech.isNailRadiation) {
mobs.statusDoT(who, tech.isFastRadiation ? 8 : 2, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles mobs.statusDoT(who, tech.isFastRadiation ? 8 : 2, tech.isSlowRadiation ? 240 : (tech.isFastRadiation ? 30 : 120)) // one tick every 30 cycles
} else { } else {
let dmg = b.dmgScale * 3 let dmg = b.dmgScale * 3.25
if (tech.isCrit && who.isStunned) dmg *= 4 if (tech.isCrit && who.isStunned) dmg *= 4
who.damage(dmg, tech.isNeedleShieldPierce); who.damage(dmg, tech.isNeedleShieldPierce);
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
@@ -3173,6 +3173,32 @@ const b = {
defaultAmmoPack: 5.5, defaultAmmoPack: 5.5,
have: false, have: false,
fire() { fire() {
// if (true) {
// const direction = {
// x: Math.cos(m.angle),
// y: Math.sin(m.angle)
// }
// for (let i = 0; i < 2; i++) {
// const push = Vector.mult(Vector.perp(direction), 0.08)
// const where = {
// x: m.pos.x + 40 * direction.x,
// y: m.pos.y + 40 * direction.y
// }
// b.missile(where, m.angle, 0, 0.5) //where, angle, speed, size = 1)
// // bullet[bullet.length - 1].force.x += push.x;
// // bullet[bullet.length - 1].force.y += push.y;
// }
// }
// setTimeout(() => {
// if (!simulation.paused) {
// b.foam(position, velocity, radius)
// bullet[bullet.length - 1].damage = (1 + 1.53 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage
// }
// }, 350 * tech.foamFutureFire);
let knock, spread let knock, spread
if (m.crouch) { if (m.crouch) {
spread = 0.75 spread = 0.75
@@ -3832,19 +3858,49 @@ const b = {
ammoPack: 36, ammoPack: 36,
have: false, have: false,
fire() { fire() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down if (tech.foamFutureFire) {
const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12 m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down
const SPEED = 18 - radius * 0.4; const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const dir = m.angle + 0.2 * (Math.random() - 0.5) const SPEED = 18 - radius * 0.4;
const velocity = { const dir = m.angle + 0.2 * (Math.random() - 0.5)
x: SPEED * Math.cos(dir), const velocity = {
y: SPEED * Math.sin(dir) x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
simulation.drawList.push({ //add dmg to draw queue
x: position.x,
y: position.y,
radius: 5,
color: "rgba(0,0,0,0.1)",
time: 21 * tech.foamFutureFire
});
setTimeout(() => {
if (!simulation.paused) {
b.foam(position, velocity, radius)
bullet[bullet.length - 1].damage = (1 + 1.53 * tech.foamFutureFire) * (tech.isFastFoam ? 0.048 : 0.012) //double damage
}
}, 350 * tech.foamFutureFire);
} else {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 15 : 5) * b.fireCD); // cool down
const radius = (m.crouch ? 10 + 5 * Math.random() : 4 + 6 * Math.random()) + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = 18 - radius * 0.4;
const dir = m.angle + 0.2 * (Math.random() - 0.5)
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, velocity, radius)
} }
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, velocity, radius)
} }
}, },
{ {

View File

@@ -760,7 +760,7 @@ const level = {
mapB.portalPair = mapA mapB.portalPair = mapA
return [portalA, portalB, mapA, mapB] return [portalA, portalB, mapA, mapB]
}, },
hazard(x, y, width, height, damage = 0.0005, color = "hsla(160, 100%, 35%,0.75)", isOptical = false) { hazard(x, y, width, height, damage = 0.0008, color = "hsla(160, 100%, 35%,0.75)", isOptical = false) {
return { return {
min: { min: {
x: x, x: x,
@@ -791,6 +791,29 @@ const level = {
} }
const drain = 0.005 const drain = 0.005
if (m.energy > drain) m.energy -= drain if (m.energy > drain) m.energy -= drain
//float
if (!isOptical) {
if (player.velocity.y > 3) player.force.y -= 0.96 * player.mass * simulation.g
const slowY = (player.velocity.y > 0) ? Math.max(0.3, 1 - 0.0015 * player.velocity.y * player.velocity.y) : Math.max(0.98, 1 - 0.001 * Math.abs(player.velocity.y)) //down : up
Matter.Body.setVelocity(player, {
x: Math.max(0.6, 1 - 0.07 * Math.abs(player.velocity.x)) * player.velocity.x,
y: slowY * player.velocity.y
});
}
}
//float power ups
if (!isOptical) {
powerUpCollide = Matter.Query.region(powerUp, this)
for (let i = 0, len = powerUpCollide.length; i < len; i++) {
const diameter = 2 * powerUpCollide[i].size
const buoyancy = 1 - 0.2 * Math.max(0, Math.min(diameter, this.min.y - powerUpCollide[i].position.y + powerUpCollide[i].size)) / diameter
powerUpCollide[i].force.y -= buoyancy * 1.1 * powerUpCollide[i].mass * simulation.g;
Matter.Body.setVelocity(powerUpCollide[i], {
x: powerUpCollide[i].velocity.x,
y: 0.95 * powerUpCollide[i].velocity.y
});
}
} }
}, },
draw() { draw() {
@@ -1054,18 +1077,19 @@ const level = {
// spawn.boost(1500, 0, 900); // spawn.boost(1500, 0, 900);
// spawn.starter(1900, -500, 200) //big boy // spawn.starter(1900, -500, 200) //big boy
spawn.starter(1900, -500) // spawn.starter(1900, -500)
// spawn.historyBoss(1900, -500) // spawn.historyBoss(1900, -500)
// spawn.sneaker(2900, -500) // spawn.ghoster(2900, -500)
// spawn.launcherBoss(1200, -500) // spawn.launcherBoss(1200, -500)
// spawn.laserTargetingBoss(1600, -400) // spawn.laserTargetingBoss(1600, -400)
// spawn.striker(1600, -500) // spawn.striker(1600, -500)
// spawn.shooter(1700, -120) // spawn.shooter(1700, -120)
// spawn.bomberBoss(1400, -500) // spawn.bomberBoss(1400, -500)
// spawn.sniper(1800, -120) spawn.sniper(1800, -120)
// spawn.cellBossCulture(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.streamBoss(1600, -500) // spawn.streamBoss(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.cellBossCulture(1600, -500)
// spawn.bomberBoss(1600, -500)
// spawn.beamer(1200, -500) // spawn.beamer(1200, -500)
// spawn.shield(mob[mob.length - 1], 1800, -120, 1); // spawn.shield(mob[mob.length - 1], 1800, -120, 1);
@@ -1139,8 +1163,10 @@ const level = {
powerUps.spawn(1675, -50, "ammo"); powerUps.spawn(1675, -50, "ammo");
powerUps.spawn(3350, -75, "ammo"); powerUps.spawn(3350, -75, "ammo");
powerUps.spawn(3925, -50, "ammo"); powerUps.spawn(3925, -50, "ammo");
powerUps.spawn(4250, -75, "ammo");
powerUps.spawn(4550, -75, "ammo"); powerUps.spawn(4550, -75, "ammo");
powerUps.spawn(5025, -50, "ammo"); powerUps.spawn(5025, -50, "ammo");
powerUps.spawn(4725, -50, "ammo");
powerUps.spawn(4975, -350, "ammo"); powerUps.spawn(4975, -350, "ammo");
powerUps.spawn(5125, -350, "ammo"); powerUps.spawn(5125, -350, "ammo");
powerUps.spawn(5075, -425, "ammo"); powerUps.spawn(5075, -425, "ammo");

View File

@@ -874,7 +874,7 @@ const mobs = {
Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 && //see player Matter.Query.ray(map, this.position, this.mPosRange()).length === 0 && //see player
Matter.Query.ray(body, this.position, this.mPosRange()).length === 0 Matter.Query.ray(body, this.position, this.mPosRange()).length === 0
) { ) {
spawn.bomb(this.position.x, this.position.y + this.radius * 0.5, 10 + Math.ceil(this.radius / 15), 5); spawn.bomb(this.position.x, this.position.y + this.radius * 0.7, 9 + Math.ceil(this.radius / 15), 5);
//add spin and speed //add spin and speed
Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5); Matter.Body.setAngularVelocity(mob[mob.length - 1], (Math.random() - 0.5) * 0.5);
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -909,7 +909,7 @@ const mobs = {
this.torque -= 0.000004 * this.inertia; this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) { } else if (this.noseLength > 1.5) {
//fire //fire
spawn.bullet(this.vertices[1].x, this.vertices[1].y, 5 + Math.ceil(this.radius / 15), 5); spawn.bullet(this.vertices[1].x, this.vertices[1].y, 9 + Math.ceil(this.radius / 15));
const v = 15; const v = 15;
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + this.fireDir.x * v + 3 * Math.random(), x: this.velocity.x + this.fireDir.x * v + 3 * Math.random(),

View File

@@ -497,7 +497,7 @@ const m = {
harmReduction() { harmReduction() {
let dmg = 1 let dmg = 1
dmg *= m.fieldHarmReduction dmg *= m.fieldHarmReduction
if (tech.isBlockHarm && m.isHolding) dmg *= 0.4 if (tech.isBlockHarm && m.isHolding) dmg *= 0.25
if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage if (tech.squirrelFx !== 1) dmg *= 1 + (tech.squirrelFx - 1) / 5 //cause more damage
if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0185, 0.55) if (tech.isSpeedHarm) dmg *= 1 - Math.min(player.speed * 0.0185, 0.55)
if (tech.isSlowFPS) dmg *= 0.8 if (tech.isSlowFPS) dmg *= 0.8
@@ -506,7 +506,7 @@ const m = {
if (tech.isBotArmor) dmg *= 0.96 ** tech.totalBots() if (tech.isBotArmor) dmg *= 0.96 ** tech.totalBots()
if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33; if (tech.isHarmArmor && m.lastHarmCycle + 600 > m.cycle) dmg *= 0.33;
if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.6 if (tech.isNoFireDefense && m.cycle > m.fireCDcycle + 120) dmg *= 0.6
if (tech.energyRegen === 0) dmg *= 0.4 if (tech.energyRegen === 0) dmg *= 0.34
if (tech.isTurret && m.crouch) dmg *= 0.5; if (tech.isTurret && m.crouch) dmg *= 0.5;
if (tech.isFireMoveLock && input.fire) dmg *= 0.4; if (tech.isFireMoveLock && input.fire) dmg *= 0.4;
if (tech.isEntanglement && b.inventory[0] === b.activeGun) { if (tech.isEntanglement && b.inventory[0] === b.activeGun) {

View File

@@ -36,7 +36,10 @@ const powerUps = {
}, },
endDraft(type, isCanceled = false) { endDraft(type, isCanceled = false) {
if (isCanceled) { if (isCanceled) {
if (tech.isCancelDuplication) tech.cancelCount++ if (tech.isCancelDuplication) {
tech.cancelCount++
tech.maxDuplicationEvent()
}
if (tech.isCancelRerolls) { if (tech.isCancelRerolls) {
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
let spawnType = (m.health < 0.25 || tech.isEnergyNoAmmo) ? "heal" : "ammo" let spawnType = (m.health < 0.25 || tech.isEnergyNoAmmo) ? "heal" : "ammo"
@@ -174,7 +177,7 @@ const powerUps = {
if (tech.isAmmoForGun && b.inventory.length > 0 && b.activeGun) { if (tech.isAmmoForGun && b.inventory.length > 0 && b.activeGun) {
const target = b.guns[b.activeGun] const target = b.guns[b.activeGun]
if (target.ammo !== Infinity) { if (target.ammo !== Infinity) {
const ammoAdded = Math.ceil(Math.random() * target.ammoPack) + Math.ceil(Math.random() * target.ammoPack) const ammoAdded = Math.ceil(Math.random() * target.ammoPack) + Math.ceil(0.7 * Math.random() * target.ammoPack)
target.ammo += ammoAdded target.ammo += ammoAdded
simulation.makeTextLog(`${target.name}.<span class='color-gun'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`) simulation.makeTextLog(`${target.name}.<span class='color-gun'>ammo</span> <span class='color-symbol'>+=</span> ${ammoAdded}`)
} }

View File

@@ -112,18 +112,23 @@ const spawn = {
} else { } else {
//reset game //reset game
setTimeout(() => { setTimeout(() => {
simulation.makeTextLog(`simulation.end()`); simulation.makeTextLog(`simulation.complete()`);
let delay = 1000 let delay = 1000
for (let i = 20; i > 0; i--) { for (let i = 0; i < 1.01; i += 0.01 + 0.1 * Math.random()) {
setTimeout(function() { setTimeout(function() {
simulation.makeTextLog(`delay = ${i*1000}`); simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> ${(i).toFixed(3)}`);
}, delay); }, delay);
delay += 1000 delay += 1000
} }
delay += 1000 setTimeout(function() {
simulation.makeTextLog(`simulation.analysis <span class='color-symbol'>=</span> 1`);
}, delay);
delay += 2000
setTimeout(() => { setTimeout(() => {
simulation.makeTextLog(`World.clear(engine.world)`); if (!simulation.paused && !simulation.testing) {
setTimeout(() => { m.death() }, 1000); simulation.makeTextLog(`World.clear(engine.world)`);
setTimeout(() => { m.death() }, 2000);
}
}, delay); }, delay);
}, 5000); }, 5000);
} }
@@ -514,22 +519,21 @@ const spawn = {
} }
}, },
cellBoss(x, y, radius = 20, cellID) { cellBoss(x, y, radius = 20, cellID) {
mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,150,155,0.7)"); mobs.spawn(x + Math.random(), y + Math.random(), 20, radius * (1 + 1.2 * Math.random()), "rgba(0,100,105,0)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "#099"
me.isBoss = true; me.isBoss = true;
me.isCell = true; me.isCell = true;
me.cellID = cellID me.cellID = cellID
me.accelMag = 0.00015 * simulation.accelScale; me.accelMag = 0.00016 * simulation.accelScale;
me.memory = 40; me.memory = 40;
me.isVerticesChange = true me.isVerticesChange = true
me.frictionAir = 0.012 me.frictionAir = 0.012
me.seePlayerFreq = Math.floor(11 + 7 * Math.random()) me.seePlayerFreq = Math.floor(11 + 7 * Math.random())
me.seeAtDistance2 = 1400000; me.seeAtDistance2 = 1400000;
me.cellMassMax = 70 me.cellMassMax = 70
me.collisionFilter.mask = cat.player | cat.bullet //| cat.map | cat.body
me.collisionFilter.mask = cat.player | cat.bullet Matter.Body.setDensity(me, 0.001) // normal density is 0.001 // this reduces life by half and decreases knockback
Matter.Body.setDensity(me, 0.0005) // normal density is 0.001 // this reduces life by half and decreases knockback
// console.log(me.mass, me.radius)
const k = 642 //k=r^2/m const k = 642 //k=r^2/m
me.split = function() { me.split = function() {
Matter.Body.scale(this, 0.4, 0.4); Matter.Body.scale(this, 0.4, 0.4);
@@ -556,16 +560,16 @@ const spawn = {
this.radius = Math.sqrt(this.mass * k / Math.PI) this.radius = Math.sqrt(this.mass * k / Math.PI)
} }
if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs if (!(simulation.cycle % this.seePlayerFreq)) { //move away from other mobs
const repelRange = 200 const repelRange = 150
const attractRange = 800 const attractRange = 700
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].isCell && mob[i].id !== this.id) { if (mob[i].isCell && mob[i].id !== this.id) {
const sub = Vector.sub(this.position, mob[i].position) const sub = Vector.sub(this.position, mob[i].position)
const dist = Vector.magnitude(sub) const dist = Vector.magnitude(sub)
if (dist < repelRange) { if (dist < repelRange) {
this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.006) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.002)
} else if (dist > attractRange) { } else if (dist > attractRange) {
this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.004) this.force = Vector.mult(Vector.normalise(sub), -this.mass * 0.003)
} }
} }
} }
@@ -594,7 +598,7 @@ const spawn = {
me.frictionAir = 0.01 me.frictionAir = 0.01
me.seeAtDistance2 = 1000000; me.seeAtDistance2 = 1000000;
me.accelMag = 0.0005 * simulation.accelScale; me.accelMag = 0.0005 * simulation.accelScale;
Matter.Body.setDensity(me, 0.0006); //normal is 0.001 Matter.Body.setDensity(me, 0.001); //normal is 0.001
me.collisionFilter.mask = cat.bullet | cat.player me.collisionFilter.mask = cat.bullet | cat.player
me.memory = Infinity; me.memory = Infinity;
me.seePlayerFreq = 30 me.seePlayerFreq = 30
@@ -908,7 +912,7 @@ const spawn = {
me.collisionFilter.mask = cat.player | cat.bullet me.collisionFilter.mask = cat.player | cat.bullet
// me.frictionAir = 0.005; // me.frictionAir = 0.005;
me.memory = 1600; me.memory = 1600;
Matter.Body.setDensity(me, 0.05); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.075); //extra dense //normal is 0.001 //makes effective life much larger
me.onDeath = function() { me.onDeath = function() {
//applying forces to player doesn't seem to work inside this method, not sure why //applying forces to player doesn't seem to work inside this method, not sure why
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -1008,7 +1012,7 @@ const spawn = {
let targets = [] //track who is in the node boss, for shields let targets = [] //track who is in the node boss, for shields
mobs.spawn(x, y, 6, radius, "#b386e8"); mobs.spawn(x, y, 6, radius, "#b386e8");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
Matter.Body.setDensity(me, 0.002); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true; me.isBoss = true;
targets.push(me.id) //add to shield protection targets.push(me.id) //add to shield protection
me.friction = 0; me.friction = 0;
@@ -1510,7 +1514,7 @@ const spawn = {
me.count = 0; me.count = 0;
me.frictionAir = 0.03; me.frictionAir = 0.03;
// me.torque -= me.inertia * 0.002 // me.torque -= me.inertia * 0.002
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.05); //extra dense //normal is 0.001 //makes effective life much larger
// spawn.shield(me, x, y, 1); //not working, not sure why // spawn.shield(me, x, y, 1); //not working, not sure why
me.onDeath = function() { me.onDeath = function() {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
@@ -2023,7 +2027,7 @@ const spawn = {
if (dist > 50) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002) if (dist > 50) this.force = Vector.mult(Vector.normalise(sub), this.mass * 0.0002)
}; };
}, },
bullet(x, y, radius = 6, sides = 0) { bullet(x, y, radius = 9, sides = 0) {
//bullets //bullets
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)"); mobs.spawn(x, y, sides, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -2038,6 +2042,7 @@ const spawn = {
me.restitution = 0.8; me.restitution = 0.8;
me.leaveBody = false; me.leaveBody = false;
me.dropPowerUp = false; me.dropPowerUp = false;
me.showHealthBar = false; me.showHealthBar = false;
me.collisionFilter.category = cat.mobBullet; me.collisionFilter.category = cat.mobBullet;
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet; me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
@@ -2046,7 +2051,7 @@ const spawn = {
this.timeLimit(); this.timeLimit();
}; };
}, },
bomb(x, y, radius = 6, sides = 5) { bomb(x, y, radius = 9, sides = 5) {
mobs.spawn(x, y, sides, radius, "rgb(255,0,0)"); mobs.spawn(x, y, sides, radius, "rgb(255,0,0)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.stroke = "transparent"; me.stroke = "transparent";
@@ -2155,7 +2160,7 @@ const spawn = {
this.torque -= 0.000004 * this.inertia; this.torque -= 0.000004 * this.inertia;
} else if (this.noseLength > 1.5) { } else if (this.noseLength > 1.5) {
//fire //fire
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 5 + Math.ceil(this.radius / 15), 4); spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4);
const v = 20 * simulation.accelScale; const v = 20 * simulation.accelScale;
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + this.fireDir.x * v + Math.random(), x: this.velocity.x + this.fireDir.x * v + Math.random(),
@@ -2208,7 +2213,7 @@ const spawn = {
} }
}; };
}, },
sniperBullet(x, y, radius = 6, sides = 4) { sniperBullet(x, y, radius = 9, sides = 4) {
//bullets //bullets
mobs.spawn(x, y, sides, radius, "rgb(255,0,155)"); mobs.spawn(x, y, sides, radius, "rgb(255,0,155)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -2252,7 +2257,7 @@ const spawn = {
Matter.Body.setAngularVelocity(this, 0.14) Matter.Body.setAngularVelocity(this, 0.14)
//fire a bullet from each vertex //fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) { for (let i = 0, len = this.vertices.length; i < len; i++) {
spawn.seeker(this.vertices[i].x, this.vertices[i].y, 6) spawn.seeker(this.vertices[i].x, this.vertices[i].y, 7)
//give the bullet a rotational velocity as if they were attached to a vertex //give the bullet a rotational velocity as if they were attached to a vertex
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -8) const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -8)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -2290,7 +2295,7 @@ const spawn = {
Matter.Body.setAngularVelocity(this, 0.11) Matter.Body.setAngularVelocity(this, 0.11)
//fire a bullet from each vertex //fire a bullet from each vertex
for (let i = 0, len = this.vertices.length; i < len; i++) { for (let i = 0, len = this.vertices.length; i < len; i++) {
spawn.seeker(this.vertices[i].x, this.vertices[i].y, 6) spawn.seeker(this.vertices[i].x, this.vertices[i].y, 8)
//give the bullet a rotational velocity as if they were attached to a vertex //give the bullet a rotational velocity as if they were attached to a vertex
const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -10) const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[i]))), -10)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -2342,14 +2347,14 @@ const spawn = {
// this.force.x -= 2 * forceMag * Math.cos(angle); // this.force.x -= 2 * forceMag * Math.cos(angle);
// this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity // this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity
} }
spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 4) spawn.seeker(this.vertices[this.closestVertex1].x, this.vertices[this.closestVertex1].y, 6)
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001 Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10) const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex1])), -10)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
x: this.velocity.x + velocity.x, x: this.velocity.x + velocity.x,
y: this.velocity.y + velocity.y y: this.velocity.y + velocity.y
}); });
spawn.seeker(this.vertices[this.closestVertex2].x, this.vertices[this.closestVertex2].y, 4) spawn.seeker(this.vertices[this.closestVertex2].x, this.vertices[this.closestVertex2].y, 6)
Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001 Matter.Body.setDensity(mob[mob.length - 1], 0.000001); //normal is 0.001
const velocity2 = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex2])), -10) const velocity2 = Vector.mult(Vector.normalise(Vector.sub(this.position, this.vertices[this.closestVertex2])), -10)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], {
@@ -2378,7 +2383,7 @@ const spawn = {
} }
}; };
}, },
seeker(x, y, radius = 5, sides = 6) { seeker(x, y, radius = 8, sides = 6) {
//bullets //bullets
mobs.spawn(x, y, sides, radius, "rgb(255,0,255)"); mobs.spawn(x, y, sides, radius, "rgb(255,0,255)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -2511,8 +2516,8 @@ const spawn = {
}); });
World.add(engine.world, consBB[consBB.length - 1]); World.add(engine.world, consBB[consBB.length - 1]);
}, },
snakeBody(x, y, radius = 20) { snakeBody(x, y, radius = 14) {
mobs.spawn(x, y, 4, radius, "rgb(55,170,170)"); mobs.spawn(x, y, 8, radius, "transparent");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
// me.onHit = function() { // me.onHit = function() {
// //run this function on hitting player // //run this function on hitting player
@@ -2523,6 +2528,8 @@ const spawn = {
me.leaveBody = false; me.leaveBody = false;
me.frictionAir = 0.02; me.frictionAir = 0.02;
me.isSnakeTail = true; me.isSnakeTail = true;
me.stroke = "#099"
me.onDeath = function() { me.onDeath = function() {
if (this.isSnakeTail) { //wake up tail mobs if (this.isSnakeTail) { //wake up tail mobs
for (let i = 0; i < mob.length; i++) { for (let i = 0; i < mob.length; i++) {

View File

@@ -132,6 +132,17 @@ const tech = {
duplicationChance() { duplicationChance() {
return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + m.duplicateChance return (tech.isBayesian ? 0.2 : 0) + tech.cancelCount * 0.045 + tech.duplicateChance + m.duplicateChance
}, },
maxDuplicationEvent() {
if (tech.is100Duplicate && tech.duplicationChance() > 0.99) {
tech.is100Duplicate = false
const range = 1000
const bossOptions = ["historyBoss", "cellBossCulture", "bomberBoss", "powerUpBoss", "suckerBoss"]
spawn.randomLevelBoss(m.pos.x + range, m.pos.y, bossOptions);
spawn.randomLevelBoss(m.pos.x, m.pos.y + range, bossOptions);
spawn.randomLevelBoss(m.pos.x - range, m.pos.y, bossOptions);
spawn.randomLevelBoss(m.pos.x, m.pos.y - range, bossOptions);
}
},
totalBots() { totalBots() {
return tech.dynamoBotCount + tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount return tech.dynamoBotCount + tech.foamBotCount + tech.nailBotCount + tech.laserBotCount + tech.boomBotCount + tech.orbitBotCount + tech.plasmaBotCount + tech.missileBotCount
}, },
@@ -1115,7 +1126,7 @@ const tech = {
}, },
{ {
name: "inelastic collision", name: "inelastic collision",
description: "while you are <strong>holding</strong> a <strong>block</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>60%</strong>", description: "while you are <strong>holding</strong> a <strong>block</strong><br>reduce <strong class='color-harm'>harm</strong> by <strong>75%</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
@@ -1814,6 +1825,7 @@ const tech = {
effect: () => { effect: () => {
tech.isBayesian = true tech.isBayesian = true
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.maxDuplicationEvent()
}, },
remove() { remove() {
tech.isBayesian = false tech.isBayesian = false
@@ -1822,7 +1834,7 @@ const tech = {
}, },
{ {
name: "replication", name: "replication",
description: "<strong>7.5%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>16</strong> junk <strong class='color-m'>tech</strong> to the potential pool", description: "<strong>7%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br>add <strong>11</strong> junk <strong class='color-m'>tech</strong> to the potential pool",
maxCount: 9, maxCount: 9,
count: 0, count: 0,
allowed() { allowed() {
@@ -1832,7 +1844,8 @@ const tech = {
effect() { effect() {
tech.duplicateChance += 0.075 tech.duplicateChance += 0.075
simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw simulation.draw.powerUp = simulation.draw.powerUpBonus //change power up draw
tech.addJunkTechToPool(16) tech.addJunkTechToPool(11)
tech.maxDuplicationEvent()
}, },
remove() { remove() {
tech.duplicateChance = 0 tech.duplicateChance = 0
@@ -1892,12 +1905,12 @@ const tech = {
} }
}, },
{ {
name: "cloning", name: "parthenogenesis",
description: "each level has a chance to spawn a <strong>level boss</strong><br>equal to <strong>double</strong> your <strong class='color-dup'>duplication</strong> chance", description: "each level has a chance to spawn a <strong>level boss</strong><br>equal to <strong>double</strong> your <strong class='color-dup'>duplication</strong> chance",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return tech.duplicationChance() > 0.2 return tech.duplicationChance() > 0
}, },
requires: "some duplication chance", requires: "some duplication chance",
effect() { effect() {
@@ -1907,6 +1920,22 @@ const tech = {
tech.isDuplicateBoss = false; tech.isDuplicateBoss = false;
} }
}, },
{
name: "apomixis",
description: "after reaching <strong>100%</strong> <strong class='color-dup'>duplication</strong> chance<br>immediately spawn <strong>4 level bosses</strong>",
maxCount: 1,
count: 0,
allowed() {
return tech.isDuplicateBoss
},
requires: "parthenogenesis",
effect() {
tech.is100Duplicate = true;
},
remove() {
tech.is100Duplicate = false;
}
},
{ {
name: "exchange symmetry", name: "exchange symmetry",
description: "convert <strong>1</strong> a random <strong class='color-m'>tech</strong> into <strong>3</strong> new <strong class='color-g'>guns</strong><br><em>recursive tech lose all stacks</em>", description: "convert <strong>1</strong> a random <strong class='color-m'>tech</strong> into <strong>3</strong> new <strong class='color-g'>guns</strong><br><em>recursive tech lose all stacks</em>",
@@ -3189,6 +3218,24 @@ const tech = {
tech.isAmmoFoamSize = false; tech.isAmmoFoamSize = false;
} }
}, },
{
name: "quantum foam",
description: "<strong>foam</strong> gun fires <strong>0.35</strong> seconds into the <strong>future</strong><br>increase <strong>foam</strong> gun <strong class='color-d'>damage</strong> by <strong>153%</strong>",
isGunTech: true,
maxCount: 9,
count: 0,
allowed() {
return tech.haveGunCheck("foam")
},
requires: "foam",
effect() {
tech.foamFutureFire++
},
remove() {
tech.foamFutureFire = 0;
}
},
// { // {
// name: "foam size", // name: "foam size",
// description: "increase <strong>foam</strong> <strong class='color-d'>damage</strong> by <strong>200%</strong><br><strong>foam</strong> dissipates <strong>50%</strong> faster", // description: "increase <strong>foam</strong> <strong class='color-d'>damage</strong> by <strong>200%</strong><br><strong>foam</strong> dissipates <strong>50%</strong> faster",
@@ -3869,7 +3916,7 @@ const tech = {
maxCount: 1, maxCount: 1,
count: 0, count: 0,
allowed() { allowed() {
return m.fieldUpgrades[m.fieldMode].name === "plasma torch" || m.fieldUpgrades[m.fieldMode].name === "pilot wave" return m.fieldUpgrades[m.fieldMode].name === "plasma torch"
}, },
requires: "plasma torch", requires: "plasma torch",
effect() { effect() {
@@ -3960,7 +4007,7 @@ const tech = {
}, },
{ {
name: "phase decoherence", name: "phase decoherence",
description: "become <strong>intangible</strong> while <strong class='color-cloaked'>cloaked</strong><br>but, passing through <strong>mobs</strong> drains your <strong class='color-f'>energy</strong>", description: "<strong>intangible</strong> to blocks and mobs while <strong class='color-cloaked'>cloaked</strong><br>passing through <strong>mobs</strong> drains your <strong class='color-f'>energy</strong>",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4221,10 +4268,31 @@ const tech = {
// }, // },
// remove() {} // remove() {}
// }, // },
{
name: "lubrication",
description: "reduce block density and friction for this level",
maxCount: 9,
count: 0,
numberInPool: 0,
isNonRefundable: true,
isCustomHide: true,
isJunk: true,
allowed() {
return true
},
requires: "",
effect() {
for (let i = 0; i < body.length; i++) {
Matter.Body.setDensity(body[i], 0.0001) // 0.001 is normal
body[i].friction = 0.01
}
},
remove() {}
},
{ {
name: "pitch", name: "pitch",
description: "oscillate the pitch of your world", description: "oscillate the pitch of your world",
maxCount: 9, maxCount: 1,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4242,7 +4310,7 @@ const tech = {
{ {
name: "umbra", name: "umbra",
description: "produce a blue glow around everything<br>and probably some simulation lag", description: "produce a blue glow around everything<br>and probably some simulation lag",
maxCount: 9, maxCount: 1,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4261,7 +4329,7 @@ const tech = {
{ {
name: "lighter", name: "lighter",
description: `ctx.globalCompositeOperation = "lighter"`, description: `ctx.globalCompositeOperation = "lighter"`,
maxCount: 9, maxCount: 1,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4736,7 +4804,7 @@ const tech = {
{ {
name: "stun", name: "stun",
description: "<strong>stun</strong> all mobs for up to <strong>8</strong> seconds", description: "<strong>stun</strong> all mobs for up to <strong>8</strong> seconds",
maxCount: 1, maxCount: 9,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4754,7 +4822,7 @@ const tech = {
{ {
name: "re-arm", name: "re-arm",
description: "<strong>eject</strong> all your <strong class='color-g'>guns</strong>", description: "<strong>eject</strong> all your <strong class='color-g'>guns</strong>",
maxCount: 1, maxCount: 9,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4782,7 +4850,7 @@ const tech = {
{ {
name: "re-research", name: "re-research",
description: "<strong>eject</strong> all your <strong class='color-r'>research</strong>", description: "<strong>eject</strong> all your <strong class='color-r'>research</strong>",
maxCount: 1, maxCount: 9,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4801,7 +4869,7 @@ const tech = {
{ {
name: "quantum black hole", name: "quantum black hole",
description: "use all your <strong class='color-f'>energy</strong> to <strong>spawn</strong> inside the event horizon of a huge <strong>black hole</strong>", description: "use all your <strong class='color-f'>energy</strong> to <strong>spawn</strong> inside the event horizon of a huge <strong>black hole</strong>",
maxCount: 1, maxCount: 9,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -4820,7 +4888,7 @@ const tech = {
{ {
name: "black hole cluster", name: "black hole cluster",
description: "spawn <strong>2</strong> <strong class='color-r'>research</strong><br><strong>spawn</strong> 40 nearby <strong>black holes</strong>", description: "spawn <strong>2</strong> <strong class='color-r'>research</strong><br><strong>spawn</strong> 40 nearby <strong>black holes</strong>",
maxCount: 1, maxCount: 9,
count: 0, count: 0,
numberInPool: 0, numberInPool: 0,
isNonRefundable: true, isNonRefundable: true,
@@ -5038,7 +5106,9 @@ const tech = {
isGunSwitchField: null, isGunSwitchField: null,
isNeedleShieldPierce: null, isNeedleShieldPierce: null,
isDuplicateBoss: null, isDuplicateBoss: null,
is100Duplicate: null,
isDynamoBotUpgrade: null, isDynamoBotUpgrade: null,
isBlockPowerUps: null, isBlockPowerUps: null,
isBlockHarm: null isBlockHarm: null,
foamFutureFire: null
} }

View File

@@ -1,10 +1,11 @@
******************************************************** NEXT PATCH ******************************************************** ******************************************************** NEXT PATCH ********************************************************
several new junk tech
unified field theory: now cycles fields after you click the field box when paused all mobs that move through walls and blocks now have a transparent fill
player and power ups float in hazards
tech: restitution - mobs killed by blocks spawn power ups tech: apomixis - after reaching 100% duplication spawn 4 level bosses
tech: inelastic collision - 60% harm reduction when holding a block tech: quantum foam - +153% foam damage, fire 0.35s into the future
bullets are bigger, and easier to see
******************************************************** BUGS ******************************************************** ******************************************************** BUGS ********************************************************
@@ -33,38 +34,26 @@ use the floor of portal sensor on the player? to unstuck player
(repeatable almost every time) bug - mines spawn extra mines when fired at thin map wall while jumping (repeatable almost every time) bug - mines spawn extra mines when fired at thin map wall while jumping
******************************************************** TODO ******************************************************** ******************************************************** TODO ********************************************************
holding a block gives some defense
can still block?
just make the block more transparent so it's clear you can't block
increase bullet size, but don't increase bullet damage
When you beat the boss without lore the output thing should read simulation complete, processing results, terminating simulation final boss: hide boss after spawning mobs
shutdown progress: 0% reduce health by 1/3?
And count up by ten to 100% before you die, so that players know they won and don't think theyre stuck or something, and so its not surprising when you die
Additionally, a stats screen would be nice. Like when you die, and it fades to white, output reads simulation result: failure (or success if you beat the boss) tech: after using anthropic principle do 100% more damage for the rest of the level
Then reads some stats like kills, tech picked up, research picked up, damage dealt/taken, etc
mechanic: immune to next collision
track number of possible collisions, if number is > 0 immune and --
graphical indication? (recolor health bar while immune)
tech: after taking damage go immune to next collision
tech: at the start of each level go immune to 1 collision
copy time-like foam to other guns?
wave gun
shotgun
nail gun
tech: when you switch guns switch all bots to a different bot
tech fire gun in the future
laser doesn't work because of draw, needs to be a bullet
foam? shotgun?
const where = {
x: m.pos.x + 20 * Math.cos(m.angle),
y: m.pos.y + 20 * Math.sin(m.angle)
}
setTimeout(() => {
}, 1000);
tech: when you switch guns switch a random bot to a different bot. If the bot you had was upgraded the new one will be too.
or switch all bots
tech: buff block throwing
require +100% damage for blocks
works with pilot wave?
lore: a tutorial / lore intro lore: a tutorial / lore intro
needs to be optional so it doesn't slow experienced players needs to be optional so it doesn't slow experienced players