path intergral

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

JUNK tech: path integral - your next tech choice has almost all possible choices

bug fixes
This commit is contained in:
landgreen
2022-06-01 19:34:29 -07:00
parent 06c1285828
commit 9bc927d7ad
9 changed files with 395 additions and 366 deletions

BIN
.DS_Store vendored

Binary file not shown.

View File

@@ -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

View File

@@ -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",

View File

@@ -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

View File

@@ -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)));

View File

@@ -758,6 +758,10 @@ const powerUps = {
text += `<div class="choose-grid-module" onclick="powerUps.choose('field',${choiceField})"><div class="grid-title"><div class="circle-grid field"></div> &nbsp; ${m.fieldUpgrades[choiceField].name}</div> ${m.fieldUpgrades[choiceField].description}</div>`
}
}
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

View File

@@ -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

View File

@@ -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 <strong class='color-j'>JUNK</strong> <strong class='color-m'>tech</strong> for the price of 1!",
@@ -9674,6 +9674,108 @@ const tech = {
},
remove() {}
},
{
name: "path integral",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Path_integral_formulation' class="link">path integral</a>`,
// description: "your next <strong>3</strong> <strong class='color-m'>tech</strong> choices<br>present almost every possible <strong>option</strong>",
description: "your next <strong class='color-m'>tech</strong> choice<br>presents almost every possible <strong>option</strong>",
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 = `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(this.name).replace(/'/g, '%27')}&title=Special:Search' class="link">${this.name}</a>`
// 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 `<span id = "cellular-rule-id${this.id}" style = "letter-spacing: 0px;font-size: 50%;line-height: normal;">${this.outputText()}</span>`
},
outputText() {
let text = ""
for (let j = 0; j < this.state.length; j++) {
text += "<p style = 'margin-bottom: -11px;'>"
for (let i = 0; i < this.state[j].length; i++) {
if (this.state[j][i]) {
text += "⬛" //"█" //"■"
} else {
text += "⬜" //"&nbsp;&nbsp;&nbsp;&nbsp;" //"□"
}
}
text += "</p>"
}
return text
},
},
{
name: "cosmogonic myth",
description: `<span style = "opacity: 9%;">open a portal to a primordial version of reality<br>in 5 minutes close the portal, spawn 1 of each power up</span>`,
@@ -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 = `<a target="_blank" href='https://en.wikipedia.org/w/index.php?search=${encodeURIComponent(this.name).replace(/'/g, '%27')}&title=Special:Search' class="link">${this.name}</a>`
// 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 `<span id = "cellular-rule-id${this.id}" style = "letter-spacing: 0px;font-size: 50%;line-height: normal;">${this.outputText()}</span>`
},
outputText() {
let text = ""
for (let j = 0; j < this.state.length; j++) {
text += "<p style = 'margin-bottom: -11px;'>"
for (let i = 0; i < this.state[j].length; i++) {
if (this.state[j][i]) {
text += "⬛" //"█" //"■"
} else {
text += "⬜" //"&nbsp;&nbsp;&nbsp;&nbsp;" //"□"
}
}
text += "</p>"
}
return text
},
},
//**************************************************
//************************************************** undefined / lore
//************************************************** tech

View File

@@ -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