diff --git a/.DS_Store b/.DS_Store index 2bf9398..8eea4f3 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/js/bullet.js b/js/bullet.js index 73f5c09..f1a7817 100644 --- a/js/bullet.js +++ b/js/bullet.js @@ -595,7 +595,8 @@ const b = { newDist < dist && !mob[i].isBadTarget && Matter.Query.ray(map, path[0], mob[i].position).length === 0 && - Matter.Query.ray(body, path[0], mob[i].position).length === 0 + Matter.Query.ray(body, path[0], mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { dist = newDist best.who = mob[i] @@ -1271,148 +1272,148 @@ const b = { } } }, - dart(where, angle = m.angle, size = 0.8) { - //find a target - const closest = { - score: 10000, - position: null - } - for (let i = 0, len = mob.length; i < len; ++i) { - if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, where, mob[i].position).length === 0) { - const dot = Vector.dot({ x: Math.cos(angle), y: Math.sin(angle) }, Vector.normalise(Vector.sub(mob[i].position, where))) //the dot product of diff and dir will return how much over lap between the vectors - const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) - // if (dist < closest.score && ((dist > 500 && dot > 0) || (dot > 0.9))) { //target closest mob that player is looking at and isn't too close to target - if (dist < closest.score && dot > 0.9 - 0.0004 * dist) { //target closest mob that player is looking at and isn't too close to target - closest.score = dist - closest.position = mob[i].position - } - } - } - if (!closest.position) { - // const unit = Vector.mult(sub(simulation.mouseInGame, where), 10000) - closest.position = Vector.mult(Vector.sub(simulation.mouseInGame, where), 10000) - } - const me = bullet.length; - bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -20 * size, y: 2 * size, index: 0, isInternal: false }, { x: -20 * size, y: -2 * size, index: 1, isInternal: false }, { x: 5 * size, y: -2 * size, index: 4, isInternal: false }, { x: 20 * size, y: 0, index: 3, isInternal: false }, { x: 5 * size, y: 2 * size, index: 4, isInternal: false }], { - cycle: 0, - angle: angle, - friction: 1, - frictionAir: 0.15, - thrustMag: 0.03, - turnRate: 0.15, //0.015 - drawStringControlMagnitude: 3000 + 5000 * Math.random(), - drawStringFlip: (Math.round(Math.random()) ? 1 : -1), - dmg: 7, //damage done in addition to the damage from momentum - classType: "bullet", - endCycle: simulation.cycle + 120, - collisionFilter: { - category: cat.bullet, - mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield, - }, - minDmgSpeed: 0, - lookFrequency: Math.floor(7 + Math.random() * 3), - density: 0.001, //0.001 is normal for blocks, 0.008 is normal for harpoon, 0.008*6 when buffed - beforeDmg(who) { - if (tech.isShieldPierce && who.isShielded) { //disable shields - who.isShielded = false - requestAnimationFrame(() => { who.isShielded = true }); - } - if (tech.fragments) { - b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + 1.5 * Math.random())) - this.endCycle = 0; - } - if (!who.isBadTarget) { - this.frictionAir = 0.01 - this.do = this.doNoTargeting - } - }, - onEnd() {}, - doNoTargeting: function() { - // this.force.y += this.mass * 0.001; - if (Matter.Query.collides(this, map).length) { //stick in walls - this.collisionFilter.mask = 0; - Matter.Body.setAngularVelocity(this, 0) - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); - this.do = () => { - // if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001; - } - } - }, - do() { - this.cycle++ - // if (this.cycle > 40) { - // this.frictionAir = 0.003 - // this.do = this.doNoTargeting - // } - // if (closest.target) { //rotate towards the target - const face = { x: Math.cos(this.angle), y: Math.sin(this.angle) }; - const vectorGoal = Vector.normalise(Vector.sub(this.position, closest.position)); - const cross = Vector.cross(vectorGoal, face) - if (cross > 0.01) { - Matter.Body.rotate(this, this.turnRate * Math.sqrt(cross)); - } else if (cross < 0.01) { - Matter.Body.rotate(this, -this.turnRate * Math.sqrt(Math.abs(cross))); - } - this.force.x += this.thrustMag * this.mass * Math.cos(this.angle); - this.force.y += this.thrustMag * this.mass * Math.sin(this.angle); - // } - if (Matter.Query.collides(this, map).length) { //stick in walls - this.collisionFilter.mask = 0; - Matter.Body.setAngularVelocity(this, 0) - Matter.Body.setVelocity(this, { - x: 0, - y: 0 - }); - this.do = this.doNoTargeting - } - // else if (!(this.cycle % 2)) { //look for a target if you don't have one - // simulation.drawList.push({ //add dmg to draw queue - // x: this.position.x, - // y: this.position.y, - // radius: 10, - // color: simulation.mobDmgColor, - // time: simulation.drawTime - // }); - // let closest = { - // distance: 2000, - // target: null - // } - // const dir = Vector.normalise(this.velocity) //make a vector for direction of length 1 - // for (let i = 0, len = mob.length; i < len; ++i) { - // if ( - // mob[i].alive && !mob[i].isBadTarget && - // Matter.Query.ray(map, this.position, mob[i].position).length === 0 && //check for map in Line of sight - // Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, this.position))) > 0.55 //the dot product of diff and dir will return how much over lap between the vectors - // ) { - // const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - // if (dist < closest.distance) { - // closest.distance = dist - // closest.target = mob[i] - // } - // } - // } - // if (closest.target) { - // target = closest.target - // this.turnRate = 0.05 - // this.frictionAir = 0.8 - // } - // } - }, - }); - Matter.Body.setVelocity(bullet[me], { - x: m.Vx / 2 + 40 * Math.cos(bullet[me].angle), - y: m.Vy / 2 + 40 * Math.sin(bullet[me].angle) - }); - // if (!closest.target) { - // bullet[me].frictionAir = 0.002 - // bullet[me].do = bullet[me].doNoTargeting - // } - Composite.add(engine.world, bullet[me]); //add bullet to world + // dart(where, angle = m.angle, size = 0.8) { + // //find a target + // const closest = { + // score: 10000, + // position: null + // } + // for (let i = 0, len = mob.length; i < len; ++i) { + // if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, where, mob[i].position).length === 0) { + // const dot = Vector.dot({ x: Math.cos(angle), y: Math.sin(angle) }, Vector.normalise(Vector.sub(mob[i].position, where))) //the dot product of diff and dir will return how much over lap between the vectors + // const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) + // // if (dist < closest.score && ((dist > 500 && dot > 0) || (dot > 0.9))) { //target closest mob that player is looking at and isn't too close to target + // if (dist < closest.score && dot > 0.9 - 0.0004 * dist) { //target closest mob that player is looking at and isn't too close to target + // closest.score = dist + // closest.position = mob[i].position + // } + // } + // } + // if (!closest.position) { + // // const unit = Vector.mult(sub(simulation.mouseInGame, where), 10000) + // closest.position = Vector.mult(Vector.sub(simulation.mouseInGame, where), 10000) + // } + // const me = bullet.length; + // bullet[me] = Bodies.fromVertices(where.x, where.y, [{ x: -20 * size, y: 2 * size, index: 0, isInternal: false }, { x: -20 * size, y: -2 * size, index: 1, isInternal: false }, { x: 5 * size, y: -2 * size, index: 4, isInternal: false }, { x: 20 * size, y: 0, index: 3, isInternal: false }, { x: 5 * size, y: 2 * size, index: 4, isInternal: false }], { + // cycle: 0, + // angle: angle, + // friction: 1, + // frictionAir: 0.15, + // thrustMag: 0.03, + // turnRate: 0.15, //0.015 + // drawStringControlMagnitude: 3000 + 5000 * Math.random(), + // drawStringFlip: (Math.round(Math.random()) ? 1 : -1), + // dmg: 7, //damage done in addition to the damage from momentum + // classType: "bullet", + // endCycle: simulation.cycle + 120, + // collisionFilter: { + // category: cat.bullet, + // mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield, + // }, + // minDmgSpeed: 0, + // lookFrequency: Math.floor(7 + Math.random() * 3), + // density: 0.001, //0.001 is normal for blocks, 0.008 is normal for harpoon, 0.008*6 when buffed + // beforeDmg(who) { + // if (tech.isShieldPierce && who.isShielded) { //disable shields + // who.isShielded = false + // requestAnimationFrame(() => { who.isShielded = true }); + // } + // if (tech.fragments) { + // b.targetedNail(this.vertices[2], tech.fragments * Math.floor(2 + 1.5 * Math.random())) + // this.endCycle = 0; + // } + // if (!who.isBadTarget) { + // this.frictionAir = 0.01 + // this.do = this.doNoTargeting + // } + // }, + // onEnd() {}, + // doNoTargeting: function() { + // // this.force.y += this.mass * 0.001; + // if (Matter.Query.collides(this, map).length) { //stick in walls + // this.collisionFilter.mask = 0; + // Matter.Body.setAngularVelocity(this, 0) + // Matter.Body.setVelocity(this, { + // x: 0, + // y: 0 + // }); + // this.do = () => { + // // if (!Matter.Query.collides(this, map).length) this.force.y += this.mass * 0.001; + // } + // } + // }, + // do() { + // this.cycle++ + // // if (this.cycle > 40) { + // // this.frictionAir = 0.003 + // // this.do = this.doNoTargeting + // // } + // // if (closest.target) { //rotate towards the target + // const face = { x: Math.cos(this.angle), y: Math.sin(this.angle) }; + // const vectorGoal = Vector.normalise(Vector.sub(this.position, closest.position)); + // const cross = Vector.cross(vectorGoal, face) + // if (cross > 0.01) { + // Matter.Body.rotate(this, this.turnRate * Math.sqrt(cross)); + // } else if (cross < 0.01) { + // Matter.Body.rotate(this, -this.turnRate * Math.sqrt(Math.abs(cross))); + // } + // this.force.x += this.thrustMag * this.mass * Math.cos(this.angle); + // this.force.y += this.thrustMag * this.mass * Math.sin(this.angle); + // // } + // if (Matter.Query.collides(this, map).length) { //stick in walls + // this.collisionFilter.mask = 0; + // Matter.Body.setAngularVelocity(this, 0) + // Matter.Body.setVelocity(this, { + // x: 0, + // y: 0 + // }); + // this.do = this.doNoTargeting + // } + // // else if (!(this.cycle % 2)) { //look for a target if you don't have one + // // simulation.drawList.push({ //add dmg to draw queue + // // x: this.position.x, + // // y: this.position.y, + // // radius: 10, + // // color: simulation.mobDmgColor, + // // time: simulation.drawTime + // // }); + // // let closest = { + // // distance: 2000, + // // target: null + // // } + // // const dir = Vector.normalise(this.velocity) //make a vector for direction of length 1 + // // for (let i = 0, len = mob.length; i < len; ++i) { + // // if ( + // // mob[i].alive && !mob[i].isBadTarget && + // // Matter.Query.ray(map, this.position, mob[i].position).length === 0 && //check for map in Line of sight + // // Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, this.position))) > 0.55 //the dot product of diff and dir will return how much over lap between the vectors + // // ) { + // // const dist = Vector.magnitude(Vector.sub(this.position, mob[i].position)) + // // if (dist < closest.distance) { + // // closest.distance = dist + // // closest.target = mob[i] + // // } + // // } + // // } + // // if (closest.target) { + // // target = closest.target + // // this.turnRate = 0.05 + // // this.frictionAir = 0.8 + // // } + // // } + // }, + // }); + // Matter.Body.setVelocity(bullet[me], { + // x: m.Vx / 2 + 40 * Math.cos(bullet[me].angle), + // y: m.Vy / 2 + 40 * Math.sin(bullet[me].angle) + // }); + // // if (!closest.target) { + // // bullet[me].frictionAir = 0.002 + // // bullet[me].do = bullet[me].doNoTargeting + // // } + // Composite.add(engine.world, bullet[me]); //add bullet to world - }, + // }, grapple(where, angle = m.angle, harpoonSize = 1) { const me = bullet.length; const returnRadius = 100 * Math.sqrt(harpoonSize) @@ -2012,7 +2013,8 @@ const b = { for (let i = 0, len = mob.length; i < len; ++i) { if ( mob[i].alive && !mob[i].isBadTarget && - Matter.Query.ray(map, this.position, mob[i].position).length === 0 + Matter.Query.ray(map, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable // && Matter.Query.ray(body, this.position, mob[i].position).length === 0 ) { const futureDist = Vector.magnitude(Vector.sub(futurePos, mob[i].position)); @@ -2639,7 +2641,8 @@ const b = { !mob[i].isBadTarget && Vector.magnitude(Vector.sub(this.position, mob[i].position)) < 700 + mob[i].radius + random && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0 + Matter.Query.ray(body, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { if (tech.isExplosionStun) b.AoEStunEffect(this.position, 700 + mob[i].radius + random); if (tech.isMineSentry) { @@ -2753,7 +2756,7 @@ const b = { this.lockedOn = null; let closeDist = Infinity; for (let i = 0, len = mob.length; i < len; ++i) { - if (!mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0) { + if (!mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && !mob[i].isInvulnerable) { const targetVector = Vector.sub(this.position, mob[i].position) const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5); if (dist < closeDist) { @@ -2841,7 +2844,7 @@ const b = { this.lockedOn = null; let closeDist = Infinity; for (let i = 0, len = mob.length; i < len; ++i) { - if (!mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0) { + if (!mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && !mob[i].isInvulnerable) { const targetVector = Vector.sub(this.position, mob[i].position) const dist = Vector.magnitude(targetVector) * (Math.random() + 0.5); if (dist < closeDist) { @@ -2957,7 +2960,8 @@ const b = { if ( !mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0 + Matter.Query.ray(body, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { const TARGET_VECTOR = Vector.sub(this.position, mob[i].position) const DIST = Vector.magnitude(TARGET_VECTOR); @@ -3059,7 +3063,6 @@ const b = { Matter.Body.scale(this, scale, scale); } else { this.force.y += this.mass * 0.0002; - if (!(simulation.cycle % this.lookFrequency)) { //find mob targets this.lockedOn = null; @@ -3068,7 +3071,8 @@ const b = { if ( !mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0 + Matter.Query.ray(body, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { const TARGET_VECTOR = Vector.sub(this.position, mob[i].position) const DIST = Vector.magnitude(TARGET_VECTOR); @@ -3297,7 +3301,8 @@ const b = { if ( !mob[i].isBadTarget && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0 + Matter.Query.ray(body, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { const TARGET_VECTOR = Vector.sub(this.position, mob[i].position) const DIST = Vector.magnitude(TARGET_VECTOR); @@ -3785,9 +3790,10 @@ const b = { const dist = Vector.magnitude(Vector.sub(position, mob[i].position)); if ( dist < range + mob[i].radius && - (!mob[i].isBadTarget) && //|| mob[i].isMobBullet + !mob[i].isBadTarget && //|| mob[i].isMobBullet Matter.Query.ray(map, position, mob[i].position).length === 0 && - Matter.Query.ray(body, position, mob[i].position).length === 0 + Matter.Query.ray(body, position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { targets.push(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, dist / 60))) //predict where the mob will be in a few cycles } @@ -4280,7 +4286,8 @@ const b = { dist < 3000000 && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && Matter.Query.ray(body, this.position, mob[i].position).length === 0 && - !mob[i].isShielded + !mob[i].isShielded && + !mob[i].isInvulnerable ) { const unit = Vector.normalise(Vector.sub(Vector.add(mob[i].position, Vector.mult(mob[i].velocity, Math.sqrt(dist) / 60)), this.position)) if (this.isUpgraded) { @@ -4338,7 +4345,8 @@ const b = { mob[i].alive && !mob[i].isBadTarget && dist2 > 40000 && - Matter.Query.ray(map, this.position, mob[i].position).length === 0 + Matter.Query.ray(map, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable ) { this.cd = simulation.cycle + this.delay; const angle = Vector.angle(this.position, mob[i].position) @@ -4670,10 +4678,12 @@ const b = { let closeDist = tech.isPlasmaRange * 1000; for (let i = 0, len = mob.length; i < len; ++i) { const DIST = Vector.magnitude(Vector.sub(this.position, mob[i].position)) - mob[i].radius; - if (DIST < closeDist && - (!mob[i].isBadTarget || mob[i].isMobBullet) && + if ( + DIST < closeDist && (!mob[i].isBadTarget || mob[i].isMobBullet) && Matter.Query.ray(map, this.position, mob[i].position).length === 0 && - Matter.Query.ray(body, this.position, mob[i].position).length === 0) { + Matter.Query.ray(body, this.position, mob[i].position).length === 0 && + !mob[i].isInvulnerable + ) { closeDist = DIST; this.lockedOn = mob[i] } @@ -6376,7 +6386,7 @@ const b = { const dir = { x: Math.cos(angle), y: Math.sin(angle) }; //make a vector for the player's direction of length 1; used in dot product for (let i = 0, len = mob.length; i < len; ++i) { - if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) { + if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) // console.log(dot, 0.95 - Math.min(dist * 0.00015, 0.3)) @@ -6521,7 +6531,7 @@ const b = { const range = 450 * (tech.isFilament ? 1 + 0.005 * Math.min(110, this.ammo) : 1) let targetCount = 0 for (let i = 0, len = mob.length; i < len; ++i) { - if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) { + if (mob[i].alive && !mob[i].isBadTarget && !mob[i].shield && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) if (dist < range && dot > 0.9) { //lower dot product threshold for targeting then if you only have one harpoon //target closest mob that player is looking at and isn't too close to target @@ -6553,7 +6563,7 @@ const b = { //single harpoon const dir = { x: Math.cos(m.angle), y: Math.sin(m.angle) }; //make a vector for the player's direction of length 1; used in dot product for (let i = 0, len = mob.length; i < len; ++i) { - if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0) { + if (mob[i].alive && !mob[i].isBadTarget && Matter.Query.ray(map, m.pos, mob[i].position).length === 0 && !mob[i].isInvulnerable) { const dot = Vector.dot(dir, Vector.normalise(Vector.sub(mob[i].position, m.pos))) //the dot product of diff and dir will return how much over lap between the vectors const dist = Vector.magnitude(Vector.sub(where, mob[i].position)) if (dist < closest.distance && dot > 0.98 - Math.min(dist * 0.00014, 0.3)) { //target closest mob that player is looking at and isn't too close to target diff --git a/js/index.js b/js/index.js index bbb4704..8278b91 100644 --- a/js/index.js +++ b/js/index.js @@ -52,7 +52,7 @@ const cat = { } const color = { //light - background: "#ddd", + // background: "#ddd", // used instead: document.body.style.backgroundColor block: "rgba(140,140,140,0.85)", blockS: "#222", map: "#444", diff --git a/js/level.js b/js/level.js index c7c8af0..43a3512 100644 --- a/js/level.js +++ b/js/level.js @@ -18,14 +18,16 @@ const level = { // // simulation.isHorizontalFlipped = true // m.addHealth(Infinity) // m.setField("time dilation") - // b.giveGuns("nail gun") + // b.giveGuns("spores") // tech.giveTech("closed timelike curve") // tech.giveTech("retrocausality") - // tech.giveTech("pneumatic actuator") + // tech.giveTech("clock gating") // tech.giveTech("6s half-life") // for (let i = 0; i < 10; i++) tech.giveTech("replication") // tech.giveTech("eternalism") - // for (let i = 0; i < 10; i++) tech.giveTech("ammonium nitrate") + // m.maxHealth = 100 + // m.health = m.maxHealth + // for (let i = 0; i < 10; i++) tech.giveTech("tungsten carbide") // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "tech"); // for (let i = 0; i < 10; i++) powerUps.directSpawn(450, -50, "research"); // for (let i = 0; i < 15; i++) tech.giveTech() @@ -33,11 +35,15 @@ const level = { // powerUps.research.changeRerolls(100000) // tech.tech[297].frequency = 100 // m.immuneCycle = Infinity //you can't take damage - // level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why + // level.difficultyIncrease(20) //30 is near max on hard //60 is near max on why // simulation.enableConstructMode() //used to build maps in testing mode // level.testing(); - // spawn.snakeSpitBoss(1900, -500) - // level.reservoir(); //not in rotation, used for testing + // simulation.fpsCap = 30 //new fps + // simulation.fpsInterval = 1000 / simulation.fpsCap; + //how long to wait to return to normal fps + // m.defaultFPSCycle = m.cycle + 20 + Math.min(90, Math.floor(200 * dmg)) + // spawn.timeSkipBoss(1900, -500) + // level.reactor(); //not in rotation, used for testing if (simulation.isTraining) { level.walk(); } else { level.intro(); } //normal starting level ************************************************ // powerUps.research.changeRerolls(3000) @@ -2619,7 +2625,7 @@ const level = { // level.difficultyIncrease(14); //hard mode level 7 level.defaultZoom = 1500 simulation.zoomTransition(level.defaultZoom) - document.body.style.backgroundColor = color.background //"#ddd"; + document.body.style.backgroundColor = "#ddd"; spawn.mapRect(-950, 0, 8200, 800); //ground spawn.mapRect(-950, -1200, 800, 1400); //left wall spawn.mapRect(-950, -1800, 8200, 800); //roof @@ -2761,22 +2767,23 @@ const level = { for (let i = 0; i < 9; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "ammo") for (let i = 0; i < 3; ++i) powerUps.spawn(1200 + 550 * Math.random(), -1700, "heal"); const scale = Math.pow(simulation.difficulty, 0.73) //hard around 30, why around 54 - if (Math.random() < 0.07 && simulation.difficulty > 24) { - for (let i = 0, len = scale * 0.25 / 4; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15 - for (let i = 0, len = scale * 0.1 / 4; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); - for (let i = 0, len = scale * 0.16 / 4; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) - for (let i = 0, len = scale * 0.23 / 4; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); - } else { - if (Math.random() < 0.25) { - for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 - } else if (Math.random() < 0.33) { - for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 - } else if (Math.random() < 0.5) { - for (let i = 0, len = scale * 0.16; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15 - } else { - for (let i = 0, len = scale * 0.23; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 - } - } + for (let i = 0, len = scale * 0.23; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 + // if (Math.random() < 0.07 && simulation.difficulty > 24) { + // for (let i = 0, len = scale * 0.25 / 4; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 60, false); //spawn 1-2 at difficulty 15 + // for (let i = 0, len = scale * 0.1 / 4; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); + // for (let i = 0, len = scale * 0.16 / 4; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) + // for (let i = 0, len = scale * 0.23 / 4; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); + // } else { + // if (Math.random() < 0.25) { + // for (let i = 0, len = scale * 0.25; i < len; ++i) spawn.timeBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 + // } else if (Math.random() < 0.33) { + // for (let i = 0, len = scale * 0.1; i < len; ++i) spawn.bounceBoss(1487 + 200 * i, -1525, 80, false); //spawn 1-2 at difficulty 15 + // } else if (Math.random() < 0.5) { + // for (let i = 0, len = scale * 0.16; i < len; ++i) spawn.sprayBoss(1487 + 200 * i, -1525, 30, false) //spawn 2-3 at difficulty 15 + // } else { + // for (let i = 0, len = scale * 0.23; i < len; ++i) spawn.mineBoss(1487 + 200 * i, -1525, 50, false); //spawn 3-4 at difficulty 15 + // } + // } spawn.secondaryBossChance(2200, -800) } } else { @@ -4740,19 +4747,15 @@ const level = { skyscrapers() { const boost1 = level.boost(475, 0, 1300) const boost2 = level.boost(4450, 0, 1300); - level.custom = () => { boost1.query(); boost2.query(); - ctx.fillStyle = "#d4f4f4" ctx.fillRect(1350, -2100, 400, 250) ctx.fillStyle = "#d4d4d7" ctx.fillRect(3350, -1300, 50, 1325) ctx.fillRect(1300, -1800, 750, 1800) - level.exit.drawAndCheck(); - level.enter.draw(); }; level.customTopLayer = () => { @@ -4766,20 +4769,16 @@ const level = { ctx.fillStyle = "rgba(0,0,0,0.15)" ctx.fillRect(-250, -300, 450, 300) }; - level.setPosToSpawn(-50, -60); //normal spawn spawn.mapRect(level.enter.x, level.enter.y + 20, 100, 20); level.exit.x = 1500; level.exit.y = -1875; - level.defaultZoom = 2000 simulation.zoomTransition(level.defaultZoom) powerUps.spawnStartingPowerUps(1475, -1175); spawn.debris(750, -2200, 3700, 16); //16 debris per level document.body.style.backgroundColor = "#dcdcde"; - // simulation.draw.mapFill = "#444" - // simulation.draw.bodyFill = "rgba(140,140,140,0.85)" - // simulation.draw.bodyStroke = "#222" + spawn.mapRect(-300, 0, 5100, 300); //***********ground spawn.mapRect(-300, -350, 50, 400); //far left starting left wall spawn.mapRect(-300, -10, 500, 50); //far left starting ground @@ -4844,13 +4843,12 @@ const level = { spawn.randomMob(-100, -1700, -0.2); spawn.randomGroup(3700, -1500, 0.4); spawn.randomGroup(1700, -900, 0.4); - if (simulation.difficulty > 1) spawn.randomLevelBoss(2600, -2300); + if (simulation.difficulty > 1) spawn.randomLevelBoss(2800 + 200 * Math.random(), -2200 + 200 * Math.random()); powerUps.addResearchToLevel() //needs to run after mobs are spawned - spawn.secondaryBossChance(3075, -2050) + spawn.secondaryBossChance(4000, -1825) if (simulation.isHorizontalFlipped) { //flip the map horizontally level.flipHorizontal(); //only flips map,body,mob,powerUp,cons,consBB, exit - boost1.boostBounds.min.x = -boost1.boostBounds.min.x - 100 boost1.boostBounds.max.x = -boost1.boostBounds.max.x + 100 boost2.boostBounds.min.x = -boost2.boostBounds.min.x - 100 diff --git a/js/player.js b/js/player.js index dfd14f6..ff046a4 100644 --- a/js/player.js +++ b/js/player.js @@ -1379,7 +1379,10 @@ const m = { x: player.velocity.x - (15 * unit.x) / massRoot, y: player.velocity.y - (15 * unit.y) / massRoot }); - if (who.isOrbital) Matter.Body.setVelocity(who, { x: 0, y: 0 }); + if (who.isUnstable) { + if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30 + who.death(); + } if (m.crouch) { Matter.Body.setVelocity(player, { @@ -1762,7 +1765,10 @@ const m = { x: player.velocity.x - (30 * unit.x) / massRoot, y: player.velocity.y - (30 * unit.y) / massRoot }); - if (mob[i].isOrbital) Matter.Body.setVelocity(mob[i], { x: 0, y: 0 }); + if (mob[i].isUnstable) { + if (m.fieldCDcycle < m.cycle + 10) m.fieldCDcycle = m.cycle + 10 + mob[i].death(); + } if (!isFree) { //player knock backs if (mob[i].isDropPowerUp && player.speed < 12) { const massRootCap = Math.sqrt(Math.min(10, Math.max(0.2, mob[i].mass))); diff --git a/js/powerup.js b/js/powerup.js index b4eca9b..92333b2 100644 --- a/js/powerup.js +++ b/js/powerup.js @@ -758,6 +758,10 @@ const powerUps = { text += `
  ${m.fieldUpgrades[choiceField].name}
${m.fieldUpgrades[choiceField].description}
` } } + if (tech.tooManyTechChoices) { + tech.tooManyTechChoices-- + for (let i = 0; i < powerUps.tech.lastTotalChoices; i++) pick() + } if (tech.isBrainstorm && !tech.isBrainstormActive && !simulation.isChoosing) { tech.isBrainstormActive = true diff --git a/js/spawn.js b/js/spawn.js index 37f9ba8..2f9fce4 100644 --- a/js/spawn.js +++ b/js/spawn.js @@ -2398,6 +2398,7 @@ const spawn = { me.memory = Infinity me.onDeath = function() { powerUps.spawnBossPowerUp(this.position.x, this.position.y) + ctx.setLineDash([]); }; me.damageReduction = 0.35 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) // me.damageReductionGoal me.awake = function() { @@ -3784,6 +3785,7 @@ const spawn = { me.isDropPowerUp = false; me.isBadTarget = true; me.isMobBullet = true; + me.isUnstable = true; //dies when blocked me.showHealthBar = false; me.explodeRange = 200 + 150 * Math.random() me.isExploding = false @@ -5179,16 +5181,16 @@ const spawn = { }; }, timeSkipBoss(x, y, radius = 50) { - mobs.spawn(x, y, 15, radius, "rgb(150, 150, 255)"); + mobs.spawn(x, y, 15, radius, "transparent"); let me = mob[mob.length - 1]; me.isBoss = true; me.eventHorizon = 0; //set in mob loop me.frictionStatic = 0; me.friction = 0; me.frictionAir = 0.004; - me.accelMag = 0.0001 + 0.00003 * simulation.accelScale + me.accelMag = 0.00008 + 0.00002 * simulation.accelScale spawn.shield(me, x, y, 1); - spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random(), true) + spawn.spawnOrbitals(me, radius + 50 + 100 * Math.random()) Matter.Body.setDensity(me, 0.003); //extra dense //normal is 0.001 //makes effective life much larger me.damageReduction = 0.07 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1) @@ -5208,14 +5210,14 @@ const spawn = { this.seePlayerByHistory(); this.attraction(); this.checkStatus(); - this.eventHorizon = 950 + 170 * Math.sin(simulation.cycle * 0.005) + this.eventHorizon = 900 + 200 * Math.sin(simulation.cycle * 0.005) if (!simulation.isTimeSkipping) { if (Vector.magnitude(Vector.sub(this.position, m.pos)) < this.eventHorizon) { this.attraction(); this.damageReduction = this.startingDamageReduction this.isInvulnerable = false if (!(simulation.cycle % 15)) requestAnimationFrame(() => { - simulation.timePlayerSkip(8) + simulation.timePlayerSkip(5) simulation.loop(); //ending with a wipe and normal loop fixes some very minor graphical issues where things are draw in the wrong locations }); //wrapping in animation frame prevents errors, probably @@ -5237,7 +5239,7 @@ const spawn = { simulation.camera(); ctx.beginPath(); //gets rid of already draw shapes ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI, false); //part you can't see - ctx.fillStyle = color.background; + ctx.fillStyle = document.body.style.backgroundColor; ctx.fill(); ctx.restore(); }) @@ -5854,7 +5856,7 @@ const spawn = { me.leaveBody = false; me.isDropPowerUp = false; me.isBadTarget = true; - me.isUnblockable = true; + me.isUnstable = true; //dies when blocked me.showHealthBar = false; me.isOrbital = true; // me.isShielded = true diff --git a/js/tech.js b/js/tech.js index 756e796..65ad875 100644 --- a/js/tech.js +++ b/js/tech.js @@ -223,22 +223,21 @@ const tech = { let dmg = 1 //m.fieldDamage if (tech.isDeathSkipTime) dmg *= 1.67 if (tech.isNoDraftPause) dmg *= 1.4 - if (tech.isTechDebt) dmg *= Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount) - if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction()) - if (tech.OccamDamage) dmg *= tech.OccamDamage if (tech.isCloakingDamage) dmg *= 1.35 - if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 - if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599 - if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg if (tech.isTechDamage) dmg *= 1.9 - if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) - if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) if (tech.isMaxEnergyTech) dmg *= 1.5 if (tech.isEnergyNoAmmo) dmg *= 1.88 + if (tech.isEnergyLoss) dmg *= 1.55 + if (tech.OccamDamage) dmg *= tech.OccamDamage + if (tech.isTechDebt) dmg *= Math.max(41 / (tech.totalCount + 21), 4 - 0.15 * tech.totalCount) + if (tech.isAxion && tech.isHarmMACHO) dmg *= 1 + 0.75 * (1 - m.harmReduction()) + if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.555 + if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599 + if (tech.isDupDamage) dmg *= 1 + Math.min(1, tech.duplicationChance()) + if (tech.isLowEnergyDamage) dmg *= 1 + 0.7 * Math.max(0, 1 - m.energy) if (tech.isDamageForGuns) dmg *= 1 + 0.13 * b.inventory.length if (tech.isLowHealthDmg) dmg *= 1 + Math.max(0, 1 - m.health) * 0.5 if (tech.isHarmDamage && m.lastHarmCycle + 600 > m.cycle) dmg *= 3; - if (tech.isEnergyLoss) dmg *= 1.55; if (tech.isAcidDmg && m.health > 1) dmg *= 1.35; if (tech.restDamage > 1 && player.speed < 1) dmg *= tech.restDamage if (tech.isEnergyDamage) dmg *= 1 + m.energy * 0.125; @@ -249,6 +248,7 @@ const tech = { if (tech.isSpeedDamage) dmg *= 1 + Math.min(0.66, player.speed * 0.0165) if (tech.isBotDamage) dmg *= 1 + 0.06 * b.totalBots() if (tech.isDamageAfterKillNoRegen && m.lastKillCycle + 300 > m.cycle) dmg *= 1.5 + if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg return dmg * tech.slowFire * tech.aimDamage }, duplicationChance() { @@ -7932,51 +7932,51 @@ const tech = { }, remove() {} }, - { - name: "translate", - description: "translate n-gon into a random language", - maxCount: 1, - count: 0, - frequency: 0, - isJunk: true, - isNonRefundable: true, - allowed() { - return true - }, - requires: "", - effect() { - // generate a container - const gtElem = document.createElement('div') - gtElem.id = "gtElem" - gtElem.style.visibility = 'hidden' // make it invisible - document.body.append(gtElem) + // { + // name: "translate", + // description: "translate n-gon into a random language", + // maxCount: 1, + // count: 0, + // frequency: 0, + // isJunk: true, + // isNonRefundable: true, + // allowed() { + // return true + // }, + // requires: "", + // effect() { + // // generate a container + // const gtElem = document.createElement('div') + // gtElem.id = "gtElem" + // gtElem.style.visibility = 'hidden' // make it invisible + // document.body.append(gtElem) - // generate a script to run after creation - function initGT() { - // create a new translate element - new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem') - // ok now since it's loaded perform a funny hack to make it work - const langSelect = document.getElementsByClassName("goog-te-combo")[0] - // select a random language. It takes a second for all langauges to load, so wait a second. - setTimeout(() => { - langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random()) - // simulate a click - langSelect.dispatchEvent(new Event('change')) - // now make it go away - const bar = document.getElementById(':1.container') - bar.style.display = 'none' - bar.style.visibility = 'hidden' - }, 1000) + // // generate a script to run after creation + // function initGT() { + // // create a new translate element + // new google.translate.TranslateElement({ pageLanguage: 'en', layout: google.translate.TranslateElement.InlineLayout.HORIZONTAL }, 'gtElem') + // // ok now since it's loaded perform a funny hack to make it work + // const langSelect = document.getElementsByClassName("goog-te-combo")[0] + // // select a random language. It takes a second for all langauges to load, so wait a second. + // setTimeout(() => { + // langSelect.selectedIndex = Math.round(langSelect.options.length * Math.random()) + // // simulate a click + // langSelect.dispatchEvent(new Event('change')) + // // now make it go away + // const bar = document.getElementById(':1.container') + // bar.style.display = 'none' + // bar.style.visibility = 'hidden' + // }, 1000) - } + // } - // add the google translate script - const translateScript = document.createElement('script') - translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT' - document.body.append(translateScript) - }, - remove() {} - }, + // // add the google translate script + // const translateScript = document.createElement('script') + // translateScript.src = '//translate.google.com/translate_a/element.js?cb=initGT' + // document.body.append(translateScript) + // }, + // remove() {} + // }, { name: "discount", description: "get 3 random JUNK tech for the price of 1!", @@ -9674,6 +9674,108 @@ const tech = { }, remove() {} }, + { + name: "path integral", + link: `path integral`, + // description: "your next 3 tech choices
present almost every possible option", + description: "your next tech choice
presents almost every possible option", + maxCount: 1, + count: 0, + frequency: 1, + frequencyDefault: 1, + isNonRefundable: true, + isJunk: true, + allowed() { return true }, + requires: "", + effect() { + tech.tooManyTechChoices = 1 + for (let i = 0; i < this.bonusResearch; i++) powerUps.spawn(m.pos.x + 40 * (Math.random() - 0.5), m.pos.y + 40 * (Math.random() - 0.5), "research", false); + }, + remove() { + tech.tooManyTechChoices = 0 + } + }, + { + name: "rule 30", + maxCount: 1, + count: 0, + frequency: 0, + isJunk: true, + allowed() { + return true + }, + requires: "", + effect() {}, + remove() {}, + state: [ + [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false] + ], + rule(state, a, b, c) { + //30 + if (state[a] && state[b] && state[c]) return false; // TTT => F + if (state[a] && state[b] && !state[c]) return false; // TTF => F + if (state[a] && !state[b] && state[c]) return false; //TFT => F + if (state[a] && !state[b] && !state[c]) return true; //TFF => T + if (!state[a] && state[b] && state[c]) return true; //FTT => T + if (!state[a] && state[b] && !state[c]) return true; //FTF => T + if (!state[a] && !state[b] && state[c]) return true; //FFT => T + if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + }, + id: 0, + descriptionFunction() { + + if (this.id === 0 && Math.random() < 0.5) { + // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed + this.name = "rule 90" + this.link = `${this.name}` + // console.log(this.name) + this.state[0] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false] + this.rule = function(state, a, b, c) { + if (state[a] && state[b] && state[c]) return false; // TTT => F + if (state[a] && state[b] && !state[c]) return true; // TTF => T + if (state[a] && !state[b] && state[c]) return false; //TFT => F + if (state[a] && !state[b] && !state[c]) return true; //TFF => T + if (!state[a] && state[b] && state[c]) return true; //FTT => T + if (!state[a] && state[b] && !state[c]) return false; //FTF => F + if (!state[a] && !state[b] && state[c]) return true; //FFT => T + if (!state[a] && !state[b] && !state[c]) return false; //FFF => F + } + } + + const loop = () => { + if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) + let b = []; //produce next row + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around + for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array + b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1)); + } + b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around + this.state.push(b) + if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML + if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); + setTimeout(() => { loop() }, 400); + } + } + setTimeout(() => { loop() }, 400); + this.id++ + return `${this.outputText()}` + }, + outputText() { + let text = "" + for (let j = 0; j < this.state.length; j++) { + text += "

" + for (let i = 0; i < this.state[j].length; i++) { + if (this.state[j][i]) { + text += "⬛" //"█" //"■" + } else { + text += "⬜" //"    " //"□" + } + } + text += "

" + } + return text + }, + }, { name: "cosmogonic myth", description: `open a portal to a primordial version of reality
in 5 minutes close the portal, spawn 1 of each power up
`, @@ -9835,87 +9937,7 @@ const tech = { // return text // }, // }, - { - name: "rule 30", - maxCount: 1, - count: 0, - frequency: 0, - isJunk: true, - allowed() { - return true - }, - requires: "", - effect() {}, - remove() {}, - state: [ - [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false] - ], - rule(state, a, b, c) { - //30 - if (state[a] && state[b] && state[c]) return false; // TTT => F - if (state[a] && state[b] && !state[c]) return false; // TTF => F - if (state[a] && !state[b] && state[c]) return false; //TFT => F - if (state[a] && !state[b] && !state[c]) return true; //TFF => T - if (!state[a] && state[b] && state[c]) return true; //FTT => T - if (!state[a] && state[b] && !state[c]) return true; //FTF => T - if (!state[a] && !state[b] && state[c]) return true; //FFT => T - if (!state[a] && !state[b] && !state[c]) return false; //FFF => F - }, - id: 0, - descriptionFunction() { - if (this.id === 0 && Math.random() < 0.5) { - // for (let i = 0; i < 29; i++) this.state[0][i] = Math.random() < 0.5 //randomize seed - this.name = "rule 90" - this.link = `${this.name}` - // console.log(this.name) - this.state[0] = [false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false] - this.rule = function(state, a, b, c) { - if (state[a] && state[b] && state[c]) return false; // TTT => F - if (state[a] && state[b] && !state[c]) return true; // TTF => T - if (state[a] && !state[b] && state[c]) return false; //TFT => F - if (state[a] && !state[b] && !state[c]) return true; //TFF => T - if (!state[a] && state[b] && state[c]) return true; //FTT => T - if (!state[a] && state[b] && !state[c]) return false; //FTF => F - if (!state[a] && !state[b] && state[c]) return true; //FFT => T - if (!state[a] && !state[b] && !state[c]) return false; //FFF => F - } - } - - const loop = () => { - if ((simulation.paused || simulation.isChoosing) && m.alive && !build.isExperimentSelection) { //&& (!simulation.isChoosing || this.count === 0) - let b = []; //produce next row - b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 1, 0, 1)); //left edge wrap around - for (let i = 1; i < this.state[this.state.length - 1].length - 1; i++) { //apply rule to the rest of the array - b.push(this.rule(this.state[this.state.length - 1], i - 1, i, i + 1)); - } - b.push(this.rule(this.state[this.state.length - 1], this.state[this.state.length - 1].length - 2, this.state[this.state.length - 1].length - 1, 0)); //right edge wrap around - this.state.push(b) - if (document.getElementById(`cellular-rule-id${this.id}`)) document.getElementById(`cellular-rule-id${this.id}`).innerHTML = this.outputText() //convert to squares and send HTML - if (this.count && this.state.length < 120 && !(this.state.length % 10)) powerUps.spawn(m.pos.x - 50 + 100 * (Math.random() - 0.5), m.pos.y + 100 * (Math.random() - 0.5), "research"); - setTimeout(() => { loop() }, 400); - } - } - setTimeout(() => { loop() }, 400); - this.id++ - return `${this.outputText()}` - }, - outputText() { - let text = "" - for (let j = 0; j < this.state.length; j++) { - text += "

" - for (let i = 0; i < this.state[j].length; i++) { - if (this.state[j][i]) { - text += "⬛" //"█" //"■" - } else { - text += "⬜" //"    " //"□" - } - } - text += "

" - } - return text - }, - }, //************************************************** //************************************************** undefined / lore //************************************************** tech diff --git a/todo.txt b/todo.txt index 904ec56..e6c8ced 100644 --- a/todo.txt +++ b/todo.txt @@ -1,40 +1,32 @@ ******************************************************** NEXT PATCH ************************************************** -tech: propagator - 67% damage, lose 1/2 second of time when a mob dies +boss orbitals and mineBoss mines are destroyed when you deflect them with your field +drones, spores and other bullets that target mobs, will not target invulnerable mobs +timeSKipBoss is a bit slower with a bit less time skipping + fixed color to better match level background colors -timeSkipBoss is back, maybe it will not cause bugs this time - immune to harm unless player is inside horizon - player loses time when inside horizon - -snake bosses are immune to harm until your remove their tail - -mob shields are 30% stronger -time dilation: retrocausality automatically grabs power ups -eternalism 50->40% damage -paradigm shift 10->16% chance to get a research when ejecting tech -reaction inhibitor 11->13% mob health reduction -recycling 1->0.5% health for 5 seconds - up to 2.5% per mob kill at normal max health +JUNK tech: path integral - your next tech choice has almost all possible choices bug fixes -******************************************************** TODO ******************************************************** -make targeting skip invulnerable mobs - drones, spores, harpoon, missiles?, mines, nail on death - this helps beat snake boss - spores are biggest issue +*********************************************************** TODO ***************************************************** -let blocking instantly destroy the red orbitals? since they can't be deflected - also mines on reactor level? - also any bullet? +timeskip flickers with tech: clock gating, and game pause after large hit + probably not related to timeskip, related to graphics effect + not a big problem, actually it's kinda neat effect + only fix if there is a clear solution + +JUNK tech show 20+ options in tech selection + +bullets that can target the player + occurs if no mobs targets around + worms? drones? missiles? spores? + all of the above? BUG time skip probably led to player being able to move, and game not being paused for a few seconds while the death screen faded in also small chance it happened with rewind instead, but unlikely -make one value to track all the +dmg effects that don't need dynamic calculations - update it with a set damage function - block manufacturing - molecular assembler tech Holding r-click will create a slowly increasing in size block, which will be thrown on release @@ -48,10 +40,6 @@ make MEE work with harm reduction how to nerf MEE maybe harm reduction could also reduce energy regen -simulation.timeSkip(60) - maybe run simulation.timeSkip(60) in a room in labs - mob fires laser/bullets that timeSkip player - Currently, the mob just deals higher damage on impact, which is annoying although not hard to compete with nor unique By "redesign" I mean replacing instances of the regular mob, since the same code is used for the tiny red projectiles (I think) just add a new mob and remove the old one from the rotation The new mob should be as such, a "real" exploding mob: @@ -65,7 +53,6 @@ Regular state: red About to explode: animation to dark red Exploding: several shockwaves from the explosion points and tiny trails given to the shrapnel for a second or two until they deaccelerate - make laser gain damage and energy drain from fire delay tech wording? put it in the gun description