double jump

tech: working mass - in midair molecular assembler or pilot wave prints a block to jump off

buckling: 100%->50% chance to spawn a power up from any block that kills a mob
  no longer requires the block to be thrown
mobs: powerUpBoss, snakeBoss tails, cellBoss, ghoster, sucker -  all collide with blocks now
added a few more blocks to towers level
deprecated: 1.05->1.07 damage per removed tech
laserLayerBoss has 33% less health and has fewer lasers at higher difficulties

bugfix
  disabled spawnDelay stopping on damage because it had too many negative tech interactions
  metastability + paradigm shift no longer makes all ejected tech explode
This commit is contained in:
landgreen
2024-06-13 12:05:40 -07:00
parent 438c16699e
commit 1903b9e938
11 changed files with 268 additions and 154 deletions

BIN
img/working mass.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

View File

@@ -3312,8 +3312,8 @@ const b = {
const distB = Vector.magnitude(Vector.sub(this.position, b.position)) const distB = Vector.magnitude(Vector.sub(this.position, b.position))
return distA < distB ? a : b return distA < distB ? a : b
}) })
if (found && m.energy > 0.05) { if (found && m.energy > 0.041) {
m.energy -= 0.05 m.energy -= 0.04
//remove the body and spawn a new drone //remove the body and spawn a new drone
Composite.remove(engine.world, found) Composite.remove(engine.world, found)
body.splice(body.indexOf(found), 1) body.splice(body.indexOf(found), 1)
@@ -3552,8 +3552,8 @@ const b = {
const distB = Vector.magnitude(Vector.sub(this.position, b.position)) const distB = Vector.magnitude(Vector.sub(this.position, b.position))
return distA < distB ? a : b return distA < distB ? a : b
}) })
if (found && m.energy > 0.05) { if (found && m.energy > 0.091) {
m.energy -= 0.1 m.energy -= 0.09
//remove the body and spawn a new drone //remove the body and spawn a new drone
Composite.remove(engine.world, found) Composite.remove(engine.world, found)
body.splice(body.indexOf(found), 1) body.splice(body.indexOf(found), 1)

View File

@@ -174,15 +174,8 @@ function collisionChecks(event) {
if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for 30 cycles
//extra kick between player and mob //this section would be better with forces but they don't work... //extra kick between player and mob //this section would be better with forces but they don't work...
let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x); let angle = Math.atan2(player.position.y - mob[k].position.y, player.position.x - mob[k].position.x);
Matter.Body.setVelocity(player, { Matter.Body.setVelocity(player, { x: player.velocity.x + 8 * Math.cos(angle), y: player.velocity.y + 8 * Math.sin(angle) });
x: player.velocity.x + 8 * Math.cos(angle), Matter.Body.setVelocity(mob[k], { x: mob[k].velocity.x - 8 * Math.cos(angle), y: mob[k].velocity.y - 8 * Math.sin(angle) });
y: player.velocity.y + 8 * Math.sin(angle)
});
Matter.Body.setVelocity(mob[k], {
x: mob[k].velocity.x - 8 * Math.cos(angle),
y: mob[k].velocity.y - 8 * Math.sin(angle)
});
if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) { if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) {
m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
@@ -250,7 +243,7 @@ function collisionChecks(event) {
if (mob[k].isShielded) dmg *= 0.7 if (mob[k].isShielded) dmg *= 0.7
mob[k].damage(dmg, true); mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) {
options = ["coupling", "boost", "heal", "research"] options = ["coupling", "boost", "heal", "research"]
if (!tech.isEnergyNoAmmo) options.push("ammo") if (!tech.isEnergyNoAmmo) options.push("ammo")
powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]); powerUps.spawn(mob[k].position.x, mob[k].position.y, options[Math.floor(Math.random() * options.length)]);

View File

@@ -44,10 +44,9 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") }); // requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization") // for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization")
// tech.giveTech("Newtons 2nd law") // tech.giveTech("Newtons 2nd law")
// for (let i = 0; i < 1; ++i) tech.giveTech("lens")
// for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide") // for (let i = 0; i < 1; ++i) tech.giveTech("tungsten carbide")
// for (let i = 0; i < 1; ++i) tech.giveTech("nitinol") // for (let i = 0; i < 1; ++i) tech.giveTech("working mass")
// for (let i = 0; i < 1; ++i) tech.giveTech("reaction mass") // for (let i = 0; i < 1; ++i) tech.giveTech("buckling")
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) }); // requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") }); // requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide") // for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
@@ -57,11 +56,11 @@ const level = {
// for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false); // for (let i = 0; i < 1; i++) powerUps.directSpawn(-50, -70, "difficulty", false);
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling"); // for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
// spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing
// level.yingYang(); // level.testing();
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) // for (let i = 0; i < 1; ++i) spawn.snakeSpitBoss(1400, -500)
// Matter.Body.setPosition(player, { x: -200, y: -3330 }); // Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.ghoster(1300, -500 + 100 * Math.random()) // for (let i = 0; i < 4; ++i) spawn.sucker(1300, -500 + 100 * Math.random())
// spawn.hopper(1900, -500) // spawn.hopper(1900, -500)
// spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color) // spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
// for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random()) // for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
@@ -4235,7 +4234,6 @@ const level = {
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
}, },
towers() { towers() {
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// simulation.isHorizontalFlipped = true // simulation.isHorizontalFlipped = true
level.announceMobTypes() level.announceMobTypes()
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
@@ -4448,6 +4446,12 @@ const level = {
spawn.bodyRect(8975, -1575, 50, 50, 0.2); spawn.bodyRect(8975, -1575, 50, 50, 0.2);
spawn.bodyRect(5725, -1700, 125, 175, 0.2); spawn.bodyRect(5725, -1700, 125, 175, 0.2);
spawn.bodyRect(6850, -1725, 150, 200, 0.2); spawn.bodyRect(6850, -1725, 150, 200, 0.2);
spawn.bodyRect(500, -400, 100, 50, 0.3);
spawn.bodyRect(6025, 1050, 100, 50, 0.2);
spawn.bodyRect(6000, -800, 75, 200, 0.2);
spawn.bodyRect(6775, -75, 125, 75, 0.5);
spawn.bodyRect(7200, 1300, 50, 200, 0.5);
//mobs //mobs
spawn.randomMob(5700, -75, 0); spawn.randomMob(5700, -75, 0);

View File

@@ -240,11 +240,7 @@ const m = {
jump() { jump() {
m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass
//apply a fraction of the jump force to the body the player is jumping off of //apply a fraction of the jump force to the body the player is jumping off of
Matter.Body.applyForce(m.standingOn, m.pos, { Matter.Body.applyForce(m.standingOn, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) });
x: 0,
y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5)
});
player.force.y = -m.jumpForce; //player jump force player.force.y = -m.jumpForce; //player jump force
Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps Matter.Body.setVelocity(player, { //zero player y-velocity for consistent jumps
x: player.velocity.x, x: player.velocity.x,
@@ -473,13 +469,10 @@ const m = {
m.displayHealth(); m.displayHealth();
document.getElementById("text-log").style.display = "none" document.getElementById("text-log").style.display = "none"
document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas document.getElementById("fade-out").style.opacity = 0.9; //slowly fade to 90% white on top of canvas
// build.shareURL(false)
setTimeout(function () { setTimeout(function () {
Composite.clear(engine.world); Composite.clear(engine.world);
Engine.clear(engine); Engine.clear(engine);
simulation.splashReturn(); simulation.splashReturn();
//if you die after clearing fewer than 4 levels the difficulty settings automatically opens
if ((level.levelsCleared < 4 || level.levelsCleared > 12) && !simulation.isTraining && !simulation.isCheating) document.getElementById("constraint-details").open = true;
}, 5000); }, 5000);
} }
}, },
@@ -3488,11 +3481,11 @@ const m = {
}, },
{ {
name: "molecular assembler", name: "molecular assembler",
description: `excess <strong class='color-f'>energy</strong> used to print ${simulation.molecularMode === 0 ? "<strong class='color-p' style='letter-spacing: 2px;'>spores" : simulation.molecularMode === 1 ? "<strong>missiles" : simulation.molecularMode === 2 ? "<strong class='color-s'>ice IX" : "<strong>drones"}</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br><strong>12</strong> <strong class='color-f'>energy</strong> per second`, description: `excess <strong class='color-f'>energy</strong> used to <strong class='color-print'>print</strong> ${simulation.molecularMode === 0 ? "<strong class='color-p' style='letter-spacing: 2px;'>spores" : simulation.molecularMode === 1 ? "<strong>missiles" : simulation.molecularMode === 2 ? "<strong class='color-s'>ice IX" : "<strong>drones"}</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br><strong>12</strong> <strong class='color-f'>energy</strong> per second`,
setDescription() { setDescription() {
return `excess <strong class='color-f'>energy</strong> used to print ${simulation.molecularMode === 0 ? "<strong class='color-p' style='letter-spacing: 2px;'>spores" : simulation.molecularMode === 1 ? "<strong>missiles" : simulation.molecularMode === 2 ? "<strong class='color-s'>ice IX" : "<strong>drones"}</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br><strong>12</strong> <strong class='color-f'>energy</strong> per second` return `excess <strong class='color-f'>energy</strong> used to <strong class='color-print'>print</strong> ${simulation.molecularMode === 0 ? "<strong class='color-p' style='letter-spacing: 2px;'>spores" : simulation.molecularMode === 1 ? "<strong>missiles" : simulation.molecularMode === 2 ? "<strong class='color-s'>ice IX" : "<strong>drones"}</strong><br>use <strong class='color-f'>energy</strong> to <strong>deflect</strong> mobs<br><strong>12</strong> <strong class='color-f'>energy</strong> per second`
}, },
doubleJumpPhase: 0, blockJumpPhase: 0,
effect: () => { effect: () => {
m.fieldMeterColor = "#ff0" m.fieldMeterColor = "#ff0"
m.eyeFillColor = m.fieldMeterColor m.eyeFillColor = m.fieldMeterColor
@@ -3604,20 +3597,106 @@ const m = {
} }
m.drawRegenEnergy() m.drawRegenEnergy()
if (tech.isDoubleJump) { if (tech.isBlockJump) {
if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block
if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall
// if (input.up && m.buttonCD_jump + 20 < m.cycle && m.yOffWhen.stand > 23 && m.lastOnGroundCycle + 5 > m.cycle) m.jump() this.blockJumpPhase = 1
} else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump
if (this.doubleJumpPhase === 0 && input.up) { //1st jump this.blockJumpPhase = 2
} else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump
} else if (this.doubleJumpPhase === 0 && input.up) { this.blockJumpPhase = 3
} else { //reset
//make a block
const radius = 25 + Math.floor(15 * Math.random())
body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 65 + radius, 4, radius, {
friction: 0.05,
frictionAir: 0.001,
collisionFilter: {
category: cat.body,
mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
},
classType: "body",
});
const block = body[body.length - 1]
//mess with the block shape (this code is horrible)
Composite.add(engine.world, block); //add to world
const r1 = radius * (1 + 0.4 * Math.random())
const r2 = radius * (1 + 0.4 * Math.random())
let angle = 0
const vertices = []
for (let i = 0, len = block.vertices.length; i < len; i++) {
angle += 2 * Math.PI / len
vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) })
}
Matter.Body.setVertices(block, vertices)
Matter.Body.setAngle(block, Math.PI / 4)
Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 });
Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) });
if (tech.isBlockRestitution) {
block.restitution = 0.999 //extra bouncy
block.friction = block.frictionStatic = block.frictionAir = 0.001
}
if (tech.isAddBlockMass) {
const expand = function (that, massLimit) {
if (that.mass < massLimit) {
const scale = 1.04;
Matter.Body.scale(that, scale, scale);
setTimeout(expand, 20, that, massLimit);
}
};
expand(block, Math.min(20, block.mass * 3))
}
//jump
m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass
let horizontalVelocity = 8 * (- input.left + input.right)
Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y });
player.force.y = -m.jumpForce; //player jump force
} else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) {
//reset
this.blockJumpPhase = 0 //reset
}
} }
}
// if (tech.isBlockJump) {
// //make sure only 1 ephemera is running
// simulation.ephemera.push({
// name: "2 jump",
// mode: 0,
// do() {
// // console.log('hi')
// if (m.buttonCD_jump + 20 < m.cycle && m.onGround) simulation.removeEphemera(this.name)
// if (this.mode === 0) {
// if (!input.up) this.mode = 1
// } else if (this.mode === 1) {
// if (input.up && m.buttonCD_jump + 20 < m.cycle) {
// simulation.removeEphemera(this.name)
// //make a block
// body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 80, 4, 30 + Math.floor(10 * Math.random()), {
// friction: 0.05,
// frictionAir: 0.001,
// collisionFilter: {
// category: cat.body,
// mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
// },
// classType: "body",
// // isPrinted: true,
// });
// const who = body[body.length - 1]
// Composite.add(engine.world, who); //add to world
// Matter.Body.setVelocity(who, { x: player.velocity.x * 0.5, y: +30 });
// Matter.Body.applyForce(who, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) });
// //jump again
// m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass
// player.force.y = -m.jumpForce; //player jump force
// Matter.Body.setVelocity(player, { x: player.velocity.x, y: -7.5 + 0.25 * player.velocity.y });
// }
// }
// },
// })
// }
} }
} }
}, },
@@ -4663,6 +4742,66 @@ const m = {
m.fieldRadius = 0 m.fieldRadius = 0
} }
m.drawRegenEnergy("rgba(0,0,0,0.2)") m.drawRegenEnergy("rgba(0,0,0,0.2)")
if (tech.isBlockJump) {
if (m.onGround && m.buttonCD_jump + 10 < m.cycle) this.blockJumpPhase = 0 //reset after touching ground or block
if (this.blockJumpPhase === 0 && !m.onGround) { //1st jump or fall
this.blockJumpPhase = 1
} else if (this.blockJumpPhase === 1 && !input.up && m.buttonCD_jump + 10 < m.cycle) { //not pressing jump
this.blockJumpPhase = 2
} else if (this.blockJumpPhase === 2 && input.up && m.buttonCD_jump + 10 < m.cycle) { //2nd jump
this.blockJumpPhase = 3
//make a block
const radius = 25 + Math.floor(15 * Math.random())
body[body.length] = Matter.Bodies.polygon(m.pos.x, m.pos.y + 60 + radius, 4, radius, {
friction: 0.05,
frictionAir: 0.001,
collisionFilter: {
category: cat.body,
mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
},
classType: "body",
});
const block = body[body.length - 1]
//mess with the block shape (this code is horrible)
Composite.add(engine.world, block); //add to world
const r1 = radius * (1 + 0.4 * Math.random())
const r2 = radius * (1 + 0.4 * Math.random())
let angle = 0
const vertices = []
for (let i = 0, len = block.vertices.length; i < len; i++) {
angle += 2 * Math.PI / len
vertices.push({ x: block.position.x + r1 * Math.cos(angle), y: block.position.y + r2 * Math.sin(angle) })
}
Matter.Body.setVertices(block, vertices)
Matter.Body.setAngle(block, Math.PI / 4)
Matter.Body.setVelocity(block, { x: 0.9 * player.velocity.x, y: 10 });
Matter.Body.applyForce(block, m.pos, { x: 0, y: m.jumpForce * 0.12 * Math.min(m.standingOn.mass, 5) });
if (tech.isBlockRestitution) {
block.restitution = 0.999 //extra bouncy
block.friction = block.frictionStatic = block.frictionAir = 0.001
}
if (tech.isAddBlockMass) {
const expand = function (that, massLimit) {
if (that.mass < massLimit) {
const scale = 1.04;
Matter.Body.scale(that, scale, scale);
setTimeout(expand, 20, that, massLimit);
}
};
expand(block, Math.min(20, block.mass * 3))
}
//jump
m.buttonCD_jump = m.cycle; //can't jump again until 20 cycles pass
let horizontalVelocity = 8 * (- input.left + input.right)
Matter.Body.setVelocity(player, { x: player.velocity.x + horizontalVelocity, y: -7.5 + 0.25 * player.velocity.y });
player.force.y = -m.jumpForce; //player jump force
} else if (this.blockJumpPhase === 3 && m.onGround && m.buttonCD_jump + 10 < m.cycle) {
//reset
this.blockJumpPhase = 0 //reset
}
}
} }
} }
}, },
@@ -5619,7 +5758,7 @@ const m = {
let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2 : 1); let dmg = tech.blockDamage * m.dmgScale * v * obj.mass * (tech.isMobBlockFling ? 2 : 1);
if (mob[k].isShielded) dmg *= 0.7 if (mob[k].isShielded) dmg *= 0.7
mob[k].damage(dmg, true); mob[k].damage(dmg, true);
if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && m.throwCycle > m.cycle) { if (tech.isBlockPowerUps && !mob[k].alive && mob[k].isDropPowerUp && Math.random() < 0.5) {
let type = tech.isEnergyNoAmmo ? "heal" : "ammo" let type = tech.isEnergyNoAmmo ? "heal" : "ammo"
if (Math.random() < 0.4) { if (Math.random() < 0.4) {
type = "heal" type = "heal"

View File

@@ -1437,11 +1437,10 @@ const powerUps = {
}, },
}, },
spawnDelay(type, count, delay = 2) { spawnDelay(type, count, delay = 2) {
const lastHarmCycle = m.lastHarmCycle //stop releasing power ups if you take damage
count *= delay count *= delay
let cycle = () => { let cycle = () => {
if (count > 0) { if (count > 0) {
if (m.alive && lastHarmCycle === m.lastHarmCycle) requestAnimationFrame(cycle); if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing && powerUp.length < 300) { //&& !(simulation.cycle % 2) if (!simulation.paused && !simulation.isChoosing && powerUp.length < 300) { //&& !(simulation.cycle % 2)
count-- count--
if (!(count % delay)) { if (!(count % delay)) {
@@ -1622,7 +1621,7 @@ const powerUps = {
for (let i = 0; i < tech.tech[choose].count; i++) { for (let i = 0; i < tech.tech[choose].count; i++) {
powerUps.directSpawn(m.pos.x, m.pos.y, "tech"); powerUps.directSpawn(m.pos.x, m.pos.y, "tech");
powerUp[powerUp.length - 1].isDuplicated = true // powerUp[powerUp.length - 1].isDuplicated = true
} }
// remove a random tech from the list of tech you have // remove a random tech from the list of tech you have
tech.tech[choose].remove(); tech.tech[choose].remove();

View File

@@ -814,7 +814,6 @@ const simulation = {
simulation.isChoosing = false; simulation.isChoosing = false;
b.setFireMethod() b.setFireMethod()
b.setFireCD(); b.setFireCD();
// simulation.updateTechHUD();
for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < b.guns.length; i++) b.guns[i].isRecentlyShown = false //reset recently shown back to zero
for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < m.fieldUpgrades.length; i++) m.fieldUpgrades[i].isRecentlyShown = false //reset recently shown back to zero
for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero for (let i = 0; i < tech.tech.length; i++) tech.tech[i].isRecentlyShown = false //reset recently shown back to zero
@@ -827,17 +826,12 @@ const simulation = {
powerUps.boost.endCycle = 0 powerUps.boost.endCycle = 0
powerUps.isFieldSpawned = false powerUps.isFieldSpawned = false
m.setFillColors(); m.setFillColors();
// m.maxHealth = 1
// m.maxEnergy = 1
// m.energy = 1
input.isPauseKeyReady = true input.isPauseKeyReady = true
simulation.wipe = function () { //set wipe to normal simulation.wipe = function () { //set wipe to normal
ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.clearRect(0, 0, canvas.width, canvas.height);
} }
m.hole.isOn = false m.hole.isOn = false
simulation.paused = false; simulation.paused = false;
// simulation.cycle = 0
// m.cycle = 0
engine.timing.timeScale = 1; engine.timing.timeScale = 1;
simulation.fpsCap = simulation.fpsCapDefault; simulation.fpsCap = simulation.fpsCapDefault;
simulation.isAutoZoom = true; simulation.isAutoZoom = true;
@@ -853,18 +847,11 @@ const simulation = {
document.getElementById("text-log").style.display = "none" document.getElementById("text-log").style.display = "none"
document.getElementById("fade-out").style.opacity = 0; document.getElementById("fade-out").style.opacity = 0;
document.title = "n-gon"; document.title = "n-gon";
// simulation.makeTextLog(`input.key.up<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]`);
// simulation.makeTextLog(`input.key.left<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]`);
// simulation.makeTextLog(`input.key.down<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]`);
// simulation.makeTextLog(`input.key.right<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]`);
simulation.makeTextLog(`Math.seed <span class='color-symbol'>=</span> ${Math.initialSeed}`); simulation.makeTextLog(`Math.seed <span class='color-symbol'>=</span> ${Math.initialSeed}`);
simulation.makeTextLog(`<span class='color-var'>const</span> engine <span class='color-symbol'>=</span> Engine.create(); <em>//simulation begin</em>`); simulation.makeTextLog(`<span class='color-var'>const</span> engine <span class='color-symbol'>=</span> Engine.create(); <em>//simulation begin</em>`);
simulation.makeTextLog(`engine.timing.timeScale <span class='color-symbol'>=</span> 1`); simulation.makeTextLog(`engine.timing.timeScale <span class='color-symbol'>=</span> 1`);
// simulation.makeTextLog(`input.key.field<span class='color-symbol'>:</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>MouseRight</span>"]`);
// document.getElementById("health").style.display = "inline"
// document.getElementById("health-bg").style.display = "inline"
m.alive = true; m.alive = true;
m.definePlayerMass();
m.onGround = false m.onGround = false
m.lastOnGroundCycle = 0 m.lastOnGroundCycle = 0
m.health = 0; m.health = 0;
@@ -874,23 +861,10 @@ const simulation = {
//set to default field //set to default field
tech.healMaxEnergyBonus = 0 tech.healMaxEnergyBonus = 0
// m.setMaxEnergy();
m.energy = 0 m.energy = 0
m.immuneCycle = 0; m.immuneCycle = 0;
// simulation.makeTextLog(`${simulation.SVGrightMouse}<strong style='font-size:30px;'> ${m.fieldUpgrades[m.fieldMode].name}</strong><br><span class='faded'></span><br>${m.fieldUpgrades[m.fieldMode].description}`, 600);
// simulation.makeTextLog(`
// input.key.up <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.up}</span>", "<span class='color-text'>ArrowUp</span>"]
// <br>input.key.left <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.left}</span>", "<span class='color-text'>ArrowLeft</span>"]
// <br>input.key.down <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.down}</span>", "<span class='color-text'>ArrowDown</span>"]
// <br>input.key.right <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.right}</span>", "<span class='color-text'>ArrowRight</span>"]
// <br>
// <br><span class='color-var'>m</span>.fieldMode <span class='color-symbol'>=</span> "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].name}</span>"
// <br>input.key.field <span class='color-symbol'>=</span> ["<span class='color-text'>${input.key.field}</span>", "<span class='color-text'>right mouse</span>"]
// <br><span class='color-var'>m</span>.field.description <span class='color-symbol'>=</span> "<span class='color-text'>${m.fieldUpgrades[m.fieldMode].description}</span>"
// `, 800);
m.coupling = 0 m.coupling = 0
m.setField(0) //this calls m.couplingChange(), which sets max health and max energy m.setField(0) //this calls m.couplingChange(), which sets max health and max energy
// m.energy = 0;
//exit testing //exit testing
if (simulation.testing) { if (simulation.testing) {
simulation.testing = false; simulation.testing = false;

View File

@@ -1427,7 +1427,7 @@ const spawn = {
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.body | cat.map me.collisionFilter.mask = cat.player | cat.bullet | cat.body// | cat.map
Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001 Matter.Body.setDensity(me, 0.0001 + 0.00002 * simulation.difficulty) // normal density is 0.001
me.damageReduction = 0.17 me.damageReduction = 0.17
@@ -1755,7 +1755,7 @@ const spawn = {
me.seeAtDistance2 = 1000000; me.seeAtDistance2 = 1000000;
me.accelMag = 0.0002 + 0.0004 * simulation.accelScale; me.accelMag = 0.0002 + 0.0004 * simulation.accelScale;
Matter.Body.setDensity(me, 0.0003); //normal is 0.001 Matter.Body.setDensity(me, 0.0003); //normal is 0.001
me.collisionFilter.mask = cat.bullet | cat.player //| cat.body me.collisionFilter.mask = cat.bullet | cat.player | cat.body
me.memory = Infinity; me.memory = Infinity;
me.seePlayerFreq = 30 me.seePlayerFreq = 30
me.lockedOn = null; me.lockedOn = null;
@@ -2314,7 +2314,7 @@ const spawn = {
me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon me.seeAtDistance2 = (me.eventHorizon + 400) * (me.eventHorizon + 400); //vision limit is event horizon
me.accelMag = 0.00012 * simulation.accelScale; me.accelMag = 0.00012 * simulation.accelScale;
me.frictionAir = 0.025; me.frictionAir = 0.025;
me.collisionFilter.mask = cat.player | cat.bullet //| cat.body me.collisionFilter.mask = cat.player | cat.bullet | cat.body
me.memory = Infinity; me.memory = Infinity;
Matter.Body.setDensity(me, 0.015); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.015); //extra dense //normal is 0.001 //makes effective life much larger
me.do = function () { me.do = function () {
@@ -4263,7 +4263,7 @@ const spawn = {
powerUps.spawnBossPowerUp(this.position.x, this.position.y) powerUps.spawnBossPowerUp(this.position.x, this.position.y)
}; };
Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger Matter.Body.setDensity(me, 0.03); //extra dense //normal is 0.001 //makes effective life much larger
me.damageReduction = 0.25 me.damageReduction = 0.33
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.isInvulnerable = false me.isInvulnerable = false
me.nextHealthThreshold = 0.75 me.nextHealthThreshold = 0.75
@@ -4279,7 +4279,7 @@ const spawn = {
} }
}; };
me.lasers = [] //keeps track of static laser beams me.lasers = [] //keeps track of static laser beams
me.laserLimit = 2 + (simulation.difficultyMode < 3 ? 1 : 2) me.laserLimit = 2 + (simulation.difficultyMode > 2) + (simulation.difficultyMode > 4)
me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5) me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
me.cycle = 0 me.cycle = 0
me.laserDelay = 210 me.laserDelay = 210
@@ -5910,7 +5910,7 @@ const spawn = {
me.alpha = 1; //used in drawGhost me.alpha = 1; //used in drawGhost
me.isNotCloaked = false; //used in drawGhost me.isNotCloaked = false; //used in drawGhost
me.isBadTarget = true; me.isBadTarget = true;
me.collisionFilter.mask = cat.bullet //| cat.body me.collisionFilter.mask = cat.bullet | cat.body
me.showHealthBar = false; me.showHealthBar = false;
me.memory = 900; me.memory = 900;
me.delay = 60 me.delay = 60
@@ -5961,7 +5961,7 @@ const spawn = {
if (!this.isNotCloaked) { if (!this.isNotCloaked) {
this.isNotCloaked = true; this.isNotCloaked = true;
this.isBadTarget = false; this.isBadTarget = false;
this.collisionFilter.mask = cat.player | cat.bullet this.collisionFilter.mask = cat.player | cat.bullet | cat.body
} }
} }
//draw body //draw body
@@ -5976,7 +5976,7 @@ const spawn = {
} else if (this.isNotCloaked) { } else if (this.isNotCloaked) {
this.isNotCloaked = false; this.isNotCloaked = false;
this.isBadTarget = true; this.isBadTarget = true;
this.collisionFilter.mask = cat.bullet; //can't touch player or walls this.collisionFilter.mask = cat.bullet | cat.body; //can't touch player or walls
} }
}; };
}, },
@@ -7392,7 +7392,7 @@ const spawn = {
snakeBody(x, y, radius = 10) { snakeBody(x, y, radius = 10) {
mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)"); mobs.spawn(x, y, 8, radius, "rgba(0,180,180,0.4)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
me.collisionFilter.mask = cat.bullet | cat.player //| cat.mob //| cat.body me.collisionFilter.mask = cat.bullet | cat.player | cat.body //| cat.mob
me.damageReduction = 0.028 me.damageReduction = 0.028
Matter.Body.setDensity(me, 0.0001); //normal is 0.001 Matter.Body.setDensity(me, 0.0001); //normal is 0.001

View File

@@ -108,20 +108,8 @@ const tech = {
if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0 if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0
} }
}, },
giveRandomJUNK() {
const list = []
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isJunk) list.push(tech.tech[i].name)
}
let name = list[Math.floor(Math.random() * list.length)]
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${name}</span>")<em>`);
tech.giveTech(name)
},
giveTech(index = 'random') { giveTech(index = 'random') {
// if (Math.random() < tech.junkChance) {
// tech.giveRandomJUNK();
// return
// }
if (index === 'random') { if (index === 'random') {
let options = []; let options = [];
for (let i = 0; i < tech.tech.length; i++) { for (let i = 0; i < tech.tech.length; i++) {
@@ -2342,7 +2330,7 @@ const tech = {
{ {
name: "buckling", name: "buckling",
descriptionFunction() { descriptionFunction() {
return `if a <strong class='color-block'>block</strong> you threw kills a mob<br>spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` return `if a <strong class='color-block'>block</strong> kills a mob there's a <strong>50%</strong> chance<br>to spawn either ${powerUps.orb.coupling(1)}, ${powerUps.orb.boost(1)}, ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4291,7 +4279,7 @@ const tech = {
remove() { remove() {
if (this.count > 0 && m.alive) { if (this.count > 0 && m.alive) {
tech.damage /= this.damage tech.damage /= this.damage
powerUps.spawnDelay("research", 15) requestAnimationFrame(() => { powerUps.spawnDelay("research", 15) });
this.frequency = 0 this.frequency = 0
} }
} }
@@ -4349,16 +4337,16 @@ const tech = {
remove() { remove() {
if (this.count > 0 && m.alive) { if (this.count > 0 && m.alive) {
tech.damage /= this.damage tech.damage /= this.damage
powerUps.spawnDelay("ammo", this.ammo)
this.frequency = 0 this.frequency = 0
requestAnimationFrame(() => { powerUps.spawnDelay("ammo", this.ammo) });
} }
} }
}, },
{ {
name: "deprecated", name: "deprecated",
scale: 0.05, scale: 0.07,
descriptionFunction() { descriptionFunction() {
return `after <span class='color-remove'>removing</span> this gain<br><strong>1.05x</strong> <strong class='color-d'>damage</strong> per <span class='color-remove'>removed</span> <strong class='color-m'>tech</strong><em>(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)</em>` return `after <span class='color-remove'>removing</span> this gain<br><strong>${1 + this.scale}x</strong> <strong class='color-d'>damage</strong> per <span class='color-remove'>removed</span> <strong class='color-m'>tech</strong><em>(${(1 + this.scale * ((this.frequency === 0 ? 0 : 1) + tech.removeCount)).toFixed(2)}x)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -6453,7 +6441,7 @@ const tech = {
}, },
{ {
name: "von Neumann probe", //"drone repair", name: "von Neumann probe", //"drone repair",
description: "after a <strong>drone</strong> expires it will use <strong>-5</strong> <strong class='color-f'>energy</strong><br>and a nearby <strong class='color-block'>block</strong> to <strong>replicate</strong> itself", description: "after a <strong>drone</strong> expires it will use <strong>-4</strong> <strong class='color-f'>energy</strong><br>and a nearby <strong class='color-block'>block</strong> to <strong>replicate</strong> itself",
// description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>", // description: "broken <strong>drones</strong> <strong>repair</strong> if the drone <strong class='color-g'>gun</strong> is active<br><strong>repairing</strong> has a <strong>25%</strong> chance to use <strong>1</strong> <strong>drone</strong>",
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
@@ -6461,7 +6449,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.haveGunCheck("drones") return tech.haveGunCheck("drones") || (m.fieldMode === 4 && simulation.molecularMode === 3)
}, },
requires: "drones", requires: "drones",
effect() { effect() {
@@ -7862,8 +7850,7 @@ const tech = {
// }, // },
{ {
name: "additive manufacturing", name: "additive manufacturing",
description: "hold <strong>crouch</strong> and use your <strong class='color-f'>field</strong> to <strong>print</strong> a <strong class='color-block'>block</strong><br> with <strong>1.8x</strong> density, <strong class='color-d'>damage</strong>, and launch speed", description: "hold <strong>crouch</strong> and use your <strong class='color-f'>field</strong> to <strong class='color-print'>print</strong> a <strong class='color-block'>block</strong><br> with <strong>1.8x</strong> density, <strong class='color-d'>damage</strong>, and launch speed",
// description: "simultaneously <strong>fire</strong> and activate your <strong class='color-f'>field</strong> to make<br>molecular assembler <strong>print</strong> a throwable <strong class='color-block'>block</strong><br><strong>+80%</strong> <strong class='color-block'>block</strong> throwing speed",
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -7881,6 +7868,29 @@ const tech = {
tech.isPrinter = false; tech.isPrinter = false;
} }
}, },
{
name: "working mass",
// description: "molecular assembler <strong class='color-print'>prints</strong> one <strong class='color-block'>block</strong><br>to <strong>jump</strong> off while midair",
descriptionFunction() {
const fieldName = m.fieldMode === 8 ? "pilot wave" : "molecular assembler"
return `${fieldName} <strong class='color-print'>prints</strong> a <strong class='color-block'>block</strong><br>to <strong>jump</strong> off while midair a second time`
},
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 2,
frequencyDefault: 2,
allowed() {
return (m.fieldMode === 4 || m.fieldMode === 8)
},
requires: "molecular assembler, pilot wave",
effect() {
tech.isBlockJump = true
},
remove() {
tech.isBlockJump = false
}
},
{ {
name: "pair production", name: "pair production",
description: "after picking up a <strong>power up</strong><br><strong>+200</strong> <strong class='color-f'>energy</strong>", description: "after picking up a <strong>power up</strong><br><strong>+200</strong> <strong class='color-f'>energy</strong>",
@@ -7901,26 +7911,6 @@ const tech = {
tech.isMassEnergy = false; tech.isMassEnergy = false;
} }
}, },
// {
// name: "working mass",
// // description: "after jumping jump again in <strong>midair</strong><br><strong>double jumping</strong> requires <strong>50%</strong> of current <strong class='color-f'>energy</strong><br><strong>double jumping</strong> boosts <strong class='color-speed'>speed</strong>",
// description: "",
// isFieldTech: true,
// maxCount: 1,
// count: 0,
// frequency: 2,
// frequencyDefault: 2,
// allowed() {
// return m.fieldMode === 4
// },
// requires: "molecular assembler",
// effect() {
// tech.isDoubleJump = true
// },
// remove() {
// tech.isDoubleJump = false
// }
// },
{ {
name: "electric generator", name: "electric generator",
description: "after <strong>deflecting</strong> mobs<br><strong>molecular assembler</strong> generates <strong>+50</strong> <strong class='color-f'>energy</strong>", description: "after <strong>deflecting</strong> mobs<br><strong>molecular assembler</strong> generates <strong>+50</strong> <strong class='color-f'>energy</strong>",
@@ -8195,7 +8185,7 @@ const tech = {
}, },
{ {
name: "Lorentz transformation", name: "Lorentz transformation",
description: `use ${powerUps.orb.research(3)}<br><strong>1.5x</strong> <strong>movement</strong>, <strong>jumping</strong>, and <em>fire rate</em>`, description: `use ${powerUps.orb.research(3)}<br><strong>1.5x</strong> movement, jumping, and <em>fire rate</em>`,
isFieldTech: true, isFieldTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -9271,9 +9261,15 @@ const tech = {
allowed: () => true, allowed: () => true,
requires: "", requires: "",
effect() { effect() {
tech.giveRandomJUNK() for (let i = 0; i < 3; i++) {
tech.giveRandomJUNK() const list = []
tech.giveRandomJUNK() for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].isJunk) list.push(tech.tech[i].name)
}
let name = list[Math.floor(Math.random() * list.length)]
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${name}</span>")<em>`);
tech.giveTech(name)
}
}, },
remove() { } remove() { }
}, },
@@ -11848,5 +11844,5 @@ const tech = {
interestRate: null, interestRate: null,
isImmunityDamage: null, isImmunityDamage: null,
isMobDeathImmunity: null, isMobDeathImmunity: null,
isDoubleJump: null, isBlockJump: null,
} }

View File

@@ -935,6 +935,11 @@ summary {
text-shadow: 1px 0px 2px #234; text-shadow: 1px 0px 2px #234;
} }
.color-print {
color: #567;
font-family: 'Courier New', Courier, monospace;
}
.color-defense { .color-defense {
background-color: hsla(227, 9%, 71%, 0.279); background-color: hsla(227, 9%, 71%, 0.279);
padding: 2px; padding: 2px;

View File

@@ -1,19 +1,17 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
you can now jump off mobs while invulnerable tech: working mass - in midair molecular assembler or pilot wave prints a block to jump off
includes time dilated
pause display text updated with details menus
difficulty parameters
0.82->0.84x damage done per level
1.25->1.23x damage taken per level
tungsten carbide 300->400 health, but 0.08->0.02 seconds of coyote time and longer crouch time
nitinol 0.08->0.17 seconds of coyote time and much less crouching on hard landings, but 0.8->1 damage taken
mass-energy equivalence no longer costs 2 research
long power up spawns, like from interest or supply chain:
will pause new spawns until total power ups are below 300 to reduce lag
stop spawning if you take damage
bug fixes buckling: 100%->50% chance to spawn a power up from any block that kills a mob
no longer requires the block to be thrown
mobs: powerUpBoss, snakeBoss tails, cellBoss, ghoster, sucker - all collide with blocks now
added a few more blocks to towers level
deprecated: 1.05->1.07 damage per removed tech
laserLayerBoss has 33% less health and has fewer lasers at higher difficulties
bugfix
disabled spawnDelay stopping on damage because it had too many negative tech interactions
metastability + paradigm shift no longer makes all ejected tech explode
******************************************************* DESIGN ****************************************************** ******************************************************* DESIGN ******************************************************
@@ -36,22 +34,33 @@ list of powerful synergies
duplication 100% duplication 100%
interest + coupling, research + (peer review? or Bayesian statistics) interest + coupling, research + (peer review? or Bayesian statistics)
electronegativity and high energy? electronegativity and high energy?
electronegativity + anyon + duplication + Maxwells demon + interest electronegativity + anyon + duplication + Maxwells demon + interest + pair production
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
tech: working mass - double jump make player mass an adjustable var in the skin
cost flat energy not a % does this mess with jump height or air control?
field Tech for molecular assembler and print and throw a block down on 2nd jump increase mass and movement speed at the same time
remove block after time or keep it around? increase jump differently because it scales extra with mass
credit to TNTiger17 (although I'm not looking for more code contributions) m.defaultMass = 4.5
m.definePlayerMass()
possible player.mass bad interactions
grapple
JUNK tech - player takes damage from block collisions
is this gonna contribute to lag?
player damage seems low
player damage taken seems fine, or maybe increase
difficulty rework: explicit changes to the game to increase difficulty difficulty rework: explicit changes to the game to increase difficulty
UI - UI -
add a wire attached to difficulty power up add a wire attached to difficulty power up
like the one attached to player, but thinner like the one attached to player, but thinner
laser: slow light is the least fun laser tech, make it more fun
tokamak synergy tech tokamak synergy tech
tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?) tech: stellarator - after firing a block with tokamak, heal (scale heal amount with block mass?)
tech: inertial confinement - while charging tokamak you can fly, and invulnerable tech: inertial confinement - while charging tokamak you can fly, and invulnerable
@@ -823,11 +832,6 @@ intro map: diegeticly draw a mouse with field highlighted
also indicate space? also indicate space?
dynamically adjust drawing after picking up a gun dynamically adjust drawing after picking up a gun
increase mass and movement speed at the same time
increase jump differently because it scales extra with mass
m.defaultMass = 4.5
m.definePlayerMass()
give history boss legs? give history boss legs?
field tech - disable blocking, but does high damage to mobs inside field field tech - disable blocking, but does high damage to mobs inside field