diff --git a/img/hyperpolarization.webp b/img/repolarization.webp
similarity index 100%
rename from img/hyperpolarization.webp
rename to img/repolarization.webp
diff --git a/js/bullet.js b/js/bullet.js
index e0af122..40bcd84 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -3790,7 +3790,7 @@ const b = {
this.force.y += this.mass * 0.001;
if (Matter.Query.collides(this, [player]).length) {
this.endCycle = 0
- m.energy -= 0.05
+ m.energy -= 0.04
if (m.energy < 0) m.energy = 0
simulation.drawList.push({ //add dmg to draw queue
x: this.position.x,
@@ -3828,8 +3828,8 @@ const b = {
if (!who.isInvulnerable) {
if (tech.oneSuperBall) mobs.statusStun(who, 120) // (2.3) * 2 / 14 ticks (2x damage over 7 seconds)
if (tech.isFoamBall) {
- for (let i = 0, len = 5 * this.mass; i < len; i++) {
- const radius = 5 + 8 * Math.random()
+ for (let i = 0, len = 6 * this.mass; i < len; i++) {
+ const radius = 6 + 9 * Math.random()
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)
}
diff --git a/js/engine.js b/js/engine.js
index 4e873b1..9a628ee 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -113,32 +113,7 @@ function collisionChecks(event) {
m.damage(dmg);
return
}
- if (tech.isFlipFlop) {
- if (tech.isFlipFlopOn) {
- tech.isFlipFlopOn = false
- if (document.getElementById("tech-flip-flop")) document.getElementById("tech-flip-flop").innerHTML = ` = OFF`
- 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 = ` = ON`
- 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
- }
+ m.damage(dmg); //normal damage
if (tech.isCollisionRealitySwitch && m.alive) {
m.switchWorlds()
diff --git a/js/index.js b/js/index.js
index 2ca3580..c19e3ba 100644
--- a/js/index.js
+++ b/js/index.js
@@ -1430,7 +1430,7 @@ window.addEventListener("keydown", function (event) {
simulation.loop = simulation.normalLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'none'
simulation.makeTextLog("", 0);
- } else { //if (keys[191])
+ } else {
simulation.testing = true;
simulation.loop = simulation.testingLoop
if (simulation.isConstructionMode) document.getElementById("construct").style.display = 'inline'
diff --git a/js/level.js b/js/level.js
index af98f4d..b1920d4 100644
--- a/js/level.js
+++ b/js/level.js
@@ -4,13 +4,12 @@ let cons = []; //all constraints between a point and a body
let consBB = []; //all constraints between two bodies
let composite = [] //rotors and other map elements that don't fit
const level = {
- isEndlessFall: false,
+ fallMode: "",
defaultZoom: 1400,
onLevel: -1,
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
- 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"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
@@ -42,9 +41,9 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("optical amplifier") });
// for (let i = 0; i < 1; ++i) tech.giveTech("combinatorial optimization")
// tech.giveTech("Pareto efficiency")
- // for (let i = 0; i < 1; ++i) tech.giveTech("Higgs mechanism")
- // for (let i = 0; i < 1; ++i) tech.giveTech("active cooling")
- // for (let i = 0; i < 1; ++i) tech.giveTech("heuristics")
+ for (let i = 0; i < 1; ++i) tech.giveTech("collider")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("anthropic principle")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("bubble fusion")
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("ersatz bots") });
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
@@ -55,13 +54,13 @@ const level = {
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// 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
- // level.testing();
+ // level.towers();
// for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500)
// Matter.Body.setPosition(player, { x: -200, y: -3330 });
// for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random())
// for (let i = 0; i < 1; ++i) spawn.stinger(1900, -500)
- // for (let i = 0; i < 1; ++i) spawn.dragonFlyBoss(1900, -500)
+ // for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// spawn.beetleBoss(1900, -500, 25)
// 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())
@@ -78,7 +77,9 @@ const level = {
// simulation.isAutoZoom = false; //look in close
// simulation.zoomScale *= 0.5;
// 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 < 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);
@@ -137,15 +138,7 @@ const level = {
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)
}
- // 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 = true`);
- }
- // if (m.plasmaBall) m.plasmaBall.reset()
+
if (m.plasmaBall) m.plasmaBall.fire()
if (localSettings.entanglement && localSettings.entanglement.levelName === level.levels[level.onLevel]) {
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") {
const ammoPerOrb = b.guns[b.activeGun].ammoPack
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)}% interest on ammo = ${a > 20 ? a + powerUps.orb.ammo(1) : powerUps.orb.ammo(a)}`)
}
if (powerUps.research.count > 0) {
const r = Math.ceil(rate * powerUps.research.count)
simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on research = ${r > 20 ? r + powerUps.orb.research(1) : powerUps.orb.research(r)}`)
- powerUps.spawnDelay("research", r);
+ powerUps.spawnDelay("research", r, 4);
}
if (m.coupling > 0) {
const c = Math.ceil(rate * m.coupling)
- powerUps.spawnDelay("coupling", c);
+ powerUps.spawnDelay("coupling", c, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on coupling = ${c > 20 ? c + powerUps.orb.coupling(1) : powerUps.orb.coupling(c)}`)
}
-
const healPerOrb = (powerUps.heal.size() / 40 / (simulation.healScale ** 0.25)) ** 2
const h = Math.ceil(rate * m.health / healPerOrb)
- powerUps.spawnDelay("heal", h);
+ powerUps.spawnDelay("heal", h, 4);
simulation.makeTextLog(`${(rate * 100).toFixed(0)}% interest on health = ${h > 20 ? h + powerUps.orb.heal(1) : powerUps.orb.heal(h)}`)
// trying to spawn smaller heals
@@ -230,7 +222,7 @@ const level = {
difficultyIncrease(num = 1) {
for (let i = 0; i < num; i++) {
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.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()
for (let i = 0; i < num; i++) {
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.CDScale < 1) simulation.CDScale /= 0.964 //mob CD time decreases each level
}
@@ -801,65 +793,147 @@ const level = {
return who
},
- boost(x, y, height = 1000) { //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"), {
- 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
+ boost(x, y, height = 1000, angle = Math.PI / 2) { //height is how high the player will be flung above y
+ if (angle !== Math.PI / 2) { //angle !== 3 * Math.PI / 2
+ angle *= -1
+ who = map[map.length] = Matter.Bodies.fromVertices(x + 50, y + 35, Vertices.fromPath("80 40 -80 40 -50 -40 50 -40"), {
+ 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
},
- 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
- });
+ yVelocity: 1.21 * Math.sqrt(Math.abs(height)),
+ query() {
+ // check for collisions
+ const rayVector = Vector.add(this.position, Vector.rotate({ x: 100, y: 0 }, angle))
+ query = (who) => {
+ const list = Matter.Query.ray(who, this.position, rayVector, 100)
+ if (list.length > 0) {
+ Matter.Body.setVelocity(list[0].bodyA, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
+ }
}
- }
- 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
- });
+ query(body)
+ query(mob)
+ query(bullet)
+ query(powerUp)
+ //player collision
+ const list = Matter.Query.ray([player], this.position, rayVector, 100)
+ if (list.length > 0) {
+ Matter.Body.setVelocity(player, Vector.rotate({ x: this.yVelocity, y: 0 }, angle));
+ m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
+ m.hardLandCD = 0 // disable hard landing
}
- }
- //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
+
+ // if (Matter.Query.region([player], this.boostBounds).length > 0 && !input.down) {
+ // m.buttonCD_jump = 0; // reset short jump counter to prevent short jumps on boosts
+ // m.hardLandCD = 0 // disable hard landing
+ // if (player.velocity.y > 26) {
+ // Matter.Body.setVelocity(player, {
+ // x: player.velocity.x,
+ // y: -15 //gentle bounce if coming down super fast
+ // });
+ // } else {
+ // Matter.Body.setVelocity(player, {
+ // x: player.velocity.x + (Math.random() - 0.5) * 2.5,
+ // y: this.yVelocity //give a upwards velocity that will put the player that the height desired
+ // });
+ // }
+ // }
+
+ //draw
+ const v1 = this.vertices[0]
+ const v2 = this.vertices[1]
+ let unit = Vector.rotate({ x: 60, y: 0 }, angle)
+ let v3 = Vector.add(v2, unit)
+ let v4 = Vector.add(v1, unit)
+ // ctx.beginPath();
+ // ctx.strokeStyle = "#000";
+ // ctx.stroke()
+ ctx.beginPath();
+ ctx.moveTo(v1.x, v1.y)
+ ctx.lineTo(v2.x, v2.y)
+ 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 = {
up: 0.01,
@@ -2570,27 +2644,6 @@ const level = {
ctx.fillStyle = "#ccc"
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
ctx.fillStyle = "#f2f2f2"
ctx.fillRect(2600, -600, 400, 300)
@@ -4198,6 +4251,250 @@ const level = {
// if (simulation.difficulty > 1) spawn.randomLevelBoss(2200, -1300);
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() {
level.announceMobTypes()
// 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
level.defaultZoom = 1500
simulation.zoomTransition(level.defaultZoom)
- document.body.style.backgroundColor = "#d0d2d4s";
+ document.body.style.backgroundColor = "#d0d2d4";
// color.map = "#262a2f"
let isPowerLeft = true
const movers = []
@@ -5596,7 +5893,7 @@ const level = {
},
pavilion() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
const vanish = []
level.exit.x = -850;
level.exit.y = -1485;
@@ -6449,7 +6746,7 @@ const level = {
},
satellite() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
const boost1 = level.boost(5825, 235, 1400)
const elevator = level.elevator(4210, -1265, 380, 50, -3450) //, 0.003, { up: 0.01, down: 0.2 }
level.custom = () => {
@@ -6626,7 +6923,7 @@ const level = {
},
rooftops() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
// level.fallPosition = { x: 5000, y:-4000}
const elevator = level.elevator(1450, -990, 235, 45, -2000)
const boost1 = level.boost(4950, 0, 1100)
@@ -6635,7 +6932,6 @@ const level = {
boost1.query();
elevator.move();
elevator.drawTrack();
-
ctx.fillStyle = "#d4f4f4"
if (isBackwards) {
ctx.fillRect(-650, -2300, 440, 300)
@@ -6643,7 +6939,6 @@ const level = {
ctx.fillRect(3460, -700, 1090, 800)
}
level.exit.drawAndCheck();
-
level.enter.draw();
};
@@ -6815,7 +7110,7 @@ const level = {
},
aerie() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
const boost1 = level.boost(-425, 100, 1400)
const boost2 = level.boost(5350, 275, 2850);
@@ -7045,7 +7340,7 @@ const level = {
},
skyscrapers() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
const boost1 = level.boost(475, 0, 1300)
const boost2 = level.boost(4450, 0, 1300);
level.custom = () => {
@@ -7184,11 +7479,8 @@ const level = {
},
highrise() {
level.announceMobTypes()
- level.isEndlessFall = true;
- 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 }) {
+ level.fallMode = "start";
+ 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 }) {
elevator1.addConstraint();
// const button1 = level.button(-500, -200)
const toggle1 = level.toggle(-300, -200) //(x,y,isOn,isLockOn = true/false)
@@ -7470,7 +7762,7 @@ const level = {
},
warehouse() {
level.announceMobTypes()
- level.isEndlessFall = true;
+ level.fallMode = "start";
level.custom = () => {
ctx.fillStyle = "#444" //light fixtures
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) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1];
@@ -27207,7 +27499,6 @@ const level = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
- me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -27229,6 +27520,12 @@ const level = {
me.shieldTargetID = target.id
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
me.onDeath = function () {
//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) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(255,255,255,0.9)");
let me = mob[mob.length - 1];
@@ -28475,7 +28772,6 @@ const level = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
- me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -28497,6 +28793,12 @@ const level = {
me.shieldTargetID = target.id
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
me.onDeath = function () {
//clear isShielded status from target
diff --git a/js/mob.js b/js/mob.js
index a284886..40ab68c 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -1161,6 +1161,7 @@ const mobs = {
this.onDeath(this); //custom death effects
this.removeConsBB();
this.alive = false; //triggers mob removal in mob[i].replace(i)
+ console.log(this.shieldCount)
if (this.isDropPowerUp) {
// if (true) {
@@ -1306,7 +1307,7 @@ const mobs = {
tech.cloakDuplication -= 0.01
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"
if (Math.random() < 0.4) {
type = "heal"
diff --git a/js/player.js b/js/player.js
index 66d2136..038d93a 100644
--- a/js/player.js
+++ b/js/player.js
@@ -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 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);
- 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
sleepThreshold: 99999999999,
isSensor: true
@@ -545,7 +545,7 @@ const m = {
},
baseHealth: 1,
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`
if (isMessage) simulation.makeTextLog(`m.maxHealth = ${m.maxHealth.toFixed(2)}`)
if (m.health > m.maxHealth) m.health = m.maxHealth;
@@ -2178,7 +2178,7 @@ const m = {
}
},
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(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`)
},
fieldMeterColor: "#0cf",
diff --git a/js/powerup.js b/js/powerup.js
index e777344..f9d4ac2 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -247,12 +247,14 @@ const powerUps = {
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
b.explosion(powerUp[i].position, 175 + (11 + 3 * Math.random()) * powerUp[i].size);
- Matter.Composite.remove(engine.world, powerUp[i]);
- powerUp.splice(i, 1);
+ if (powerUp[i]) {
+ Matter.Composite.remove(engine.world, powerUp[i]);
+ powerUp.splice(i, 1);
+ }
break
}
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 path = { x: powerUp[i].position.x + unit.x, y: powerUp[i].position.y + unit.y }
ctx.beginPath();
@@ -328,7 +330,7 @@ const powerUps = {
simulation.circleFlare(value);
}
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
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) {
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);
}
}
- if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 8)
+ if (tech.isCancelCouple) powerUps.spawnDelay("coupling", 7)
if (tech.isCancelTech && tech.cancelTechCount === 0 && type !== "entanglement") {
tech.cancelTechCount++
// powerUps.research.use('tech')
@@ -524,7 +526,7 @@ const powerUps = {
name: "heal",
color: "#0eb",
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() {
if (!tech.isEnergyHealth && m.alive) {
@@ -819,30 +821,92 @@ const powerUps = {
${tech.tech[choose].name} ${techCountText}
${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}`
},
+ // 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 `
+ //
+ //
${tech.tech[choose].name} ${techCountText}
+ // ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
`
+ // },
+ // 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 `
+ //
+ //
${tech.tech[choose].name} ${techCountText}
+ // ${tech.tech[choose].descriptionFunction ? tech.tech[choose].descriptionFunction() : tech.tech[choose].description}
`
+ // },
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;
+ const url = `https://api.openverse.engineering/v1/images/?q=${tech.tech[choose].name}`;
fetch(url, { signal: AbortSignal.timeout(1000) }) //give up if it takes over 1 second
- .then((response) => response.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
+ .then((response) => response.json())
+ .then((responseJson) => {
+ if (responseJson.results.length > 0) {
+ const index = Math.floor(Math.random() * responseJson.results.length) //randomly choose from the images
+ tech.tech[choose].url = responseJson.results[index].url //store the url
document.getElementById(`junk-${choose}`).style.backgroundImage = `url('${tech.tech[choose].url}')` //make the url the background image
- } else 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 {
@@ -878,7 +942,6 @@ const powerUps = {
// console.log(options.length)
if (options.length > 0 || !tech.isSuperDeterminism) {
let totalChoices = Math.min(options.length, (tech.isDeterminism ? 1 : 2 + tech.extraChoices + 2 * (m.fieldMode === 8)))
- if (tech.isFlipFlopChoices) totalChoices += tech.isRelay ? (tech.isFlipFlopOn ? -1 : 7) : (tech.isFlipFlopOn ? 7 : -1) //flip the order for relay
function removeOption(index) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -940,8 +1003,6 @@ const powerUps = {
if (i !== m.fieldMode) options.push(i);
}
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) {
for (let i = 0; i < options.length; i++) {
if (options[i] === index) {
@@ -1016,7 +1077,6 @@ const powerUps = {
}
//set total choices
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
totalChoices = optionLengthNoDuplicates
if (tech.isBanish) { //when you run out of options eject banish
@@ -1214,7 +1274,7 @@ const powerUps = {
} else if (tech.tech[choose].isSkin) {
text += powerUps.skinTechText(choose, `powerUps.choose('tech',${choose})`)
} 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
text += powerUps.techText(choose, `powerUps.choose('tech',${choose})`)
}
@@ -1229,14 +1289,14 @@ const powerUps = {
}
},
},
- spawnDelay(type, count) {
- count *= 2
+ spawnDelay(type, count, delay = 2) {
+ count *= delay
let cycle = () => {
if (count > 0) {
if (m.alive) requestAnimationFrame(cycle);
if (!simulation.paused && !simulation.isChoosing) { //&& !(simulation.cycle % 2)
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) }
powerUps.spawn(where.x, where.y, type);
}
@@ -1256,18 +1316,6 @@ const powerUps = {
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 = ` = OFF`
- 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 = ` = ON`
- 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
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)
// } else {
// }
+ tech.tech[index].frequency = 0 //banish tech
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.animation = ""
document.getElementById(`${index}-pause-tech`).onclick = null
@@ -1478,15 +1528,9 @@ const powerUps = {
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);
- } else if (smallIndexes.length > 2 && Math.random() < 0.33) {
- // console.log("no big, at least 3 small can combine")
+
+ if (smallIndexes.length > 2 && Math.random() < 0.66) { // console.log("no big, at least 3 small can combine")
for (let j = 0; j < 3; j++) {
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") {
@@ -1499,8 +1543,13 @@ const powerUps = {
options = ["tech", "gun", "field"]
powerUps.directSpawn(where.x, where.y, options[Math.floor(Math.random() * options.length)], false)
- } else if (smallIndexes.length > 0) {
- // console.log("no big, at least 1 small will swap flavors")
+ } else if (bigIndexes.length > 0 && Math.random() < 0.5) { // console.log("at least 1 big can 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);
+ } else if (smallIndexes.length > 0) { // console.log("no big, at least 1 small will swap flavors")
const index = Math.floor(Math.random() * powerUp.length)
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)
diff --git a/js/simulation.js b/js/simulation.js
index 48a53d0..e1f05d2 100644
--- a/js/simulation.js
+++ b/js/simulation.js
@@ -184,7 +184,7 @@ const simulation = {
fpsCapDefault: 72, //use to change fpsCap back to normal after a hit from a mob
isCommunityMaps: false,
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
delta: 1000 / 60, //speed of game engine //looks like it has to be 16.6666 to match player input
buttonCD: 0,
@@ -435,10 +435,10 @@ const simulation = {
} else if (tech.tech[i].count > 0 && !tech.tech[i].isInstant) {
if (text) text += "
" //add a new line, but not on the first line
text += tech.tech[i].name
- if (tech.tech[i].nameInfo) {
- text += tech.tech[i].nameInfo
- tech.tech[i].addNameInfo();
- }
+ // if (tech.tech[i].nameInfo) {
+ // text += tech.tech[i].nameInfo
+ // tech.tech[i].addNameInfo();
+ // }
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%
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 (level.isEndlessFall) {
+ if (level.fallMode === "start") {
//infinite falling. teleport to sky after falling
simulation.ephemera.push({
@@ -957,7 +943,6 @@ const simulation = {
do() {
this.count--
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 > 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);
// 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));
- // 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 });
- }
+ if (bullet[i].botType) Matter.Body.setPosition(bullet[i], Vector.sub(bullet[i].position, change));
}
- } 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.setPosition(player, { x: level.enter.x + 50, y: level.enter.y - 20 });
// m.damage(0.02 * simulation.difficultyMode);
@@ -1049,7 +1057,7 @@ const simulation = {
do() {
if (Matter.Query.point(map, m.pos).length > 0 || Matter.Query.point(map, player.position).length > 0) {
this.count--
- // console.log('halp, stuck in map!', Matter.Query.point(map, m.pos))
+
if (this.count < 0) {
simulation.removeEphemera(this.name)
Matter.Body.setVelocity(player, { x: 0, y: 0 });
@@ -1116,7 +1124,7 @@ const simulation = {
clearNow: false,
clearMap() {
level.isProcedural = false;
- level.isEndlessFall = false;
+ level.fallMode = "";
ctx.setTransform(1, 0, 0, 1, 0, 0);
if (m.alive) {
if (tech.isLongitudinal) b.guns[3].waves = []; //empty array of wave bullets
@@ -1370,7 +1378,6 @@ const simulation = {
// window.getSelection().addRange(range);
// document.execCommand("copy");
// 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 = [];
for (const line of outerCollisions) {
for (const vertex of line) {
- // console.log('hi')
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 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 }
-
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 dx = Math.max(25, round(simulation.mouseInGame.x) - x)
const dy = Math.max(25, round(simulation.mouseInGame.y) - y)
- // console.log(e.button)
if (e.button === 1) {
if (level.isProcedural) {
simulation.outputMapString(`spawn.randomMob(x+${x}, ${y}, 0);\n`);
@@ -1965,8 +1965,8 @@ const simulation = {
});
//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
- if (simulation.testing && e.keyCode === 90 && simulation.constructMapString.length) {
+ document.body.addEventListener("keydown", (event) => { // e.keyCode z=90 m=77 b=66 shift = 16 c = 67
+ if (simulation.testing && event.code === "KeyZ" && simulation.constructMapString.length) {
if (simulation.constructMapString[simulation.constructMapString.length - 1][6] === 'm') { //remove map from current level
const index = map.length - 1
Matter.Composite.remove(engine.world, map[index]);
diff --git a/js/spawn.js b/js/spawn.js
index 885fee2..1ac4b8f 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -1691,6 +1691,7 @@ const spawn = {
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, "ammo");
+ powerUps.spawn(me.position.x, me.position.y, "ammo");
} else if (!m.isCloak) {
me.foundPlayer();
}
@@ -1698,7 +1699,7 @@ const spawn = {
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
- me.invulnerabilityCountDown = 25 + simulation.difficulty
+ me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
@@ -1713,10 +1714,7 @@ const spawn = {
if (vertices > 3) {
this.isDropPowerUp = false;
spawn.powerUpBossBaby(this.position.x, this.position.y, vertices - 1)
- Matter.Body.setVelocity(mob[mob.length - 1], {
- x: this.velocity.x,
- y: this.velocity.y
- })
+ Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
}
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.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");
} else if (!m.isCloak) {
me.foundPlayer();
}
- me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
- // me.isInvulnerable = true
- // me.startingDamageReduction = me.damageReduction
- // me.damageReduction = 0
- // me.invulnerabilityCountDown = 60 + simulation.difficulty * 2
+ me.damageReduction = 0.22 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.isInvulnerable = true
+ me.startingDamageReduction = me.damageReduction
+ me.damageReduction = 0
+ me.invulnerabilityCountDown = 30 + simulation.difficulty
me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) {
@@ -1794,10 +1793,7 @@ const spawn = {
if (vertices > 3) {
this.isDropPowerUp = false;
spawn.powerUpBoss(this.position.x, this.position.y, vertices - 1)
- Matter.Body.setVelocity(mob[mob.length - 1], {
- x: this.velocity.x,
- y: this.velocity.y
- })
+ Matter.Body.setVelocity(mob[mob.length - 1], { x: this.velocity.x, y: this.velocity.y })
}
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.do = function () {
this.stroke = `hsl(0,0%,${80 + 25 * Math.sin(simulation.cycle * 0.01)}%)`
- // if (this.isInvulnerable) {
- // if (this.invulnerabilityCountDown > 0) {
- // this.invulnerabilityCountDown--
- // ctx.beginPath();
- // let vertices = this.vertices;
- // ctx.moveTo(vertices[0].x, vertices[0].y);
- // for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
- // ctx.lineTo(vertices[0].x, vertices[0].y);
- // ctx.lineWidth = 20;
- // ctx.strokeStyle = "rgba(255,255,255,0.7)";
- // ctx.stroke();
- // } else {
- // this.isInvulnerable = false
- // this.damageReduction = this.startingDamageReduction
- // }
- // }
+ if (this.isInvulnerable) {
+ if (this.invulnerabilityCountDown > 0) {
+ this.invulnerabilityCountDown--
+ ctx.beginPath();
+ let vertices = this.vertices;
+ ctx.moveTo(vertices[0].x, vertices[0].y);
+ for (let j = 1; j < vertices.length; j++) ctx.lineTo(vertices[j].x, vertices[j].y);
+ ctx.lineTo(vertices[0].x, vertices[0].y);
+ ctx.lineWidth = 13 + 5 * Math.random();
+ ctx.strokeStyle = `rgba(255,255,255,${0.5 + 0.2 * Math.random()})`;
+ ctx.stroke();
+ } else {
+ this.isInvulnerable = false
+ this.damageReduction = this.startingDamageReduction
+ }
+ }
//steal all power ups
// for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
// 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)
const phase = (this.vertices.length + 1) * this.cycle / this.maxCycles
if (phase > 1) ctx.lineTo(this.vertices[0].x, this.vertices[0].y)
- for (let i = 1; i < phase - 1; i++) {
- ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
- }
+ for (let i = 1; i < phase - 1; i++) ctx.lineTo(this.vertices[i].x, this.vertices[i].y)
ctx.lineWidth = 5
ctx.strokeStyle = "rgb(255,255,255)"
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) {
mobs.spawn(x, y, 9, target.radius + 30, "rgba(220,220,255,0.9)");
let me = mob[mob.length - 1];
@@ -7593,7 +7587,6 @@ const spawn = {
me.shield = true;
me.damageReduction = 0.05 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
me.isUnblockable = true
- me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
me.collisionFilter.category = cat.mobShield
me.collisionFilter.mask = cat.bullet;
consBB[consBB.length] = Constraint.create({
@@ -7615,7 +7608,14 @@ const spawn = {
me.shieldTargetID = target.id
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
+
me.onDeath = function () {
//clear isShielded status from target
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
if (Math.random() < chance) {
body[body.length] = Bodies.rectangle(x + width / 2, y + height / 2, width, height, properties);
diff --git a/js/tech.js b/js/tech.js
index eb5b396..322b3cb 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -19,6 +19,7 @@ const tech = {
//remove lore if it's your first time playing since it's confusing
//also remove lore if cheating
tech.removeCount = 0;
+ tech.pauseEjectTech = 1; //used in paradigm shift
lore.techCount = 0;
if (simulation.isCheating || localSettings.runCount < 1) { //simulation.isCommunityMaps ||
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 (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.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.71828
if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance())
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() {
return `the damage from depolarization
resets 1.25 seconds sooner after a mob dies`
},
@@ -826,7 +826,7 @@ const tech = {
}
if (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(`tech.giveTech("${tech.tech[gunTechPool[index]].name}")`, 360)
// tech.tech[gunTechPool[index]].isInstant = true //makes it not remove properly under paradigm shift
tech.giveTech(gunTechPool[index]) // choose from the gun pool
@@ -1390,7 +1390,7 @@ const tech = {
},
{
name: "thermal runaway",
- description: "after mobs die
they explode",
+ description: "after mobs die they explode",
maxCount: 1,
count: 0,
frequency: 1,
@@ -1472,7 +1472,7 @@ const tech = {
{
name: "bubble fusion",
descriptionFunction() {
- return `after destroying a mob's natural shield
spawn 1-2 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
+ return `after destroying a mob's shield
spawn 1-2 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)} (once per mob)`
},
maxCount: 1,
count: 0,
@@ -2295,7 +2295,7 @@ const tech = {
},
{
name: "decorrelation",
- description: "if your gun or field are unused for 2 seconds
0.3x damage taken",
+ description: "if your gun and field are unused for 2 seconds
0.3x damage taken",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2313,7 +2313,7 @@ const tech = {
},
{
name: "anticorrelation",
- description: "if your gun or field are unused for 2 seconds
2x damage",
+ description: "if your gun and field are unused for 2 seconds
2x damage",
maxCount: 1,
count: 0,
frequency: 1,
@@ -2422,285 +2422,285 @@ const tech = {
tech.isBlockPowerUps = false
}
},
- {
- name: "NOR gate",
- description: "if flip-flop is OFF
become invulnerable 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 flip-flop is ON
+400 maximum health and 2x ${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: `flip-flop`,
- description: `toggle ON and OFF after a collision
unlock advanced tech that runs if ON`,
- nameInfo: "",
- addNameInfo() {
- setTimeout(function () {
- if (document.getElementById("tech-flip-flop")) {
- if (tech.isFlipFlopOn) {
- document.getElementById("tech-flip-flop").innerHTML = ` = ON`
- m.eyeFillColor = m.fieldMeterColor //'#5af'
- } else {
- document.getElementById("tech-flip-flop").innerHTML = ` = OFF`
- 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 ON
1.555x damage",
- 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 ON +7 power up choices
if OFF -1 power up choices",
- 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 ON generate +20 energy per second
if OFF drain -1 energy 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: `decoupling`,
+ // name: "NOR gate",
+ // description: "if flip-flop is OFF
become invulnerable 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() {
- // //(${ m.couplingDescription(this.bonus)})
- // return `if ON +5 coupling
if OFF a dangerous particle slowly chases you`
+ // return `if flip-flop is ON
+400 maximum health and 2x ${powerUps.orb.heal()} effect`
// },
// maxCount: 1,
// count: 0,
// frequency: 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: `flip-flop`,
+ // description: `toggle ON and OFF after a collision
unlock advanced tech that runs if ON`,
+ // // nameInfo: "",
+ // // addNameInfo() {
+ // // setTimeout(function () {
+ // // if (document.getElementById("tech-flip-flop")) {
+ // // if (tech.isFlipFlopOn) {
+ // // document.getElementById("tech-flip-flop").innerHTML = ` = ON`
+ // // m.eyeFillColor = m.fieldMeterColor //'#5af'
+ // // } else {
+ // // document.getElementById("tech-flip-flop").innerHTML = ` = OFF`
+ // // 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 ON
1.555x damage",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 3,
+ // frequencyDefault: 3,
// 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
- // }
+ // tech.isFlipFlopDamage = true;
// },
// 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
- // }
- // }
- // }
- // }
+ // tech.isFlipFlopDamage = false;
+ // }
+ // },
+ // {
+ // name: "integrated circuit",
+ // description: "if ON +7 power up choices
if OFF -1 power up choices",
+ // 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 ON generate +20 energy per second
if OFF drain -1 energy 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: `decoupling`,
+ // // descriptionFunction() {
+ // // //(${ m.couplingDescription(this.bonus)})
+ // // return `if ON +5 coupling
if OFF a dangerous particle slowly chases 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 ON and OFF after picking up a power up
unlock advanced tech that runs if ON`,
+ // // nameInfo: "",
+ // // addNameInfo() {
+ // // setTimeout(function () {
+ // // if (document.getElementById("tech-switch")) {
+ // // if (tech.isFlipFlopOn) {
+ // // document.getElementById("tech-switch").innerHTML = ` = ON`
+ // // m.eyeFillColor = m.fieldMeterColor //'#5af'
+ // // } else {
+ // // document.getElementById("tech-switch").innerHTML = ` = OFF`
+ // // 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 relay switch is ON
+300 maximum energy",
+ // 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 relay switch is ON
condense 4-13 ice IX 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 ON and OFF after picking up a power up
unlock advanced tech that runs if ON`,
- nameInfo: "",
- addNameInfo() {
- setTimeout(function () {
- if (document.getElementById("tech-switch")) {
- if (tech.isFlipFlopOn) {
- document.getElementById("tech-switch").innerHTML = ` = ON`
- m.eyeFillColor = m.fieldMeterColor //'#5af'
- } else {
- document.getElementById("tech-switch").innerHTML = ` = OFF`
- 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 relay switch is ON
+300 maximum energy",
- 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 relay switch is ON
condense 4-13 ice IX 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",
descriptionFunction() {
@@ -3421,6 +3421,7 @@ const tech = {
effect() {
tech.isHealAttract = true
powerUps.setPowerUpMode();
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
},
remove() {
tech.isHealAttract = false
@@ -3515,12 +3516,12 @@ const tech = {
},
{
name: "anthropic principle",
- nameInfo: "",
- addNameInfo() {
- setTimeout(function () {
- powerUps.research.changeRerolls(0)
- }, 1000);
- },
+ // nameInfo: "",
+ // addNameInfo() {
+ // setTimeout(function () {
+ // powerUps.research.changeRerolls(0)
+ // }, 1000);
+ // },
descriptionFunction() {
return `once per level, instead of dying
use ${powerUps.orb.research(1)} and spawn ${powerUps.orb.heal(16)}`
},
@@ -3871,9 +3872,12 @@ const tech = {
requires: "not determinism",
effect() {
tech.isExtraGunField = true;
+ powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.05);
},
remove() {
tech.isExtraGunField = false;
+ if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -3936,7 +3940,7 @@ const tech = {
isBadRandomOption: true,
isInstant: true,
allowed() {
- return !tech.extraChoices && !tech.isExtraGunField && !tech.isFlipFlopChoices && !tech.isExtraBotOption
+ return !tech.extraChoices && !tech.isExtraGunField && !tech.isExtraBotOption
},
requires: "not emergence, cross-disciplinary, integrated circuit",
effect() {
@@ -4106,9 +4110,13 @@ const tech = {
requires: "",
effect() {
tech.isMassProduction = true
+ powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.03);
},
remove() {
tech.isMassProduction = false
+ if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+
}
},
{
@@ -4307,7 +4315,7 @@ const tech = {
name: "residual dipolar coupling",
descriptionFunction() {
// return `clicking cancel for a field, tech, or gun
spawns ${powerUps.orb.coupling(5)}that each give +0.1 coupling`//
${m.couplingDescription(1)} ${m.fieldMode === 0 ? "" : "per coupling"}
- return `clicking cancel spawns ${powerUps.orb.coupling(8)}
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}`
+ return `clicking cancel spawns ${powerUps.orb.coupling(7)}
${m.couplingDescription(1)} per ${powerUps.orb.coupling(1)}`
},
maxCount: 1,
count: 0,
@@ -4327,7 +4335,7 @@ const tech = {
{
name: "commodities exchange",
descriptionFunction() {
- return `clicking cancel for a field, tech, or gun
spawns 10-14 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
+ return `clicking cancel for a field, tech, or gun
spawns 8-12 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
},
maxCount: 1,
count: 0,
@@ -4382,7 +4390,7 @@ const tech = {
},
remove() {
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() {
tech.isPowerUpsVanish = false
- powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+ if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance }
}
},
{
name: "correlated damage",
descriptionFunction() {
- return `duplication increases damage by the same percent
(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)`
+ return `duplication increases damage
(${(1 + Math.min(1, tech.duplicationChance())).toFixed(2)}x)`
},
maxCount: 1,
count: 0,
@@ -4467,9 +4475,11 @@ const tech = {
effect() {
tech.isDuplicateMobs = true;
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.08);
},
remove() {
tech.isDuplicateMobs = false;
+ if (this.count) powerUps.setPowerUpMode(); //needed after adjusting duplication chance
}
},
{
@@ -4506,11 +4516,11 @@ const tech = {
effect() {
tech.isStimulatedEmission = true
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() {
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) {
tech.duplication += 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
+ if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.11);
tech.damage /= this.damage
this.frequency = 0
}
@@ -4684,7 +4695,7 @@ const tech = {
{
name: "paradigm shift",
descriptionFunction() {
- return `when paused clicking a tech ejects it
–4 ${tech.isEnergyHealth ? "energy" : "health"} each time`
+ return `when paused clicking a tech ejects it
–${tech.pauseEjectTech.toFixed(1)} ${tech.isEnergyHealth ? "energy" : "health"} cost (1.2x cost each use)`
},
maxCount: 1,
count: 0,
@@ -4699,6 +4710,7 @@ const tech = {
},
remove() {
tech.isPauseEjectTech = false;
+
}
},
{
@@ -5332,7 +5344,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5351,7 +5363,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5370,7 +5382,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5389,7 +5401,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5408,7 +5420,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
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",
effect() {
@@ -5433,7 +5445,7 @@ const tech = {
// },
// requires: "perfect diamagnetism",
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",
effect() {
@@ -5485,7 +5497,7 @@ const tech = {
},
{
name: "Zectron",
- description: `2x super ball density and damage, but
after colliding with super balls -5 energy`,
+ description: `2x super ball density and damage, but
after colliding with super balls -4 energy`,
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5630,7 +5642,7 @@ const tech = {
tech.wavePacketDamage *= 1.4
},
remove() {
- tech.waveFrequency = 0.2
+ tech.waveFrequency = 0.2 //adjust this to make the waves much larger
tech.wavePacketDamage = 1
}
},
@@ -8549,7 +8561,7 @@ const tech = {
},
remove() {
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() {
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)
}
},
@@ -10964,6 +10976,25 @@ const tech = {
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",
description: "stand a bit taller",
@@ -11935,6 +11966,7 @@ const tech = {
isExplodeRadio: null,
isPauseSwitchField: null,
isPauseEjectTech: null,
+ pauseEjectTech: null,
isShieldPierce: null,
isDuplicateMobs: null,
is100Duplicate: null,
@@ -11945,15 +11977,6 @@ const tech = {
isSwitchReality: null,
isResearchReality: null,
isAnthropicDamage: null,
- isFlipFlop: null,
- isFlipFlopHarm: null,
- isFlipFlopOn: null,
- // isFlipFlopLevelReset: null,
- isFlipFlopDamage: null,
- isFlipFlopEnergy: null,
- isFlipFlopChoices: null,
- isRelay: null,
- relayIce: null,
isMetaAnalysis: null,
isFoamAttract: null,
droneCycleReduction: null,
@@ -12046,8 +12069,6 @@ const tech = {
isTechDebt: null,
isPlasmaBall: null,
plasmaDischarge: null,
- isFlipFlopHealth: null,
- isRelayEnergy: null,
coyoteTime: null,
missileFireCD: null,
isBotField: null,
diff --git a/todo.txt b/todo.txt
index 1b9f918..be9c180 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,31 +1,76 @@
******************************************************** NEXT PATCH **************************************************
-adjusted text and math for the fire rate system to use the new "x" syntax
-tech search is no longer case sensitive
+newLevel - towers
+ please give feedback
+boost level elements can now be pointed at any angle
-Zectron 1.9->2x damage, -25% -> -5 energy
-exothermic process -20% -> -5 energy
+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
-instant/unRemovable tech has a unique icon and no longer shows up in the tech list
- marginal utility - no longer spawns ammo
- heuristics - no longer spawn a gun, 1.2->1.3 fire rate
- open-source - gives 1 extra bot option and 3x bot tech frequency
- robotics - now just spawns 2 bots
- induction brake - doesn't spawn heals, but lasts 15->17 seconds
- accretion - doesn't spawn heals, but gets 3% duplication
- mass production - doesn't spawn power ups, but gets 3% duplication
- Ψ(t) collapse - doesn't spawn research, spawns 5 research from bosses
- decoherence - doesn't spawn research, spawns 2 research from bosses
- 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
+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
*********************************************************** 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
+ fade in on right side text list?
tech - getting caught in an explosion gives you _____
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
-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
reactor only?
will rewind time
@@ -1182,8 +1219,20 @@ possible names for 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
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
make n-gon a progressive web app to manage image downloads, cache