new level corridor
  new level element fizzler - it removes blocks
interferometer has wider platforms, a few helpful blocks, and fewer mobs
level constraints are announced in console

foam gun no longer pushes the player back when firing
wave gun buffs
  1.2x base damage
  1.1x base ammo
  0.1->0.13x speed in map
  0.25->0.30x speed in blocks
  tech: phase velocity 1.4->1.5x damage
pigeonhole principle gives 1.3->1.4 damage per gun
  you can no longer switch guns, your gun cycles each level
quenching 0.4->0.5x overheal converts into max health
tungsten carbide no longer has reduced coyote cycles
control theory 1.5->2x damage at max health
stability 0.3->0.2 damage taken at max health
overcharge +88->100 max energy, 4->5% JUNK
zoospore vector 10->13% chance for spores on mob death
replication 15->10% JUNK
interest 6->5% of your power ups spawn each level

updated "about" details menu
  moved classic n-gon to here from settings
  added links to community content in "about"
    Are there more links I should add?
  added an n-gon SVG head image

bugs
  fixed outline on splash screen doesn't sync right on safari browser
  fixed possible lock out on training levels: "hold", "throw", "throwAt"
    from losing block behind a door
  shortcut sort buttons in experiment mode properly order tech without clicking sort
  fixed/increased the horizontal velocity contribution for some guns
    this makes bullets shot on moving platforms more realistic
    nail gun, super balls, foam, harpoon
This commit is contained in:
landgreen
2024-12-24 11:22:57 -08:00
parent 1966173f88
commit 2daeae1ff4
12 changed files with 643 additions and 603 deletions

View File

@@ -280,8 +280,8 @@ const b = {
fireProps(cd, speed, dir, me) {
m.fireCDcycle = m.cycle + Math.floor(cd * b.fireCDscale); // cool down
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(dir),
y: m.Vy / 2 + speed * Math.sin(dir)
x: 0.5 * player.velocity.x + speed * Math.cos(dir),
y: 0.5 * player.velocity.y + speed * Math.sin(dir)
});
Composite.add(engine.world, bullet[me]); //add bullet to world
},
@@ -734,8 +734,8 @@ const b = {
};
speed = m.crouch ? 43 : 32
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
});
bullet[me].endCycle = simulation.cycle + Math.floor(m.crouch ? 120 : 80) * tech.bulletsLastLonger;
bullet[me].restitution = 0.4;
@@ -759,8 +759,8 @@ const b = {
};
speed = m.crouch ? 46 : 32
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
});
Composite.add(engine.world, bullet[me]); //add bullet to world
@@ -794,8 +794,8 @@ const b = {
};
speed = m.crouch ? 46 : 32
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
});
Composite.add(engine.world, bullet[me]); //add bullet to world
bullet[me].endCycle = simulation.cycle + 70 * tech.bulletsLastLonger;
@@ -924,8 +924,8 @@ const b = {
bullet[me].endCycle += 20;
}
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
});
Composite.add(engine.world, bullet[me]); //add bullet to world
}
@@ -951,7 +951,7 @@ const b = {
Matter.Body.scale(bullet[me], SCALE, SCALE);
speed = m.crouch ? 25 : 15
// speed = m.crouch ? 43 : 32
Matter.Body.setVelocity(bullet[me], { x: m.Vx / 2 + speed * Math.cos(angle), y: m.Vy / 2 + speed * Math.sin(angle) });
Matter.Body.setVelocity(bullet[me], { x: 0.5 * player.velocity.x + speed * Math.cos(angle), y: 0.5 * player.velocity.y + speed * Math.sin(angle) });
const MAG = 0.005
bullet[me].thrust = { x: bullet[me].mass * MAG * Math.cos(angle), y: bullet[me].mass * MAG * Math.sin(angle) }
}
@@ -1140,148 +1140,6 @@ 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
// },
grapple(where, angle = m.angle) {
const me = bullet.length;
const returnRadius = 100
@@ -1962,8 +1820,8 @@ const b = {
});
if (!isReturn && !target) {
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + 600 * thrust * Math.cos(bullet[me].angle),
y: m.Vy / 2 + 600 * thrust * Math.sin(bullet[me].angle)
x: 0.7 * player.velocity.x + 600 * thrust * Math.cos(bullet[me].angle),
y: 0.5 * player.velocity.x + 600 * thrust * Math.sin(bullet[me].angle)
});
bullet[me].frictionAir = 0.002
bullet[me].do = function () {
@@ -2084,8 +1942,8 @@ const b = {
});
const thrust = 0.0066 * bullet[me].mass * (tech.isMissileBig ? (tech.isMissileBiggest ? 0.3 : 0.7) : 1);
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.5 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
});
Composite.add(engine.world, bullet[me]); //add bullet to world
},
@@ -2972,11 +2830,6 @@ const b = {
y: speed * Math.sin(dir)
});
Matter.Body.setAngularVelocity(bullet[me], 3000 * bullet[me].spin);
// Matter.Body.setVelocity(bullet[me], {
// x: m.Vx / 2 + speed * Math.cos(dir),
// y: m.Vy / 2 + speed * Math.sin(dir)
// });
},
flea(where, velocity, radius = 6 + 3 * Math.random() + 10 * tech.wormSize * Math.random()) {
const me = bullet.length;
@@ -3810,165 +3663,6 @@ const b = {
}
return shotsFired
},
// plasmaBall(position, velocity, radius) {
// // radius *= Math.sqrt(tech.bulletSize)
// const me = bullet.length;
// bullet[me] = Bodies.polygon(position.x, position.y, 20, radius, {
// density: 0.000001, // 0.001 is normal density
// inertia: Infinity,
// frictionAir: 0.003,
// dmg: 0, //damage on impact
// damage: 0, //damage done over time
// scale: 1 - 0.006 / tech.bulletsLastLonger,
// classType: "bullet",
// collisionFilter: {
// category: cat.bullet,
// mask: 0 //cat.mob | cat.mobBullet // cat.map | cat.body | cat.mob | cat.mobShield
// },
// minDmgSpeed: 0,
// endCycle: Infinity,
// count: 0,
// radius: radius,
// portFrequency: 5 + Math.floor(5 * Math.random()),
// nextPortCycle: Infinity, //disabled unless you have the teleport tech
// beforeDmg(who) {
// if (!this.target && who.alive) {
// this.target = who;
// if (who.radius < 20) {
// this.targetRelativePosition = {
// x: 0,
// y: 0
// } //find relative position vector for zero mob rotation
// } else if (Matter.Query.collides(this, [who]).length > 0) {
// const normal = Matter.Query.collides(this, [who])[0].normal
// this.targetRelativePosition = Vector.rotate(Vector.sub(Vector.sub(this.position, who.position), Vector.mult(normal, -this.radius)), -who.angle) //find relative position vector for zero mob rotation
// } else {
// this.targetRelativePosition = Vector.rotate(Vector.sub(this.position, who.position), -who.angle) //find relative position vector for zero mob rotation
// }
// this.collisionFilter.category = cat.body;
// this.collisionFilter.mask = null;
// let bestVertexDistance = Infinity
// let bestVertex = null
// for (let i = 0; i < this.target.vertices.length; i++) {
// const dist = Vector.magnitude(Vector.sub(this.position, this.target.vertices[i]));
// if (dist < bestVertexDistance) {
// bestVertex = i
// bestVertexDistance = dist
// }
// }
// this.targetVertex = bestVertex
// }
// },
// onEnd() {},
// do() {
// if (this.count < 20) {
// this.count++
// //grow
// const SCALE = 1.06
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// //shrink
// Matter.Body.scale(this, this.scale, this.scale);
// this.radius *= this.scale;
// if (this.radius < 8) this.endCycle = 0;
// }
// if (this.target && this.target.alive) { //if stuck to a target
// const rotate = Vector.rotate(this.targetRelativePosition, this.target.angle) //add in the mob's new angle to the relative position vector
// if (this.target.isVerticesChange) {
// Matter.Body.setPosition(this, this.target.vertices[this.targetVertex])
// } else {
// Matter.Body.setPosition(this, Vector.add(Vector.add(rotate, this.target.velocity), this.target.position))
// }
// if (this.target.isBoss) {
// if (this.target.speed > 8) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.98))
// } else {
// if (this.target.speed > 4) Matter.Body.setVelocity(this.target, Vector.mult(this.target.velocity, 0.95))
// }
// Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9);
// // Matter.Body.setAngularVelocity(this.target, this.target.angularVelocity * 0.9)
// if (this.target.isShielded) {
// this.target.damage(m.dmgScale * this.damage, true); //shield damage bypass
// const SCALE = 1 - 0.004 / tech.bulletsLastLonger //shrink if mob is shielded
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// this.target.damage(m.dmgScale * this.damage);
// }
// } else if (this.target !== null) { //look for a new target
// this.collisionFilter.category = cat.bullet;
// this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
// if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
// let targets = []
// for (let i = 0, len = mob.length; i < len; i++) {
// const dist = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
// if (dist < 1000000) targets.push(mob[i])
// }
// const radius = Math.min(this.radius * 0.5, 9)
// const len = bullet.length < 80 ? 2 : 1
// for (let i = 0; i < len; i++) {
// if (targets.length - i > 0) {
// const index = Math.floor(Math.random() * targets.length)
// const speed = 6 + 6 * Math.random()
// const velocity = Vector.mult(Vector.normalise(Vector.sub(targets[index].position, this.position)), speed)
// b.foam(this.position, Vector.rotate(velocity, 0.5 * (Math.random() - 0.5)), radius)
// } else {
// b.foam(this.position, Vector.rotate({
// x: 15 + 10 * Math.random(),
// y: 0
// }, 2 * Math.PI * Math.random()), radius)
// }
// }
// }
// this.target = null
// } else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map or blocks
// const slow = 0.85
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// const SCALE = 0.96
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// // } else if (Matter.Query.collides(this, body).length > 0) {
// } else if (Matter.Query.point(body, this.position).length > 0) {
// const slow = 0.9
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// const SCALE = 0.96
// Matter.Body.scale(this, SCALE, SCALE);
// this.radius *= SCALE;
// } else {
// this.force.y += this.mass * tech.foamGravity; //gravity
// if (tech.isFoamAttract) {
// for (let i = 0, len = mob.length; i < len; i++) {
// if (!mob[i].isBadTarget && Vector.magnitude(Vector.sub(mob[i].position, this.position)) < 375 && mob[i].alive && Matter.Query.ray(map, this.position, mob[i].position).length === 0) {
// this.force = Vector.mult(Vector.normalise(Vector.sub(mob[i].position, this.position)), this.mass * 0.004)
// const slow = 0.9
// Matter.Body.setVelocity(this, {
// x: this.velocity.x * slow,
// y: this.velocity.y * slow
// });
// break
// }
// }
// }
// }
// if (this.nextPortCycle < simulation.cycle) { //teleport around if you have tech.isBulletTeleport
// this.nextPortCycle = simulation.cycle + this.portFrequency
// const range = 15 * Math.sqrt(this.radius) * Math.random()
// Matter.Body.setPosition(this, Vector.add(this.position, Vector.rotate({ x: range, y: 0 }, 2 * Math.PI * Math.random())))
// }
// }
// });
// if (tech.isBulletTeleport) bullet[me].nextPortCycle = simulation.cycle + bullet[me].portFrequency
// Composite.add(engine.world, bullet[me]); //add bullet to world
// Matter.Body.setVelocity(bullet[me], velocity);
// },
foam(position, velocity, radius) {
if (tech.isFoamCavitation && Math.random() < 0.25) {
velocity = Vector.mult(velocity, 1.35)
@@ -4024,10 +3718,7 @@ const b = {
}
}
this.targetVertex = bestVertex
Matter.Body.setVelocity(this, {
x: 0,
y: 0
});
Matter.Body.setVelocity(this, { x: 0, y: 0 });
}
},
onEnd() { },
@@ -4070,10 +3761,7 @@ const b = {
} else if (this.target !== null) { //look for a new target
this.collisionFilter.category = cat.bullet;
this.collisionFilter.mask = cat.mob //| cat.mobShield //cat.map | cat.body | cat.mob | cat.mobBullet | cat.mobShield
Matter.Body.setVelocity(this, {
x: this.target.velocity.x,
y: this.target.velocity.y
});
Matter.Body.setVelocity(this, { x: this.target.velocity.x, y: this.target.velocity.y });
if (tech.isSpawnBulletsOnDeath && bullet.length < 180 && !this.target.isMobBullet) {
let targets = []
for (let i = 0, len = mob.length; i < len; i++) {
@@ -4099,20 +3787,14 @@ const b = {
this.target = null
} else if (Matter.Query.point(map, this.position).length > 0) { //slow when touching map
const slow = 0.87
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
Matter.Body.setVelocity(this, { x: this.velocity.x * slow, y: this.velocity.y * slow });
const SCALE = 0.97
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
// } else if (Matter.Query.collides(this, body).length > 0) {
} else if (Matter.Query.point(body, this.position).length > 0) { //slow when touching blocks
const slow = 0.94
Matter.Body.setVelocity(this, {
x: this.velocity.x * slow,
y: this.velocity.y * slow
});
Matter.Body.setVelocity(this, { x: this.velocity.x * slow, y: this.velocity.y * slow });
const SCALE = 0.99
Matter.Body.scale(this, SCALE, SCALE);
this.radius *= SCALE;
@@ -4417,8 +4099,8 @@ const b = {
}
const SPEED = 90
Matter.Body.setVelocity(bullet[me], {
x: m.Vx / 2 + SPEED * Math.cos(angle),
y: m.Vy / 2 + SPEED * Math.sin(angle)
x: 0.5 * player.velocity.x + SPEED * Math.cos(angle),
y: 0.5 * player.velocity.y + SPEED * Math.sin(angle)
});
// Matter.Body.setDensity(bullet[me], 0.00001);
Composite.add(engine.world, bullet[me]); //add bullet to world
@@ -5928,8 +5610,8 @@ const b = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}, {
x: m.Vx / 2 + speed * Math.cos(angle),
y: m.Vy / 2 + speed * Math.sin(angle)
x: 0.8 * player.velocity.x + speed * Math.cos(angle),
y: 0.5 * player.velocity.y + speed * Math.sin(angle)
}) //position, velocity, damage
if (tech.isIceCrystals) {
bullet[bullet.length - 1].beforeDmg = function (who) {
@@ -6201,8 +5883,8 @@ const b = {
const SPEED = 13 + 4 * Math.random();
const angle = m.angle + spread * (Math.random() - 0.5)
b.foam(where, {
x: SPEED * Math.cos(angle),
y: SPEED * Math.sin(angle)
x: 0.6 * player.velocity.x + SPEED * Math.cos(angle),
y: 0.5 * player.velocity.y + SPEED * Math.sin(angle)
}, 8 + 7 * Math.random())
}
} else if (tech.isNeedles) {
@@ -6333,8 +6015,8 @@ const b = {
return `emit <strong>wave packets</strong> that propagate through <strong>solids</strong><br>waves <strong class='color-s'>slow</strong> mobs<br><strong>${this.ammoPack.toFixed(0)}</strong> wave packets per ${powerUps.orb.ammo()}`
},
ammo: 0,
ammoPack: 52,
defaultAmmoPack: 52,
ammoPack: 60,
defaultAmmoPack: 60,
have: false,
wavePacketCycle: 0,
delay: 40,
@@ -6655,12 +6337,12 @@ const b = {
}
}
}
let waveSpeedMap = 0.1
let waveSpeedBody = 0.25
let waveSpeedMap = 0.13
let waveSpeedBody = 0.3
if (tech.isPhaseVelocity) {
waveSpeedMap = 3.5
waveSpeedBody = 2
bullet[me].dmg *= 1.4
bullet[me].dmg *= 1.5
}
if (tech.waveReflections) {
bullet[me].reflectCycle = totalCycles / tech.waveReflections //tech.waveLengthRange
@@ -7083,10 +6765,13 @@ const b = {
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
const SPEED = (m.crouch ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5)
const velocity = { x: SPEED * Math.cos(dir), y: SPEED * Math.sin(dir) }
const velocity = {
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
}
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
b.foam(position, Vector.rotate(velocity, spread), radius)
this.applyKnock(velocity)
// this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
},
doCharges() {
@@ -7105,15 +6790,15 @@ const b = {
const SPEED = (m.crouch ? 1.2 : 1) * 10 - radius * 0.4 + Math.min(5, Math.sqrt(this.charge));
const dir = m.angle + 0.15 * (Math.random() - 0.5)
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
b.foam(position, Vector.rotate(velocity, spread), radius)
this.applyKnock(velocity)
// this.applyKnock(velocity)
this.charge -= 0.75
m.fireCDcycle = m.cycle + 2; //disable firing and adding more charge until empty
} else if (!input.fire) {
@@ -7135,31 +6820,13 @@ const b = {
const SPEED = (m.crouch ? 1.2 : 1) * Math.max(2, 14 - radius * 0.25)
const dir = m.angle + 0.15 * (Math.random() - 0.5)
const velocity = {
x: SPEED * Math.cos(dir),
y: SPEED * Math.sin(dir)
x: 0.7 * player.velocity.x + SPEED * Math.cos(dir),
y: 0.5 * player.velocity.y + SPEED * Math.sin(dir)
}
const position = {
x: m.pos.x + 30 * Math.cos(m.angle),
y: m.pos.y + 30 * Math.sin(m.angle)
}
// if (tech.foamFutureFire) {
// simulation.drawList.push({ //add dmg to draw queue
// x: position.x,
// y: position.y,
// radius: 5,
// color: "rgba(0,50,50,0.3)",
// time: 15 * tech.foamFutureFire
// });
// setTimeout(() => {
// if (!simulation.paused) {
// b.foam(position, Vector.rotate(velocity, spread), radius)
// bullet[bullet.length - 1].damage *= (1 + 0.7 * tech.foamFutureFire)
// }
// }, 210 * tech.foamFutureFire);
// } else {
// }
const position = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
b.foam(position, Vector.rotate(velocity, spread), radius)
this.applyKnock(velocity)
// this.applyKnock(velocity)
m.fireCDcycle = m.cycle + Math.floor(1.5 * b.fireCDscale);
this.charge += 1 + tech.isCapacitor
},

View File

@@ -643,7 +643,7 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
}
}
document.getElementById("sort-input").addEventListener('keydown', pressEnterSort);
requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
// requestAnimationFrame(() => { document.getElementById("sort-input").focus(); });
},
sortTech(find, isExperiment = false) {
const sortKeyword = (a, b) => {
@@ -730,6 +730,8 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
});
} else if (find === 'damage') {
tech.tech.sort(sortKeyword);
} else if (find === 'damage taken') {
tech.tech.sort(sortKeyword);
} else if (find === 'defense') {
tech.tech.sort(sortKeyword);
} else if (find === 'energy') {
@@ -954,8 +956,8 @@ ${simulation.difficultyMode > 4 ? `<details id="constraints-details" style="padd
<button onclick="build.sortTech('fieldtech', true)" class='sort-button'>${powerUps.orb.fieldTech()}</button>
<button onclick="build.sortTech('damage', true)" class='sort-button'><strong class='color-d'>damage</strong></button>
<button onclick="build.sortTech('damage taken', true)" class='sort-button'><strong style="letter-spacing: 1px;font-weight: 100;">dmg taken</strong></button>
<button onclick="build.sortTech('heal')" class='sort-button'><strong class='color-h'>heal</strong></button>
<button onclick="build.sortTech('energy')" class='sort-button'><strong class='color-f'>energy</strong></button>
<button onclick="build.sortTech('heal', true)" class='sort-button'><strong class='color-h'>heal</strong></button>
<button onclick="build.sortTech('energy', true)" class='sort-button'><strong class='color-f'>energy</strong></button>
<input type="search" id="sort-input" style="width: 7.5em;font-size: 0.6em;color:#000;" placeholder="sort by" />
<button onclick="build.sortTech('input', true)" class='sort-button' style="border-radius: 0em;border: 1.5px #000 solid;font-size: 0.6em;" value="damage">sort</button>
</div>
@@ -1416,11 +1418,13 @@ window.addEventListener("keydown", function (event) {
build.pauseGrid()
} else if (simulation.paused) {
build.unPauseGrid()
simulation.paused = false;
// level.levelAnnounce();
document.body.style.cursor = "none";
requestAnimationFrame(cycle);
if (document.activeElement !== document.getElementById('sort-input')) {
build.unPauseGrid()
simulation.paused = false;
// level.levelAnnounce();
document.body.style.cursor = "none";
requestAnimationFrame(cycle);
}
} else { //if (!tech.isNoDraftPause)
simulation.paused = true;
build.pauseGrid()
@@ -1542,7 +1546,7 @@ window.addEventListener("keydown", function (event) {
}
break
}
if (b.inventory.length > 1 && !simulation.testing && !tech.isGunCycle) {
if (b.inventory.length > 1 && !simulation.testing && !(tech.isGunChoice || tech.isGunCycle)) {
switch (event.code) {
case "Digit1":
simulation.switchToGunInInventory(0);

View File

@@ -10,7 +10,7 @@ const level = {
levelsCleared: 0,
isFlipped: false,
uniqueLevels: ["initial", "reservoir", "factory", "interferometer", "reactor", "subway", "final"], //see level.populateLevels: (initial, ... , (reservoir, factory, or interferometer), reactor, ... , subway, final) added later
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron", "substructure"],
playableLevels: ["labs", "rooftops", "skyscrapers", "warehouse", "highrise", "office", "aerie", "satellite", "sewers", "testChamber", "pavilion", "lock", "towers", "flocculation", "gravitron", "substructure", "corridor"],
communityLevels: ["gauntlet", "stronghold", "basement", "crossfire", "vats", "run", "ngon", "house", "perplex", "coliseum", "tunnel", "islands", "temple", "dripp", "biohazard", "stereoMadness", "yingYang", "staircase", "fortress", "commandeer", "clock", "buttonbutton", "downpour", "superNgonBros", "underpass", "cantilever", "tlinat", "ruins", "ace", "crimsonTowers", "LaunchSite", "shipwreck", "unchartedCave", "dojo", "arena", "soft", "flappyGon", "rings", "trial"],
trainingLevels: ["walk", "crouch", "jump", "hold", "throw", "throwAt", "deflect", "heal", "fire", "nailGun", "shotGun", "superBall", "matterWave", "missile", "stack", "mine", "grenades", "harpoon"],
levels: [],
@@ -23,7 +23,7 @@ const level = {
// level.levelsCleared = 10
// level.updateDifficulty()
// tech.giveTech("performance")
// m.maxHealth = m.health = 1//00000000
// m.maxHealth = m.health = 100000000
// m.maxEnergy = m.energy = 10000000
// tech.isRerollDamage = true
// powerUps.research.changeRerolls(99999)
@@ -48,24 +48,24 @@ const level = {
// requestAnimationFrame(() => { tech.giveTech("non-renewables") });
// tech.giveTech("dark matter")
// tech.addJunkTechToPool(0.5)
// for (let i = 0; i < 1; ++i) tech.giveTech("nail-bot")
// for (let i = 0; i < 1; ++i) tech.giveTech("quantum immortality")
// for (let i = 0; i < 1; ++i) tech.giveTech("pigeonhole principle")
// for (let i = 0; i < 1; ++i) tech.giveTech("generalist")
// m.skin.egg();
// for (let i = 0; i < 1; ++i) tech.giveTech("many-worlds")
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("quasiparticles") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("field coupling") });
// requestAnimationFrame(() => { for (let i = 0; i < 1; i++) tech.giveTech("interest") });
// for (let i = 0; i < 1; i++) tech.giveTech("interest")
// m.lastKillCycle = m.cycle
// for (let i = 0; i < 1; i++) powerUps.directSpawn(450, -50, "warp");
// for (let i = 0; i < 7; i++) powerUps.directSpawn(m.pos.x + 200, m.pos.y - 250, "research", false);
// spawn.bodyRect(575, -700, 150, 150); //block mob line of site on testing
// level.cocoon();
// level.corridor();
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
// for (let i = 0; i < 1; ++i) spawn.shieldingBoss(1900, -500)
// for (let i = 0; i < 1; ++i) spawn.powerUpBossBaby(1900, -500)
// for (let i = 0; i < 1; i++) spawn.mantisBoss(1900, -500)
// for (let i = 0; i < 1; ++i) powerUps.directSpawn(m.pos.x + 50 * Math.random(), m.pos.y + 50 * Math.random(), "entanglement");
@@ -168,14 +168,14 @@ const level = {
tech.tokamakHealCount = 0
tech.buffedGun++
if (tech.buffedGun > b.inventory.length - 1) tech.buffedGun = 0;
if (tech.isGunCycle && (b.activeGun !== null && b.activeGun !== undefined) && b.inventory.length) {
if ((tech.isGunCycle || tech.isGunChoice) && (b.activeGun !== null && b.activeGun !== undefined) && b.inventory.length) {
b.inventoryGun = tech.buffedGun;
simulation.switchGun();
}
if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) {
var gun = b.guns[b.inventory[tech.buffedGun]].name
simulation.inGameConsole(`pigeonhole principle: <strong>${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`, 600);
}
// if (tech.isGunChoice && Number.isInteger(tech.buffedGun) && b.inventory.length) {
// var gun = b.guns[b.inventory[tech.buffedGun]].name
// simulation.inGameConsole(`pigeonhole principle: <strong>${(1 + 0.4 * Math.max(0, b.inventory.length)).toFixed(2)}x</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`, 600);
// }
if (tech.isSwitchReality && level.levelsCleared !== 0) {
simulation.inGameConsole(`simulation.amplitude <span class='color-symbol'>=</span> ${Math.random()}`);
m.switchWorlds("many-worlds")
@@ -187,7 +187,12 @@ const level = {
for (let i = 0; i < len; i++) powerUps.spawn(player.position.x + 90 * (Math.random() - 0.5), player.position.y + 90 * (Math.random() - 0.5), "heal", false);
}
if (tech.interestRate > 0) {
const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels
// const rate = ((level[level.levels[level.onLevel]].name === "final" || level[level.levels[level.onLevel]].name === "subway") ? 1 / 3 : 1) * tech.interestRate //this effect triggers extra times on these final levels
let rate = tech.interestRate
if (level.onLevel < level.levels.length - 1) {//make sure it's not on the lore level which has an undefined name
const levelName = level.levels[level.onLevel]
if (levelName === "final" || levelName === "subway") rate *= 1 / 3
}
let ammoSum = 0
for (let i = 0; i < b.inventory.length; i++) {
@@ -315,10 +320,13 @@ const level = {
}
//update HUD with constraints
let text = `${level.constraintDescription1}`
if (level.constraintDescription1) simulation.inGameConsole(`<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);">constraint</span>: ${level.constraintDescription1}`)
if (simulation.difficultyMode > 6 && level.constraintDescription2) {
text += `<br>${level.constraintDescription2}`
if (level.constraintDescription2) simulation.inGameConsole(`<span style="color:#624;background-color: rgba(255, 215, 241, 0.4);">constraint</span>: ${level.constraintDescription2}`)
}
document.getElementById("right-HUD-constraint").innerHTML = text
if (level.constraintDescription1) {
if (level.constraintDescription2) {
document.getElementById("right-HUD").style.top = "80px";
@@ -2290,6 +2298,55 @@ const level = {
},
}
},
fizzler(p1, p2) {
return {
isOn: true,
position: p1,
look: p2,
color: color,
query() {
if (!m.isTimeDilated) {
// let best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null }
// best = vertexCollision(this.position, this.look, [body]);
const hits = Matter.Query.ray(body, this.position, this.look, 25)
for (let i = hits.length - 1; i > -1; i--) {
// console.log(what)
const what = hits[i].bodyA
simulation.drawList.push({ x: what.position.x, y: what.position.y, radius: 11, color: "rgba(0,160,255,0.7)", time: 10 });
if (what === m.holdingTarget) m.drop()
for (let i = 0; i < body.length; i++) {
if (body[i] === what) {
body.splice(i, 1);
break
}
}
Matter.Composite.remove(engine.world, what);
}
//draw
ctx.beginPath();
ctx.moveTo(this.position.x, this.position.y);
ctx.lineTo(this.look.x, this.look.y);
// ctx.strokeStyle = "rgba(50,200,255,0.3)";
// ctx.lineWidth = 2 + 5 * Math.random()
// ctx.stroke();
ctx.strokeStyle = "rgba(50,160,255,0.17)";
ctx.lineWidth = 35 + 25 * Math.random() * Math.random();
ctx.stroke();
//draw random dots in the path
if (Math.random() < 0.05) {
const r = Math.random();
const where = {
x: this.position.x + r * (this.look.x - this.position.x) + 60 * (Math.random() - 0.5),
y: this.position.y + r * (this.look.y - this.position.y) + 60 * (Math.random() - 0.5)
};
simulation.drawList.push({ x: where.x, y: where.y, radius: 6, color: "rgba(0,160,255,0.7)", time: 5 });
}
}
},
}
},
isHazardRise: false,
hazard(x, y, width, height, damage = 0.002) {
return {
@@ -2474,6 +2531,19 @@ const level = {
ctx.lineDashOffset = (-simulation.cycle * this.VxGoal) % 80;
ctx.stroke();
ctx.setLineDash([0, 0]);
},
drawFast() {
ctx.beginPath();
const v = this.vertices;
ctx.moveTo(v[0].x + 2, v[0].y);
// for (let i = 1; i < v.length; ++i) ctx.lineTo(v[i].x, v[i].y);
ctx.lineTo(v[1].x - 2, v[1].y);
ctx.strokeStyle = "#000"
ctx.lineWidth = 4;
ctx.setLineDash([60, 60]);
ctx.lineDashOffset = (-simulation.cycle * this.VxGoal) % 120;
ctx.stroke();
ctx.setLineDash([0, 0]);
}
});
Matter.Body.setStatic(rect, true); //make static
@@ -5410,7 +5480,7 @@ const level = {
if (badBlocks[j] === body[i]) index = i
}
//remove block
console.log(index, j)
// console.log(index, j)
if (index) {
Matter.Composite.remove(engine.world, badBlocks[j]);
body.splice(index, 1);
@@ -7199,7 +7269,7 @@ const level = {
let buildMapOutline = function () {
//boxes center on zero,zero with deep walls to hide background
spawn.mapRect(2000, -2000, 2000, 4000); //right map wall
spawn.mapRect(2025, -2000, 1975, 4000); //right map wall
spawn.mapRect(-4000, -2000, 2000, 4000); //left map wall
spawn.mapRect(-4000, -5000, 8000, 3000); //map ceiling
spawn.mapRect(-4000, 2000, 8000, 3000); //floor
@@ -7233,7 +7303,7 @@ const level = {
balance.push(level.rotor(-750, 1755, 400, 25, 0.01, Math.PI / 2, 0.5))
balance.push(level.rotor(-275, 1675, 550, 32, 0.01, 0, 0.5))
lasers.push(level.laser({ x: -1625, y: -850 }, { x: 1980, y: -850 })) ////x, y, width, height, damage = 0.002)
lasers.push(level.laser({ x: 1610, y: -850 }, { x: -1625, y: -850 })) ////x, y, width, height, damage = 0.002)
// spawn.mapRect(1980, -862, 25, 25); //laser entrance
// balance.push(level.rotor(1000, -910, 550, 32, 0.01, 0, 0.5))
@@ -7263,9 +7333,9 @@ const level = {
spawn.mapRect(1925, 800, 200, 200);
spawn.mapRect(1925, 1300, 200, 200);
spawn.mapRect(1400, 1650, 200, 25);
spawn.mapRect(1400, 1125, 200, 25);
spawn.mapRect(1400, 600, 200, 25);
spawn.mapRect(1250, 1650, 500, 25);
spawn.mapRect(1300, 1125, 400, 25);
spawn.mapRect(1350, 600, 300, 25);
spawn.mapRect(1400, 75, 200, 25);
spawn.mapRect(650, 1287, 475, 50);
@@ -7273,9 +7343,9 @@ const level = {
spawn.mapRect(650, 150, 500, 225);
spawn.mapRect(350, 1300, 800, 375);
spawn.mapRect(350, 950, 150, 400);
spawn.mapRect(175, 950, 325, 100);
spawn.mapRect(150, 525, 350, 200);
spawn.mapRect(150, 75, 350, 200);
spawn.mapRect(-25, 950, 525, 100);
spawn.mapRect(-75, 525, 575, 200);
spawn.mapRect(-75, 75, 575, 200);
spawn.mapRect(475, 1987, 550, 50);
//ceiling zone
@@ -7315,7 +7385,7 @@ const level = {
balance.push(level.rotor(-750, -1755 - 25, 400, 25, 0.01, Math.PI / 2, 0.5))
balance.push(level.rotor(-250, -1675 - 32, 500, 32, 0.01, 0, 0.5))
lasers.push(level.laser({ x: -1625, y: 850 }, { x: 1980, y: 850 })) ////x, y, width, height, damage = 0.002)
lasers.push(level.laser({ x: 1610, y: 850 }, { x: -1625, y: 850 })) ////x, y, width, height, damage = 0.002)
// spawn.mapRect(1980, 862 - 25, 25, 25); //laser entrance
// balance.push(level.rotor(1000, 910 - 32, 550, 32, 0.01, 0, 0.5))
@@ -7340,9 +7410,9 @@ const level = {
spawn.mapRect(1925, -800 - 200, 200, 200);
spawn.mapRect(1925, -1300 - 200, 200, 200);
spawn.mapRect(1400, -1650 - 25, 200, 25);
spawn.mapRect(1400, -1125 - 25, 200, 25);
spawn.mapRect(1400, -600 - 25, 200, 25);
spawn.mapRect(1250, -1650 - 25, 500, 25);
spawn.mapRect(1300, -1125 - 25, 400, 25);
spawn.mapRect(1350, -600 - 25, 300, 25);
spawn.mapRect(1400, -75 - 25, 200, 25);
spawn.mapRect(650, -1287 - 50, 475, 50);
@@ -7350,11 +7420,10 @@ const level = {
spawn.mapRect(650, -150 - 225, 500, 225);
spawn.mapRect(350, -1300 - 375, 800, 375);
spawn.mapRect(350, -950 - 400, 150, 400);
spawn.mapRect(175, -950 - 100, 325, 100);
spawn.mapRect(150, -525 - 200, 350, 200);
spawn.mapRect(150, -75 - 200, 350, 200);
spawn.mapRect(-25, -950 - 100, 525, 100);
spawn.mapRect(-75, -525 - 200, 575, 200);
spawn.mapRect(-75, -75 - 200, 575, 200);
spawn.mapRect(475, -1987 - 50, 550, 50);
//ceiling zone
spawn.mapRect(1200, 1575, 400, 25);
spawn.mapRect(-75, 1700, 1075, 25);
@@ -7463,16 +7532,16 @@ const level = {
//spawn second wave of flipped mobs only once
spawn.randomMob(-1500, -1425, 0);
spawn.randomMob(-950, -1425, 0);
spawn.randomMob(-800, -1475, 0.1);
spawn.randomMob(-425, -1425, 0.1);
spawn.randomMob(850, -1750, 0.2);
spawn.randomMob(325, -850, 0.2);
spawn.randomMob(400, -400, 0.3);
spawn.randomMob(825, -475, 0.3);
spawn.randomMob(875, -1050, 0.4);
spawn.randomMob(1425, 1425, 0.5);
spawn.randomMob(675, 1450, 0.7);
spawn.randomMob(225, 1475, 0.9);
spawn.randomMob(-800, -1475, 0);
spawn.randomMob(-425, -1425, 0);
spawn.randomMob(850, -1750, 0.1);
spawn.randomMob(325, -850, 0.1);
spawn.randomMob(400, -400, 0.2);
spawn.randomMob(825, -475, 0.2);
spawn.randomMob(875, -1050, 0.3);
spawn.randomMob(1425, 1425, 0.4);
spawn.randomMob(675, 1450, 0.5);
spawn.randomMob(225, 1475, 0.6);
spawn.randomMob(-275, 1425, 1);
spawn.randomMob(-800, 1375, 1);
@@ -7551,7 +7620,7 @@ const level = {
ctx.fillRect(-1075, -2025, 450, 725);
ctx.fillRect(-575, -2025, 450, 725);
ctx.fillRect(175, -250 - 725, 325, 725);
ctx.fillRect(-25, -250 - 725, 525, 725);
ctx.fillRect(650, -350 - 975, 475, 975);
ctx.fillRect(375, -1650 - 400, 750, 400);
//ceiling
@@ -7569,7 +7638,7 @@ const level = {
ctx.fillRect(-1075, 1300, 450, 725);
ctx.fillRect(-575, 1300, 450, 725);
ctx.fillRect(175, 250, 325, 725);
ctx.fillRect(-25, 250, 525, 725);
ctx.fillRect(650, 350, 475, 975);
ctx.fillRect(375, 1650, 750, 400);
//ceiling
@@ -7581,6 +7650,9 @@ const level = {
ctx.fillRect(-1625, -2025, 475, 450);
}
};
spawn.bodyRect(1325, -1775, 175, 175);
spawn.bodyRect(-375, -1725, 100, 75, 0.5);
spawn.bodyRect(-900, -1625, 125, 200, 0.5);
spawn.bodyRect(-1662, 1325, 25, 175);
spawn.bodyRect(-1662, 1825, 25, 175);
@@ -7601,24 +7673,24 @@ const level = {
spawn.randomMob(-1350, -1750, 0);
spawn.randomMob(-875, -1575, 0);
spawn.randomMob(500, -1875, 0);
spawn.randomMob(350, 825, 0.1);
spawn.randomMob(375, 400, 0.1);
spawn.randomMob(1500, -25, 0.2);
spawn.randomMob(650, -1950, 0.3);
spawn.randomMob(775, 700, 0.3);
spawn.randomMob(275, -50, 0.4);
spawn.randomMob(75, -1750, 0.5);
spawn.randomMob(1750, -1425, 0.5);
spawn.randomMob(950, 50, 0.6);
spawn.randomMob(-1375, 175, 0.6);
spawn.randomMob(-350, 175, 0.7);
spawn.randomMob(725, 1175, 0.7);
spawn.randomMob(-850, -1950, 0.8);
spawn.randomMob(-1400, -1725, 0.9);
spawn.randomMob(1400, -1700, 0.9);
spawn.randomMob(-800, 200, 0.9);
spawn.randomMob(1475, 1550, 1);
spawn.randomMob(1475, 500, 1);
spawn.randomMob(350, 825, 0);
spawn.randomMob(375, 400, 0);
spawn.randomMob(1500, -25, 0.1);
spawn.randomMob(650, -1950, 0.2);
spawn.randomMob(775, 700, 0.2);
spawn.randomMob(275, -50, 0.3);
spawn.randomMob(75, -1750, 0.3);
spawn.randomMob(1750, -1425, 0.4);
spawn.randomMob(950, 50, 0.4);
spawn.randomMob(-1375, 175, 0.4);
spawn.randomMob(-350, 175, 0.5);
spawn.randomMob(725, 1175, 0.5);
spawn.randomMob(-850, -1950, 0.6);
spawn.randomMob(-1400, -1725, 0.7);
spawn.randomMob(1400, -1700, 0.7);
spawn.randomMob(-800, 200, 0.7);
spawn.randomMob(1475, 1550, 0.8);
spawn.randomMob(1475, 500, 0.8);
powerUps.spawnStartingPowerUps(-875, -1925);
spawn.randomLevelBoss(-875, -200);
@@ -8155,45 +8227,256 @@ const level = {
powerUps.directSpawn(2100, 925, "heal");
powerUps.directSpawn(625, -100, "heal");
},
cocoon() {
corridor() {
// simulation.fallHeight = 4000
level.announceMobTypes()
level.setPosToSpawn(-3800, 950);
level.exit.x = 3750
level.exit.y = -625
level.defaultZoom = 2000
level.defaultZoom = 2400
simulation.zoomTransition(level.defaultZoom)
document.body.style.backgroundColor = "#d0d5d5";
color.map = "#444"
// level.isHorizontalFlipped = true
if (level.isHorizontalFlipped) {
level.setPosToSpawn(14075, -625);
level.exit.x = -350
level.exit.y = 505
spawn.bodyRect(13525, -675, 50, 100);
var color1 = "rgba(0,20,60,0.09)"
var color2 = "rgba(0,255,255,0.1)"
} else {
level.setPosToSpawn(-350, 475);
level.exit.x = 14025
level.exit.y = -600
spawn.bodyRect(-225, 475, 50, 50);
var color1 = "rgba(0,255,255,0.1)"
var color2 = "rgba(0,20,60,0.09)"
}
spawn.mapRect(14015, -585, 120, 75); //exit/entrance platform
const buttonLeft = level.button(-4100, 991)
const buttonRight = level.button(4050, 991)
buttonLeft.isUp = true
// const buttonCamera = level.button(940, -1545)
// buttonRight.isUp = false
const boosts = []
boosts.push(level.boost(-3650, 990, 2700, 1.45))
boosts.push(level.boost(3325, 990, 1600, 1.4))
boosts.push(level.boost(7960, -1110, 1650, 2.3))
boosts.push(level.boost(13345, -460, 2070, 2.35))
const fizzlers = []
fizzlers.push(level.fizzler({ x: -135, y: 265 }, { x: -135, y: 535 }))
fizzlers.push(level.fizzler({ x: -3850, y: 650 }, { x: -3850, y: 1025 }))
fizzlers.push(level.fizzler({ x: 3875, y: 675 }, { x: 3875, y: 1025 }))
fizzlers.push(level.fizzler({ x: 13425, y: -1275 }, { x: 13425, y: -550 }))
const movers = []
const baseMoverSpeed = 15
movers.push(level.mover(-3550, 995, 6875, 150, -baseMoverSpeed))
movers.push(level.mover(225, -1190, 2450, 50, -baseMoverSpeed))
movers.push(level.mover(-3000, -1190, 3000, 50, baseMoverSpeed))
movers.push(level.mover(4000, -2025, 2000, 150, -23))
movers.push(level.mover(8000, -1125, 2000, 150, -23))
movers.push(level.mover(3775, -425, 1650, 150, 20))
movers.push(level.mover(5425, -425, 1925, 150, 40))
movers.push(level.mover(7350, -425, 6000, 150, 60))
function setMoverDirection(index, VxGoal, force) {
movers[index].VxGoal = VxGoal
movers[index].force = force
}
level.custom = () => {
// buttonCamera.query()
// if (!buttonCamera.isUp) {
// simulation.setCameraPosition(100, -1000, 0.29)
// //block spawner
// spawn.mapRect(0, -2375, 200, 100);
// if (!(simulation.cycle % 10) && !m.isTimeDilated && body.length < 200) {
// const where = { x: 112, y: -3800 }
// // simulation.drawList.push({ x: where.x + 100 * (Math.random() - 0.5), y: where.y + 100 * (Math.random() - 0.5), radius: 11, color: "rgba(0,160,255,0.5)", time: 10 });
// let makeBlock = function (where, size) {
// const sides = Math.floor(4 + 6 * Math.random() * Math.random())
// body[body.length] = Matter.Bodies.polygon(where.x, where.y, sides, size, {
// friction: 0.05,
// frictionAir: 0.001,
// collisionFilter: {
// category: cat.body,
// mask: cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet
// },
// classType: "body",
// density: 0.001,
// });
// const who = body[body.length - 1]
// Composite.add(engine.world, who); //add to world
// }
// makeBlock({ x: where.x, y: where.y }, Math.floor(20 + 35 * Math.random() * Math.random()))
// }
// }
ctx.fillStyle = "#c8cccc"//background color is "#d0d5d5"
ctx.fillRect(-2150, 675, 500, 400);
ctx.fillRect(-1050, 675, 500, 400);
ctx.fillRect(750, 675, 500, 400);
ctx.fillRect(1850, 675, 500, 400);
ctx.fillRect(-2250, -2425, 700, 1325);
ctx.fillRect(-1150, -2400, 700, 1300);
ctx.fillRect(650, -2375, 700, 1325);
ctx.fillRect(1750, -2375, 700, 1350);
ctx.fillRect(8000, -2425, 2000, 2225);
ctx.fillRect(4000, -2375, 2000, 2100);
ctx.fillRect(11125, -2425, 1000, 2150)
level.exit.drawAndCheck();
level.enter.draw();
if (buttonRight.isUp) {
buttonRight.query();
if (!buttonRight.isUp) {
requestAnimationFrame(() => buttonLeft.isUp = true);
setMoverDirection(0, -baseMoverSpeed, -0.0005)
const list = Matter.Query.region(body, buttonLeft) //are any blocks colliding with this
if (list.length > 0) Matter.Body.setVelocity(list[0], { x: baseMoverSpeed, y: -20 });
}
} else if (buttonLeft.isUp) {
buttonLeft.query();
if (!buttonLeft.isUp) {
requestAnimationFrame(() => buttonRight.isUp = true);
setMoverDirection(0, 20, 0.0005)
const list = Matter.Query.region(body, buttonRight) //are any blocks colliding with this
if (list.length > 0) Matter.Body.setVelocity(list[0], { x: -15, y: -20 });
}
}
buttonRight.draw();
buttonLeft.draw();
for (let i = 0; i < movers.length; i++) movers[i].push();
for (let i = 0; i < boosts.length; i++) boosts[i].query();
};
level.customTopLayer = () => {
ctx.fillStyle = "rgba(0,255,255,0.1)" //"#d4f4f4" //exit
ctx.fillRect(3535, -1050, 500, 475);
for (let i = 0; i < fizzlers.length; i++) fizzlers[i].query();
ctx.fillStyle = color1 //exit
ctx.fillRect(13400, -1325, 1000, 825);
//shadows
ctx.fillStyle = "rgba(0,20,60,0.09)"
// ctx.fillRect(-4025, -1050, 1750, 2275);
ctx.fillStyle = color2
ctx.fillRect(-500, 225, 494, 350);
ctx.fillStyle = "rgba(0,5,10,0.06)"
ctx.beginPath();
ctx.moveTo(0, -1180)
ctx.lineTo(225, -1180)
ctx.lineTo(3220, 669)
ctx.lineTo(3180, 1010)
ctx.lineTo(-2960, 1010)
ctx.lineTo(-2995, 674)
ctx.fill()
ctx.beginPath();
//right button room
ctx.beginPath();
ctx.moveTo(3780, 720)
ctx.lineTo(4325, 720)
ctx.lineTo(4325, 1010)
ctx.lineTo(3810, 1010)
ctx.fill()
//left button room
ctx.beginPath();
ctx.moveTo(-3755, 675)
ctx.lineTo(-3785, 1010)
ctx.lineTo(-4250, 1010)
ctx.lineTo(-4250, 675)
ctx.fill()
ctx.fillStyle = "rgba(68, 68, 68,0.9)"
ctx.fillRect(-50, -4300, 325, 1950);
for (let i = 0; i < movers.length; i++) movers[i].draw();
};
//boxes center on zero,zero with deep walls to hide background
spawn.mapRect(4000, -2000, 2000, 4000); //right map wall
spawn.mapRect(-6000, -2000, 2000, 4000); //left map wall
spawn.mapRect(-6000, -4000, 12000, 3000); //map ceiling
spawn.mapRect(-6000, 1000, 12000, 3000); //floor
spawn.mapRect(-6000, -4300, 6020, 1950);
spawn.mapRect(205, -4300, 15120, 1950);
spawn.mapVertex(-250, 602.5, "-200 0 235 0 400 50 400 150 -200 150");
spawn.mapVertex(-3675, -2275, "0 0 500 0 0 500");
spawn.mapVertex(13275, -2275, "0 0 -500 0 0 500");
spawn.mapRect(-525, -1175, 525, 1450);
spawn.mapRect(225, -1175, 3000, 1850);
spawn.mapRect(-3000, -1175, 2525, 1850);
spawn.mapRect(-4350, -2500, 600, 3175);
spawn.mapRect(-6000, -2350, 1775, 3350);
spawn.mapVertex(-1900, 675, "-350 0 -250 100 250 100 350 0");
spawn.mapVertex(-800, 675, "-350 0 -250 100 250 100 350 0");
spawn.mapVertex(1000, 675, "-350 0 -250 100 250 100 350 0");
spawn.mapVertex(2100, 675, "-350 0 -250 100 250 100 350 0");
spawn.mapVertex(-1900, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(-800, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(1000, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(2100, -1450, "-400 -40 -350 -90 350 -90 400 -40 400 40 350 90 -350 90 -400 40");
spawn.mapVertex(-1900, -2350, "-450 0 -350 100 350 100 450 0");
spawn.mapVertex(-800, -2350, "-450 0 -350 100 350 100 450 0");
spawn.mapVertex(1000, -2350, "-450 0 -350 100 350 100 450 0");
spawn.mapVertex(2100, -2350, "-450 0 -350 100 350 100 450 0");
spawn.mapRect(-1500, 840, 300, 20);
spawn.mapRect(1400, 840, 300, 20);
//ramp to catch blocks
spawn.mapVertex(3001, -1260, "0 0 400 -200 550 -200 550 75 0 75");
spawn.mapVertex(4100, -1100, "-625 0 -600 -60 600 -60 625 0 600 60 -600 60");
spawn.mapVertex(5550, -750, "-625 0 -600 -60 600 -60 625 0 600 60 -600 60");
spawn.mapVertex(11625, -900, "-525 0 -500 -50 500 -50 525 0 500 50 -500 50");
//base for mover
spawn.mapVertex(5000, -1935, "-1050 0 -1000 -90 1000 -90 1050 0 1000 90 -1000 90");
spawn.mapVertex(9000, -1035, "-1050 0 -1000 -90 1000 -90 1050 0 1000 90 -1000 90");
spawn.mapVertex(5000, -2370, "-1200 0 -1000 100 1000 100 1200 0");
spawn.mapVertex(9000, -2310, "-1200 0 -1000 100 1000 100 1200 0");
spawn.mapVertex(11625, -2310, "-600 0 -500 100 500 100 600 0");
spawn.mapRect(3775, -400, 675, 1125);
spawn.mapRect(4300, -400, 11025, 4400);
//exit
spawn.mapRect(13400, -575, 1925, 300);
spawn.mapRect(14275, -2375, 1050, 2050);
spawn.mapRect(13400, -2375, 900, 1125);
// spawn.randomMob(2825, 75, 0.9);
// spawn.randomLevelBoss(2400, 600);
// spawn.secondaryBossChance(800, -300)
// powerUps.spawnStartingPowerUps(600, 375);
// powerUps.addResearchToLevel() //needs to run after mobs are spawned
//blocks on movers
spawn.bodyRect(-200, 950, 50, 50);
spawn.bodyRect(-1100, 925, 65, 75);
spawn.bodyRect(-2275, 975, 70, 25);
spawn.bodyRect(-3325, 925, 75, 75);
spawn.bodyRect(-2950, -1225, 90, 25);
spawn.bodyRect(-1425, -1275, 45, 75);
spawn.bodyRect(600, -1275, 70, 75);
spawn.bodyRect(1900, -1225, 90, 50);
spawn.bodyRect(4250, -2100, 115, 50);
spawn.bodyRect(2175, 900, 100, 65);
spawn.bodyRect(4075, -450, 75, 20);
spawn.bodyRect(8350, -1175, 90, 50);
spawn.bodyRect(6525, -525, 70, 100);
spawn.bodyRect(12025, -475, 130, 50);
spawn.bodyRect(625, 950, 55, 45);
spawn.bodyRect(6250, -450, 55, 25);
spawn.bodyRect(3950, -475, 46, 53);
//other blocks
spawn.bodyRect(3525, -1300, 100, 125, 0.6);
spawn.bodyRect(11550, -1150, 100, 200, 0.4);
spawn.randomMob(-1775, -1650, 0);
spawn.randomMob(950, -1775, 0);
spawn.randomMob(1550, 775, 0);
spawn.randomMob(4500, -1250, 0);
spawn.randomMob(11400, -1300, 0);
spawn.randomMob(-800, -1675, 0);
spawn.randomMob(-1325, 775, 0.1);
spawn.randomMob(2050, -1625, 0.1);
spawn.randomMob(3100, -1475, 0.2);
spawn.randomMob(5400, -900, 0.2);
spawn.randomMob(11950, -1025, 0.3);
spawn.randomMob(-925, -1700, 0.3);
spawn.randomMob(2025, -1725, 0.4);
spawn.randomMob(1575, 775, 0.4);
spawn.randomMob(-1350, 775, 0.6);
spawn.randomMob(11925, -1275, 0.6);
spawn.randomMob(4325, -1425, 0.6);
spawn.randomMob(5425, -950, 0.6);
spawn.randomMob(3575, 375, 0.6);
spawn.randomGroup(5300, -1400, 1.3);
spawn.randomLevelBoss(2025, -1825);
spawn.secondaryBossChance(-1900, -1800);
powerUps.spawnStartingPowerUps(11750, -1000);
powerUps.addResearchToLevel() //needs to run after mobs are spawned
},
lock() {
level.announceMobTypes()
@@ -8930,9 +9213,9 @@ const level = {
simulation.zoomTransition(level.defaultZoom)
powerUps.spawnStartingPowerUps(4900, -500); //1 per level
spawn.debris(1000, 20, 1800, 3); //16 debris per level //but less here because a few mobs die from laser
spawn.debris(4830, -1330, 850, 3); //16 debris per level
spawn.debris(3035, -3900, 1500, 3); //16 debris per level
spawn.debris(1000, 20, 1800, 6); //16 debris per level
// spawn.debris(4830, -1330, 850, 3); //16 debris per level
// spawn.debris(3035, -3900, 1500, 3); //16 debris per level
document.body.style.backgroundColor = "#dbdcde";
@@ -8998,6 +9281,11 @@ const level = {
spawn.mapRect(4100, -3450, 100, 850); //left top shelf
spawn.mapRect(4600, -3450, 100, 1850);
//steps up and down
spawn.mapVertex(4525, 250, "-650 0 -625 -20 625 -20 650 0");
spawn.mapVertex(4525, 237, "-550 0 -525 -20 525 -20 550 0");
// spawn.mapVertex(4525, 225, "-400 0 -375 -20 375 -20 400 0");
spawn.randomSmallMob(4400, -3500);
spawn.randomSmallMob(4800, -800);
spawn.randomMob(800, -2600);
@@ -36987,6 +37275,19 @@ const level = {
level.enter.draw();
level.exit.drawAndCheck();
//check if blocks are in the exit zone and destroy them
for (let i = 0; i < body.length; i++) {
if (body[i].position.x > 1675) {
Matter.Composite.remove(engine.world, body[i]);
body.splice(i, 1);
break
}
}
//if no blocks left make a new one
if (body.length < 2) { //< 2 because the door is a body
spawn.bodyRect(1025, -550, 50, 50);
}
};
level.customTopLayer = () => {
buttonDoor.query();
@@ -37076,6 +37377,18 @@ const level = {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
//check if blocks are in the exit zone and destroy them
for (let i = 0; i < body.length; i++) {
if (body[i].position.x > 1675 && body[i].position.y > -350) {
Matter.Composite.remove(engine.world, body[i]);
body.splice(i, 1);
break
}
}
//if no blocks left make a new one
if (body.length < 2) { //< 2 because the door is a body
spawn.bodyRect(1025, -550, 50, 50);
}
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall
@@ -37136,6 +37449,19 @@ const level = {
//exit room glow
ctx.fillStyle = "rgba(0,255,255,0.05)"
ctx.fillRect(1600, -400, 400, 400)
//check if blocks are in the exit zone and destroy them
for (let i = 0; i < body.length; i++) {
if (body[i].position.x > 1675 && body[i].position.y > -350) {
Matter.Composite.remove(engine.world, body[i]);
body.splice(i, 1);
break
}
}
//if no blocks left make a new one
if (body.length < 2) { //< 2 because the door is a body
spawn.bodyRect(1025, -550, 50, 50);
}
};
spawn.mapRect(-2750, -2800, 2600, 4600); //left wall

View File

@@ -41,23 +41,15 @@ const mobs = {
ctx.fillRect(x, y, w, h);
ctx.fillStyle = "rgba(255,0,0,0.7)";
ctx.fillRect(x, y, w * mob[i].health, h);
// if (mob[i].isInvulnerable) {
// ctx.strokeStyle = "rgba(255,255,255,1)";
// ctx.lineWidth = 5
// ctx.strokeRect(x, y, w, h);
// }
}
}
},
healthBar() {
for (let i = 0, len = mob.length; i < len; i++) {
if (mob[i].seePlayer.recall && mob[i].showHealthBar) {
const h = mob[i].radius * 0.3;
const w = mob[i].radius * 2;
const x = mob[i].position.x - w / 2;
const y = mob[i].position.y - w * 0.7;
ctx.fillStyle = "rgba(100, 100, 100, 0.3)";
ctx.fillRect(x, y, w, h);
ctx.fillStyle = "rgba(255,0,0,0.7)";
ctx.fillRect(x, y, w * mob[i].health, h);
}
}
},
healthBar() { },
statusSlow(who, cycles = 60) {
applySlow(who)
//look for mobs near the target
@@ -1384,7 +1376,7 @@ const mobs = {
//replace dead mob with a regular body
replace(i) {
//if there are too many bodies don't turn into blocks to help performance
if (this.leaveBody && body.length < mobs.maxMobBody && this.mass < 200 && this.radius > 18) {
if (this.leaveBody && body.length < mobs.maxMobBody && this.mass < 200 && this.mass > 2 && this.radius > 18) {
let v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
if (v.length > 5 && body.length < 35 && Math.random() < 0.25) {
const cutPoint = 3 + Math.floor((v.length - 6) * Math.random()) //Math.floor(v.length / 2)
@@ -1397,6 +1389,8 @@ const mobs = {
body[len].collisionFilter.category = cat.body;
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
body[len].classType = "body";
body[len].frictionAir = 0.001
body[len].friction = 0.05
Composite.add(engine.world, body[len]); //add to world
const len2 = body.length;
@@ -1406,6 +1400,8 @@ const mobs = {
body[len2].collisionFilter.category = cat.body;
body[len2].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
body[len2].classType = "body";
body[len2].frictionAir = 0.001
body[len2].friction = 0.05
Composite.add(engine.world, body[len2]); //add to world
//large mobs shrink so they don't block paths
@@ -1429,8 +1425,9 @@ const mobs = {
body[len].collisionFilter.category = cat.body;
body[len].collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet | cat.mob | cat.mobBullet;
body[len].classType = "body";
body[len].frictionAir = 0.001
body[len].friction = 0.05
Composite.add(engine.world, body[len]); //add to world
//large mobs shrink so they don't block paths
if (body[len].mass > 9) {
const massLimit = 7 + 4 * Math.random()

View File

@@ -782,7 +782,7 @@ const m = {
defense() {
let dmg = 1
if (powerUps.boost.isDefense && powerUps.boost.endCycle > simulation.cycle) dmg *= 0.3
if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.3
if (tech.isMaxHealthDefense && m.health === m.maxHealth) dmg *= 0.2
if (tech.isDiaphragm) dmg *= 0.55 + 0.35 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
if (tech.isFieldHarmReduction) dmg *= 0.6
@@ -1773,7 +1773,7 @@ const m = {
tungsten() {
m.hardLandCDScale = 2
m.hardLanding = 60
m.coyoteCycles = 0
// m.coyoteCycles = 0
m.isAltSkin = true
m.color = {
hue: 210,

View File

@@ -785,7 +785,7 @@ const powerUps = {
m.addHealth(heal);
if (healOutput > 0) simulation.inGameConsole(`<div class="circle-grid heal"></div> &nbsp; <span class='color-var'>m</span>.health <span class='color-symbol'>+=</span> ${(healOutput).toFixed(3)}`) // <br>${m.health.toFixed(3)}
if (tech.isOverHeal && overHeal > 0) { //tech quenching
tech.extraMaxHealth += 0.4 * overHeal //increase max health
tech.extraMaxHealth += 0.5 * overHeal //increase max health
m.setMaxHealth();
simulation.inGameConsole(`<div class="circle-grid heal"></div> &nbsp; <span class='color-var'>m</span>.maxHealth <span class='color-symbol'>+=</span> ${(0.3 * overHeal).toFixed(3)}`)
simulation.drawList.push({ //add dmg to draw queue

View File

@@ -558,14 +558,14 @@ const simulation = {
}
},
nextGun() {
if (b.inventory.length > 1 && !tech.isGunCycle) {
if (b.inventory.length > 1 && !(tech.isGunCycle || tech.isGunChoice)) {
b.inventoryGun++;
if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
simulation.switchGun();
}
},
previousGun() {
if (b.inventory.length > 1 && !tech.isGunCycle) {
if (b.inventory.length > 1 && !(tech.isGunCycle || tech.isGunChoice)) {
b.inventoryGun--;
if (b.inventoryGun < 0) b.inventoryGun = b.inventory.length - 1;
simulation.switchGun();
@@ -768,7 +768,7 @@ const simulation = {
}
},
setupCamera() { //makes the camera not scroll after changing locations
// //only works if velocity is zero
// only works if velocity is zero
m.pos.x = player.position.x;
m.pos.y = playerBody.position.y - m.yOff;
const scale = 0.8;
@@ -794,6 +794,20 @@ const simulation = {
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
},
//for moving camera away from player
setCameraPosition(x, y, zoom = 1) {
ctx.restore();
ctx.save();
ctx.translate(canvas.width2, canvas.height2); //center
ctx.scale(zoom, zoom); //zoom in once centered
ctx.translate(- x, - y); //center
// ctx.scale(simulation.zoom / simulation.edgeZoomOutSmooth, simulation.zoom / simulation.edgeZoomOutSmooth); //zoom in once centered
// ctx.translate(-canvas.width2, -canvas.height2); //translate
//calculate in game mouse position by undoing the zoom and translations
simulation.mouseInGame.x = (simulation.mouse.x - canvas.width2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.width2 - m.transX;
simulation.mouseInGame.y = (simulation.mouse.y - canvas.height2) / simulation.zoom * simulation.edgeZoomOutSmooth + canvas.height2 - m.transY;
},
cameraNoLook() {
ctx.save();
ctx.translate(canvas.width2, canvas.height2); //center

View File

@@ -1015,7 +1015,7 @@ const spawn = {
return
}
}
if (simulation.testing || simulation.difficultyMode > 5) {
if (simulation.testing || simulation.difficultyMode > 6) {
unlockExit()
setTimeout(function () {
simulation.inGameConsole(`level.levels.length <span class='color-symbol'>=</span> <strong>Infinite</strong>`);
@@ -2704,7 +2704,10 @@ const spawn = {
this.isInvulnerable = false
this.damageReduction = this.startingDamageReduction
for (let i = 0; i < this.babyList.length; i++) {
if (this.babyList[i].alive) this.babyList[i].damageReduction = this.startingDamageReduction
if (this.babyList[i].alive) {
this.babyList[i].isInvulnerable = false
this.babyList[i].damageReduction = this.startingDamageReduction
}
}
}
} else if (this.invulnerabilityCountDown < 0) {
@@ -6022,7 +6025,7 @@ const spawn = {
simulation.drawList.push({
x: this.position.x,
y: this.position.y,
radius: 3000,
radius: 5000,
color: `rgba(0, 0, 0,${1 - 0.1 * i})`,
time: (i + 2) * 4
});

View File

@@ -67,7 +67,7 @@ const tech = {
tech.junkChance += percent
if (tech.junkChance < 0.001 || tech.junkChance === undefined) tech.junkChance = 0
if (tech.junkChance > 1) tech.junkChance = 1
simulation.inGameConsole(`<strong>+${(100 * percent).toFixed(0)}%</strong> <span class='color-text'>JUNK</span><span class='color-var'>tech</span> chance (${(100 * tech.junkChance).toFixed(0)} total chance)`)
simulation.inGameConsole(`<strong>+${(100 * percent).toFixed(0)}%</strong> <span class='color-text'>JUNK</span><span class='color-var'>tech</span> chance (${(100 * tech.junkChance).toFixed(0)}% total chance)`)
// tech.junkChance += (1 - tech.junkChance) * percent
return percent
@@ -266,7 +266,7 @@ const tech = {
damageFromTech() {
let dmg = tech.damage * m.fieldDamage
if (level.isNoDamage && (m.cycle - 180 < level.noDamageCycle)) dmg *= 0.3
if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 1.5
if (tech.isMaxHealthDamage && m.health === m.maxHealth) dmg *= 2
if (tech.noDefenseSettingDamage && m.defense() === 1) dmg *= 2.5
if (tech.isImmunityDamage && m.immuneCycle > m.cycle) dmg *= 3
if (tech.isPowerUpDamage) dmg *= 1 + 0.07 * powerUp.length
@@ -275,7 +275,7 @@ const tech = {
if (tech.isDivisor && b.activeGun !== undefined && b.activeGun !== null && b.guns[b.activeGun].ammo % 3 === 0) dmg *= 1.9
if (tech.isNoGroundDamage) dmg *= m.onGround ? 0.9 : 2
if (tech.isDilate) dmg *= 1.9 + 1.1 * Math.sin(m.cycle * 0.01)
if (tech.isGunChoice && tech.buffedGun === b.inventoryGun) dmg *= 1 + 0.3 * b.inventory.length
if (tech.isGunChoice) dmg *= 1 + 0.4 * b.inventory.length
if (powerUps.boost.endCycle > simulation.cycle) dmg *= 1 + powerUps.boost.damage
if (m.coupling && (m.fieldMode === 0 || m.fieldMode === 5)) dmg *= 1 + 0.025 * m.coupling
if (tech.isVerlet) dmg *= 3
@@ -781,13 +781,16 @@ const tech = {
{
name: "pigeonhole principle",
descriptionFunction() {
let info = ""
if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
let gun = b.guns[b.inventory[tech.buffedGun]].name
info = `<br>this level: <strong>${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`
}
return `<span style = 'font-size:95%;'>a new ${powerUps.orb.gun()} in your inventory is <strong>chosen</strong> each <strong>level</strong><br>if it's equipped, <strong>1.3x</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.gun()} in your inventory${info}</span>`
return `<strong>1.4x</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()}<br>cycles each level and you can't <strong>switch</strong>`
},
// descriptionFunction() {
// let info = ""
// if (this.count > 0 && Number.isInteger(tech.buffedGun) && b.inventory.length) {
// let gun = b.guns[b.inventory[tech.buffedGun]].name
// info = `<br>this level: <strong>${(1.3 * Math.max(0, b.inventory.length)).toFixed(2)}x</strong> <strong class='color-d'>damage</strong> for <strong class="highlight">${gun}</strong>`
// }
// return `<span style = 'font-size:95%;'>a new ${powerUps.orb.gun()} in your inventory is <strong>chosen</strong> each <strong>level</strong><br>if it's equipped, <strong>1.3x</strong> <strong class='color-d'>damage</strong> per ${powerUps.orb.gun()} in your inventory${info}</span>`
// },
maxCount: 1,
count: 0,
frequency: 1,
@@ -807,7 +810,7 @@ const tech = {
},
{
name: "generalist",
description: `spawn <strong>7</strong> ${powerUps.orb.gun()}, but you can't <strong>switch</strong> ${powerUps.orb.gun()}<br>your equipped ${powerUps.orb.gun()} cycles after each level`,
description: `spawn <strong>7</strong> ${powerUps.orb.gun()}, but your equipped ${powerUps.orb.gun()}<br>cycles each level and you can't <strong>switch</strong>`,
maxCount: 1,
count: 0,
frequency: 1,
@@ -815,9 +818,9 @@ const tech = {
isInstant: true,
isBadRandomOption: true,
allowed() {
return (b.inventory.length < b.guns.length - 5) && (b.inventory.length > 1)
return (b.inventory.length < b.guns.length - 5) && b.inventory.length > 1
},
requires: "at least 2 guns, at least 5 unclaimed guns",
requires: "you have at least 2 guns and 5 unclaimed guns",
effect() {
tech.isGunCycle = true;
for (let i = 0; i < 7; i++) powerUps.spawn(m.pos.x + 10 * Math.random(), m.pos.y + 10 * Math.random(), "gun");
@@ -982,7 +985,7 @@ const tech = {
if (this.count === 0) this.gun = Math.floor(Math.random() * (b.guns.length - 1)) //don't pick laser
return `<strong>2x</strong> <strong class='color-ammo'>ammo</strong> per ${powerUps.orb.ammo(1)} for <strong class='color-g'>${b.guns[this.gun].name}</strong>`
},
maxCount: 9,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
@@ -1432,7 +1435,7 @@ const tech = {
name: "zoospore vector",
link: `<a target="_blank" href='https://en.wikipedia.org/wiki/Disease_vector' class="link">zoospore vector</a>`,
descriptionFunction() {
return `after mobs <strong>die</strong> there is a <strong>10%</strong> chance<br>they grow ${b.guns[6].nameString('s')}`
return `after mobs <strong>die</strong> there is a <strong>13%</strong> chance<br>they grow ${b.guns[6].nameString('s')}`
},
// description: "after mobs <strong>die</strong><br>they have a <strong>+10%</strong> chance to grow <strong class='color-p' style='letter-spacing: 2px;'>spores</strong>",
maxCount: 9,
@@ -1444,7 +1447,7 @@ const tech = {
},
requires: "no other mob death tech",
effect() {
tech.sporesOnDeath += 0.1;
tech.sporesOnDeath += 0.13;
// if (tech.isSporeWorm) {
// for (let i = 0; i < 4; i++) b.worm(m.pos)
// } else {
@@ -2890,7 +2893,7 @@ const tech = {
},
{
name: "overcharge",
description: "<strong>+88</strong> maximum <strong class='color-f'>energy</strong><br><strong>+4%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>",
description: "<strong>+100</strong> maximum <strong class='color-f'>energy</strong><br><strong>+5%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -2900,9 +2903,9 @@ const tech = {
},
requires: "",
effect() {
tech.bonusEnergy += 0.88
tech.bonusEnergy += 1
m.setMaxEnergy()
this.refundAmount += tech.addJunkTechToPool(0.04)
this.refundAmount += tech.addJunkTechToPool(0.05)
},
refundAmount: 0,
remove() {
@@ -3063,7 +3066,7 @@ const tech = {
{
name: "stability",
descriptionFunction() {
return `<strong>0.3x</strong> <strong class='color-defense'>damage taken</strong><br>while your <strong class='color-h'>health</strong> is at maximum`
return `<strong>0.2x</strong> <strong class='color-defense'>damage taken</strong><br>while your <strong class='color-h'>health</strong> is at maximum`
},
maxCount: 1,
count: 0,
@@ -3103,7 +3106,7 @@ const tech = {
{
name: "control theory",
descriptionFunction() {
return `<strong>1.5x</strong> <strong class='color-d'>damage</strong><br>while your <strong class='color-h'>health</strong> is at maximum`
return `<strong>2x</strong> <strong class='color-d'>damage</strong><br>while your <strong class='color-h'>health</strong> is at maximum`
},
maxCount: 1,
count: 0,
@@ -3329,7 +3332,7 @@ const tech = {
{
name: "quenching",
descriptionFunction() {
return `<strong>0.4x</strong> of ${powerUps.orb.heal()} over<strong class='color-h'>healing</strong><br>is added to <strong>maximum</strong> <strong class='color-h'>health</strong>`
return `<strong>0.5x</strong> of ${powerUps.orb.heal()} over<strong class='color-h'>healing</strong><br>is added to <strong>maximum</strong> <strong class='color-h'>health</strong>`
},
maxCount: 1,
count: 0,
@@ -3455,7 +3458,7 @@ const tech = {
return true
},
requires: "",
rate: 0.06,
rate: 0.05,
effect() {
tech.interestRate += this.rate;
},
@@ -4318,7 +4321,7 @@ const tech = {
},
{
name: "replication",
description: "<strong>+10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+15%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>",
description: "<strong>+10%</strong> chance to <strong class='color-dup'>duplicate</strong> spawned <strong>power ups</strong><br><strong>+10%</strong> <strong class='color-junk'>JUNK</strong> <strong class='color-choice'><span>ch</span><span>oi</span><span>ces</span></strong>",
maxCount: 9,
count: 0,
frequency: 1,
@@ -4331,7 +4334,7 @@ const tech = {
tech.duplicateChance += 0.1
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
if (!build.isExperimentSelection && !simulation.isTextLogOpen) simulation.circleFlare(0.1);
this.refundAmount += tech.addJunkTechToPool(0.15)
this.refundAmount += tech.addJunkTechToPool(0.10)
},
refundAmount: 0,
remove() {
@@ -5532,7 +5535,7 @@ const tech = {
},
{
name: "phase velocity",
description: "wave particles <strong>propagate</strong> faster as <strong>solids</strong><br><strong>1.4x</strong> wave <strong class='color-d'>damage</strong>",
description: "wave particles <strong>propagate</strong> faster as <strong>solids</strong><br><strong>1.5x</strong> wave <strong class='color-d'>damage</strong>",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -5584,11 +5587,11 @@ const tech = {
requires: "wave",
effect() {
tech.waveBeamSpeed *= 0.75;
tech.waveBeamDamage += 0.3 * 0.4 //this sets base wave damage
tech.waveBeamDamage *= 1.4 //this sets base wave damage
},
remove() {
tech.waveBeamSpeed = 11;
tech.waveBeamDamage = 0.3 //this sets base wave damage
tech.waveBeamDamage = 0.4 //this sets base wave damage
}
},
{