newLevel - towers
  please give feedback
boost level elements can now be pointed at any angle

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

removed all ON/OFF tech
  I just don't think they are fun

JUNK tech - wall jump

fixed some bugs

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
This commit is contained in:
landgreen
2024-04-28 09:55:12 -07:00
parent 3ce6becec9
commit 773ee5c1ae
12 changed files with 1012 additions and 621 deletions

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -3790,7 +3790,7 @@ const b = {
this.force.y += this.mass * 0.001; this.force.y += this.mass * 0.001;
if (Matter.Query.collides(this, [player]).length) { if (Matter.Query.collides(this, [player]).length) {
this.endCycle = 0 this.endCycle = 0
m.energy -= 0.05 m.energy -= 0.04
if (m.energy < 0) m.energy = 0 if (m.energy < 0) m.energy = 0
simulation.drawList.push({ //add dmg to draw queue simulation.drawList.push({ //add dmg to draw queue
x: this.position.x, x: this.position.x,
@@ -3828,8 +3828,8 @@ const b = {
if (!who.isInvulnerable) { if (!who.isInvulnerable) {
if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds) if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
if (tech.isFoamBall) { if (tech.isFoamBall) {
for (let i = 0, len = 5 * this.mass; i < len; i++) { for (let i = 0, len = 6 * this.mass; i < len; i++) {
const radius = 5 + 8 * Math.random() const radius = 6 + 9 * Math.random()
const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 } const velocity = { x: Math.max(0.5, 2 - radius * 0.1), y: 0 }
b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius) b.foam(this.position, Vector.rotate(velocity, 6.28 * Math.random()), radius)
} }

View File

@@ -113,32 +113,7 @@ function collisionChecks(event) {
m.damage(dmg); m.damage(dmg);
return return
} }
if (tech.isFlipFlop) { m.damage(dmg); //normal damage
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = 'transparent'
m.damage(dmg);
} else {
tech.isFlipFlopOn = true //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#0cf'
if (!tech.isFlipFlopHarm) m.damage(dmg);
}
if (tech.isFlipFlopHealth) {
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
}
} else {
m.damage(dmg); //normal damage
}
if (tech.isCollisionRealitySwitch && m.alive) { if (tech.isCollisionRealitySwitch && m.alive) {
m.switchWorlds() m.switchWorlds()

View File

@@ -1430,7 +1430,7 @@ window.addEventListener("keydown", function (event) {
simulation.loop = simulation.normalLoop simulation.loop = simulation.normalLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'none' if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'none'
simulation.makeTextLog("", 0); simulation.makeTextLog("", 0);
} else { //if (keys[191]) } else {
simulation.testing = true; simulation.testing = true;
simulation.loop = simulation.testingLoop simulation.loop = simulation.testingLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline' if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'

View File

@@ -4,13 +4,12 @@ let cons = []; //all constraints between a point and a body
let consBB = []; //all constraints between two bodies let consBB = []; //all constraints between two bodies
let composite = [] //rotors and other map elements that don't fit let composite = [] //rotors and other map elements that don't fit
const level = { const level = {
isEndlessFall: false, fallMode: "",
defaultZoom: 1400, defaultZoom: 1400,
onLevel: -1, onLevel: -1,
levelsCleared: 0, levelsCleared: 0,
// playableLevels: ["pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion", "pavilion"],
//see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later //see level.populateLevels: (initial, ... , reservoir or factory, reactor, ... , subway, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock"], playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft"], communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"], trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [], levels: [],
@@ -42,9 +41,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("Pareto efficiency") // tech.giveTech("Pareto efficiency")
// for (let i = 0; i < 1; ++i) tech.giveTech("Higgs mechanism") for (let i = 0; i < 1; ++i) tech.giveTech("collider")
// for (let i = 0; i < 1; ++i) tech.giveTech("active cooling") // for (let i = 0; i < 1; ++i) tech.giveTech("anthropic principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("heuristics") // for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
// 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")
@@ -55,13 +54,13 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// 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.testing(); // level.towers();
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500) // for (let i = 0; i < 1; ++i) spawn.laserLayer(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.laserLayer(1300, -500 + 100 * Math.random()) // 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.stinger(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.dragonFlyBoss(1900, -500) // for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// spawn.beetleBoss(1900, -500, 25) // spawn.beetleBoss(1900, -500, 25)
// 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())
@@ -78,7 +77,9 @@ const level = {
// simulation.isAutoZoom = false; //look in close // simulation.isAutoZoom = false; //look in close
// simulation.zoomScale *= 0.5; // simulation.zoomScale *= 0.5;
// simulation.setZoom(); // simulation.setZoom();
// for (let i = 0; i < 3; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "tech"); // 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 < 2; ++i) powerUps.directSpawn(m.pos.x + 450, m.pos.y + 50 * Math.random(), "boost"); // 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 < 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); // for (let i = 0; i < 2; i++) powerUps.spawn(player.position.x + Math.random() * 50, player.position.y - Math.random() * 50, "field", false);
@@ -137,15 +138,7 @@ const level = {
mob[mob.length - 1].isDecoupling = true //so you can find it to remove mob[mob.length - 1].isDecoupling = true //so you can find it to remove
for (let j = 0, len = 4; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false) for (let j = 0, len = 4; j < len; j++) powerUps.spawn(level.exit.x + 100 * (Math.random() - 0.5), level.exit.y - 100 + 100 * (Math.random() - 0.5), "research", false)
} }
// if (tech.isFlipFlopLevelReset && !tech.isFlipFlopOn) {
if ((tech.isRelay || tech.isFlipFlop) && !tech.isFlipFlopOn) {
tech.isFlipFlopOn = true
if (tech.isFlipFlopHealth) m.setMaxHealth()
if (tech.isRelayEnergy) m.setMaxEnergy()
m.eyeFillColor = m.fieldMeterColor
simulation.makeTextLog(`tech.isFlipFlopOn <span class='color-symbol'>=</span> true`);
}
// if (m.plasmaBall) m.plasmaBall.reset()
if (m.plasmaBall) m.plasmaBall.fire() if (m.plasmaBall) m.plasmaBall.fire()
if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) { if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) {
const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1 const flip = localSettings.entanglement.isHorizontalFlipped === simulation.isHorizontalFlipped ? 1 : -1
@@ -180,23 +173,22 @@ const level = {
if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].name !== "laser") { if (b.activeGun !== null && b.activeGun !== undefined && b.guns[b.activeGun].name !== "laser") {
const ammoPerOrb = b.guns[b.activeGun].ammoPack const ammoPerOrb = b.guns[b.activeGun].ammoPack
const a = Math.ceil(rate * b.guns[b.activeGun].ammo / ammoPerOrb) const a = Math.ceil(rate * b.guns[b.activeGun].ammo / ammoPerOrb)
powerUps.spawnDelay("ammo", a); powerUps.spawnDelay("ammo", a, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${a > 20 ? a + powerUps.orb.ammo(1) : powerUps.orb.ammo(a)}`) simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-g'>ammo</span> <span class='color-symbol'>=</span> ${a > 20 ? a + powerUps.orb.ammo(1) : powerUps.orb.ammo(a)}`)
} }
if (powerUps.research.count > 0) { if (powerUps.research.count > 0) {
const r = Math.ceil(rate * powerUps.research.count) const r = Math.ceil(rate * powerUps.research.count)
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-r'>research</span> <span class='color-symbol'>=</span> ${r > 20 ? r + powerUps.orb.research(1) : powerUps.orb.research(r)}`) simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-r'>research</span> <span class='color-symbol'>=</span> ${r > 20 ? r + powerUps.orb.research(1) : powerUps.orb.research(r)}`)
powerUps.spawnDelay("research", r); powerUps.spawnDelay("research", r, 4);
} }
if (m.coupling > 0) { if (m.coupling > 0) {
const c = Math.ceil(rate * m.coupling) const c = Math.ceil(rate * m.coupling)
powerUps.spawnDelay("coupling", c); powerUps.spawnDelay("coupling", c, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-coupling'>coupling</span> <span class='color-symbol'>=</span> ${c > 20 ? c + powerUps.orb.coupling(1) : powerUps.orb.coupling(c)}`) simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-coupling'>coupling</span> <span class='color-symbol'>=</span> ${c > 20 ? c + powerUps.orb.coupling(1) : powerUps.orb.coupling(c)}`)
} }
const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2 const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2
const h = Math.ceil(rate * m.health / healPerOrb) const h = Math.ceil(rate * m.health / healPerOrb)
powerUps.spawnDelay("heal", h); powerUps.spawnDelay("heal", h, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-h'>health</span> <span class='color-symbol'>=</span> ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`) simulation.makeTextLog(`${(rate * 100).toFixed(0)}<span class='color-symbol'>%</span> <span class='color-m'>interest</span> on <span class='color-h'>health</span> <span class='color-symbol'>=</span> ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`)
// trying to spawn smaller heals // trying to spawn smaller heals
@@ -230,7 +222,7 @@ const level = {
difficultyIncrease(num = 1) { difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
simulation.difficulty++ simulation.difficulty++
m.dmgScale *= 0.9; //damage done by player decreases each level m.dmgScale *= 0.89; //damage done by player decreases each level
if (simulation.accelScale < 6) simulation.accelScale *= 1.024 //mob acceleration increases each level if (simulation.accelScale < 6) simulation.accelScale *= 1.024 //mob acceleration increases each level
if (simulation.CDScale > 0.15) simulation.CDScale *= 0.964 //mob CD time decreases each level if (simulation.CDScale > 0.15) simulation.CDScale *= 0.964 //mob CD time decreases each level
} }
@@ -241,7 +233,7 @@ const level = {
difficultyDecrease(num = 1) { //used in easy mode for simulation.reset() difficultyDecrease(num = 1) { //used in easy mode for simulation.reset()
for (let i = 0; i < num; i++) { for (let i = 0; i < num; i++) {
simulation.difficulty-- simulation.difficulty--
m.dmgScale /= 0.9; //damage done by player decreases each level m.dmgScale /= 0.89; //damage done by player decreases each level
if (simulation.accelScale > 1) simulation.accelScale /= 1.024 //mob acceleration increases each level if (simulation.accelScale > 1) simulation.accelScale /= 1.024 //mob acceleration increases each level
if (simulation.CDScale < 1) simulation.CDScale /= 0.964 //mob CD time decreases each level if (simulation.CDScale < 1) simulation.CDScale /= 0.964 //mob CD time decreases each level
} }
@@ -801,65 +793,147 @@ const level = {
return who return who
}, },
boost(x, y, height = 1000) { //height is how high the player will be flung above y boost(x, y, height = 1000, angle = Math.PI / 2) { //height is how high the player will be flung above y
who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("120 40 -120 40 -50 -40 50 -40"), { if (angle !== Math.PI / 2) { //angle !== 3 * Math.PI / 2
collisionFilter: { angle *= -1
category: cat.body, who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("80 40 -80 40 -50 -40 50 -40"), {
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 collisionFilter: {
}, category: cat.body,
boostBounds: { 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
min: {
x: x,
y: y - 20
}, },
max: { yVelocity: 1.21 * Math.sqrt(Math.abs(height)),
x: x + 100, query() {
y: y // check for collisions
} const rayVector = Vector.add(this.position, Vector.rotate({ x: 100, y: 0 }, angle))
}, query = (who) => {
yVelocity: -1.21 * Math.sqrt(Math.abs(height)), const list = Matter.Query.ray(who, this.position, rayVector, 100)
query() { if (list.length > 0) {
// check for collisions Matter.Body.setVelocity(list[0].bodyA, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
query = (who) => { }
if (Matter.Query.region(who, this.boostBounds).length > 0) {
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
});
} }
} query(body)
query(body) query(mob)
query(mob) query(bullet)
query(bullet) query(powerUp)
query(powerUp) //player collision
//player collision const list = Matter.Query.ray([player], this.position, rayVector, 100)
if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) { if (list.length > 0) {
m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts Matter.Body.setVelocity(player, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
m.hardLandCD = 0 // disable hard landing m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
if (player.velocity.y > 26) { m.hardLandCD = 0 // disable hard landing
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
ctx.fillStyle = "rgba(200,0,255,0.15)"; // if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 10, 100, 30); // m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
ctx.fillStyle = "rgba(200,0,255,0.05)"; // m.hardLandCD = 0 // disable hard landing
ctx.fillRect(this.boostBounds.min.x, this.boostBounds.min.y - 50, 100, 70); // if (player.velocity.y > 26) {
// ctx.fillStyle = "rgba(200,0,255,0.02)"; // Matter.Body.setVelocity(player, {
// ctx.fillRect(x, y - 120, 100, 120); // x: player.velocity.x,
}, // y: -15 //gentle bounce if coming down super fast
}); // });
return who // } 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)
ctx.lineTo(v3.x, v3.y)
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)
ctx.beginPath();
ctx.moveTo(v1.x, v1.y)
ctx.lineTo(v2.x, v2.y)
ctx.lineTo(v3.x, v3.y)
ctx.lineTo(v4.x, v4.y)
ctx.fillStyle = "rgba(200,0,255,0.15)";
ctx.fill()
},
});
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"), {
collisionFilter: {
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
},
boostBounds: {
min: {
x: x,
y: y - 20
},
max: {
x: x + 100,
y: y
}
},
yVelocity: -1.21 * Math.sqrt(Math.abs(height)),
query() {
// check for collisions
query = (who) => {
if (Matter.Query.region(who, this.boostBounds).length > 0) {
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
});
}
}
query(body)
query(mob)
query(bullet)
query(powerUp)
//player collision
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
ctx.fillStyle = "rgba(200,0,255,0.15)";
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
}
}, },
elevator(x, y, width, height, maxHeight, force = 0.003, friction = { elevator(x, y, width, height, maxHeight, force = 0.003, friction = {
up: 0.01, up: 0.01,
@@ -2570,27 +2644,6 @@ const level = {
ctx.fillStyle = "#ccc" ctx.fillStyle = "#ccc"
ctx.fill() ctx.fill()
//power up dispenser
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.moveTo(2000, -100 * i)
// ctx.lineTo(2080, -100 * i)
// }
// ctx.strokeStyle = "#ddd"
// ctx.lineWidth = 5;
// ctx.stroke();
// ctx.beginPath()
// for (let i = 2; i < 10; i++) {
// ctx.arc(2040, -100 * i, 30, 0, 2 * Math.PI);
// ctx.moveTo(2040, -100 * i)
// }
// ctx.fillStyle = "rgba(0,0,0,0.3)"
// ctx.fill()
// ctx.fillStyle = "rgba(240,255,255,0.5)"
// ctx.fillRect(2000, -1000, 80, 700)
//exit room //exit room
ctx.fillStyle = "#f2f2f2" ctx.fillStyle = "#f2f2f2"
ctx.fillRect(2600, -600, 400, 300) ctx.fillRect(2600, -600, 400, 300)
@@ -4198,6 +4251,250 @@ const level = {
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300); // if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
powerUps.addResearchToLevel() //needs to run after mobs are spawned powerUps.addResearchToLevel() //needs to run after mobs are spawned
}, },
towers() {
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
level.difficultyIncrease(10 * 4) //30 is near max on hard //60 is near max on why
// simulation.isHorizontalFlipped = true
const isFlipped = (simulation.isHorizontalFlipped && Math.random() < 0.33) ? true : false
level.announceMobTypes()
if (isFlipped) {
level.setPosToSpawn(9150 + 50, -2230 - 25);
level.exit.x = -100 - 50;
level.exit.y = -50 + 25;
leftRoomColor = "#cff"
rightRoomColor = "rgba(0,0,0,0.13)"
} else {
level.setPosToSpawn(-100, -50);
level.exit.x = 9150;
level.exit.y = -2230;
}
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";
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
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#cdd9df";
powerUps.spawnStartingPowerUps(6300, 1025)
const boost1 = level.boost(7560, 1480, 1700, 1.75)
const boost2 = level.boost(7098, 0, 1250, Math.PI / 3) //x,y,push,angle radians
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 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
let portal1, portal2
portal1 = level.portal({
x: 3675,
y: -2225 + 1025
}, -Math.PI / 2, { //up
x: 3675,
y: -375
}, Math.PI / 2) //down
portal2 = level.portal({
x: 6300,
y: -1225
}, -Math.PI / 2, { //up
x: 6300,
y: -375
}, Math.PI / 2) //down
level.custom = () => {
boost1.query();
boost2.query();
boost3.query();
boost4.query();
boost5.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
} else if (train1.position.x > 3850) {
train1.changeDirection(false) //go left
}
if (train2.position.x < 1450) {
train2.changeDirection(true) //go right
} else if (train2.position.x > 2450) {
train2.changeDirection(false) //go left
}
if (train3.position.x < 4250) {
train3.changeDirection(true) //go right
} else if (train3.position.x > 5250) {
train3.changeDirection(false) //go left
}
train1.move();
train2.move();
train3.move();
ctx.fillStyle = "rgba(0,0,0,0.25)"
ctx.fillRect(1250, 121, 4200, 6)
ctx.fillStyle = "rgba(50,70,100,0.04)"
ctx.fillRect(2500, -10000, 1800, 30000);
ctx.fillRect(8300, -10000, 1800, 30000);
ctx.fillRect(-500, -10000, 1800, 30000);
ctx.fillRect(5400, -10000, 1800, 30000);
portal1[2].query()
portal1[3].query()
portal2[2].query()
portal2[3].query()
ctx.fillStyle = "#cff"
if (isFlipped) {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
} else {
ctx.fillRect(8925, -2575, 525, 400) //exit typically
}
level.exit.drawAndCheck();
level.enter.draw();
};
level.customTopLayer = () => {
ctx.fillStyle = "rgba(0,0,0,0.13)"
ctx.fillRect(8300, -1950, 1550, 1275);
ctx.fillRect(5400, 875, 1800, 650);
ctx.fillRect(2950, -2200, 875, 1050);
if (isFlipped) {
ctx.fillRect(8925, -2575, 575, 400) //exit typically
} else {
ctx.fillRect(-350, -300, 525, 325); //entrance typically
}
ctx.fillStyle = "rgba(0,0,0,0.5)"
ctx.fillRect(7175, -1515, 125, 180);
portal1[0].draw();
portal1[1].draw();
portal1[2].draw();
portal1[3].draw();
portal2[0].draw();
portal2[1].draw();
portal2[2].draw();
portal2[3].draw();
};
// four large rounded squares
let a = 900 //side length
let c = 100 //corner offset
// spawn.mapVertex(3400, -1300, `${-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(9200, -1300, `${-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, 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);
//2nd zone upper hollow square
spawn.mapVertex(5650 - 2900, 900 - 2200, `${-a} ${-a + c} ${-a + c} ${-a} ${-400} ${-a} ${-400} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //1/2 square with edges cut off
spawn.mapVertex(6950 - 2900, 900 - 2200, `${400} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${a - c} ${a - c} ${a} ${400} ${a}`); //1/2 square with edges cut off
// spawn.mapRect(5600 - 2900, 1400 - 2200, 1350, 400);
spawn.mapRect(2950, -1175, 650, 775);
spawn.mapRect(3750, -1175, 100, 775);
spawn.mapRect(3575, -1025, 200, 475);
//4th zone far right hollow square near exit
spawn.mapVertex(9200, -2050, `${-a} ${-a + c} ${-a + c} ${-a} ${a - c} ${-a} ${a} ${-a + c} ${a} ${-600} ${-a} ${-600}`); //square with edges cut off --- hollow top
spawn.mapVertex(9200, -550, `${-a} ${600} ${a} ${600} ${a} ${a - c} ${a - c} ${a} ${-a + c} ${a} ${-a} ${a - c}`); //square with edges cut off --- hollow bottom
spawn.mapRect(9800, -2100, 300, 1600); //hollow left wall
spawn.mapVertex(8175, -1425, "-1400 -90 350 -90 400 -40 400 40 350 90 -1400 90");
spawn.mapVertex(6856, -1425, "300 -90 -350 -90 -400 -40 -400 40 -350 90 300 90");
//exit housing
spawn.mapRect(8925, -2575, 575, 75);
if (isFlipped) {
spawn.mapRect(8925, -2550, 75, 400);
spawn.mapRect(9425, -2550, 75, 125);
spawn.mapRect(9425, -2215, 75, 50);
spawn.bodyRect(9425, -2425, 75, 210);
} else {
spawn.mapRect(9425, -2550, 75, 400);
spawn.mapRect(8925, -2550, 75, 125);
spawn.mapRect(8925, -2215, 75, 50);
}
//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");
//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(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(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");
//no debris on this level, so spawn some heals and ammo
powerUps.chooseRandomPowerUp(6275, 1425);
powerUps.chooseRandomPowerUp(3350, -1250);
powerUps.chooseRandomPowerUp(9550, -750);
//random blocks
spawn.bodyRect(7725, -2200, 150, 250, 0.2);
spawn.bodyRect(4625, -825, 75, 125, 0.2);
spawn.bodyRect(3250, -1200, 25, 25, 0.2);
spawn.bodyRect(3375, -1275, 25, 75, 0.2);
spawn.bodyRect(3450, -1200, 50, 25, 0.2);
spawn.bodyRect(2825, -2225, 25, 25, 0.2);
spawn.bodyRect(4075, -2225, 50, 25, 0.2);
spawn.bodyRect(8850, -800, 75, 100, 0.2);
spawn.bodyRect(6900, -100, 75, 100, 0.2);
spawn.bodyRect(8975, -1575, 50, 50, 0.2);
spawn.bodyRect(5725, -1700, 125, 175, 0.2);
spawn.bodyRect(6850, -1725, 150, 200, 0.2);
//mobs
spawn.randomMob(5700, -75, 0);
spawn.randomMob(6200, -100, 0);
spawn.randomMob(6900, -100, 0.1);
spawn.randomMob(5550, -500, 0.1);
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);
spawn.randomMob(5850, -1625, 0.3);
spawn.randomMob(6775, -1600, 0.3);
spawn.randomMob(7700, -1625, 0.4);
spawn.randomMob(7850, -2000, 0.4);
spawn.randomMob(7225, -2000, 0.4);
spawn.randomMob(6350, -2400, 0.5);
spawn.randomMob(8850, -1650, 0.5);
spawn.randomMob(9500, -1300, 0.5);
spawn.randomMob(9250, -900, 0.5);
spawn.randomMob(8600, -875, 0.6);
spawn.randomMob(5575, 1350, 0.6);
spawn.randomMob(6075, 1025, 0.6);
spawn.randomMob(6300, 1025, 0.7);
spawn.randomMob(6525, 1425, 0.8);
spawn.randomMob(7125, 1450, 0.9);
// spawn.randomMob(8600, -2325, 0.7);
// spawn.randomMob(8650, -2825, 0.8);
// spawn.randomMob(9225, -2850, 0.9);
// spawn.randomMob(8525, -2375, 0.9);
spawn.randomGroup(4925, -2850, 1);
if (simulation.difficulty > 1) {
spawn.randomLevelBoss(7275, -2475);
spawn.secondaryBossChance(8400, -1025)
}
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
factory() { factory() {
level.announceMobTypes() level.announceMobTypes()
// simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! // simulation.enableConstructMode() //remove this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -4211,7 +4508,7 @@ const level = {
spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit spawn.mapRect(level.exit.x, level.exit.y + 20, 100, 20); //bump for level exit
level.defaultZoom = 1500 level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom) simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d2d4s"; document.body.style.backgroundColor = "#d0d2d4";
// color.map = "#262a2f" // color.map = "#262a2f"
let isPowerLeft = true let isPowerLeft = true
const movers = [] const movers = []
@@ -5596,7 +5893,7 @@ const level = {
}, },
pavilion() { pavilion() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
const vanish = [] const vanish = []
level.exit.x = -850; level.exit.x = -850;
level.exit.y = -1485; level.exit.y = -1485;
@@ -6449,7 +6746,7 @@ const level = {
}, },
satellite() { satellite() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
const boost1 = level.boost(5825, 235, 1400) const boost1 = level.boost(5825, 235, 1400)
const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 } const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 }
level.custom = () => { level.custom = () => {
@@ -6626,7 +6923,7 @@ const level = {
}, },
rooftops() { rooftops() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
// level.fallPosition = { x: 5000, y:-4000} // level.fallPosition = { x: 5000, y:-4000}
const elevator = level.elevator(1450, -990, 235, 45, -2000) const elevator = level.elevator(1450, -990, 235, 45, -2000)
const boost1 = level.boost(4950, 0, 1100) const boost1 = level.boost(4950, 0, 1100)
@@ -6635,7 +6932,6 @@ const level = {
boost1.query(); boost1.query();
elevator.move(); elevator.move();
elevator.drawTrack(); elevator.drawTrack();
ctx.fillStyle = "#d4f4f4" ctx.fillStyle = "#d4f4f4"
if (isBackwards) { if (isBackwards) {
ctx.fillRect(-650, -2300, 440, 300) ctx.fillRect(-650, -2300, 440, 300)
@@ -6643,7 +6939,6 @@ const level = {
ctx.fillRect(3460, -700, 1090, 800) ctx.fillRect(3460, -700, 1090, 800)
} }
level.exit.drawAndCheck(); level.exit.drawAndCheck();
level.enter.draw(); level.enter.draw();
}; };
@@ -6815,7 +7110,7 @@ const level = {
}, },
aerie() { aerie() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
const boost1 = level.boost(-425, 100, 1400) const boost1 = level.boost(-425, 100, 1400)
const boost2 = level.boost(5350, 275, 2850); const boost2 = level.boost(5350, 275, 2850);
@@ -7045,7 +7340,7 @@ const level = {
}, },
skyscrapers() { skyscrapers() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
const boost1 = level.boost(475, 0, 1300) const boost1 = level.boost(475, 0, 1300)
const boost2 = level.boost(4450, 0, 1300); const boost2 = level.boost(4450, 0, 1300);
level.custom = () => { level.custom = () => {
@@ -7184,11 +7479,8 @@ const level = {
}, },
highrise() { highrise() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { const elevator1 = level.elevator(-790, -190, 180, 25, -1150, 0.0025, { up: 0.01, down: 0.2 }, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
up: 0.01,
down: 0.2
}, true) //x, y, width, height, maxHeight, force = 0.003, friction = { up: 0.01, down: 0.2 }) {
elevator1.addConstraint(); elevator1.addConstraint();
// const button1 = level.button(-500, -200) // const button1 = level.button(-500, -200)
const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false) const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false)
@@ -7470,7 +7762,7 @@ const level = {
}, },
warehouse() { warehouse() {
level.announceMobTypes() level.announceMobTypes()
level.isEndlessFall = true; level.fallMode = "start";
level.custom = () => { level.custom = () => {
ctx.fillStyle = "#444" //light fixtures ctx.fillStyle = "#444" //light fixtures
ctx.fillRect(-920, -505, 40, 10) ctx.fillRect(-920, -505, 40, 10)
@@ -27198,7 +27490,7 @@ const level = {
} }
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -27207,7 +27499,6 @@ const level = {
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
@@ -27229,6 +27520,12 @@ const level = {
me.shieldTargetID = target.id me.shieldTargetID = target.id
target.isShielded = true; target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id target.shieldID = me.id
me.onDeath = function () { me.onDeath = function () {
//clear isShielded status from target //clear isShielded status from target
@@ -28466,7 +28763,7 @@ const level = {
} }
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -28475,7 +28772,6 @@ const level = {
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
@@ -28497,6 +28793,12 @@ const level = {
me.shieldTargetID = target.id me.shieldTargetID = target.id
target.isShielded = true; target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id target.shieldID = me.id
me.onDeath = function () { me.onDeath = function () {
//clear isShielded status from target //clear isShielded status from target

View File

@@ -1161,6 +1161,7 @@ const mobs = {
this.onDeath(this); //custom death effects this.onDeath(this); //custom death effects
this.removeConsBB(); this.removeConsBB();
this.alive = false; //triggers mob removal in mob[i].replace(i) this.alive = false; //triggers mob removal in mob[i].replace(i)
console.log(this.shieldCount)
if (this.isDropPowerUp) { if (this.isDropPowerUp) {
// if (true) { // if (true) {
@@ -1306,7 +1307,7 @@ const mobs = {
tech.cloakDuplication -= 0.01 tech.cloakDuplication -= 0.01
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
} else if (tech.isShieldAmmo && this.shield && !this.isExtraShield && this.isDropPowerUp) { } else if (tech.isShieldAmmo && this.shield && this.shieldCount === 1) {
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

@@ -8,7 +8,7 @@ const m = {
// let vector = Vertices.fromPath("0 40 50 40 50 115 0 115 30 130 20 130"); //player as a series of vertices // let vector = Vertices.fromPath("0 40 50 40 50 115 0 115 30 130 20 130"); //player as a series of vertices
let vertices = Vertices.fromPath("0,40, 50,40, 50,115, 30,130, 20,130, 0,115, 0,40"); //player as a series of vertices let vertices = Vertices.fromPath("0,40, 50,40, 50,115, 30,130, 20,130, 0,115, 0,40"); //player as a series of vertices
playerBody = Bodies.fromVertices(0, 0, vertices); playerBody = Bodies.fromVertices(0, 0, vertices);
jumpSensor = Bodies.rectangle(0, 46, 36, 6, { jumpSensor = Bodies.rectangle(0, 46, 36, 6, { //(0, 46, 50, 6, { //for wall jumping
//this sensor check if the player is on the ground to enable jumping //this sensor check if the player is on the ground to enable jumping
sleepThreshold: 99999999999, sleepThreshold: 99999999999,
isSensor: true isSensor: true
@@ -545,7 +545,7 @@ const m = {
}, },
baseHealth: 1, baseHealth: 1,
setMaxHealth(isMessage) { setMaxHealth(isMessage) {
m.maxHealth = m.baseHealth + tech.extraMaxHealth + 3 * tech.isFallingDamage + 4 * tech.isFlipFlop * tech.isFlipFlopOn * tech.isFlipFlopHealth m.maxHealth = m.baseHealth + tech.extraMaxHealth + 3 * tech.isFallingDamage
document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px` document.getElementById("health-bg").style.width = `${Math.floor(300 * m.maxHealth)}px`
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`) if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-h'>maxHealth</span> <span class='color-symbol'>=</span> ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth; if (m.health > m.maxHealth) m.health = m.maxHealth;
@@ -2178,7 +2178,7 @@ const m = {
} }
}, },
setMaxEnergy(isMessage = true) { setMaxEnergy(isMessage = true) {
m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand
if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`) if (isMessage) simulation.makeTextLog(`<span class='color-var'>m</span>.<span class='color-f'>maxEnergy</span> <span class='color-symbol'>=</span> ${(m.maxEnergy.toFixed(2))}`)
}, },
fieldMeterColor: "#0cf", fieldMeterColor: "#0cf",

View File

@@ -247,12 +247,14 @@ const powerUps = {
if (powerUp[i].isDuplicated) { if (powerUp[i].isDuplicated) {
if (Math.random() < 0.003 && !m.isBodiesAsleep) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second if (Math.random() < 0.003 && !m.isBodiesAsleep) { // (1-0.003)^240 = chance to be removed after 4 seconds, 240 = 4 seconds * 60 cycles per second
b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size); b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size);
Matter.Composite.remove(engine.world, powerUp[i]); if (powerUp[i]) {
powerUp.splice(i, 1); Matter.Composite.remove(engine.world, powerUp[i]);
powerUp.splice(i, 1);
}
break break
} }
if (Math.random() < 0.3) { //draw electricity if (Math.random() < 0.3) { //draw electricity
const mag = 4 + powerUp[i].size / 5 const mag = Math.max(1, 4 + powerUp[i].size / 5)
let unit = Vector.rotate({ x: mag, y: mag }, 2 * Math.PI * Math.random()) let unit = Vector.rotate({ x: mag, y: mag }, 2 * Math.PI * Math.random())
let path = { x: powerUp[i].position.x + unit.x, y: powerUp[i].position.y + unit.y } let path = { x: powerUp[i].position.x + unit.x, y: powerUp[i].position.y + unit.y }
ctx.beginPath(); ctx.beginPath();
@@ -328,7 +330,7 @@ const powerUps = {
simulation.circleFlare(value); simulation.circleFlare(value);
} }
if (tech.isCancelRerolls) { if (tech.isCancelRerolls) {
for (let i = 0, len = 10 + 4 * Math.random(); i < len; i++) { for (let i = 0, len = 8 + 4 * Math.random(); i < len; i++) {
let spawnType let spawnType
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) { if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) {
spawnType = "ammo" spawnType = "ammo"
@@ -340,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); 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", 8) if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 7)
if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") { if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") {
tech.cancelTechCount++ tech.cancelTechCount++
// powerUps.research.use('tech') // powerUps.research.use('tech')
@@ -524,7 +526,7 @@ const powerUps = {
name: "heal", name: "heal",
color: "#0eb", color: "#0eb",
size() { size() {
return Math.sqrt(0.1 + 0.25) * 40 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)) * (tech.isFlipFlopOn && tech.isFlipFlopHealth ? Math.sqrt(2) : 1); //(simulation.healScale ** 0.25) gives a smaller radius as heal scale goes down return Math.sqrt(0.1 + 0.25) * 40 * (simulation.healScale ** 0.25) * Math.sqrt(tech.largerHeals * (tech.isHalfHeals ? 0.5 : 1)); //(simulation.healScale ** 0.25) gives a smaller radius as heal scale goes down
}, },
effect() { effect() {
if (!tech.isEnergyHealth && m.alive) { if (!tech.isEnergyHealth && m.alive) {
@@ -819,30 +821,92 @@ const powerUps = {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div> &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>` ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
}, },
// junkTechText(choose, click) { //old code with yahoo images
// 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://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
// fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
// .then((response) => response.text())
// .then((html) => {
// const parser = new DOMParser();
// const doc = parser.parseFromString(html, "text/html");
// const elements = doc.getElementsByClassName("ld");
// // console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
// const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
// if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
// tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
// } else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// } else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// });
// } else {
// 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">
// <div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
// ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
// },
// junkTechText(choose, click) {
// 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://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name;
// fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
// .then((response) => response.text())
// .then((html) => {
// const parser = new DOMParser();
// const doc = parser.parseFromString(html, "text/html");
// const elements = doc.getElementsByClassName("ld");
// // console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
// const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
// if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
// tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
// } else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// } else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
// tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
// document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
// }
// });
// } else {
// 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">
// <div class="grid-title"><div class="circle-grid junk"></div> &nbsp; ${tech.tech[choose].name} ${techCountText}</div>
// ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}</div></div>`
// },
junkTechText(choose, click) { junkTechText(choose, click) {
const techCountText = tech.tech[choose].count > 0 ? `(${tech.tech[choose].count + 1}x)` : ""; 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');"` const style = localSettings.isHideImages ? powerUps.hideStyle : `style="background-size: contain;background-repeat: no-repeat;background-image: url('img/junk.webp');"`
if (!localSettings.isHideImages) { if (!localSettings.isHideImages) {
setTimeout(() => { //delay so that the html element exists setTimeout(() => { //delay so that the html element exists
if (tech.tech[choose].url === undefined) { //if on url has been set yet if (tech.tech[choose].url === undefined) { //if on url has been set yet
const url = "https://images.search.yahoo.com/search/images?p=" + tech.tech[choose].name; 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 fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
.then((response) => response.text()) .then((response) => response.json())
.then((html) => { .then((responseJson) => {
const parser = new DOMParser(); if (responseJson.results.length > 0) {
const doc = parser.parseFromString(html, "text/html"); const index = Math.floor(Math.random() * responseJson.results.length) //randomly choose from the images
const elements = doc.getElementsByClassName("ld"); tech.tech[choose].url = responseJson.results[index].url //store the url
// console.log(i, elements[i].getAttribute("data"), JSON.parse(elements[i].getAttribute("data")).iurl)
const index = Math.floor(Math.random() * 4) //randomly choose from the first 4 images
if (parseInt(JSON.parse(elements[index].getAttribute("data")).s.slice(0, -2)) < 500) { //make sure it isn't too big
tech.tech[choose].url = JSON.parse(elements[index].getAttribute("data")).iurl //store the url
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
} else if (parseInt(JSON.parse(elements[index + 1].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 1].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
} else if (parseInt(JSON.parse(elements[index + 2].getAttribute("data")).s.slice(0, -2)) < 500) { //try a different images and see if it is smaller
tech.tech[choose].url = JSON.parse(elements[index + 2].getAttribute("data")).iurl
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')`
} }
}); });
} else { } else {
@@ -878,7 +942,6 @@ const powerUps = {
// console.log(options.length) // console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) { if (options.length > 0 || !tech.isSuperDeterminism) {
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)))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) { function removeOption(index) {
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
if (options[i] === index) { if (options[i] === index) {
@@ -940,8 +1003,6 @@ const powerUps = {
if (i !== m.fieldMode) options.push(i); 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)))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) { function removeOption(index) {
for (let i = 0; i < options.length; i++) { for (let i = 0; i < options.length; i++) {
if (options[i] === index) { if (options[i] === index) {
@@ -1016,7 +1077,6 @@ const powerUps = {
} }
//set total choices //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))
if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices if (optionLengthNoDuplicates < totalChoices + 1) { //if not enough options for all the choices
totalChoices = optionLengthNoDuplicates totalChoices = optionLengthNoDuplicates
if (tech.isBanish) { //when you run out of options eject banish if (tech.isBanish) { //when you run out of options eject banish
@@ -1214,7 +1274,7 @@ const powerUps = {
} else if (tech.tech[choose].isSkin) { } else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} else if (tech.tech[choose].isInstant) { } else if (tech.tech[choose].isInstant) {
text += powerUps.instantTechTextTechText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.instantTechText(choose, `powerUps.choose('tech',${choose})`)
} else { //normal tech } else { //normal tech
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`) text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
} }
@@ -1229,14 +1289,14 @@ const powerUps = {
} }
}, },
}, },
spawnDelay(type, count) { spawnDelay(type, count, delay = 2) {
count *= 2 count *= delay
let cycle = () => { let cycle = () => {
if (count > 0) { if (count > 0) {
if (m.alive) requestAnimationFrame(cycle); if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2) if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
count-- count--
if (!(count % 2)) { if (!(count % delay)) {
const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) } const where = { x: m.pos.x + 50 * (Math.random() - 0.5), y: m.pos.y + 50 * (Math.random() - 0.5) }
powerUps.spawn(where.x, where.y, type); powerUps.spawn(where.x, where.y, type);
} }
@@ -1256,18 +1316,6 @@ const powerUps = {
b.mine(who.position, { x: 0, y: 0 }, 0) b.mine(who.position, { x: 0, y: 0 }, 0)
} }
} }
if (tech.isRelay) {
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false
if (document.getElementById("tech-switch")) document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = 'transparent'
} else {
tech.isFlipFlopOn = true //immune to damage this hit, lose immunity for next hit
if (document.getElementById("tech-switch")) document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#0cf'
}
if (tech.isRelayEnergy) m.setMaxEnergy();
}
}, },
spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up spawnRandomPowerUp(x, y) { //mostly used after mob dies, doesn't always return a power up
if (!tech.isEnergyHealth && (Math.random() * Math.random() - 0.3 > Math.sqrt(m.health)) || Math.random() < 0.04) { //spawn heal chance is higher at low health if (!tech.isEnergyHealth && (Math.random() * Math.random() - 0.3 > Math.sqrt(m.health)) || Math.random() < 0.04) { //spawn heal chance is higher at low health
@@ -1449,8 +1497,10 @@ const powerUps = {
// tech.removeTech(index) // tech.removeTech(index)
// } else { // } else {
// } // }
tech.tech[index].frequency = 0 //banish tech
powerUps.ejectTech(index) powerUps.ejectTech(index)
m.damage(0.04) 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.textDecoration = "line-through"
document.getElementById(`${index}-pause-tech`).style.animation = "" document.getElementById(`${index}-pause-tech`).style.animation = ""
document.getElementById(`${index}-pause-tech`).onclick = null document.getElementById(`${index}-pause-tech`).onclick = null
@@ -1478,15 +1528,9 @@ const powerUps = {
smallIndexes.push(i) smallIndexes.push(i)
} }
} }
if (bigIndexes.length > 0) {
// console.log("at least 1 big will always spilt")
const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)]
for (let i = 0; i < 3; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
Matter.Composite.remove(engine.world, powerUp[index]);
powerUp.splice(index, 1); if (smallIndexes.length > 2 && Math.random() < 0.66) { // console.log("no big, at least 3 small can combine")
} else if (smallIndexes.length > 2 && Math.random() < 0.33) {
// console.log("no big, at least 3 small can combine")
for (let j = 0; j < 3; j++) { for (let j = 0; j < 3; j++) {
for (let i = 0; i < powerUp.length; i++) { for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal" || powerUp[i].name === "research" || powerUp[i].name === "ammo" || powerUp[i].name === "coupling" || powerUp[i].name === "boost") { if (powerUp[i].name === "heal" || powerUp[i].name === "research" || powerUp[i].name === "ammo" || powerUp[i].name === "coupling" || powerUp[i].name === "boost") {
@@ -1499,8 +1543,13 @@ const powerUps = {
options = ["tech", "gun", "field"] options = ["tech", "gun", "field"]
powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
} else if (smallIndexes.length > 0) { } else if (bigIndexes.length > 0 && Math.random() < 0.5) { // console.log("at least 1 big can spilt")
// console.log("no big, at least 1 small will swap flavors") const index = bigIndexes[Math.floor(Math.random() * bigIndexes.length)]
for (let i = 0; i < 3; i++) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
Matter.Composite.remove(engine.world, powerUp[index]);
powerUp.splice(index, 1);
} else if (smallIndexes.length > 0) { // console.log("no big, at least 1 small will swap flavors")
const index = Math.floor(Math.random() * powerUp.length) const index = Math.floor(Math.random() * powerUp.length)
options = options.filter(e => e !== powerUp[index].name); //don't repeat the current power up type options = options.filter(e => e !== powerUp[index].name); //don't repeat the current power up type
powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false) powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)

View File

@@ -184,7 +184,7 @@ const simulation = {
fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob
isCommunityMaps: false, isCommunityMaps: false,
cyclePaused: 0, cyclePaused: 0,
fallHeight: 6000, //below this y position the player dies fallHeight: 6000, //below this y position the player will teleport to start, take damage, or teleport to the sky based on the value of level.fallMode
lastTimeStamp: 0, //tracks time stamps for measuring delta lastTimeStamp: 0, //tracks time stamps for measuring delta
delta: 1000 / 60, //speed of game engine //looks like it has to be 16.6666 to match player input delta: 1000 / 60, //speed of game engine //looks like it has to be 16.6666 to match player input
buttonCD: 0, buttonCD: 0,
@@ -435,10 +435,10 @@ const simulation = {
} else if (tech.tech[i].count > 0 && !tech.tech[i].isInstant) { } else if (tech.tech[i].count > 0 && !tech.tech[i].isInstant) {
if (text) text += "<br>" //add a new line, but not on the first line if (text) text += "<br>" //add a new line, but not on the first line
text += tech.tech[i].name text += tech.tech[i].name
if (tech.tech[i].nameInfo) { // if (tech.tech[i].nameInfo) {
text += tech.tech[i].nameInfo // text += tech.tech[i].nameInfo
tech.tech[i].addNameInfo(); // tech.tech[i].addNameInfo();
} // }
if (tech.tech[i].count > 1) text += ` (${tech.tech[i].count}x)` if (tech.tech[i].count > 1) text += ` (${tech.tech[i].count}x)`
} }
} }
@@ -933,22 +933,8 @@ const simulation = {
m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25% m.energy = m.maxEnergy + (m.energy - m.maxEnergy) * tech.overfillDrain //every second energy above max energy loses 25%
if (m.energy > 1000000) m.energy = 1000000 if (m.energy > 1000000) m.energy = 1000000
} }
if (tech.isFlipFlopEnergy && m.immuneCycle < m.cycle) {
if (tech.isFlipFlopOn) {
if (m.immuneCycle < m.cycle) m.energy += 0.2;
} else {
m.energy -= 0.01;
if (m.energy < 0) m.energy = 0
}
}
if (tech.relayIce && tech.isFlipFlopOn) {
for (let j = 0; j < tech.relayIce; j++) {
for (let i = 0, len = 3 + Math.ceil(9 * Math.random()); i < len; i++) b.iceIX(2)
}
}
if (m.pos.y > simulation.fallHeight) { // if 4000px deep if (m.pos.y > simulation.fallHeight) { // if 4000px deep
if (level.isEndlessFall) { if (level.fallMode === "start") {
//infinite falling. teleport to sky after falling //infinite falling. teleport to sky after falling
simulation.ephemera.push({ simulation.ephemera.push({
@@ -957,7 +943,6 @@ const simulation = {
do() { do() {
this.count-- this.count--
if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name) if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name)
// console.log(player.velocity.y)
if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 }); if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 }); if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
}, },
@@ -976,13 +961,36 @@ const simulation = {
m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x); m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x);
// move bots // move bots
for (let i = 0; i < bullet.length; i++) { for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) { if (bullet[i].botType) Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
// Matter.Body.setPosition(bullet[i], Vector.add(player.position, { x: 250 * (Math.random() - 0.5), y: 250 * (Math.random() - 0.5) }));
// Matter.Body.setVelocity(bullet[i], { x: 0, y: 0 });
}
} }
} else { } else if (level.fallMode === "position") { //fall and stay in the same horizontal position
simulation.ephemera.push({
name: "slow player",
count: 180, //cycles before it self removes
do() {
this.count--
if (this.count < 0 || m.onGround) simulation.removeEphemera(this.name)
if (player.velocity.y > 70) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
if (player.velocity.y > 90) Matter.Body.setVelocity(player, { x: player.velocity.x * 0.99, y: player.velocity.y * 0.99 });
},
})
const before = { x: player.position.x, y: player.position.y, }
let posXClamped = Math.min(Math.max(level.fallModeBounds.left, player.position.x), level.fallModeBounds.right)
Matter.Body.setPosition(player, { x: posXClamped, y: level.enter.y - 4000 });
// translate camera smoothly to preserve illusion to endless fall
const change = { x: before.x - posXClamped, y: before.y - player.position.y }
m.transX += change.x
m.transY += change.y
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
m.angle = Math.atan2(simulation.mouseInGame.y - m.pos.y, simulation.mouseInGame.x - m.pos.x);
// move bots
for (let i = 0; i < bullet.length; i++) {
if (bullet[i].botType) Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
}
} else { //get hurt and go to start
Matter.Body.setVelocity(player, { x: 0, y: 0 }); Matter.Body.setVelocity(player, { x: 0, y: 0 });
Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 }); Matter.Body.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 });
// m.damage(0.02 * simulation.difficultyMode); // m.damage(0.02 * simulation.difficultyMode);
@@ -1049,7 +1057,7 @@ const simulation = {
do() { do() {
if (Matter.Query.point(map, m.pos).length > 0 || Matter.Query.point(map, player.position).length > 0) { if (Matter.Query.point(map, m.pos).length > 0 || Matter.Query.point(map, player.position).length > 0) {
this.count-- this.count--
// console.log('halp, stuck in map!', Matter.Query.point(map, m.pos))
if (this.count < 0) { if (this.count < 0) {
simulation.removeEphemera(this.name) simulation.removeEphemera(this.name)
Matter.Body.setVelocity(player, { x: 0, y: 0 }); Matter.Body.setVelocity(player, { x: 0, y: 0 });
@@ -1116,7 +1124,7 @@ const simulation = {
clearNow: false, clearNow: false,
clearMap() { clearMap() {
level.isProcedural = false; level.isProcedural = false;
level.isEndlessFall = false; level.fallMode = "";
ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.setTransform(1, 0, 0, 1, 0, 0);
if (m.alive) { if (m.alive) {
if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets
@@ -1370,7 +1378,6 @@ const simulation = {
// window.getSelection().addRange(range); // window.getSelection().addRange(range);
// document.execCommand("copy"); // document.execCommand("copy");
// window.getSelection().removeAllRanges(); // window.getSelection().removeAllRanges();
// console.log(`spawn.mapRect(${simulation.getCoords.pos1.x}, ${simulation.getCoords.pos1.y}, ${simulation.getCoords.pos2.x - simulation.getCoords.pos1.x}, ${simulation.getCoords.pos2.y - simulation.getCoords.pos1.y}); //`);
// } // }
// } // }
// }, // },
@@ -1544,15 +1551,9 @@ const simulation = {
const circleCollisions = []; const circleCollisions = [];
for (const line of outerCollisions) { for (const line of outerCollisions) {
for (const vertex of line) { for (const vertex of line) {
// console.log('hi')
const distance = Math.sqrt((vertex.x - pos.x) ** 2 + (vertex.y - pos.y) ** 2) const distance = Math.sqrt((vertex.x - pos.x) ** 2 + (vertex.y - pos.y) ** 2)
const angle = Math.atan2(vertex.y - pos.y, vertex.x - pos.x); const angle = Math.atan2(vertex.y - pos.y, vertex.x - pos.x);
// const queryPoint = {
// x: Math.cos(angle) * (distance - 1) + pos.x,
// y: Math.sin(angle) * (distance - 1) + pos.y
// }
const queryPoint = { x: Math.cos(angle + Math.PI) + vertex.x, y: Math.sin(angle + Math.PI) + vertex.y } const queryPoint = { x: Math.cos(angle + Math.PI) + vertex.x, y: Math.sin(angle + Math.PI) + vertex.y }
if (Math.abs(distance - radius) < 1 && Matter.Query.ray(map, pos, queryPoint).length == 0) circleCollisions.push(vertex) if (Math.abs(distance - radius) < 1 && Matter.Query.ray(map, pos, queryPoint).length == 0) circleCollisions.push(vertex)
} }
} }
@@ -1917,7 +1918,6 @@ const simulation = {
const y = round(simulation.constructMouseDownPosition.y) const y = round(simulation.constructMouseDownPosition.y)
const dx = Math.max(25, round(simulation.mouseInGame.x) - x) const dx = Math.max(25, round(simulation.mouseInGame.x) - x)
const dy = Math.max(25, round(simulation.mouseInGame.y) - y) const dy = Math.max(25, round(simulation.mouseInGame.y) - y)
// console.log(e.button)
if (e.button === 1) { if (e.button === 1) {
if (level.isProcedural) { if (level.isProcedural) {
simulation.outputMapString(`spawn.randomMob(x+${x}, ${y}, 0);\n`); simulation.outputMapString(`spawn.randomMob(x+${x}, ${y}, 0);\n`);
@@ -1965,8 +1965,8 @@ const simulation = {
}); });
//undo last element added after you press z //undo last element added after you press z
document.body.addEventListener("keydown", (e) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67 document.body.addEventListener("keydown", (event) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67
if (simulation.testing && e.keyCode === 90 && simulation.constructMapString.length) { if (simulation.testing && event.code === "KeyZ" && simulation.constructMapString.length) {
if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level
const index = map.length - 1 const index = map.length - 1
Matter.Composite.remove(engine.world, map[index]); Matter.Composite.remove(engine.world, map[index]);

View File

@@ -1691,6 +1691,7 @@ const spawn = {
powerUps.spawnBossPowerUp(me.position.x, me.position.y) powerUps.spawnBossPowerUp(me.position.x, me.position.y)
powerUps.spawn(me.position.x, me.position.y, "heal"); powerUps.spawn(me.position.x, me.position.y, "heal");
powerUps.spawn(me.position.x, me.position.y, "ammo"); powerUps.spawn(me.position.x, me.position.y, "ammo");
powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) { } else if (!m.isCloak) {
me.foundPlayer(); me.foundPlayer();
} }
@@ -1698,7 +1699,7 @@ const spawn = {
me.isInvulnerable = true me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
me.damageReduction = 0 me.damageReduction = 0
me.invulnerabilityCountDown = 25 + simulation.difficulty me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) { if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255"); powerUps.ejectGraphic("150, 138, 255");
@@ -1713,10 +1714,7 @@ const spawn = {
if (vertices > 3) { if (vertices > 3) {
this.isDropPowerUp = false; this.isDropPowerUp = false;
spawn.powerUpBossBaby(this.position.x, this.position.y, vertices - 1) spawn.powerUpBossBaby(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
x: this.velocity.x,
y: this.velocity.y
})
} }
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
}; };
@@ -1770,15 +1768,16 @@ const spawn = {
powerUps.spawnBossPowerUp(me.position.x, me.position.y) powerUps.spawnBossPowerUp(me.position.x, me.position.y)
powerUps.spawn(me.position.x, me.position.y, "heal"); powerUps.spawn(me.position.x, me.position.y, "heal");
powerUps.spawn(me.position.x, me.position.y, "ammo"); powerUps.spawn(me.position.x, me.position.y, "ammo");
powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) { } else if (!m.isCloak) {
me.foundPlayer(); me.foundPlayer();
} }
me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.isInvulnerable = true me.isInvulnerable = true
// me.startingDamageReduction = me.damageReduction me.startingDamageReduction = me.damageReduction
// me.damageReduction = 0 me.damageReduction = 0
// me.invulnerabilityCountDown = 60 + simulation.difficulty * 2 me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) { if (powerUps.ejectTech()) {
@@ -1794,10 +1793,7 @@ const spawn = {
if (vertices > 3) { if (vertices > 3) {
this.isDropPowerUp = false; this.isDropPowerUp = false;
spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1) spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1)
Matter.Body.setVelocity(mob[mob.length - 1], { Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
x: this.velocity.x,
y: this.velocity.y
})
} }
for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp for (let i = 0; i < powerUp.length; i++) powerUp[i].collisionFilter.mask = cat.map | cat.powerUp
}; };
@@ -1843,22 +1839,22 @@ const spawn = {
// me.constrainPowerUps() // me.constrainPowerUps()
me.do = function () { me.do = function () {
this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)` this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
// if (this.isInvulnerable) { if (this.isInvulnerable) {
// if (this.invulnerabilityCountDown > 0) { if (this.invulnerabilityCountDown > 0) {
// this.invulnerabilityCountDown-- this.invulnerabilityCountDown--
// ctx.beginPath(); ctx.beginPath();
// let vertices = this.vertices; let vertices = this.vertices;
// ctx.moveTo(vertices[0].x, vertices[0].y); 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.lineTo(vertices[0].x, vertices[0].y);
// ctx.lineWidth = 20; ctx.lineWidth = 13 + 5 * Math.random();
// ctx.strokeStyle = "rgba(255,255,255,0.7)"; ctx.strokeStyle = `rgba(255,255,255,${0.5 + 0.2 * Math.random()})`;
// ctx.stroke(); ctx.stroke();
// } else { } else {
// this.isInvulnerable = false this.isInvulnerable = false
// this.damageReduction = this.startingDamageReduction this.damageReduction = this.startingDamageReduction
// } }
// } }
//steal all power ups //steal all power ups
// for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) { // for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
// powerUp[i].collisionFilter.mask = 0 // powerUp[i].collisionFilter.mask = 0
@@ -6898,9 +6894,7 @@ const spawn = {
ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y) ctx.moveTo(this.vertices[this.vertices.length - 1].x, this.vertices[this.vertices.length - 1].y)
const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles
if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y) if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y)
for (let i = 1; i < phase - 1; i++) { for (let i = 1; i < phase - 1; i++) ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
}
ctx.lineWidth = 5 ctx.lineWidth = 5
ctx.strokeStyle = "rgb(255,255,255)" ctx.strokeStyle = "rgb(255,255,255)"
ctx.stroke(); ctx.stroke();
@@ -7584,7 +7578,7 @@ const spawn = {
} }
}; };
}, },
shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance(), isExtraShield = false) { shield(target, x, y, chance = Math.min(0.02 + simulation.difficulty * 0.005, 0.2) + tech.duplicationChance()) {
if (this.allowShields && Math.random() < chance) { if (this.allowShields && Math.random() < chance) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)"); mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1]; let me = mob[mob.length - 1];
@@ -7593,7 +7587,6 @@ const spawn = {
me.shield = true; me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true me.isUnblockable = true
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet; me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({ consBB[consBB.length] = Constraint.create({
@@ -7615,7 +7608,14 @@ const spawn = {
me.shieldTargetID = target.id me.shieldTargetID = target.id
target.isShielded = true; target.isShielded = true;
if (target.shieldCount > 0) {
target.shieldCount++
} else {
target.shieldCount = 1
}
me.shieldCount = target.shieldCount //used with "bubble fusion"
target.shieldID = me.id target.shieldID = me.id
me.onDeath = function () { me.onDeath = function () {
//clear isShielded status from target //clear isShielded status from target
for (let i = 0, len = mob.length; i < len; i++) { for (let i = 0, len = mob.length; i < len; i++) {
@@ -8210,12 +8210,6 @@ const spawn = {
} }
} }
}, },
// bodyRect(x, y, width, height, chance = 1, properties = { friction: 0.05, frictionAir: 0.001 }) {
// if (Math.random() < chance) body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties);
// },
// bodyVertex(x, y, vector, properties) { //adds shape to body array
// body[body.length] = Matter.Bodies.fromVertices(x, y, Vertices.fromPath(vector), properties);
// },
bodyRect(x, y, width, height, chance = 1, properties = { friction: 0.05, frictionAir: 0.001 }) { //this is the command that adds blocks to the world in the middle of a level bodyRect(x, y, width, height, chance = 1, properties = { friction: 0.05, frictionAir: 0.001 }) { //this is the command that adds blocks to the world in the middle of a level
if (Math.random() < chance) { if (Math.random() < chance) {
body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties); body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties);

View File

@@ -19,6 +19,7 @@ const tech = {
//remove lore if it's your first time playing since it's confusing //remove lore if it's your first time playing since it's confusing
//also remove lore if cheating //also remove lore if cheating
tech.removeCount = 0; tech.removeCount = 0;
tech.pauseEjectTech = 1; //used in paradigm shift
lore.techCount = 0; lore.techCount = 0;
if (simulation.isCheating || localSettings.runCount < 1) { //simulation.isCommunityMaps || if (simulation.isCheating || localSettings.runCount < 1) { //simulation.isCommunityMaps ||
for (let i = 0, len = tech.tech.length; i < len; i++) { for (let i = 0, len = tech.tech.length; i < len; i++) {
@@ -231,7 +232,6 @@ const tech = {
if (m.isSneakAttack && m.sneakAttackCycle + Math.min(100, 0.66 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.5 * (1 + 0.033 * m.coupling) if (m.isSneakAttack && m.sneakAttackCycle + Math.min(100, 0.66 * (m.cycle - m.enterCloakCycle)) > m.cycle) dmg *= 4.5 * (1 + 0.033 * m.coupling)
if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime if (tech.deathSkipTime) dmg *= 1 + 0.6 * tech.deathSkipTime
if (tech.isTechDebt) dmg *= tech.totalCount > 20 ? Math.pow(0.85, tech.totalCount - 20) : 4 - 0.15 * tech.totalCount if (tech.isTechDebt) dmg *= tech.totalCount > 20 ? Math.pow(0.85, tech.totalCount - 20) : 4 - 0.15 * tech.totalCount
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828 if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
if (tech.isDamageForGuns) dmg *= 1 + 0.22 * Math.max(0, b.inventory.length - 1) if (tech.isDamageForGuns) dmg *= 1 + 0.22 * Math.max(0, b.inventory.length - 1)
@@ -545,7 +545,7 @@ const tech = {
} }
}, },
{ {
name: "hyperpolarization", name: "repolarization",
descriptionFunction() { descriptionFunction() {
return `the <strong class= 'color-d'> damage</strong> from <strong> depolarization</strong> <br>resets <strong>1.25 seconds</strong> sooner after a mob <strong>dies</strong>` return `the <strong class= 'color-d'> damage</strong> from <strong> depolarization</strong> <br>resets <strong>1.25 seconds</strong> sooner after a mob <strong>dies</strong>`
}, },
@@ -826,7 +826,7 @@ const tech = {
} }
if (gunTechPool.length) { if (gunTechPool.length) {
const index = Math.floor(Math.random() * gunTechPool.length) const index = Math.floor(Math.random() * gunTechPool.length)
console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name) // console.log(gunTechPool, index, gunTechPool[index], tech.tech[gunTechPool[index]].name)
simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[gunTechPool[index]].name}</span>")`, 360) simulation.makeTextLog(`<span class='color-var'>tech</span>.giveTech("<span class='color-text'>${tech.tech[gunTechPool[index]].name}</span>")`, 360)
// tech.tech[gunTechPool[index]].isInstant = true //makes it not remove properly under paradigm shift // tech.tech[gunTechPool[index]].isInstant = true //makes it not remove properly under paradigm shift
tech.giveTech(gunTechPool[index]) // choose from the gun pool tech.giveTech(gunTechPool[index]) // choose from the gun pool
@@ -1390,7 +1390,7 @@ const tech = {
}, },
{ {
name: "thermal runaway", name: "thermal runaway",
description: "after mobs <strong>die</strong><br>they <strong class='color-e'>explode</strong>", description: "after mobs <strong>die</strong> they <strong class='color-e'>explode</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -1472,7 +1472,7 @@ const tech = {
{ {
name: "bubble fusion", name: "bubble fusion",
descriptionFunction() { descriptionFunction() {
return `after destroying a mob's natural <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` return `after destroying a mob's <strong>shield</strong><br>spawn <strong>1-2</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)} <em>(once per mob)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -2295,7 +2295,7 @@ const tech = {
}, },
{ {
name: "decorrelation", name: "decorrelation",
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>0.3x</strong> <strong class='color-defense'>damage taken</strong>", description: "if your <strong class='color-g'>gun</strong> and <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>0.3x</strong> <strong class='color-defense'>damage taken</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2313,7 +2313,7 @@ const tech = {
}, },
{ {
name: "anticorrelation", name: "anticorrelation",
description: "if your <strong class='color-g'>gun</strong> or <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>2x</strong> <strong class='color-d'>damage</strong>", description: "if your <strong class='color-g'>gun</strong> and <strong class='color-f'>field</strong> are unused for <strong>2</strong> seconds<br><strong>2x</strong> <strong class='color-d'>damage</strong>",
maxCount: 1, maxCount: 1,
count: 0, count: 0,
frequency: 1, frequency: 1,
@@ -2422,285 +2422,285 @@ const tech = {
tech.isBlockPowerUps = false tech.isBlockPowerUps = false
} }
}, },
{
name: "NOR gate",
description: "if <strong>flip-flop</strong> is <strong class='color-flop'>OFF</strong><br>become <strong>invulnerable</strong> to your next collision",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop
},
requires: "flip-flop",
effect() {
tech.isFlipFlopHarm = true //do you have this tech
},
remove() {
tech.isFlipFlopHarm = false
}
},
{
name: "shape-memory alloy",
descriptionFunction() {
return `if <strong>flip-flop</strong> is <strong class='color-flop'>ON</strong><br><strong>+400</strong> maximum <strong class='color-h'>health</strong> and <strong>2x</strong> ${powerUps.orb.heal()} effect`
},
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop
},
requires: "flip-flop",
effect() {
tech.isFlipFlopHealth = true;
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
},
remove() {
tech.isFlipFlopHealth = false;
m.setMaxHealth();
for (let i = 0; i < powerUp.length; i++) {
if (powerUp[i].name === "heal") {
const oldSize = powerUp[i].size
powerUp[i].size = powerUps.heal.size() //update current heals
const scale = powerUp[i].size / oldSize
Matter.Body.scale(powerUp[i], scale, scale); //grow
}
}
}
},
{
name: "flip-flop",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Flip-flop_(electronics)' class="link">flip-flop</a>`,
description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after a <strong>collision</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
nameInfo: "<span id = 'tech-flip-flop'></span>",
addNameInfo() {
setTimeout(function () {
if (document.getElementById("tech-flip-flop")) {
if (tech.isFlipFlopOn) {
document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#5af'
} else {
document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = "transparent"
}
}
}, 100);
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isRelay
},
requires: "not relay switch",
effect() {
tech.isFlipFlop = true //do you have this tech?
if (!tech.isFlipFlopOn) {
tech.isFlipFlopOn = true //what is the state of flip-Flop?
}
// if (!m.isShipMode) {
// m.skin.flipFlop()
// }
},
remove() {
tech.isFlipFlop = false
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false //what is the state of flip-Flop?
}
m.eyeFillColor = 'transparent'
// m.resetSkin();
}
},
{
name: "NAND gate",
description: "if <strong class='color-flop'>ON</strong><br><strong>1.555x</strong> <strong class='color-d'>damage</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop || tech.isRelay
},
requires: "ON/OFF tech",
effect() {
tech.isFlipFlopDamage = true;
},
remove() {
tech.isFlipFlopDamage = false;
}
},
{
name: "integrated circuit",
description: "if <strong class='color-flop'>ON</strong> <strong>+7</strong> power up <strong>choices</strong><br>if <strong class='color-flop'>OFF</strong> <strong>-1</strong> power up <strong>choices</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return (tech.isFlipFlop || tech.isRelay) && !tech.isDeterminism
},
requires: "ON/OFF tech, not determinism",
effect() {
tech.isFlipFlopChoices = true //do you have this tech
},
remove() {
tech.isFlipFlopChoices = false
}
},
{
name: "transistor",
description: "if <strong class='color-flop'>ON</strong> generate <strong>+20</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>-1</strong> <strong class='color-f'>energy</strong> per second",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isFlipFlop || tech.isRelay
},
requires: "ON/OFF tech",
effect() {
tech.isFlipFlopEnergy = true;
},
remove() {
tech.isFlipFlopEnergy = false;
}
},
// { // {
// name: "decoupling", // name: "NOR gate",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Decoupling_(cosmology)' class="link">decoupling</a>`, // description: "if <strong>flip-flop</strong> is <strong class='color-flop'>OFF</strong><br>become <strong>invulnerable</strong> to your next collision",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isFlipFlop
// },
// requires: "flip-flop",
// effect() {
// tech.isFlipFlopHarm = true //do you have this tech
// },
// remove() {
// tech.isFlipFlopHarm = false
// }
// },
// {
// name: "shape-memory alloy",
// descriptionFunction() { // descriptionFunction() {
// //<span style = 'font-size:80%;'>(${ m.couplingDescription(this.bonus)})</span> // return `if <strong>flip-flop</strong> is <strong class='color-flop'>ON</strong><br><strong>+400</strong> maximum <strong class='color-h'>health</strong> and <strong>2x</strong> ${powerUps.orb.heal()} effect`
// return `if <strong class='color-flop'>ON</strong> <strong>+5</strong> <strong class='color-coupling'>coupling</strong><br>if <strong class='color-flop'>OFF</strong> a dangerous particle slowly <strong>chases</strong> you`
// }, // },
// maxCount: 1, // maxCount: 1,
// count: 0, // count: 0,
// frequency: 3, // frequency: 3,
// frequencyDefault: 3, // frequencyDefault: 3,
// bonus: 5, //coupling given // allowed() {
// return tech.isFlipFlop
// },
// requires: "flip-flop",
// effect() {
// tech.isFlipFlopHealth = true;
// m.setMaxHealth();
// for (let i = 0; i < powerUp.length; i++) {
// if (powerUp[i].name === "heal") {
// const oldSize = powerUp[i].size
// powerUp[i].size = powerUps.heal.size() //update current heals
// const scale = powerUp[i].size / oldSize
// Matter.Body.scale(powerUp[i], scale, scale); //grow
// }
// }
// },
// remove() {
// tech.isFlipFlopHealth = false;
// m.setMaxHealth();
// for (let i = 0; i < powerUp.length; i++) {
// if (powerUp[i].name === "heal") {
// const oldSize = powerUp[i].size
// powerUp[i].size = powerUps.heal.size() //update current heals
// const scale = powerUp[i].size / oldSize
// Matter.Body.scale(powerUp[i], scale, scale); //grow
// }
// }
// }
// },
// {
// name: "flip-flop",
// link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Flip-flop_(electronics)' class="link">flip-flop</a>`,
// description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after a <strong>collision</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
// // nameInfo: "<span id = 'tech-flip-flop'></span>",
// // addNameInfo() {
// // setTimeout(function () {
// // if (document.getElementById("tech-flip-flop")) {
// // if (tech.isFlipFlopOn) {
// // document.getElementById("tech-flip-flop").innerHTML = ` = <strong>ON</strong>`
// // m.eyeFillColor = m.fieldMeterColor //'#5af'
// // } else {
// // document.getElementById("tech-flip-flop").innerHTML = ` = <strong>OFF</strong>`
// // m.eyeFillColor = "transparent"
// // }
// // }
// // }, 100);
// // },
// maxCount: 1,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return !tech.isRelay
// },
// requires: "not relay switch",
// effect() {
// tech.isFlipFlop = true //do you have this tech?
// if (!tech.isFlipFlopOn) {
// tech.isFlipFlopOn = true //what is the state of flip-Flop?
// }
// // if (!m.isShipMode) {
// // m.skin.flipFlop()
// // }
// },
// remove() {
// tech.isFlipFlop = false
// if (tech.isFlipFlopOn) {
// tech.isFlipFlopOn = false //what is the state of flip-Flop?
// }
// m.eyeFillColor = 'transparent'
// // m.resetSkin();
// }
// },
// {
// name: "NAND gate",
// description: "if <strong class='color-flop'>ON</strong><br><strong>1.555x</strong> <strong class='color-d'>damage</strong>",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() { // allowed() {
// return tech.isFlipFlop || tech.isRelay // return tech.isFlipFlop || tech.isRelay
// }, // },
// requires: "ON/OFF tech", // requires: "ON/OFF tech",
// effect() { // effect() {
// tech.isFlipFlopCoupling = true; // tech.isFlipFlopDamage = true;
// if (tech.isFlipFlopOn) {
// m.couplingChange(this.bonus)
// } else {
// for (let i = 0; i < mob.length; i++) {
// if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// }
// spawn.WIMP()
// mob[mob.length - 1].isDecoupling = true //so you can find it to remove
// }
// }, // },
// remove() { // remove() {
// tech.isFlipFlopCoupling = false; // tech.isFlipFlopDamage = false;
// if (this.count) { // }
// if (tech.isFlipFlop || tech.isRelay) { // },
// if (tech.isFlipFlopOn) { // {
// m.couplingChange(-this.bonus) // name: "integrated circuit",
// } else { // description: "if <strong class='color-flop'>ON</strong> <strong>+7</strong> power up <strong>choices</strong><br>if <strong class='color-flop'>OFF</strong> <strong>-1</strong> power up <strong>choices</strong>",
// for (let i = 0; i < mob.length; i++) { // maxCount: 1,
// if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP // count: 0,
// } // frequency: 3,
// } // frequencyDefault: 3,
// } // allowed() {
// } // return (tech.isFlipFlop || tech.isRelay) && !tech.isDeterminism
// },
// requires: "ON/OFF tech, not determinism",
// effect() {
// tech.isFlipFlopChoices = true //do you have this tech
// },
// remove() {
// tech.isFlipFlopChoices = false
// }
// },
// {
// name: "transistor",
// description: "if <strong class='color-flop'>ON</strong> generate <strong>+20</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>-1</strong> <strong class='color-f'>energy</strong> per second",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isFlipFlop || tech.isRelay
// },
// requires: "ON/OFF tech",
// effect() {
// tech.isFlipFlopEnergy = true;
// },
// remove() {
// tech.isFlipFlopEnergy = false;
// }
// },
// // {
// // name: "decoupling",
// // link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Decoupling_(cosmology)' class="link">decoupling</a>`,
// // descriptionFunction() {
// // //<span style = 'font-size:80%;'>(${ m.couplingDescription(this.bonus)})</span>
// // return `if <strong class='color-flop'>ON</strong> <strong>+5</strong> <strong class='color-coupling'>coupling</strong><br>if <strong class='color-flop'>OFF</strong> a dangerous particle slowly <strong>chases</strong> you`
// // },
// // maxCount: 1,
// // count: 0,
// // frequency: 3,
// // frequencyDefault: 3,
// // bonus: 5, //coupling given
// // allowed() {
// // return tech.isFlipFlop || tech.isRelay
// // },
// // requires: "ON/OFF tech",
// // effect() {
// // tech.isFlipFlopCoupling = true;
// // if (tech.isFlipFlopOn) {
// // m.couplingChange(this.bonus)
// // } else {
// // for (let i = 0; i < mob.length; i++) {
// // if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// // }
// // spawn.WIMP()
// // mob[mob.length - 1].isDecoupling = true //so you can find it to remove
// // }
// // },
// // remove() {
// // tech.isFlipFlopCoupling = false;
// // if (this.count) {
// // if (tech.isFlipFlop || tech.isRelay) {
// // if (tech.isFlipFlopOn) {
// // m.couplingChange(-this.bonus)
// // } else {
// // for (let i = 0; i < mob.length; i++) {
// // if (mob[i].isDecoupling) mob[i].alive = false //remove WIMP
// // }
// // }
// // }
// // }
// // }
// // },
// {
// name: "relay switch",
// description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after picking up a <strong>power up</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
// // nameInfo: "<span id = 'tech-switch'></span>",
// // addNameInfo() {
// // setTimeout(function () {
// // if (document.getElementById("tech-switch")) {
// // if (tech.isFlipFlopOn) {
// // document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
// // m.eyeFillColor = m.fieldMeterColor //'#5af'
// // } else {
// // document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
// // m.eyeFillColor = "transparent"
// // }
// // }
// // }, 100);
// // },
// maxCount: 1,
// count: 0,
// frequency: 1,
// frequencyDefault: 1,
// allowed() {
// return !tech.isFlipFlop
// },
// requires: "not flip-flop",
// effect() {
// m.isAltSkin = true
// tech.isRelay = true //do you have this tech?
// if (!tech.isFlipFlopOn) {
// tech.isFlipFlopOn = true //what is the state of flip-Flop?
// }
// // if (!m.isShipMode) {
// // m.skin.flipFlop()
// // }
// },
// remove() {
// tech.isRelay = false
// if (tech.isFlipFlopOn) {
// tech.isFlipFlopOn = false //what is the state of flip-Flop?
// }
// m.eyeFillColor = 'transparent'
// // m.resetSkin();
// }
// },
// {
// name: "lithium-ion",
// description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br><strong>+300</strong> maximum <strong class='color-f'>energy</strong>",
// maxCount: 1,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isRelay
// },
// requires: "relay switch",
// effect() {
// tech.isRelayEnergy = true
// m.setMaxEnergy()
// },
// remove() {
// tech.isRelayEnergy = false
// m.setMaxEnergy()
// }
// },
// {
// name: "thermocouple",
// description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals per second",
// maxCount: 9,
// count: 0,
// frequency: 3,
// frequencyDefault: 3,
// allowed() {
// return tech.isRelay
// },
// requires: "relay switch",
// effect() {
// tech.relayIce++
// },
// remove() {
// tech.relayIce = 0
// } // }
// }, // },
{
name: "relay switch",
description: `toggle <strong class="color-flop">ON</strong> and <strong class="color-flop">OFF</strong> after picking up a <strong>power up</strong><br>unlock advanced <strong class='color-m'>tech</strong> that runs if <strong class="color-flop">ON</strong>`,
nameInfo: "<span id = 'tech-switch'></span>",
addNameInfo() {
setTimeout(function () {
if (document.getElementById("tech-switch")) {
if (tech.isFlipFlopOn) {
document.getElementById("tech-switch").innerHTML = ` = <strong>ON</strong>`
m.eyeFillColor = m.fieldMeterColor //'#5af'
} else {
document.getElementById("tech-switch").innerHTML = ` = <strong>OFF</strong>`
m.eyeFillColor = "transparent"
}
}
}, 100);
},
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
return !tech.isFlipFlop
},
requires: "not flip-flop",
effect() {
m.isAltSkin = true
tech.isRelay = true //do you have this tech?
if (!tech.isFlipFlopOn) {
tech.isFlipFlopOn = true //what is the state of flip-Flop?
}
// if (!m.isShipMode) {
// m.skin.flipFlop()
// }
},
remove() {
tech.isRelay = false
if (tech.isFlipFlopOn) {
tech.isFlipFlopOn = false //what is the state of flip-Flop?
}
m.eyeFillColor = 'transparent'
// m.resetSkin();
}
},
{
name: "lithium-ion",
description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br><strong>+300</strong> maximum <strong class='color-f'>energy</strong>",
maxCount: 1,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isRelay
},
requires: "relay switch",
effect() {
tech.isRelayEnergy = true
m.setMaxEnergy()
},
remove() {
tech.isRelayEnergy = false
m.setMaxEnergy()
}
},
{
name: "thermocouple",
description: "if <strong>relay switch</strong> is <strong class='color-flop'>ON</strong><br>condense <strong>4-13</strong> <strong class='color-s'>ice IX</strong> crystals per second",
maxCount: 9,
count: 0,
frequency: 3,
frequencyDefault: 3,
allowed() {
return tech.isRelay
},
requires: "relay switch",
effect() {
tech.relayIce++
},
remove() {
tech.relayIce = 0
}
},
{ {
name: "first derivative", name: "first derivative",
descriptionFunction() { descriptionFunction() {
@@ -3421,6 +3421,7 @@ const tech = {
effect() { effect() {
tech.isHealAttract = true tech.isHealAttract = true
powerUps.setPowerUpMode(); powerUps.setPowerUpMode();
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
}, },
remove() { remove() {
tech.isHealAttract = false tech.isHealAttract = false
@@ -3515,12 +3516,12 @@ const tech = {
}, },
{ {
name: "anthropic principle", name: "anthropic principle",
nameInfo: "<span id = 'tech-anthropic'></span>", // nameInfo: "<span id = 'tech-anthropic'></span>",
addNameInfo() { // addNameInfo() {
setTimeout(function () { // setTimeout(function () {
powerUps.research.changeRerolls(0) // powerUps.research.changeRerolls(0)
}, 1000); // }, 1000);
}, // },
descriptionFunction() { descriptionFunction() {
return `once per level, instead of <strong>dying</strong><br>use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}` return `once per level, instead of <strong>dying</strong><br>use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}`
}, },
@@ -3871,9 +3872,12 @@ const tech = {
requires: "not determinism", requires: "not determinism",
effect() { effect() {
tech.isExtraGunField = true; tech.isExtraGunField = true;
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.05);
}, },
remove() { remove() {
tech.isExtraGunField = false; tech.isExtraGunField = false;
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -3936,7 +3940,7 @@ const tech = {
isBadRandomOption: true, isBadRandomOption: true,
isInstant: true, isInstant: true,
allowed() { allowed() {
return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices && !tech.isExtraBotOption return !tech.extraChoices && !tech.isExtraGunField && !tech.isExtraBotOption
}, },
requires: "not emergence, cross-disciplinary, integrated circuit", requires: "not emergence, cross-disciplinary, integrated circuit",
effect() { effect() {
@@ -4106,9 +4110,13 @@ const tech = {
requires: "", requires: "",
effect() { effect() {
tech.isMassProduction = true tech.isMassProduction = true
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
}, },
remove() { remove() {
tech.isMassProduction = false tech.isMassProduction = false
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -4307,7 +4315,7 @@ const tech = {
name: "residual dipolar coupling", name: "residual dipolar coupling",
descriptionFunction() { descriptionFunction() {
// return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns ${powerUps.orb.coupling(5)}that each give <strong>+0.1</strong> <strong class='color-coupling'>coupling</strong>`//<br>${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per <strong class='color-coupling'>coupling</strong>"} // return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns ${powerUps.orb.coupling(5)}that each give <strong>+0.1</strong> <strong class='color-coupling'>coupling</strong>`//<br>${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per <strong class='color-coupling'>coupling</strong>"}
return `clicking <strong class='color-cancel'>cancel</strong> spawns ${powerUps.orb.coupling(8)}<br><em>${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}</em>` return `clicking <strong class='color-cancel'>cancel</strong> spawns ${powerUps.orb.coupling(7)}<br><em>${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4327,7 +4335,7 @@ const tech = {
{ {
name: "commodities exchange", name: "commodities exchange",
descriptionFunction() { descriptionFunction() {
return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>10-14</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}` return `clicking <strong class='color-cancel'>cancel</strong> for a <strong class='color-f'>field</strong>, <strong class='color-m'>tech</strong>, or <strong class='color-g'>gun</strong><br>spawns <strong>8-12</strong> ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4382,7 +4390,7 @@ const tech = {
}, },
remove() { remove() {
tech.isCancelDuplication = false tech.isCancelDuplication = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -4430,13 +4438,13 @@ const tech = {
}, },
remove() { remove() {
tech.isPowerUpsVanish = false tech.isPowerUpsVanish = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance }
} }
}, },
{ {
name: "correlated damage", name: "correlated damage",
descriptionFunction() { descriptionFunction() {
return `<strong class='color-dup'>duplication</strong> increases <strong class='color-d'>damage</strong> by the same percent<br><em>(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)</em>` return `<strong class='color-dup'>duplication</strong> increases <strong class='color-d'>damage</strong><br><em>(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4467,9 +4475,11 @@ const tech = {
effect() { effect() {
tech.isDuplicateMobs = true; tech.isDuplicateMobs = true;
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.08);
}, },
remove() { remove() {
tech.isDuplicateMobs = false; tech.isDuplicateMobs = false;
if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -4506,11 +4516,11 @@ const tech = {
effect() { effect() {
tech.isStimulatedEmission = true tech.isStimulatedEmission = true
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.15); if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.20);
}, },
remove() { remove() {
tech.isStimulatedEmission = false tech.isStimulatedEmission = false
powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -4536,6 +4546,7 @@ const tech = {
if (this.count > 0 && m.alive) { if (this.count > 0 && m.alive) {
tech.duplication += 0.11 tech.duplication += 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
tech.damage /= this.damage tech.damage /= this.damage
this.frequency = 0 this.frequency = 0
} }
@@ -4684,7 +4695,7 @@ const tech = {
{ {
name: "paradigm shift", name: "paradigm shift",
descriptionFunction() { descriptionFunction() {
return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>4</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} each time` return `when <strong>paused</strong> clicking a <strong class='color-m'>tech</strong> <span class='color-remove'>ejects</span> it<br><strong>${tech.pauseEjectTech.toFixed(1)}</strong> ${tech.isEnergyHealth ? "<strong class='color-f'>energy</strong>" : "<strong class='color-h'>health</strong>"} cost <em>(1.2x cost each use)</em>`
}, },
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -4699,6 +4710,7 @@ const tech = {
}, },
remove() { remove() {
tech.isPauseEjectTech = false; tech.isPauseEjectTech = false;
} }
}, },
{ {
@@ -5332,7 +5344,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
}, },
requires: "a freeze effect", requires: "a freeze effect",
effect() { effect() {
@@ -5351,7 +5363,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))
}, },
requires: "a freeze effect", requires: "a freeze effect",
effect() { effect() {
@@ -5370,7 +5382,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) && !tech.sporesOnDeath && !tech.isExplodeMob && !tech.botSpawner && !tech.isMobBlockFling && !tech.nailsDeathMob
}, },
requires: "a localized freeze effect, no other mob death tech", requires: "a localized freeze effect, no other mob death tech",
effect() { effect() {
@@ -5389,7 +5401,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot return (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
}, },
requires: "ice IX", requires: "ice IX",
effect() { effect() {
@@ -5408,7 +5420,7 @@ const tech = {
frequency: 2, frequency: 2,
frequencyDefault: 2, frequencyDefault: 2,
allowed() { allowed() {
return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot return tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)) || tech.iceIXOnDeath || tech.isIceShot
}, },
requires: "a localized freeze effect", requires: "a localized freeze effect",
effect() { effect() {
@@ -5433,7 +5445,7 @@ const tech = {
// }, // },
// requires: "perfect diamagnetism", // requires: "perfect diamagnetism",
allowed() { allowed() {
return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.relayIce || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0))) return (tech.isIceCrystals || tech.isSporeFreeze || (m.fieldMode === 4 && simulation.molecularMode === 2) || tech.isIceShot || tech.isNeedleIce || (m.coupling && (m.fieldMode === 3 || m.fieldMode === 0)))
}, },
requires: "a localized freeze effect", requires: "a localized freeze effect",
effect() { effect() {
@@ -5485,7 +5497,7 @@ const tech = {
}, },
{ {
name: "Zectron", name: "Zectron",
description: `<strong>2x</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-5</strong> <strong class='color-f'>energy</strong>`, description: `<strong>2x</strong> <strong>super ball</strong> density and <strong class='color-d'>damage</strong>, but<br>after colliding with <strong>super balls</strong> <strong>-4</strong> <strong class='color-f'>energy</strong>`,
isGunTech: true, isGunTech: true,
maxCount: 1, maxCount: 1,
count: 0, count: 0,
@@ -5630,7 +5642,7 @@ const tech = {
tech.wavePacketDamage *= 1.4 tech.wavePacketDamage *= 1.4
}, },
remove() { remove() {
tech.waveFrequency = 0.2 tech.waveFrequency = 0.2 //adjust this to make the waves much larger
tech.wavePacketDamage = 1 tech.wavePacketDamage = 1
} }
}, },
@@ -8549,7 +8561,7 @@ const tech = {
}, },
remove() { remove() {
tech.cloakDuplication = 0 tech.cloakDuplication = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
} }
}, },
{ {
@@ -8719,7 +8731,7 @@ const tech = {
}, },
remove() { remove() {
tech.fieldDuplicate = 0 tech.fieldDuplicate = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (this.count > 0) powerUps.research.changeRerolls(3) if (this.count > 0) powerUps.research.changeRerolls(3)
} }
}, },
@@ -10964,6 +10976,25 @@ const tech = {
if (this.count) m.resetSkin(); if (this.count) m.resetSkin();
} }
}, },
{
name: "wall jump",
description: "jump on walls",
maxCount: 1,
count: 0,
frequency: 0,
isJunk: true,
allowed() {
return !m.isShipMode
},
requires: "",
effect() {
jumpSensor.vertices[0].x += -22
jumpSensor.vertices[3].x += -22
jumpSensor.vertices[1].x += 22
jumpSensor.vertices[2].x += 22
},
remove() { }
},
{ {
name: "posture", name: "posture",
description: "stand a bit taller", description: "stand a bit taller",
@@ -11935,6 +11966,7 @@ const tech = {
isExplodeRadio: null, isExplodeRadio: null,
isPauseSwitchField: null, isPauseSwitchField: null,
isPauseEjectTech: null, isPauseEjectTech: null,
pauseEjectTech: null,
isShieldPierce: null, isShieldPierce: null,
isDuplicateMobs: null, isDuplicateMobs: null,
is100Duplicate: null, is100Duplicate: null,
@@ -11945,15 +11977,6 @@ const tech = {
isSwitchReality: null, isSwitchReality: null,
isResearchReality: null, isResearchReality: null,
isAnthropicDamage: null, isAnthropicDamage: null,
isFlipFlop: null,
isFlipFlopHarm: null,
isFlipFlopOn: null,
// isFlipFlopLevelReset: null,
isFlipFlopDamage: null,
isFlipFlopEnergy: null,
isFlipFlopChoices: null,
isRelay: null,
relayIce: null,
isMetaAnalysis: null, isMetaAnalysis: null,
isFoamAttract: null, isFoamAttract: null,
droneCycleReduction: null, droneCycleReduction: null,
@@ -12046,8 +12069,6 @@ const tech = {
isTechDebt: null, isTechDebt: null,
isPlasmaBall: null, isPlasmaBall: null,
plasmaDischarge: null, plasmaDischarge: null,
isFlipFlopHealth: null,
isRelayEnergy: null,
coyoteTime: null, coyoteTime: null,
missileFireCD: null, missileFireCD: null,
isBotField: null, isBotField: null,

107
todo.txt
View File

@@ -1,31 +1,76 @@
******************************************************** NEXT PATCH ************************************************** ******************************************************** NEXT PATCH **************************************************
adjusted text and math for the fire rate system to use the new "x" syntax newLevel - towers
tech search is no longer case sensitive please give feedback
boost level elements can now be pointed at any angle
Zectron 1.9->2x damage, -25% -> -5 energy paradigm shift costs 1 health, but cost increases after each use
exothermic process -20% -> -5 energy 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
instant/unRemovable tech has a unique icon and no longer shows up in the tech list removed all ON/OFF tech
marginal utility - no longer spawns ammo I just don't think they are fun
heuristics - no longer spawn a gun, 1.2->1.3 fire rate
open-source - gives 1 extra bot option and 3x bot tech frequency JUNK tech - wall jump
robotics - now just spawns 2 bots
induction brake - doesn't spawn heals, but lasts 15->17 seconds fixed some bugs
accretion - doesn't spawn heals, but gets 3% duplication
mass production - doesn't spawn power ups, but gets 3% duplication player damage reduction adjustment: 0.9x -> 0.89x per level per difficulty mode (1,2,4,5)
Ψ(t) collapse - doesn't spawn research, spawns 5 research from bosses on easy that's 0.28 -> 0.245 by level 12 (a 12% player damage nerf)
decoherence - doesn't spawn research, spawns 2 research from bosses on why a 50% player damage nerf by level 12
fine-structure constant - doesn't spawn coupling, spawn 9 coupling from bosses
Bayesian statistics - 1.03->1.05x damage, doesn't spawn research
Born rule code rewritten, but it should have a similar effect as before
triple point - 1.5->5 second freeze, but no coupling spawn
geodesics - no longer spawns ammo and guns, but gives 1.5x damage
ideal gas law - doesn't remove ammo, 12->6x foam ammo per ammo power up
*********************************************************** TODO ***************************************************** *********************************************************** TODO *****************************************************
increase difficulty
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.
flip player upside down
how
rotate player in matter.js
make sure floor sensor works
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
become immune to damage taken for 5 seconds
summon JUNK bots for 10 seconds
2x current energy
gain 1.01x damage permanently
field tech: negative mass - quickly pull/teleport in all nearby blocks and then fire them away from player
what triggers effect?
auto aim blocks?
after picking up heals gain ____
0.1x damage taken for 12s
after picking up ammo gain ____
4x fire rate for 12s
after picking up research gain ____
+10 choices for 12s
tech: Energy generation increases with you velocity
Newtons' 3rd law?
after clicking on a new tech (or getting it in any way) animate adding the tech to your collection after clicking on a new tech (or getting it in any way) animate adding the tech to your collection
fade in on right side text list?
tech - getting caught in an explosion gives you _____ tech - getting caught in an explosion gives you _____
damage for 10 seconds? damage for 10 seconds?
@@ -52,14 +97,6 @@ make sure healing isn't effected by simulation.healScale
tech - destroys a random tech each new level and gains +damage each time tech - destroys a random tech each new level and gains +damage each time
List of ways to break the game
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?
boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires boss - tracks the position, velocity, angle of power ups, blocks, and bullets it fires
reactor only? reactor only?
will rewind time will rewind time
@@ -1182,8 +1219,20 @@ possible names for tech
retrovirus: these things make JUNK DNA so link it somehow to that tech? retrovirus: these things make JUNK DNA so link it somehow to that 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 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. amalgam, amalgamation - the action, process, or result of combining or uniting.
thermoplastic - the stuff in 3-D printers, use for molecular assembler tech
******************************************************** CARS IMAGES ******************************************************** ******************************************************** 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?
******************************************************** IMAGES ********************************************************
process: discord midjourney prompts -> "pixelmator pro" adjust color, repair, scale to 384x256, export PNG -> webP? -> place in /img folder process: discord midjourney prompts -> "pixelmator pro" adjust color, repair, scale to 384x256, export PNG -> webP? -> place in /img folder
make n-gon a progressive web app to manage image downloads, cache make n-gon a progressive web app to manage image downloads, cache