invulnerable

tech: anyon - 2x energy after duplicating a power up, +6% duplication chance
tech: Abelian group - 4x damage while invulnerable
tech: fermion - become invulnerable for 5 seconds after a mob dies
tech: entropic gravity - crouching pulls MACHO towards the player, and 1.5x to all MACHO effects (damage, damage reduction, AoE damage)
tech: modified Newtonian dynamics - +20 speed for all Newtonian law tech

choice, MACHO, invulnerable, speed - have text keyword CSS style
removed chance to find a random tech in early levels from mobs
  this reduces tech per full game by about 2
tower level has a few changes
options exchange only works once per level, but it gives 3x choices after randomizing
dark star has a 1.2->1.3x MACHO radius
autocannon fires 1->2 extra super balls, but balls have higher gravity
grappling hook field starts with 0.6x damage reduction
super balls + uncertainty principle makes all balls start in the same spot and only separate after teleporting
ablative drones spawns 50% more drones on collision
von Neumann probe gives 40% more drones per block mass
  also added text clarification that it uses 5 energy
tech lens rotates 50% faster
ghoster mobs are more aggressive once they have lost 20% health
sneakBoss doesn't start accelerating until it is partly uncloaked, but it spawns sneaker mobs after cloaking

fixed bug with 2 different boost power up sizes
paradigm shift doesn't do damage while player is invulnerable
random internet JUNK images disabled because some of the images are bad
entanglement bug fix, maybe
This commit is contained in:
landgreen
2024-05-11 09:52:56 -07:00
parent a1164eddae
commit 507b0605d6
15 changed files with 652 additions and 760 deletions

BIN
img/Abelian group.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

BIN
img/anyon.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

BIN
img/entropic gravity.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
img/fermion.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -3331,7 +3331,7 @@ const b = {
//remove the body and spawn a new drone
Composite.remove(engine.world, found)
body.splice(body.indexOf(found), 1)
b.delayDrones(found.position, 0.7 * Math.sqrt(found.mass))
b.delayDrones(found.position, Math.sqrt(found.mass))
//draw a line from the drone to the body on the canvas
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
@@ -3350,9 +3350,7 @@ const b = {
ctx.beginPath();
let vertices = found.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
for (let j = 1; j < vertices.length; j++) {
ctx.lineTo(vertices[j].x, vertices[j].y);
}
for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
ctx.lineWidth = 2;
ctx.strokeStyle = `rgba(0,0,0,${this.count / 60})`
@@ -3573,7 +3571,7 @@ const b = {
//remove the body and spawn a new drone
Composite.remove(engine.world, found)
body.splice(body.indexOf(found), 1)
b.delayDrones(found.position, 0.35 * Math.sqrt(found.mass))
b.delayDrones(found.position, 0.5 * Math.sqrt(found.mass))
//draw a line from the drone to the body on the canvas
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
@@ -3772,6 +3770,11 @@ const b = {
});
},
superBall(where, velocity, radius) {
let gravity = 0.001
if (tech.superBallDelay) {
velocity = Vector.mult(velocity, 1.4)
gravity *= 6
}
let dir = m.angle
const me = bullet.length;
bullet[me] = Bodies.polygon(where.x, where.y, 12, radius, b.fireAttributes(dir, false));
@@ -3787,7 +3790,7 @@ const b = {
bullet[me].frictionStatic = 0;
if (tech.isSuperHarm) {
bullet[me].collidePlayerDo = function () {
this.force.y += this.mass * 0.001;
this.force.y += this.mass * gravity;;
if (Matter.Query.collides(this, [player]).length) {
this.endCycle = 0
m.energy -= 0.04
@@ -3811,7 +3814,7 @@ const b = {
bullet[me].portFrequency = 25 + Math.floor(10 * Math.random())
bullet[me].nextPortCycle = simulation.cycle + bullet[me].portFrequency
bullet[me].do = function () {
this.force.y += this.mass * 0.001;
this.force.y += this.mass * gravity;
if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
this.nextPortCycle = simulation.cycle + this.portFrequency
const range = 33 * Math.sqrt(radius) * Math.random()
@@ -3821,7 +3824,7 @@ const b = {
};
} else {
bullet[me].do = function () {
this.force.y += this.mass * 0.001;
this.force.y += this.mass * gravity;
};
}
bullet[me].beforeDmg = function (who) {
@@ -3843,7 +3846,6 @@ const b = {
Matter.Body.setDensity(bullet[me], bullet[me].calcDensity() * 1.33);//33% more density and damage
this.endCycle = simulation.cycle + Math.floor(300 + 90 * Math.random()); //reset to full duration of time
Matter.Body.setVelocity(this, Vector.mult(Vector.normalise(this.velocity), 60)); //reset to high velocity
let count = 5
const wait = () => {
count--
@@ -3857,7 +3859,6 @@ const b = {
});
}
requestAnimationFrame(wait);
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
y: this.position.y,
@@ -6426,10 +6427,7 @@ const b = {
have: false,
// num: 5,
do() { },
foamBall() {
},
foamBall() { },
fireOne() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 27 : 19) * b.fireCDscale); // cool down
const speed = m.crouch ? 43 : 36
@@ -6446,21 +6444,33 @@ const b = {
const SPREAD = m.crouch ? 0.08 : 0.13
const num = 3 + Math.floor(tech.extraSuperBalls * Math.random())
const speed = m.crouch ? 43 : 36
let dir = m.angle - SPREAD * (num - 1) / 2;
for (let i = 0; i < num; i++) {
b.superBall({
x: m.pos.x + 30 * Math.cos(dir),
y: m.pos.y + 30 * Math.sin(dir)
}, {
x: speed * Math.cos(dir),
y: speed * Math.sin(dir)
}, 11 * tech.bulletSize)
dir += SPREAD;
if (tech.isBulletTeleport) {
for (let i = 0; i < num; i++) {
b.superBall({
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}, {
x: speed * Math.cos(m.angle),
y: speed * Math.sin(m.angle)
}, 11 * tech.bulletSize)
}
} else {
let dir = m.angle - SPREAD * (num - 1) / 2;
for (let i = 0; i < num; i++) {
b.superBall({
x: m.pos.x + 30 * Math.cos(dir),
y: m.pos.y + 30 * Math.sin(dir)
}, {
x: speed * Math.cos(dir),
y: speed * Math.sin(dir)
}, 11 * tech.bulletSize)
dir += SPREAD;
}
}
},
fireQueue() {
m.fireCDcycle = m.cycle + Math.floor((m.crouch ? 23 : 15) * b.fireCDscale); // cool down
const num = 1 + 3 + Math.floor(tech.extraSuperBalls * Math.random()) //1 extra
const num = 2 + 3 + Math.floor(tech.extraSuperBalls * Math.random()) //2 extra
const speed = m.crouch ? 43 : 36
const delay = Math.floor((m.crouch ? 18 : 12) * b.fireCDscale)
@@ -6479,8 +6489,6 @@ const b = {
}
let count = 0
requestAnimationFrame(cycle);
},
chooseFireMethod() { //set in simulation.startGame
if (tech.oneSuperBall) {
@@ -7789,7 +7797,7 @@ const b = {
lensDamageOn: 0, //set in tech
lens() {
this.stuckOn();
this.angle += 0.02
this.angle += 0.03
if (this.isInsideArc(m.angle)) {
this.lensDamage = this.lensDamageOn
ctx.lineWidth = 6 + this.lensDamageOn

View File

@@ -25,6 +25,7 @@ const level = {
// powerUps.research.changeRerolls(99999)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// tech.addJunkTechToPool(0.5)
// m.couplingChange(10)
// m.setField("plasma torch") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0
@@ -33,23 +34,23 @@ const level = {
// m.energy = 0
// simulation.molecularMode = 2
// m.damage(0.1);
// b.giveGuns("drones") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("super balls") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("shotgun") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("wave") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization")
// tech.giveTech("Pareto efficiency")
// for (let i = 0; i < 1; ++i) tech.giveTech("collider")
// for (let i = 0; i < 1; ++i) tech.giveTech("anthropic principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
// tech.giveTech("Newtons 2nd law")
// for (let i = 0; i < 1; ++i) tech.giveTech("lens")
// for (let i = 0; i < 1; ++i) tech.giveTech("modified Newtonian dynamics")
// for (let i = 0; i < 1; ++i) tech.giveTech("Newtons 1st law")
// for (let i = 0; i < 1; ++i) tech.giveTech("entropic gravity")
// 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") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
// m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; ++i) tech.giveTech("Lorentz transformation")
// for (let i = 0; i < 1; ++i) tech.giveTech("unified field theory")
// for (let i = 0; i < 1; ++i) tech.giveTech("anyon")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
@@ -59,9 +60,8 @@ const level = {
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500)
// Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random())
// for (let i = 0; i < 1; ++i) spawn.stinger(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// spawn.beetleBoss(1900, -500, 25)
// spawn.sneakBoss(1900, -500)
// 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())
// tech.addJunkTechToPool(2)
@@ -71,7 +71,7 @@ const level = {
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 2; i++) spawn.ghoster(1300, -500) //ghosters need to spawn after the map loads
// for (let i = 0; i < 2; i++) spawn.ghoster(level.exit.x, level.exit.y) //ghosters need to spawn after the map loads
// spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass)
// simulation.isAutoZoom = false; //look in close
@@ -79,7 +79,7 @@ const level = {
// simulation.setZoom();
// tech.addJunkTechToPool(0.7)
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech");
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
// for (let i = 0; i < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "boost");
// for (let i = 0; i < 100; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "ammo");
// for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
@@ -148,6 +148,7 @@ const level = {
},
newLevelOrPhase() { //runs on each new level but also on final boss phases
//used for generalist and pigeonhole principle
tech.cancelTechCount = 0
tech.buffedGun++
if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0;
if (tech.isGunCycle && b.activeGun !== null && b.inventory.length) {
@@ -170,7 +171,7 @@ const level = {
}
if (tech.interestRate > 0) {
const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels
if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].name !== "laser") {
if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].ammo !== Infinity) {
const ammoPerOrb = b.guns[b.activeGun].ammoPack
const a = Math.ceil(rate * b.guns[b.activeGun].ammo / ammoPerOrb)
powerUps.spawnDelay("ammo", a, 4);
@@ -793,7 +794,7 @@ const level = {
return who
},
boost(x, y, height = 1000, angle = Math.PI / 2) { //height is how high the player will be flung above y
boost(x, y, speed = 1000, angle = Math.PI / 2) { //height is how high the player will be flung above y
if (angle !== Math.PI / 2) { //angle !== 3 * Math.PI / 2
angle *= -1
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("80 40 -80 40 -50 -40 50 -40"), {
@@ -801,14 +802,13 @@ const level = {
category: cat.body,
mask: cat.player | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet //cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet
},
yVelocity: 1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
const rayVector = Vector.add(this.position, Vector.rotate({ x: 100, y: 0 }, angle))
query = (who) => {
const list = Matter.Query.ray(who, this.position, rayVector, 100)
if (list.length > 0) {
Matter.Body.setVelocity(list[0].bodyA, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
Matter.Body.setVelocity(list[0].bodyA, Vector.rotate({ x: 1.21 * Math.sqrt(Math.abs(speed)), y: 0 }, angle));
}
}
query(body)
@@ -818,37 +818,17 @@ const level = {
//player collision
const list = Matter.Query.ray([player], this.position, rayVector, 100)
if (list.length > 0) {
Matter.Body.setVelocity(player, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
Matter.Body.setVelocity(player, Vector.rotate({ x: 1.21 * Math.sqrt(Math.abs(speed)), y: 0 }, angle));
m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
m.hardLandCD = 0 // disable hard landing
}
// if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
// m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
// m.hardLandCD = 0 // disable hard landing
// if (player.velocity.y > 26) {
// Matter.Body.setVelocity(player, {
// x: player.velocity.x,
// y: -15 //gentle bounce if coming down super fast
// });
// } else {
// Matter.Body.setVelocity(player, {
// x: player.velocity.x + (Math.random() - 0.5) * 2.5,
// y: this.yVelocity //give a upwards velocity that will put the player that the height desired
// });
// }
// }
//draw
const v1 = this.vertices[0]
const v2 = this.vertices[1]
let unit = Vector.rotate({ x: 60, y: 0 }, angle)
let v3 = Vector.add(v2, unit)
let v4 = Vector.add(v1, unit)
// ctx.beginPath();
// ctx.strokeStyle = "#000";
// ctx.stroke()
ctx.beginPath();
ctx.moveTo(v1.x, v1.y)
ctx.lineTo(v2.x, v2.y)
@@ -856,9 +836,6 @@ const level = {
ctx.lineTo(v4.x, v4.y)
ctx.fillStyle = "rgba(200,0,255,0.05)";
ctx.fill()
// ctx.strokeStyle = "#000";
// ctx.stroke()
unit = Vector.rotate({ x: 20, y: 0 }, angle)
v3 = Vector.add(v2, unit)
v4 = Vector.add(v1, unit)
@@ -872,7 +849,6 @@ const level = {
},
});
Matter.Body.rotate(who, angle + Math.PI / 2);
return who
} else {
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("120 40 -120 40 -50 -40 50 -40"), {
@@ -890,7 +866,6 @@ const level = {
y: y
}
},
yVelocity: -1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
query = (who) => {
@@ -898,7 +873,7 @@ const level = {
list = Matter.Query.region(who, this.boostBounds)
Matter.Body.setVelocity(list[0], {
x: list[0].velocity.x + (Math.random() - 0.5) * 2.5, //add a bit of horizontal drift to reduce endless bounces
y: this.yVelocity //give a upwards velocity
y: -1.21 * Math.sqrt(Math.abs(speed)) //give a upwards velocity
});
}
}
@@ -918,7 +893,7 @@ const level = {
} else {
Matter.Body.setVelocity(player, {
x: player.velocity.x + (Math.random() - 0.5) * 2.5,
y: this.yVelocity //give a upwards velocity that will put the player that the height desired
y: -1.21 * Math.sqrt(Math.abs(speed)) //give an upwards velocity that will put the player that the height desired
});
}
}
@@ -928,8 +903,6 @@ const level = {
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 10, 100, 30);
ctx.fillStyle = "rgba(200,0,255,0.05)";
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 50, 100, 70);
// ctx.fillStyle = "rgba(200,0,255,0.02)";
// ctx.fillRect(x, y - 120, 100, 120);
},
});
return who
@@ -4259,12 +4232,12 @@ const level = {
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
if (isFlipped) {
level.setPosToSpawn(9150 + 50, -2230 - 25);
level.exit.x = -100 - 50;
level.exit.x = 400 - 50;
level.exit.y = -50 + 25;
leftRoomColor = "#cff"
rightRoomColor = "rgba(0,0,0,0.13)"
} else {
level.setPosToSpawn(-100, -50);
level.setPosToSpawn(400, -50);
level.exit.x = 9150;
level.exit.y = -2230;
}
@@ -4272,9 +4245,10 @@ const level = {
spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); //bump for level entrance
level.fallMode = "position"; //must set level.fallModeBounds in this mode to prevent player getting stuck left or right
level.fallModeBounds = { left: level.enter.x, right: level.exit.x } //used with level.fallMode = "position";
if (isFlipped) level.fallModeBounds = { left: level.exit.x, right: level.enter.x } //used with level.fallMode = "position";
simulation.fallHeight = 5000 //level.enter.y - 4000
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 2500
level.defaultZoom = 2300
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#cdd9df";
powerUps.spawnStartingPowerUps(6300, 1025)
@@ -4284,6 +4258,10 @@ const level = {
const boost3 = level.boost(9700, -730, 1050, 1.95)
const boost4 = level.boost(4300, -720, 1500, 1.25)
const boost5 = level.boost(3000, -1215, 3000, 1.25)
const boost6 = level.boost(8251, -619, 1200, 2.7)
const boost7 = level.boost(7750, -1540, 1050, 1.2)
// const boost6 = level.boost(8235, -619, 3500, 2.9)
const train1 = level.transport(3650, 100, 415, 500, 8); //x,y,width.height,VxGoal,force
const train2 = level.transport(1250, 100, 415, 500, -8); //x,y,width.height,VxGoal,force
const train3 = level.transport(4050, 100, 415, 500, 8); //x,y,width.height,VxGoal,force
@@ -4310,6 +4288,8 @@ const level = {
boost3.query();
boost4.query();
boost5.query();
boost6.query();
boost7.query();
//trains oscillate back and forth and act like they are bouncing off each other
if (train1.position.x < 2850) {
train1.changeDirection(true) //go right
@@ -4344,7 +4324,7 @@ const level = {
ctx.fillStyle = "#cff"
if (isFlipped) {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
ctx.fillRect(150, -300, 525, 325); //entrance typically
} else {
ctx.fillRect(8925, -2575, 525, 400) //exit typically
}
@@ -4357,10 +4337,11 @@ const level = {
ctx.fillRect(8300, -1950, 1550, 1275);
ctx.fillRect(5400, 875, 1800, 650);
ctx.fillRect(2950, -2200, 875, 1050);
ctx.fillRect(5900, -1025, 800, 450);
if (isFlipped) {
ctx.fillRect(8925, -2575, 575, 400) //exit typically
} else {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
ctx.fillRect(150, -300, 525, 325); //entrance typically
}
ctx.fillStyle = "rgba(0,0,0,0.5)"
@@ -4383,10 +4364,10 @@ const level = {
// spawn.mapVertex(6300, 900, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
spawn.mapVertex(400, 900, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
//lower 1st zone entrance /exit
spawn.mapRect(-400, -350, 575, 75);
spawn.mapRect(-400, -300, 75, 375);
spawn.mapRect(100, -325, 75, 175);
spawn.mapRect(100, -10, 75, 50);
spawn.mapRect(100, -350, 575, 75);
spawn.mapRect(100, -300, 75, 375);
spawn.mapRect(600, -325, 75, 175);
spawn.mapRect(600, -10, 75, 50);
//2nd zone upper hollow square
@@ -4421,24 +4402,28 @@ const level = {
//lower 3rd zone
spawn.mapVertex(6300, 450, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${0} ${-a} ${0}`); //square with edges cut off --- hollow top
spawn.mapVertex(6550, 1650, `${-a} ${600} ${a + 500} ${600} ${a + 500} ${a - c} ${a - c + 500} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off --- hollow bottom
spawn.mapVertex(6300, 1200, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(6450, 1650, `${-a} ${600} ${a + 700} ${600} ${a + 700} ${a - c} ${a - c + 700} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off --- hollow bottom
//upper 3rd zone
a = 400 //side length
c = 50 //corner offset
spawn.mapVertex(6300, -800, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
// spawn.mapVertex(6300, -800, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
spawn.mapVertex(6300, -1100, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${-200} ${-a} ${-200}`); //square with edges cut off
spawn.mapVertex(6300, -500, `${-a} ${200} ${a} ${200} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off
spawn.mapVertex(5800, -1425, "-300 -40 -250 -90 250 -90 300 -40 300 40 250 90 -250 90 -300 40");
spawn.mapVertex(5485, -1850, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(7365, -1850, "-650 -40 -600 -90 600 -90 650 -40 650 40 600 90 -600 90 -650 40"); //long
spawn.mapVertex(7115, -1850, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40"); //long
spawn.mapVertex(6300, -2175, "-300 -40 -250 -90 250 -90 300 -40 300 40 250 90 -250 90 -300 40"); //highest
spawn.mapVertex(4450, -1850, "-200 -40 -150 -90 150 -90 200 -40 200 40 150 90 -150 90 -200 40");
spawn.mapVertex(5500, -300, "-200 -60 -170 -90 170 -90 200 -60 200 60 170 90 -170 90 -200 60");
spawn.mapVertex(4600, -590, "-500 -90 170 -90 200 -60 200 60 170 90 -500 90");
// spawn.mapVertex(5300, -300, "-300 -60 -270 -90 270 -90 300 -60 300 60 270 90 -270 90 -300 60");
spawn.mapVertex(5300, -300, "-300 -40 -250 -90 250 -90 300 -40 300 40 250 90 -250 90 -300 40");
spawn.mapVertex(4500, -590, "-300 -90 250 -90 300 -40 300 40 250 90 -300 90");
// spawn.mapVertex(4600, -590, "-500 -90 170 -90 200 -60 200 60 170 90 -500 90");
//no debris on this level, so spawn some heals and ammo
powerUps.chooseRandomPowerUp(6275, 1425);
powerUps.chooseRandomPowerUp(3350, -1250);
powerUps.chooseRandomPowerUp(6300, -650);
powerUps.chooseRandomPowerUp(9550, -750);
//random blocks
@@ -4463,7 +4448,6 @@ const level = {
spawn.randomMob(4675, -850, 0.1);
spawn.randomMob(4450, -2050, 0.1);
spawn.randomMob(4050, -2325, 0.1);
spawn.randomMob(2850, -2325, 0.1);
spawn.randomMob(3350, -1325, 0.2);
spawn.randomMob(5300, -2050, 0.2);
spawn.randomMob(5675, -2050, 0.2);
@@ -12121,12 +12105,6 @@ const level = {
return bound.has(player.bounds.min) || bound.has(player.bounds.max);
}
function addWIMP(x, y) {
spawn.WIMP(x, y);
const me = mob[mob.length - 1];
me.isWIMP = true;
}
function relocateWIMPs(x, y) {
for (const i of mob) {
if (i.isWIMP) {
@@ -12665,10 +12643,11 @@ const level = {
Promise.resolve().then(() => {
// Clear all WIMPS and their research
for (let i = 0; i < mob.length; i++) {
while (mob[i] && !mob[i].isMACHO) {
mob[i].replace(i);
if (mob[i] && !mob[i].isMACHO) {
mob[i].isWIMP = true;
}
}
relocateWIMPs(0, -10030);
for (let i = 0; i < powerUp.length; i++) {
while (powerUp[i] && powerUp[i].name === "research") {
Matter.Composite.remove(engine.world, powerUp[i]);
@@ -12884,7 +12863,7 @@ const level = {
return this.rings.length;
},
get cap() {
return (this.ringNumber + 1) * 90 + 240;
return this.ringNumber * 90 + 180;
},
get capped() {
return templePlayer.room2.spawnInitiatorCycles > this.cap;
@@ -12919,8 +12898,8 @@ const level = {
y: -300
}), simulation.cycle - 5);
}
if (!this.capped && cycle >= this.cap - 200) {
const multCoeff = (cycle - this.cap + 200) * 0.4
if (!this.capped && cycle >= this.cap - 180) {
const multCoeff = (cycle - this.cap + 180) * 0.4
ctx.translate((Math.random() - 0.5) * multCoeff, (Math.random() - 0.5) * multCoeff);
}
ctx.shadowBlur = 20;
@@ -12930,12 +12909,12 @@ const level = {
DrawTools.arcOut(this.pos.x, this.pos.y, 100, 0, Math.PI * 2);
if (templePlayer.room2.cycles <= 100) {
for (let i = 0; i < this.ringNumber; i++) {
if (cycle < i * 90 + 90) break;
if (cycle < i * 90) break;
const ring = this.rings[i];
ctx.shadowColor = `rgb(${ring.colour.join(",")})`;
const opacity = this.capped ? 1 - 0.01 * templePlayer.room2.cycles : (cycle / 180 - i / 2 - 0.5);
const opacity = this.capped ? 1 - 0.01 * templePlayer.room2.cycles : (cycle / 180 - i / 2);
ctx.strokeStyle = `rgba(${ring.colour.join(",")}, ${Math.min(opacity, 1)})`;
const radius = (this.capped ? 1 + 0.07 * templePlayer.room2.cycles : Math.sin(Math.min(cycle - i * 90 - 90, 45) / 90 * Math.PI)) * ring.radius;
const radius = (this.capped ? 1 + 0.07 * templePlayer.room2.cycles : Math.sin(Math.min(cycle - i * 90, 45) / 90 * Math.PI)) * ring.radius;
DrawTools.arcOut(this.pos.x, this.pos.y, radius, 0, Math.PI * 2);
}
}
@@ -13083,14 +13062,15 @@ const level = {
room0() {
if (templePlayer.startAnim <= 0) return;
templePlayer.startAnim++;
if (templePlayer.startAnim == 120) {
if (templePlayer.startAnim == 60) {
makeLore("Not so fast.");
}
if (templePlayer.startAnim < 360) {
if (templePlayer.startAnim < 180) {
trapPlayer(1000, templePlayer.initialTrapY);
} else {
level.exit.x = 4500;
level.exit.y = -2030;
relocateWIMPs(level.exit.x, level.exit.y);
relocateTo(50, -2050);
simulation.fallHeight = -1000;
// simulation.setZoom(1800);
@@ -13101,49 +13081,31 @@ const level = {
}
},
room1() {
if (templePlayer.room1ToRoom2Anim <= 0) return;
if (templePlayer.room1ToRoom2Anim === 1) {
const frame = templePlayer.room1ToRoom2Anim;
if (frame <= 0) return;
if (frame === 1) {
level.exit.x = -50;
level.exit.y = -10030;
makeLore("Pathetic.");
}
if (templePlayer.room1ToRoom2Anim === 121) {
makeLore("You will never succeed.");
}
if (templePlayer.room1ToRoom2Anim >= 360 && templePlayer.room1ToRoom2Anim <= 720) {
const factor = 200 - 200 * Math.cos((templePlayer.room1ToRoom2Anim / 120 - 3) * Math.PI);
if (frame >= 1 && frame <= 360) {
const factor = 100 - 100 * Math.cos((frame / 90) * Math.PI);
ctx.translate(factor, factor);
Promise.resolve().then(() => {
ctx.save();
ctx.globalCompositeOperation = "color-burn";
ctx.fillStyle = DrawTools.randomColours;
ctx.fillStyle = DrawTools.randomColours((frame) * (360 - frame) / 32400);
DrawTools.updateRandomColours(5);
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
});
}
if (templePlayer.room1ToRoom2Anim === 720) {
if (frame === 180) {
makeLore("You are trying too hard.");
relocateTo(0, -7050);
simulation.fallHeight = -6000;
templePlayer.stage = 2;
}
if (templePlayer.room1ToRoom2Anim === 960) {
makeLore("I have mastered the understandings of the universe.");
}
if (templePlayer.room1ToRoom2Anim === 1200) {
// Congrats, you discovered the actual words by looking at the source code. Are you happy now?
const x = (
["a speck of dust", "an insignificant hindrance", "a tiny obstacle"]
)[Math.floor(Math.random() * 3)].split("");
for (let i = 0; i < x.length / 1.6; i++) {
const randomIndex = Math.floor(Math.random() * x.length);
if (x[randomIndex] !== " ") {
x[randomIndex] = String.fromCharCode(Math.floor(Math.random() * 50) + 192);
}
};
makeLore(`You are no more than ${x.join("")} to me.</h3></h2>`);
relocateWIMPs(0, -10030);
relocateWIMPs(level.exit.x, level.exit.y - 3000);
}
templePlayer.room1ToRoom2Anim++;
},
@@ -13154,23 +13116,10 @@ const level = {
level.exit.y = -13130;
makeLore("Do not try me.");
}
if (templePlayer.room2ToRoom3Anim >= 1 && templePlayer.room2ToRoom3Anim <= 180) {
canvas.style.filter = `sepia(${templePlayer.room2ToRoom3Anim / 180}) invert(${templePlayer.room2ToRoom3Anim / 180})`;
}
if (templePlayer.room2ToRoom3Anim === 180) {
makeLore("I have absolute power over you.");
canvas.style.filter = "hue-rotate(90deg)";
}
if (templePlayer.room2ToRoom3Anim === 360) {
makeLore("You will not succeed...");
canvas.style.filter = "invert(0.2)";
}
if (templePlayer.room2ToRoom3Anim === 420) {
makeLore("<h6 style='display: inline-block'>...</h6>");
canvas.style.filter = "invert(0.4)";
}
if (templePlayer.room2ToRoom3Anim > 480 && templePlayer.room2ToRoom3Anim <= 660) {
canvas.style.filter = `sepia(${(templePlayer.room2ToRoom3Anim - 480) / 180}) invert(${0.5 + (templePlayer.room2ToRoom3Anim - 480) / 180})`;
}
if (templePlayer.room2ToRoom3Anim === 780) {
makeLore("Do not interfere with me.");
templePlayer.stage = 3;
relocateTo(50, -13150);
simulation.fallHeight = -10000;
@@ -13182,43 +13131,28 @@ const level = {
mob[i].replace(i);
}
}
templePlayer.drawExit = true;
for (let i = 0; i < 5 * tech.wimpCount; i++) {
powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false);
}
canvas.style.filter = "";
}
if (templePlayer.room2ToRoom3Anim > 780 && templePlayer.room2ToRoom3Anim <= 960) {
canvas.style.filter = `sepia(${(960 - templePlayer.room2ToRoom3Anim) / 180}) invert(${(960 - templePlayer.room2ToRoom3Anim) / 180})`;
if (templePlayer.room2ToRoom3Anim > 180 && templePlayer.room2ToRoom3Anim <= 360) {
canvas.style.filter = `sepia(${(360 - templePlayer.room2ToRoom3Anim) / 180}) invert(${(360 - templePlayer.room2ToRoom3Anim) / 180})`;
}
templePlayer.room2ToRoom3Anim++;
},
room3() {
if (templePlayer.room3ToEndAnim <= 0) return;
if (templePlayer.room3ToEndAnim === 1) {
makeLore("No.");
}
if (templePlayer.room3ToEndAnim === 120) {
makeLore("This cannot be.");
}
if (templePlayer.room3ToEndAnim === 240) {
makeLore("Has my power failed me?");
}
if (templePlayer.room3ToEndAnim === 360) {
makeLore("Was it worth it, destroying this place?");
}
if (templePlayer.room3ToEndAnim === 600) {
makeLore("No one is greater than me.");
}
const text = "noone-";
for (let i = 0; i < 12; i++) {
if (templePlayer.room3ToEndAnim === 720 + i * 20) {
name = name.slice(0, -1);
simulation.makeTextLog(`<span style="font-size: 1em"><span style="color: #f00">${name}:</span> &nbsp; ${text[i % 6]}</span>`);
canvas.style.filter = `brightness(${1 - i / 22})`;
}
}
if (templePlayer.room3ToEndAnim === 1060) {
templePlayer.drawExit = true;
for (let i = 0; i < 5 * tech.wimpCount; i++) {
powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false);
}
canvas.style.filter = "";
const x = "Nooooooooooo".split("");
for (let i = 0; i < x.length / 1.6; i++) {
const randomIndex = Math.floor(Math.random() * x.length);
if (x[randomIndex] !== " ") {
x[randomIndex] = String.fromCharCode(Math.floor(Math.random() * 50) + 192);
}
};
makeLore(x.join(""));
}
templePlayer.room3ToEndAnim++;
},
@@ -13227,11 +13161,11 @@ const level = {
Promise.resolve().then(() => {
ctx.save();
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.fillStyle = `rgba(0, 0, 0, ${(simulation.cycle - templePlayer.clearedCycle) / 300})`;
ctx.fillStyle = `rgba(0, 0, 0, ${(simulation.cycle - templePlayer.clearedCycle) / 30})`;
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.restore();
});
if (simulation.cycle - templePlayer.clearedCycle > 420) level.nextLevel();
if (simulation.cycle - templePlayer.clearedCycle > 30) level.nextLevel();
}
};
const LogicHandler = {
@@ -13383,7 +13317,7 @@ const level = {
const roomConditions = [
isInBound(firstRoomBounds) && templePlayer.room1.cycles < 2400,
isInBound(secondRoomBounds) && templePlayer.room2.cycles > 0 && templePlayer.room2.cycles < 2160,
isInBound(thirdRoomBounds) && templePlayer.room2ToRoom3Anim < 1320
isInBound(thirdRoomBounds) && templePlayer.room2ToRoom3Anim < 540
];
Promise.resolve(roomConditions).then(roomConditions => {
// First Room
@@ -13413,7 +13347,7 @@ const level = {
ctx.fillStyle = "#0004";
ctx.fillRect(canvas.width2 - 288, 50, 576, 20);
ctx.fillStyle = "#000";
ctx.fillRect(canvas.width2 - 288, 50, 1.6 * (1320 - templePlayer.room2ToRoom3Anim), 20);
ctx.fillRect(canvas.width2 - 288, 50, 1.6 * (540 - templePlayer.room2ToRoom3Anim), 20);
ctx.restore();
}
});
@@ -13465,7 +13399,7 @@ const level = {
}
},
room3() {
if (templePlayer.room2ToRoom3Anim === 1320) {
if (templePlayer.room2ToRoom3Anim === 540) {
thirdRoomBoss(1800, -13700);
for (let i = 0; i < 3; i++) {
powerUps.spawn(m.spawnPos.x, m.spawnPos.y, "heal");
@@ -13474,8 +13408,8 @@ const level = {
}
};
const DrawTools = {
get randomColours() {
return `rgb(${this._randomColours.join(",")})`
randomColours(alpha = 1) {
return `rgba(${this._randomColours.join(",")},${alpha})`
},
_randomColours: [Math.random() * 255, Math.random() * 255, Math.random() * 255],
updateRandomColours(x = 0.8) {

View File

@@ -1161,7 +1161,7 @@ const mobs = {
this.onDeath(this); //custom death effects
this.removeConsBB();
this.alive = false; //triggers mob removal in mob[i].replace(i)
console.log(this.shieldCount)
// console.log(this.shieldCount)
if (this.isDropPowerUp) {
// if (true) {
@@ -1267,6 +1267,10 @@ const mobs = {
bullet[bullet.length - 1].endCycle = simulation.cycle + 900 //15 seconds
this.leaveBody = false; // no body since it turned into the bot
}
if (tech.isMobDeathImmunity) {
const immuneTime = 360
if (m.immuneCycle < m.cycle + immuneTime) m.immuneCycle = m.cycle + immuneTime; //player is immune to damage
}
if (tech.isAddRemoveMaxHealth) {
if (!this.isBoss) {
const amount = 0.0025
@@ -1280,28 +1284,6 @@ const mobs = {
m.setMaxHealth();
}
}
// if (this.isBoss && this.isDropPowerUp) {
// powerUps.spawn(this.position.x + 20, this.position.y, "tech", false)
// powerUps.spawn(this.position.x - 20, this.position.y, "research", false)
// powerUps.spawn(this.position.x - 40, this.position.y, "research", false)
// powerUps.spawn(this.position.x + 40, this.position.y, "research", false)
// powerUps.spawn(this.position.x, this.position.y + 20, "research", false)
// powerUps.spawn(this.position.x, this.position.y - 20, "heal", false)
// powerUps.spawn(this.position.x, this.position.y + 40, "heal", false)
// powerUps.spawn(this.position.x, this.position.y - 40, "heal", false)
// } else {
// const amount = 0.005
// if (tech.isEnergyHealth) {
// if (m.maxEnergy > amount) {
// tech.healMaxEnergyBonus -= amount
// m.setMaxEnergy();
// }
// } else if (m.maxHealth > amount) {
// tech.extraMaxHealth -= amount //decrease max health
// m.setMaxHealth();
// }
// }
}
if (tech.cloakDuplication && !this.isBoss) {
tech.cloakDuplication -= 0.01

View File

@@ -492,7 +492,7 @@ const m = {
for (i = 0, len = b.inventory.length; i < len; i++) gunList.push(b.inventory[i])
const techList = [] //store tech names
for (let i = 0; i < tech.tech.length; i++) {
if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) techList.push(i)
if (tech.tech[i].count > 0 && !tech.tech[i].isNonRefundable) techList.push(tech.tech[i].name)
}
if (techList.length) {
localSettings.entanglement = {
@@ -560,14 +560,14 @@ const m = {
if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.6
if (tech.isHarmMACHO) dmg *= 0.4
if (tech.isHarmMACHO) dmg *= tech.isMoveMACHO ? 0.3 : 0.4
if (tech.isImmortal) dmg *= 0.7
if (m.fieldMode === 0 || m.fieldMode === 3) dmg *= 0.973 ** m.coupling
if (tech.isLowHealthDefense) dmg *= 1 - Math.max(0, 1 - m.health) * 0.8
if (tech.isHarmReduceNoKill && m.lastKillCycle + 300 < m.cycle) dmg *= 0.3
if (tech.squirrelFx !== 1) dmg *= 0.8//Math.pow(0.78, (tech.squirrelFx - 1) / 0.4)
if (tech.isAddBlockMass && m.isHolding) dmg *= 0.1
if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min(player.speed * 0.0193, 0.8) //capped at speed of 55
if (tech.isSpeedHarm && player.speed > 0.1) dmg *= 1 - Math.min((tech.speedAdded + player.speed) * 0.0193, 0.8) //capped at speed of 55
if (tech.isHarmReduce && input.field) dmg *= 0.1
if (tech.isNeutronium && input.field && m.fieldCDcycle < m.cycle) dmg *= 0.05
if (tech.isBotArmor) dmg *= 0.95 ** b.totalBots()
@@ -693,7 +693,7 @@ const m = {
}
m.lastHarmCycle = m.cycle
if (tech.isDroneOnDamage && bullet.length < 150) { //chance to build a drone on damage from tech
const len = Math.min((dmg - 0.06 * Math.random()) * 40, 40) / tech.droneEnergyReduction * (tech.isEnergyHealth ? 0.5 : 1)
const len = Math.min((dmg - 0.06 * Math.random()) * 80, 60) / tech.droneEnergyReduction * (tech.isEnergyHealth ? 0.5 : 1)
for (let i = 0; i < len; i++) {
if (Math.random() < 0.5) b.drone({
x: m.pos.x + 30 * Math.cos(m.angle) + 100 * (Math.random() - 0.5),
@@ -3298,7 +3298,7 @@ const m = {
m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
m.fieldMeterColor = "#333"
m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.4; //55% reduction
m.fieldHarmReduction = 0.4;
m.fieldDrawRadius = 0;
m.hold = function () {
@@ -5192,12 +5192,13 @@ const m = {
},
{
name: "grappling hook",
description: `use <strong class='color-f'>energy</strong> to fire a hook that <strong>pulls</strong> player<br><strong class='color-d'>damages</strong> mobs and grabs <strong class='color-block'>blocks</strong><br><strong>9</strong> <strong class='color-f'>energy</strong> per second`,
description: `use <strong class='color-f'>energy</strong> to fire a hook that <strong>pulls</strong> you<br><strong>0.6x</strong> <strong class='color-defense'>damage taken</strong><br><strong>9</strong> <strong class='color-f'>energy</strong> per second`,
effect: () => {
m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
// m.fieldMeterColor = "#789"//"#456"
m.eyeFillColor = m.fieldMeterColor
m.fieldHarmReduction = 0.6; //40% reduction
m.grabPowerUpRange2 = 300000 //m.grabPowerUpRange2 = 200000;
m.hold = function () {

View File

@@ -342,7 +342,7 @@ const powerUps = {
powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), spawnType, false);
}
}
if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 7)
if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 8)
if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") {
tech.cancelTechCount++
// powerUps.research.use('tech')
@@ -350,7 +350,7 @@ const powerUps = {
return
}
}
tech.cancelTechCount = 0
if (tech.isAnsatz && powerUps.research.count < 1) {
for (let i = 0; i < 3; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false);
}
@@ -655,7 +655,7 @@ const powerUps = {
if (tech.isSuperDeterminism) {
return `<div></div>`
} else if (tech.isCancelTech && tech.cancelTechCount === 0) {
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;">randomize</div>`
return `<div class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;"><span class="color-randomize">randomize</span></div>`
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) { //don't show cancel if on initial level and haven't done tutorial
return `<div class='cancel-card' style="visibility: hidden;"></div>`
} else {
@@ -707,7 +707,7 @@ const powerUps = {
if (tech.isSuperDeterminism) {
text += `<span class='cancel-card' style="width: 95px;float: right;background-color: #aaa;color:#888;">cancel</span>`
} else if (tech.isCancelTech && tech.cancelTechCount === 0) {
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;float: right;font-size:0.9em;padding-top:5px">randomize</span>`
text += `<span class='cancel-card' onclick='powerUps.endDraft("${type}",true)' style="width: 115px;float: right;font-size:0.9em;padding-top:5px;"><span class="color-randomize">randomize</span></span>`
} else if (level.levelsCleared === 0 && localSettings.isTrainingNotAttempted && b.inventory.length === 0) {
text += `<span class='cancel-card' style="visibility: hidden;">cancel</span>` //don't show cancel if on initial level and haven't done tutorial
} else {
@@ -897,22 +897,25 @@ const powerUps = {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;background-image: url('img/junk.webp');"`
if (!localSettings.isHideImages) {
setTimeout(() => { //delay so that the html element exists
if (tech.tech[choose].url === undefined) { //if on url has been set yet
const url = `https://api.openverse.engineering/v1/images/?q=${tech.tech[choose].name}`;
fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
.then((response) => response.json())
.then((responseJson) => {
if (responseJson.results.length > 0) {
const index = Math.floor(Math.random() * responseJson.results.length) //randomly choose from the images
tech.tech[choose].url = responseJson.results[index].url //store the url
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
}
});
} else {
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
}
}, 1);
// setTimeout(() => { //delay so that the html element exists
// if (tech.tech[choose].url === undefined) { //if on url has been set yet
// const url = `https://api.openverse.engineering/v1/images/?q=${tech.tech[choose].name}`;
// fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
// .then((response) => response.json())
// .then((responseJson) => {
// if (responseJson.results.length > 0) {
// const index = Math.floor(Math.random() * responseJson.results.length) //randomly choose from the images
// tech.tech[choose].url = responseJson.results[index].url //store the url
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
// }
// });
// } else {
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// }, 1);
// setTimeout(() => { //delay so that the html element exists
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }, 1);
}
return `<div id = "junk-${choose}" class="choose-grid-module card-background" onclick="${click}" onauxclick="${click}"${style}>
<div class="card-text">
@@ -941,7 +944,13 @@ const powerUps = {
}
// console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) {
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
let totalChoices = 2 + tech.extraChoices + 2 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3
tech.cancelTechCount++
}
if (tech.isDeterminism) totalChoices = 1
totalChoices = Math.min(options.length, totalChoices)
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -1002,7 +1011,14 @@ const powerUps = {
for (let i = 1; i < m.fieldUpgrades.length; i++) { //skip field emitter
if (i !== m.fieldMode) options.push(i);
}
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
// let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
let totalChoices = 2 + tech.extraChoices + 2 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3
tech.cancelTechCount++
}
if (tech.isDeterminism) totalChoices = 1
totalChoices = Math.min(options.length, totalChoices)
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -1076,7 +1092,15 @@ const powerUps = {
}
}
//set total choices
let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8))
// let totalChoices = (tech.isDeterminism ? 1 : 3 + tech.extraChoices + 2 * (m.fieldMode === 8))
let totalChoices = 3 + tech.extraChoices + 2 * (m.fieldMode === 8)
if (tech.isCancelTech && tech.cancelTechCount === 1) {
totalChoices *= 3
tech.cancelTechCount++
}
if (tech.isDeterminism) totalChoices = 1
totalChoices = Math.min(options.length, totalChoices)
if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices
totalChoices = optionLengthNoDuplicates
if (tech.isBanish) { //when you run out of options eject banish
@@ -1256,8 +1280,20 @@ const powerUps = {
if (!alreadyHasGun) text += powerUps.gunText(choose, `powerUps.choose('gun',${choose})`)
}
for (let i = 0; i < localSettings.entanglement.techIndexes.length; i++) { //add tech
let choose = localSettings.entanglement.techIndexes[i]
if (tech.tech[choose]) {
let found = false;
let choose = undefined
console.log(localSettings.entanglement.techIndexes[i])
for (let j = 0; j < tech.tech.length; j++) {
if (localSettings.entanglement.techIndexes[i] === tech.tech[j].name) {
choose = j;
found = true;
break;
}
}
// let choose = localSettings.entanglement.techIndexes[i]
console.log(choose)
if (found && tech.tech[choose]) {
const isCount = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : "";
if (choose === null || tech.tech[choose].count + 1 > tech.tech[choose].maxCount || !tech.tech[choose].allowed()) {
// text += `<div class="choose-grid-module" style = "background-color: #efeff5; border: 0px; opacity:0.5; font-size: 60%; line-height: 130%; margin: 1px; padding-top: 6px; padding-bottom: 6px;"><div class="grid-title">${tech.tech[choose].name} <span style = "color: #aaa;font-weight: normal;font-size:80%;">- incoherent</span></div></div>`
@@ -1330,12 +1366,11 @@ const powerUps = {
powerUps.spawn(x, y, "gun");
return;
}
// if (Math.random() < 0.0027 * (22 - tech.totalCount)) { //a new tech has a low chance for each not acquired tech up to 25
if (Math.random() < 0.005 * (10 - level.levelsCleared)) { //a new tech has a low chance that decreases in later levels
powerUps.spawn(x, y, "tech");
return;
}
if (Math.random() < 0.0015) {
// if (Math.random() < 0.005 * (10 - level.levelsCleared)) { //a new tech has a low chance that decreases in later levels
// powerUps.spawn(x, y, "tech");
// return;
// }
if (Math.random() < 0.0016) {
powerUps.spawn(x, y, "field");
return;
}
@@ -1499,7 +1534,7 @@ const powerUps = {
// }
tech.tech[index].frequency = 0 //banish tech
powerUps.ejectTech(index)
m.damage(tech.pauseEjectTech * 0.01)
if (m.immuneCycle < m.cycle) m.damage(tech.pauseEjectTech * 0.01)
tech.pauseEjectTech *= 1.2
document.getElementById(`${index}-pause-tech`).style.textDecoration = "line-through"
document.getElementById(`${index}-pause-tech`).style.animation = ""
@@ -1591,12 +1626,16 @@ const powerUps = {
(!tech.isSuperDeterminism || (target !== 'research')) &&
!(tech.isEnergyNoAmmo && target === 'ammo')
) {
if (tech.isBoostReplaceAmmo && target === 'ammo') target = 'boost'
if (tech.isBoostReplaceAmmo && target === 'ammo') {
target = 'boost'
size = powerUps[target].size()
}
powerUps.directSpawn(x, y, target, moving, mode, size)
if (Math.random() < tech.duplicationChance()) {
powerUps.directSpawn(x, y, target, moving, mode, size, true)
powerUp[powerUp.length - 1].isDuplicated = true
// if (tech.isPowerUpsVanish) powerUp[powerUp.length - 1].endCycle = simulation.cycle + 300
if (tech.isDupEnergy) m.energy *= 2
}
}
},

View File

@@ -158,7 +158,7 @@ const spawn = {
me.do = function () {
if (!simulation.isTimeSkipping) {
const sine = Math.sin(simulation.cycle * 0.015)
this.radius = 55 * tech.isDarkStar + 370 * (1 + 0.1 * sine)
this.radius = 111 * tech.isDarkStar + 370 * (1 + 0.1 * sine)
//chase player
const sub = Vector.sub(player.position, this.position)
const mag = Vector.magnitude(sub)
@@ -167,7 +167,21 @@ const spawn = {
// const where = Vector.add(this.position, Vector.mult(Vector.normalise(sub), this.chaseSpeed))
// if (mag > 10) Matter.Body.setPosition(this, { x: where.x, y: where.y });
//realistic physics
// if (true) {
// if (m.crouch) {
// if (Vector.magnitude(Vector.sub(this.position, m.pos)) > this.radius) {
// attract *= 40
// } else {
// Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.9)); //friction
// }
// }
// }
if (tech.isMoveMACHO && m.crouch) {
Matter.Body.setVelocity(this, Vector.add(Vector.mult(this.velocity, 0.97), Vector.mult(player.velocity, 0.03)))
Matter.Body.setPosition(this, Vector.add(Vector.mult(this.position, 0.95), Vector.mult(player.position, 0.05)))
}
const force = Vector.mult(Vector.normalise(sub), 0.000000003)
this.force.x += force.x
this.force.y += force.y
@@ -175,18 +189,12 @@ const spawn = {
if (mag < this.radius) { //buff to player when inside radius
tech.isHarmMACHO = true;
//draw halo
ctx.strokeStyle = "rgba(80,120,200,0.2)" //"rgba(255,255,0,0.2)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
ctx.beginPath();
ctx.arc(m.pos.x, m.pos.y, 36, 0, 2 * Math.PI);
ctx.lineWidth = 10;
ctx.stroke();
// ctx.strokeStyle = "rgba(255,255,0,0.17)" //ctx.strokeStyle = `rgba(0,0,255,${0.5+0.5*Math.random()})`
// ctx.beginPath();
// ctx.arc(this.position.x, this.position.y, this.radius, 0, 2 * Math.PI);
// ctx.lineWidth = 30;
// ctx.stroke();
} else {
tech.isHarmMACHO = false;
}
@@ -203,14 +211,13 @@ const spawn = {
for (let i = 0, len = mob.length; i < len; ++i) {
if (mob[i].alive && !mob[i].isShielded) {
if (Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius < this.radius) {
mob[i].damage(0.025 * m.dmgScale);
// mob[i].locatePlayer();//
const dmg = 0.025 * m.dmgScale * (tech.isMoveMACHO ? 1.5 : 1)
mob[i].damage(dmg);
simulation.drawList.push({ //add dmg to draw queue
x: mob[i].position.x,
y: mob[i].position.y,
radius: mob[i].radius + 8,
color: `rgba(10,0,40,0.1)`, // random hue, but not red
color: `rgba(10,0,40,0.1)`,
time: 4
});
}
@@ -5731,9 +5738,9 @@ const spawn = {
sneakBoss(x, y, radius = 70) {
mobs.spawn(x, y, 5, radius, "transparent");
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.001); //extra dense //normal is 0.001 //makes effective life much larger
me.isBoss = true;
me.damageReduction = 0.25 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.accelMag = 0.0017 * Math.sqrt(simulation.accelScale);
me.frictionAir = 0.01;
@@ -5748,6 +5755,7 @@ const spawn = {
me.vanishesLeft = Math.ceil(1 + simulation.difficultyMode * 0.5)
me.onDeath = function () {
powerUps.spawnBossPowerUp(this.position.x, this.position.y)
for (let i = 0; i < simulation.difficultyMode / 2 - 0.5; i++) spawn.sneaker(this.position.x + 10 * Math.random(), this.position.y + 10 * Math.random())
};
me.onDamage = function () {
if (this.vanishesLeft > 0 && this.health < 0.1) { //if health is below 10% teleport to a random spot on player history, heal, and cloak
@@ -5772,6 +5780,7 @@ const spawn = {
this.seePlayer.recall = 0
this.cloak();
this.health = 1;
for (let i = 0; i < simulation.difficultyMode / 2 - 0.5; i++) spawn.sneaker(this.position.x + 10 * Math.random(), this.position.y + 10 * Math.random())
}
};
me.cloak = function () {
@@ -5803,7 +5812,7 @@ const spawn = {
this.gravity();
this.seePlayerByHistory(55);
this.checkStatus();
this.attraction();
if (this.alpha > 0.8) this.attraction();
//draw
if (this.seePlayer.recall) {
if (this.alpha < 1) this.alpha += 0.005 + 0.003 / simulation.CDScale;
@@ -5908,7 +5917,7 @@ const spawn = {
ghoster(x, y, radius = 50 + Math.ceil(Math.random() * 90)) {
mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1];
me.seeAtDistance2 = 300000;
me.seeAtDistance2 = 500000;
me.accelMag = 0.00007 + 0.0001 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
Matter.Body.setDensity(me, 0.0002); //normal is 0.001
@@ -5917,10 +5926,9 @@ const spawn = {
me.alpha = 1; //used in drawGhost
me.isNotCloaked = false; //used in drawGhost
me.isBadTarget = true;
// me.leaveBody = false;
me.collisionFilter.mask = cat.bullet //| cat.body
me.showHealthBar = false;
me.memory = 600;
me.memory = 900;
me.delay = 60
me.cd = 0;
me.onHit = function () {
@@ -5948,6 +5956,9 @@ const spawn = {
}
}
};
me.onDamage = function () {
if (this.health < 0.8) me.seeAtDistance2 = 2000000;
}
me.do = function () {
if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
this.seePlayerCheckByDistance();
@@ -5957,8 +5968,8 @@ const spawn = {
//draw
if (this.distanceToPlayer2() < this.seeAtDistance2) {
if (this.alpha < 1) this.alpha += 0.011 * simulation.CDScale; //near player go solid
} else {
if (this.alpha > 0) this.alpha -= 0.05; ///away from player, hide
} else if (this.alpha > 0) {
this.alpha -= 0.05; ///away from player, hide
}
if (this.alpha > 0) {
if (this.alpha > 0.7 && this.seePlayer.recall) {

File diff suppressed because it is too large Load Diff

View File

@@ -744,13 +744,6 @@ summary {
user-select: none;
}
/* color for in game console output */
/* .ammo-flash {
color: #f33;
transition: color 2s;
} */
.color-text {
color: #000;
}
@@ -817,6 +810,58 @@ summary {
color: #356;
}
.color-choice {
display: inline-block;
}
.color-choice span {
display: inline-block;
animation: bounce 3s infinite;
transform-origin: bottom;
color: #555;
}
.color-choice span:nth-child(1) {
animation-delay: 0s;
}
.color-choice span:nth-child(2) {
animation-delay: 1s;
}
.color-choice span:nth-child(3) {
animation-delay: 2s;
}
@keyframes bounce {
0% {
transform: translateY(0);
}
15% {
transform: translateY(-2px);
color: #aaa;
}
30% {
transform: translateY(0);
}
100% {
transform: translateY(0);
}
}
.color-invulnerable {
color: #fff;
text-shadow: 0px 0px 7px #000;
}
.color-MACHO {
color: #246;
text-shadow: 0px 0px 7px #246;
}
.color-dup {
font-variant: small-caps;
letter-spacing: 1px;
@@ -1071,6 +1116,44 @@ summary {
background-color: #f7b;
}
.color-speed {
display: inline-block;
transform: skew(-27deg);
/* font-weight: 400; */
color: #038;
}
.color-randomize {
display: inline-block;
animation: randomize 4s linear infinite alternate;
transform-origin: bottom;
color: #555;
}
@keyframes randomize {
0%,
100% {
font-family: Arial;
}
20% {
font-family: Times New Roman;
}
40% {
font-family: Verdana;
}
60% {
font-family: Georgia;
}
80% {
font-family: Courier New;
}
}
.alt {
animation: alt 8s linear infinite alternate;
font-weight: 400;

117
todo.txt
View File

@@ -1,34 +1,85 @@
******************************************************** NEXT PATCH **************************************************
newLevel - towers
please give feedback
boost level elements can now be pointed at any angle
tech: anyon - 2x energy after duplicating a power up, +6% duplication chance
tech: Abelian group - 4x damage while invulnerable
tech: fermion - become invulnerable for 5 seconds after a mob dies
tech: entropic gravity - crouching pulls MACHO towards the player, and 1.5x to all MACHO effects (damage, damage reduction, AoE damage)
tech: modified Newtonian dynamics - +20 speed for all Newtonian law tech
paradigm shift costs 1 health, but cost increases after each use
ejecting with paradigm shift tech sets their frequency to zero, so they don't show up again
polyurethane foam - makes more foam from super balls
bubble fusion - now works with any shield, but only once per mob
so it triggers from the shieldingBoss
collider - has a higher chance to form tech vs. other power ups
choice, MACHO, invulnerable, speed - have text keyword CSS style
removed chance to find a random tech in early levels from mobs
this reduces tech per full game by about 2
tower level has a few changes
options exchange only works once per level, but it gives 3x choices after randomizing
dark star has a 1.2->1.3x MACHO radius
autocannon fires 1->2 extra super balls, but balls have higher gravity
grappling hook field starts with 0.6x damage reduction
super balls + uncertainty principle makes all balls start in the same spot and only separate after teleporting
ablative drones spawns 50% more drones on collision
von Neumann probe gives 40% more drones per block mass
also added text clarification that it uses 5 energy
tech lens rotates 50% faster
ghoster mobs are more aggressive once they have lost 20% health
sneakBoss doesn't start accelerating until it is partly uncloaked, but it spawns sneaker mobs after cloaking
removed all ON/OFF tech
I just don't think they are fun
fixed bug with 2 different boost power up sizes
paradigm shift doesn't do damage while player is invulnerable
random internet JUNK images disabled because some of the images are bad
entanglement bug fix, maybe
JUNK tech - wall jump
******************************************************* DESIGN ******************************************************
fixed some bugs
priorities
synergies between tech
difficult to achieve synergies that feel so powerful they are game breaking / changing
randomized content adds repeatability
bosses, mobs, levels, tech
graphical indicators of tech effects and quantity
subtle lore woven into unexpected places
player damage reduction adjustment: 0.9x -> 0.89x per level per difficulty mode (1,2,4,5)
on easy that's 0.28 -> 0.245 by level 12 (a 12% player damage nerf)
on why a 50% player damage nerf by level 12
add more randomize sub level map content
left/right sides of lock
small lab rooms
powerful synergies
CPT + high energy regen
research + bot fabrication + ersatz bots + various bot upgrades
harpoon + high fire rate + alternator + time dilation
duplication 100%
interest + coupling, research + (peer review? or Bayesian statistics)
electronegativity and high energy?
electronegativity + anyon + duplication + Maxwells demon + interest
chain reaction + invulnerable + Abelian group + parasitism = clear all mobs on level
*********************************************************** TODO *****************************************************
increase difficulty
make each difficulty level have specific listed changes
to motivate people to try that difficulty to see the difference
make difficulty easier to see
in pause menu
before game begins
automatically increase difficulty when player wins?
difficulty based changes (maybe in the order)
more bosses
more mobs
mobs attack faster
mobs move faster
reduced heals
reduced damage done
increased damage taken
mobs regen health
-1 choice for tech, field, gun
no starting power ups (heal, research)
starting JUNK chance?
quantum physics lecture notes:
https://www.scottaaronson.com/democritus/lec9.html
Quantum mechanics is what you would inevitably come up with if you started from probability theory, and then said, let's try to generalize it so that the numbers we used to call "probabilities" can be negative numbers.
bug Newton's 1st law image not showing up on github server
shows up on n-gon, and landgreen github, but webp file isn't loading onto server?
try name change,
wait and see if next patch fixes it
Boss mob - takes a snapshot of the positions of all mobs, player, blocks, power ups. Then 3 seconds later it teleports everything back to those spots.
after snap shot is stored draw outline of body positions for a second to show the change
immune after snapshot? or immune after teleport?
flip player upside down
how
@@ -37,15 +88,10 @@ flip player upside down
flip player crouch direction
redraw legs, orb
flip gravity
when to use?
fieldTech: negative mass?
effect in level
tech - while immune to damage taken:
3x damage
no ammo costs?
tech - immune to damage taken after killing a mob
tech - after a power up is duplicated
update text to random effect after choosing tech, or after each trigger, or on first display of tech
pick 1 effect at random
@@ -53,11 +99,13 @@ tech - after a power up is duplicated
summon JUNK bots for 10 seconds
2x current energy
gain 1.01x damage permanently
cool name:
field tech: negative mass - quickly pull/teleport in all nearby blocks and then fire them away from player
what triggers effect?
auto aim blocks?
how does player triggers effect?
picking up a block pulls in all nearby blocks, throwing block fires all nearby blocks
taking damage
auto aim 50% of blocks at mobs
after picking up heals gain ____
0.1x damage taken for 12s
@@ -1220,17 +1268,8 @@ possible names for tech
Upon infection with a retrovirus, a cell converts the retroviral RNA into DNA and sometimes the DNA will be passed on to progeny as JUNK DNA
amalgam, amalgamation - the action, process, or result of combining or uniting.
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
******************************************************** DESIGN ********************************************************
List of ways to break the game
options exchange + paradigm shift + CPT to undo health cost = repeatable cancel triggers
CPT + high energy regen
research -> bot fabrication -> ersatz bots -> various bot upgrades
grappling hook + high fire rate + alternator + time dilation
duplication 100%
interest + coupling, research + peer review?
electronegativity and high energy?
ergosphere - region of a spinning black hole that might allow FTL or alternate realities.
equivalence principle - gravity and acceleration are the same
******************************************************** IMAGES ********************************************************