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