shield blocking
relativistic momentum: laser pushes harder and slows mobs a bit to give a more predictable effect laserBombingBoss targets faster at higher levels you can now block shielded mobs, but your shield gets disabled for a bit fixed bug that made perfect diamagnetism have trouble blocking too many things at once and more small bug fixes, of course
This commit is contained in:
131
js/bullet.js
131
js/bullet.js
@@ -957,23 +957,16 @@ const b = {
|
||||
bullet[me].beforeDmg = function() {};
|
||||
bullet[me].stuck = function() {};
|
||||
bullet[me].do = function() {
|
||||
function onCollide(that) {
|
||||
that.collisionFilter.mask = 0; //non collide with everything
|
||||
Matter.Body.setVelocity(that, {
|
||||
x: 0,
|
||||
y: 0
|
||||
});
|
||||
if (tech.isRPG) that.thrust = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
that.do = that.radiationMode;
|
||||
// if (collides(that, map).length || Matter.Query.collides(that, body).length || Matter.Query.collides(that, mob).length) {
|
||||
const onCollide = () => {
|
||||
this.collisionFilter.mask = 0; //non collide with everything
|
||||
Matter.Body.setVelocity(this, { x: 0, y: 0 });
|
||||
if (tech.isRPG) this.thrust = { x: 0, y: 0 }
|
||||
this.do = this.radiationMode;
|
||||
}
|
||||
|
||||
const mobCollisions = Matter.Query.collides(this, mob)
|
||||
if (mobCollisions.length) {
|
||||
onCollide(this)
|
||||
onCollide()
|
||||
this.stuckTo = mobCollisions[0].bodyA
|
||||
mobs.statusDoT(this.stuckTo, 0.5, 360) //apply radiation damage status effect on direct hits
|
||||
|
||||
@@ -1002,7 +995,7 @@ const b = {
|
||||
const bodyCollisions = Matter.Query.collides(this, body)
|
||||
if (bodyCollisions.length) {
|
||||
if (!bodyCollisions[0].bodyA.isNotHoldable) {
|
||||
onCollide(this)
|
||||
onCollide()
|
||||
this.stuckTo = bodyCollisions[0].bodyA
|
||||
//find the relative position for when the mob is at angle zero by undoing the mobs rotation
|
||||
this.stuckToRelativePosition = Vector.rotate(Vector.sub(this.position, this.stuckTo.position), -this.stuckTo.angle)
|
||||
@@ -1020,7 +1013,7 @@ const b = {
|
||||
}
|
||||
} else {
|
||||
if (Matter.Query.collides(this, map).length) {
|
||||
onCollide(this)
|
||||
onCollide()
|
||||
} else if (tech.isRPG) { //if colliding with nothing
|
||||
this.force.x += this.thrust.x;
|
||||
this.force.y += this.thrust.y;
|
||||
@@ -1142,7 +1135,7 @@ const b = {
|
||||
// const futurePos = this.lockedOn ? :Vector.add(this.position, Vector.mult(this.velocity, 50))
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
mob[i].alive && !mob[i].isBadTarget && !mob[i].isBadTarget &&
|
||||
mob[i].alive && !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
|
||||
) {
|
||||
@@ -1525,7 +1518,8 @@ const b = {
|
||||
});
|
||||
if (tech.isLaserPush) { //push mobs away
|
||||
const index = path.length - 1
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.0035 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.94, y: best.who.velocity.y * 0.94 });
|
||||
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.006 * push * Math.min(6, best.who.mass))
|
||||
Matter.Body.applyForce(best.who, path[index], force)
|
||||
}
|
||||
}
|
||||
@@ -3123,7 +3117,11 @@ const b = {
|
||||
if (this.cd < simulation.cycle && !(simulation.cycle % this.lookFrequency) && !m.isCloak) {
|
||||
for (let i = 0, len = mob.length; i < len; i++) {
|
||||
const dist2 = Vector.magnitudeSquared(Vector.sub(this.position, mob[i].position));
|
||||
if (Matter.Query.ray(map, this.position, mob[i].position).length === 0 && dist2 > 250000) {
|
||||
if (
|
||||
mob[i].alive && !mob[i].isBadTarget &&
|
||||
dist2 > 250000 &&
|
||||
Matter.Query.ray(map, this.position, mob[i].position).length === 0
|
||||
) {
|
||||
this.cd = simulation.cycle + this.delay;
|
||||
const angle = Vector.angle(this.position, mob[i].position)
|
||||
Matter.Body.setAngle(this, angle)
|
||||
@@ -4750,48 +4748,30 @@ const b = {
|
||||
name: "drones",
|
||||
description: "deploy drones that <strong>crash</strong> into mobs<br>crashes reduce their <strong>lifespan</strong> by 1 second",
|
||||
ammo: 0,
|
||||
ammoPack: 14,
|
||||
defaultAmmoPack: 14,
|
||||
ammoPack: 14.5,
|
||||
defaultAmmoPack: 14.5,
|
||||
have: false,
|
||||
do() {},
|
||||
fire() {
|
||||
if (tech.isDroneRadioactive) {
|
||||
if (m.crouch) {
|
||||
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(5 * 13 * b.fireCDscale); // cool down
|
||||
m.fireCDcycle = m.cycle + Math.floor(50 * b.fireCDscale); // cool down
|
||||
} else {
|
||||
b.droneRadioactive({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 10)
|
||||
m.fireCDcycle = m.cycle + Math.floor(5 * 6 * b.fireCDscale); // cool down
|
||||
m.fireCDcycle = m.cycle + Math.floor(25 * b.fireCDscale); // cool down
|
||||
}
|
||||
} else {
|
||||
if (m.crouch) {
|
||||
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 45)
|
||||
m.fireCDcycle = m.cycle + Math.floor(13 * b.fireCDscale); // cool down
|
||||
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 55)
|
||||
m.fireCDcycle = m.cycle + Math.floor(10 * b.fireCDscale); // cool down
|
||||
} else {
|
||||
b.drone()
|
||||
m.fireCDcycle = m.cycle + Math.floor(6 * b.fireCDscale); // cool down
|
||||
b.drone({ x: m.pos.x + 30 * Math.cos(m.angle) + 10 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 10 * (Math.random() - 0.5) }, 20)
|
||||
m.fireCDcycle = m.cycle + Math.floor(5 * b.fireCDscale); // cool down
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// {
|
||||
// name: "ice IX",
|
||||
// description: "synthesize <strong>short-lived</strong> ice crystals<br>crystals <strong>seek</strong> out and <strong class='color-s'>freeze</strong> mobs",
|
||||
// ammo: 0,
|
||||
// ammoPack: 64,
|
||||
// have: false,
|
||||
// do() {},
|
||||
// fire() {
|
||||
// if (m.crouch) {
|
||||
// b.iceIX(10, 0.3)
|
||||
// m.fireCDcycle = m.cycle + Math.floor(8 * b.fireCDscale); // cool down
|
||||
// } else {
|
||||
// b.iceIX(2)
|
||||
// m.fireCDcycle = m.cycle + Math.floor(3 * b.fireCDscale); // cool down
|
||||
// }
|
||||
|
||||
// }
|
||||
// },
|
||||
{
|
||||
name: "foam",
|
||||
description: "spray bubbly foam that <strong>sticks</strong> to mobs<br><strong class='color-s'>slows</strong> mobs and does <strong class='color-d'>damage</strong> over time",
|
||||
@@ -4812,7 +4792,36 @@ const b = {
|
||||
|
||||
if (this.isDischarge) {
|
||||
this.charge--
|
||||
this.fireFoam()
|
||||
const spread = (m.crouch ? 0.05 : 0.6) * (Math.random() - 0.5)
|
||||
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
|
||||
const SPEED = 18 - radius * 0.4;
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = {
|
||||
x: SPEED * Math.cos(dir),
|
||||
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)
|
||||
// (tech.isFastFoam ? 0.044 : 0.011) * (tech.isFoamTeleport ? 1.60 : 1)
|
||||
bullet[bullet.length - 1].damage *= (1 + 0.75 * tech.foamFutureFire)
|
||||
}
|
||||
}, 250 * tech.foamFutureFire);
|
||||
} else {
|
||||
b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
}
|
||||
m.fireCDcycle = m.cycle + 1; //disable firing and adding more charge
|
||||
} else if (!input.fire) {
|
||||
this.isDischarge = true;
|
||||
@@ -4825,38 +4834,6 @@ const b = {
|
||||
this.charge++
|
||||
m.fireCDcycle = m.cycle + Math.floor((1 + 0.35 * this.charge) * b.fireCDscale);
|
||||
},
|
||||
fireFoam() {
|
||||
const spread = (m.crouch ? 0.05 : 0.6) * (Math.random() - 0.5)
|
||||
const radius = 5 + 8 * Math.random() + (tech.isAmmoFoamSize && this.ammo < 300) * 12
|
||||
const SPEED = 18 - radius * 0.4;
|
||||
const dir = m.angle + 0.15 * (Math.random() - 0.5)
|
||||
const velocity = {
|
||||
x: SPEED * Math.cos(dir),
|
||||
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)
|
||||
// (tech.isFastFoam ? 0.044 : 0.011) * (tech.isFoamTeleport ? 1.60 : 1)
|
||||
bullet[bullet.length - 1].damage *= (1 + 0.75 * tech.foamFutureFire)
|
||||
}
|
||||
}, 250 * tech.foamFutureFire);
|
||||
} else {
|
||||
b.foam(position, Vector.rotate(velocity, spread), radius)
|
||||
}
|
||||
}
|
||||
}, {
|
||||
name: "rail gun",
|
||||
description: "use <strong class='color-f'>energy</strong> to launch a high-speed <strong>dense</strong> rod<br><strong>hold</strong> left mouse to charge, <strong>release</strong> to fire",
|
||||
|
||||
17
js/level.js
17
js/level.js
@@ -12,7 +12,7 @@ const level = {
|
||||
start() {
|
||||
if (level.levelsCleared === 0) { //this code only runs on the first level
|
||||
// localSettings.levelsClearedLastGame = 10
|
||||
// level.difficultyIncrease(10) //30 is near max on hard //60 is near max on why
|
||||
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||
// simulation.isHorizontalFlipped = true
|
||||
// tech.isFieldFree = true
|
||||
// m.setField("perfect diamagnetism")
|
||||
@@ -2267,12 +2267,16 @@ const level = {
|
||||
spawn.mapRect(5050, -100, 50, 150);
|
||||
spawn.mapRect(4850, -275, 50, 175);
|
||||
// level.difficultyIncrease(30) //30 is near max on hard //60 is near max on why
|
||||
// spawn.starter(1900, -500, 200) //big boy
|
||||
spawn.starter(1900, -500, 200) //big boy
|
||||
// spawn.spiderBoss(1900, -500)
|
||||
// spawn.laserBombingBoss(1900, -500)
|
||||
// for (let i = 0; i < 5; i++) spawn.focuser(1900, -500)
|
||||
|
||||
// spawn.growBossCulture(1900, -500)
|
||||
spawn.laserBombingBoss(1900, -500)
|
||||
// spawn.snakeSpitBoss(1900, -500)
|
||||
// spawn.growBossCulture(1900, -500)
|
||||
// spawn.sneaker(1900, -500)
|
||||
spawn.sneaker(1900, -500)
|
||||
spawn.sneaker(1900, -500)
|
||||
spawn.shield(mob[mob.length - 1], 1900, -500, 1);
|
||||
// mob[mob.length - 1].isShielded = true
|
||||
// spawn.historyBoss(1200, -500)
|
||||
// spawn.laserTargetingBoss(1600, -400)
|
||||
// spawn.focuser(1600, -500)
|
||||
@@ -2284,7 +2288,6 @@ const level = {
|
||||
// spawn.cellBossCulture(1600, -500)
|
||||
// spawn.laserTargetingBoss(1600, -500)
|
||||
// spawn.grenadierBoss(1200, -500)
|
||||
// spawn.shield(mob[mob.length - 1], 1800, -120, 1);
|
||||
|
||||
// spawn.nodeGroup(1200, -500, "grenadier")
|
||||
// spawn.snakeBoss(1200, -500)
|
||||
|
||||
@@ -305,7 +305,7 @@ const lore = {
|
||||
lore.talkingColor = "#dff"
|
||||
level.isHazardRise = true
|
||||
//remove all bullets, so they can't get endless energy
|
||||
for (let i = 0; i < bullet.length; ++i) Matter.Composite.remove(engine.world, bullet[i]);
|
||||
for (let i = 0; i < bullet.length; ++i) Matter.World.remove(engine.world, bullet[i]);
|
||||
bullet = [];
|
||||
setTimeout(() => { lore.anand.text("I'm actually surprised you haven't been attacked by the adversarial network this time.") }, 500);
|
||||
},
|
||||
|
||||
118
js/player.js
118
js/player.js
@@ -1332,12 +1332,13 @@ const m = {
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < m.fieldRange &&
|
||||
!mob[i].isShielded &&
|
||||
m.lookingAt(mob[i]) &&
|
||||
!mob[i].isUnblockable &&
|
||||
Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
) {
|
||||
mob[i].locatePlayer();
|
||||
m.pushMass(mob[i]);
|
||||
if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 60
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1499,7 +1500,7 @@ const m = {
|
||||
ctx.fill();
|
||||
//360 block
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netfieldRange && !mob[i].isShielded) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < netfieldRange && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
mob[i].locatePlayer();
|
||||
if (this.drainCD > m.cycle) {
|
||||
m.pushMass(mob[i], 0);
|
||||
@@ -1507,6 +1508,7 @@ const m = {
|
||||
m.pushMass(mob[i]);
|
||||
this.drainCD = m.cycle + 10
|
||||
}
|
||||
if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1527,7 +1529,7 @@ const m = {
|
||||
}
|
||||
//360 block
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < radius && !mob[i].isShielded) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) - mob[i].radius < radius && !mob[i].isUnblockable) { // && Matter.Query.ray(map, mob[i].position, m.pos).length === 0
|
||||
mob[i].locatePlayer();
|
||||
if (this.drainCD > m.cycle) {
|
||||
m.pushMass(mob[i], 0);
|
||||
@@ -1535,6 +1537,7 @@ const m = {
|
||||
m.pushMass(mob[i]);
|
||||
this.drainCD = m.cycle + 10
|
||||
}
|
||||
if (mob[i].isShielded) m.fieldCDcycle = m.cycle + 45
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1584,27 +1587,25 @@ const m = {
|
||||
m.fieldPosition = { x: m.pos.x, y: m.pos.y }
|
||||
m.fieldAngle = m.angle
|
||||
m.perfectPush = (isFree = false) => {
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) - mob[i].radius < m.fieldRange &&
|
||||
!mob[i].isShielded &&
|
||||
Vector.dot({ x: Math.cos(m.fieldAngle), y: Math.sin(m.fieldAngle) }, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
|
||||
Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
|
||||
) {
|
||||
mob[i].locatePlayer();
|
||||
|
||||
const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
|
||||
if (m.fieldCDcycle < m.cycle) {
|
||||
m.fieldCDcycle = m.cycle + m.fieldBlockCD;
|
||||
if (m.fieldCDcycle < m.cycle) {
|
||||
for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
if (
|
||||
Vector.magnitude(Vector.sub(mob[i].position, m.fieldPosition)) - mob[i].radius < m.fieldRange &&
|
||||
!mob[i].isUnblockable &&
|
||||
Vector.dot({ x: Math.cos(m.fieldAngle), y: Math.sin(m.fieldAngle) }, Vector.normalise(Vector.sub(mob[i].position, m.fieldPosition))) > m.fieldThreshold &&
|
||||
Matter.Query.ray(map, mob[i].position, m.fieldPosition).length === 0
|
||||
) {
|
||||
mob[i].locatePlayer();
|
||||
const unit = Vector.normalise(Vector.sub(m.fieldPosition, mob[i].position))
|
||||
m.fieldCDcycle = m.cycle + m.fieldBlockCD + (mob[i].isShielded ? 15 : 0);
|
||||
if (tech.blockingIce) {
|
||||
for (let i = 0; i < tech.blockingIce; i++) {
|
||||
const angle = m.fieldAngle + 1.55 * (Math.random() - 0.5)
|
||||
b.iceIX(10, angle, Vector.add(m.fieldPosition, { x: m.fieldRange * Math.cos(angle), y: m.fieldRange * Math.sin(angle) }))
|
||||
}
|
||||
}
|
||||
if (tech.blockDmg) {
|
||||
if (tech.blockDmg) { //electricity
|
||||
mob[i].damage(tech.blockDmg * b.dmgScale)
|
||||
//draw electricity
|
||||
const step = 40
|
||||
ctx.beginPath();
|
||||
for (let i = 0, len = 1.5 * tech.blockDmg; i < len; i++) {
|
||||
@@ -1622,32 +1623,9 @@ const m = {
|
||||
ctx.stroke();
|
||||
} else if (isFree) {
|
||||
//when blocking draw this graphic
|
||||
// const len = mob[i].vertices.length - 1;
|
||||
ctx.fillStyle = "rgba(110,170,200," + (0.2 + 0.4 * Math.random()) + ")";
|
||||
ctx.lineWidth = 2;
|
||||
ctx.strokeStyle = "#000";
|
||||
// const angleOff = m.fieldAngle + 2 * m.fieldArc * (Math.random() - 0.5)
|
||||
// const off = {
|
||||
// x: m.fieldRange * Math.cos(angleOff),
|
||||
// y: m.fieldRange * Math.sin(angleOff),
|
||||
// }
|
||||
// const where = Vector.add(m.fieldPosition, off)
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(where.x, where.y);
|
||||
// ctx.lineTo(mob[i].vertices[len].x, mob[i].vertices[len].y);
|
||||
// ctx.lineTo(mob[i].vertices[0].x, mob[i].vertices[0].y);
|
||||
// ctx.fill();
|
||||
// ctx.stroke();
|
||||
// for (let j = 0; j < len; j++) {
|
||||
// ctx.beginPath();
|
||||
// ctx.moveTo(where.x, where.y);
|
||||
// ctx.lineTo(mob[i].vertices[j].x, mob[i].vertices[j].y);
|
||||
// ctx.lineTo(mob[i].vertices[j + 1].x, mob[i].vertices[j + 1].y);
|
||||
// ctx.fill();
|
||||
// ctx.stroke();
|
||||
// }
|
||||
|
||||
|
||||
const len = mob[i].vertices.length - 1;
|
||||
const mag = mob[i].radius
|
||||
ctx.beginPath();
|
||||
@@ -1681,31 +1659,26 @@ const m = {
|
||||
}
|
||||
}
|
||||
if (tech.isStunField) mobs.statusStun(mob[i], tech.isStunField)
|
||||
//knock backs
|
||||
const massRoot = Math.sqrt(Math.max(0.15, mob[i].mass));
|
||||
//mob knock backs
|
||||
const massRoot = Math.sqrt(Math.max(1, mob[i].mass));
|
||||
Matter.Body.setVelocity(mob[i], {
|
||||
x: player.velocity.x - (20 * unit.x) / massRoot,
|
||||
y: player.velocity.y - (20 * unit.y) / massRoot
|
||||
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 (isFree) {
|
||||
|
||||
} else {
|
||||
if (mob[i].isDropPowerUp && player.speed < 12) {
|
||||
const massRootCap = Math.sqrt(Math.min(10, Math.max(0.2, mob[i].mass)));
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap,
|
||||
y: 0.9 * player.velocity.y + 0.6 * unit.y * massRootCap
|
||||
});
|
||||
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)));
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: 0.9 * player.velocity.x + 0.6 * unit.x * massRootCap,
|
||||
y: 0.9 * player.velocity.y + 0.6 * unit.y * massRootCap
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m.hold = function() {
|
||||
const wave = Math.sin(m.cycle * 0.022);
|
||||
m.fieldRange = 190 + 12 * wave
|
||||
@@ -1744,13 +1717,12 @@ const m = {
|
||||
cp1y = m.pos.y + curve * m.fieldRange * Math.sin(a)
|
||||
ctx.quadraticCurveTo(cp1x, cp1y, m.pos.x + 1 * m.fieldRange * Math.cos(m.angle - Math.PI * m.fieldArc), m.pos.y + 1 * m.fieldRange * Math.sin(m.angle - Math.PI * m.fieldArc))
|
||||
ctx.fill();
|
||||
// m.pushMobsFacing();
|
||||
m.perfectPush();
|
||||
} else if (m.holdingTarget && m.fieldCDcycle < m.cycle) { //holding, but field button is released
|
||||
m.pickUp();
|
||||
} else {
|
||||
m.holdingTarget = null; //clears holding target (this is so you only pick up right after the field button is released and a hold target exists)
|
||||
if (tech.isFieldFree && !input.field) {
|
||||
if (!input.field) { //tech.isFieldFre
|
||||
//draw field free of player
|
||||
ctx.fillStyle = "rgba(110,170,200," + (0.27 + 0.2 * Math.random() - 0.1 * wave) + ")";
|
||||
ctx.strokeStyle = "rgba(110, 200, 235, " + (0.4 + 0.5 * Math.random()) + ")"
|
||||
@@ -1769,7 +1741,7 @@ const m = {
|
||||
}
|
||||
m.drawFieldMeter()
|
||||
if (tech.isPerfectBrake) { //cap mob speed around player
|
||||
const range = 160 + 140 * wave + 200 * m.energy
|
||||
const range = 200 + 140 * wave + 150 * m.energy
|
||||
for (let i = 0; i < mob.length; i++) {
|
||||
const distance = Vector.magnitude(Vector.sub(m.pos, mob[i].position))
|
||||
if (distance < range) {
|
||||
@@ -2705,6 +2677,26 @@ const m = {
|
||||
y: powerUp[i].velocity.y * 0.05
|
||||
});
|
||||
if (dist2 < 1000 && !simulation.isChoosing) { //use power up if it is close enough
|
||||
|
||||
// if (true) { //AoE radiation effect
|
||||
// const range = 800
|
||||
|
||||
// for (let i = 0, len = mob.length; i < len; ++i) {
|
||||
// if (mob[i].alive && !mob[i].isShielded) {
|
||||
// dist = Vector.magnitude(Vector.sub(powerUp[i].position, mob[i].position)) - mob[i].radius;
|
||||
// if (dist < range) mobs.statusDoT(mob[i], 0.5) //apply radiation damage status effect on direct hits
|
||||
// }
|
||||
// }
|
||||
|
||||
// simulation.drawList.push({
|
||||
// x: powerUp[i].position.x,
|
||||
// y: powerUp[i].position.y,
|
||||
// radius: range,
|
||||
// color: "rgba(0,150,200,0.3)",
|
||||
// time: 4
|
||||
// });
|
||||
// }
|
||||
|
||||
m.fieldRange *= 0.8
|
||||
powerUps.onPickUp(powerUp[i]);
|
||||
powerUp[i].effect();
|
||||
@@ -2846,19 +2838,19 @@ const m = {
|
||||
) {
|
||||
const sub = Vector.sub(simulation.mouseInGame, m.pos)
|
||||
const mag = Vector.magnitude(sub)
|
||||
const drain = 0.03 + 0.005 * Math.sqrt(mag)
|
||||
const drain = 0.06 + 0.006 * Math.sqrt(mag)
|
||||
if (m.energy > drain && mag > 300) {
|
||||
m.energy -= drain
|
||||
m.hole.isReady = false;
|
||||
m.fieldRange = 0
|
||||
Matter.Body.setPosition(player, simulation.mouseInGame);
|
||||
m.buttonCD_jump = 0 //this might fix a bug with jumping
|
||||
const velocity = Vector.mult(Vector.normalise(sub), 18)
|
||||
const velocity = Vector.mult(Vector.normalise(sub), 20)
|
||||
Matter.Body.setVelocity(player, {
|
||||
x: velocity.x,
|
||||
y: velocity.y - 4 //an extra vertical kick so the player hangs in place longer
|
||||
});
|
||||
if (m.immuneCycle < m.cycle + tech.collisionImmuneCycles) m.immuneCycle = m.cycle + tech.collisionImmuneCycles; //player is immune to damage
|
||||
if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 15; //player is immune to damage for 1/4 seconds
|
||||
// move bots to player
|
||||
for (let i = 0; i < bullet.length; i++) {
|
||||
if (bullet[i].botType) {
|
||||
|
||||
@@ -812,13 +812,13 @@ const simulation = {
|
||||
if (tech.isFlipFlopOn) {
|
||||
if (m.immuneCycle < m.cycle) m.energy += 0.22;
|
||||
} else {
|
||||
m.energy -= 0.041;
|
||||
m.energy -= 0.022;
|
||||
if (m.energy < 0) m.energy = 0
|
||||
}
|
||||
}
|
||||
if (tech.relayIce && tech.isFlipFlopOn) {
|
||||
for (let j = 0; j < tech.relayIce; j++) {
|
||||
for (let i = 0, len = Math.ceil(8 * Math.random()); i < len; i++) b.iceIX(2)
|
||||
for (let i = 0, len = Math.ceil(9 * Math.random()); i < len; i++) b.iceIX(2)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
49
js/spawn.js
49
js/spawn.js
@@ -110,6 +110,7 @@ const spawn = {
|
||||
me.isShielded = true; //makes it immune to damage
|
||||
me.leaveBody = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.collisionFilter.category = 0;
|
||||
@@ -166,6 +167,7 @@ const spawn = {
|
||||
me.isShielded = true; //makes it immune to damage
|
||||
me.leaveBody = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.collisionFilter.category = 0;
|
||||
@@ -1998,19 +2000,19 @@ const spawn = {
|
||||
|
||||
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
|
||||
Matter.Body.rotate(me, Math.random() * Math.PI * 2);
|
||||
me.accelMag = 0.0005 * Math.sqrt(simulation.accelScale);
|
||||
me.accelMag = 0.00055 * Math.sqrt(simulation.accelScale);
|
||||
me.seePlayerFreq = Math.floor(30 * simulation.lookFreqScale);
|
||||
me.memory = 420;
|
||||
me.restitution = 1;
|
||||
me.frictionAir = 0.05;
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.lookTorque = 0.000005 * (Math.random() > 0.5 ? -1 : 1);
|
||||
me.lookTorque = 0.0000055 * (Math.random() > 0.5 ? -1 : 1) * (1 + 0.1 * Math.sqrt(simulation.difficulty))
|
||||
me.fireDir = {
|
||||
x: 0,
|
||||
y: 0
|
||||
}
|
||||
Matter.Body.setDensity(me, 0.008); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
Matter.Body.setDensity(me, 0.01); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
spawn.shield(me, x, y, 1);
|
||||
spawn.spawnOrbitals(me, radius + 200 + 300 * Math.random())
|
||||
me.onHit = function() {};
|
||||
@@ -2019,7 +2021,7 @@ const spawn = {
|
||||
};
|
||||
me.damageReduction = 0.25
|
||||
me.targetingCount = 0;
|
||||
me.targetingTime = 60 - Math.min(55, 2 * simulation.difficulty)
|
||||
me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty)
|
||||
me.do = function() {
|
||||
// this.armor();
|
||||
this.seePlayerByLookingAt();
|
||||
@@ -2103,7 +2105,7 @@ const spawn = {
|
||||
this.targetingCount -= 10;
|
||||
const sub = Vector.sub(player.position, this.position)
|
||||
const dist = Vector.magnitude(sub)
|
||||
const speed = 30
|
||||
const speed = Math.min(55, 5 + 20 * simulation.accelScale)
|
||||
const velocity = Vector.mult(Vector.normalise(sub), speed)
|
||||
spawn.grenade(this.vertices[1].x, this.vertices[1].y, dist / speed, Math.min(550, 250 + simulation.difficulty * 3), 6); // grenade(x, y, lifeSpan = 90 + Math.ceil(60 / simulation.accelScale), pulseRadius = Math.min(550, 250 + simulation.difficulty * 3), size = 4) {
|
||||
Matter.Body.setVelocity(mob[mob.length - 1], velocity);
|
||||
@@ -2125,15 +2127,15 @@ const spawn = {
|
||||
ctx.moveTo(this.vertices[1].x, this.vertices[1].y);
|
||||
ctx.lineTo(best.x, best.y);
|
||||
ctx.strokeStyle = "rgba(0,235,255,1)";
|
||||
ctx.lineWidth = 2
|
||||
ctx.lineWidth = 3
|
||||
ctx.stroke();
|
||||
if (this.targetingCount / this.targetingTime > 0.33) {
|
||||
ctx.strokeStyle = "rgba(0,235,255,0.4)";
|
||||
ctx.lineWidth = 8
|
||||
ctx.strokeStyle = "rgba(0,235,255,0.45)";
|
||||
ctx.lineWidth = 10
|
||||
ctx.stroke();
|
||||
if (this.targetingCount / this.targetingTime > 0.66) {
|
||||
ctx.strokeStyle = "rgba(0,235,255,0.2)";
|
||||
ctx.lineWidth = 25
|
||||
ctx.strokeStyle = "rgba(0,235,255,0.25)";
|
||||
ctx.lineWidth = 30
|
||||
ctx.stroke();
|
||||
}
|
||||
}
|
||||
@@ -2144,20 +2146,20 @@ const spawn = {
|
||||
};
|
||||
},
|
||||
blinkBoss(x, y) {
|
||||
mobs.spawn(x, y, 5, 50, "rgb(215,80,190)"); //"rgb(221,102,119)"
|
||||
mobs.spawn(x, y, 5, 50, "rgb(0,235,255)"); //"rgb(221,102,119)"
|
||||
let me = mob[mob.length - 1];
|
||||
Matter.Body.rotate(me, Math.PI * 0.1);
|
||||
Matter.Body.setDensity(me, 0.02); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
Matter.Body.setDensity(me, 0.018); //extra dense //normal is 0.001 //makes effective life much larger
|
||||
me.isBoss = true;
|
||||
|
||||
me.frictionStatic = 0;
|
||||
me.friction = 0;
|
||||
me.memory = 240
|
||||
me.seePlayerFreq = 60
|
||||
me.delay = 20 + 30 * simulation.CDScale;
|
||||
me.delay = 25 + 30 * simulation.CDScale;
|
||||
me.nextBlinkCycle = me.delay;
|
||||
me.blinkRange = 235
|
||||
me.grenadeDelay = 30 + 60 * simulation.CDScale
|
||||
me.grenadeDelay = 35 + 60 * simulation.CDScale
|
||||
me.pulseRadius = 2 * Math.min(550, 220 + simulation.difficulty * 4)
|
||||
spawn.shield(me, x, y, 1);
|
||||
me.onDamage = function() {
|
||||
@@ -3185,7 +3187,7 @@ const spawn = {
|
||||
} else if (this.noseLength > 1.5 && dot > -0.2 && dot < 0.2) {
|
||||
//fire
|
||||
spawn.sniperBullet(this.vertices[1].x, this.vertices[1].y, 7 + Math.ceil(this.radius / 15), 4);
|
||||
const v = 20 * simulation.accelScale;
|
||||
const v = 10 + 15 * simulation.accelScale;
|
||||
Matter.Body.setVelocity(mob[mob.length - 1], {
|
||||
x: this.velocity.x + this.fireDir.x * v + Math.random(),
|
||||
y: this.velocity.y + this.fireDir.y * v + Math.random()
|
||||
@@ -3246,8 +3248,8 @@ const spawn = {
|
||||
this.explode(this.mass * 20);
|
||||
};
|
||||
Matter.Body.setDensity(me, 0.00005); //normal is 0.001
|
||||
me.timeLeft = 240;
|
||||
me.g = 0.0005; //required if using 'gravity'
|
||||
me.timeLeft = 120;
|
||||
// me.g = 0.0005; //required if using 'gravity'
|
||||
me.frictionAir = 0;
|
||||
me.restitution = 0;
|
||||
me.leaveBody = false;
|
||||
@@ -3258,7 +3260,7 @@ const spawn = {
|
||||
me.collisionFilter.category = cat.mobBullet;
|
||||
me.collisionFilter.mask = cat.player | cat.map | cat.body | cat.bullet;
|
||||
me.do = function() {
|
||||
this.gravity();
|
||||
// this.gravity();
|
||||
this.timeLimit();
|
||||
if (Matter.Query.collides(this, map).length > 0 || Matter.Query.collides(this, body).length > 0 && this.speed < 3) {
|
||||
this.isDropPowerUp = false;
|
||||
@@ -3339,7 +3341,7 @@ const spawn = {
|
||||
};
|
||||
},
|
||||
grenadierBoss(x, y, radius = 95) {
|
||||
mobs.spawn(x, y, 6, radius, "rgb(215,80,190)");
|
||||
mobs.spawn(x, y, 6, radius, "rgb(0,235,255)");
|
||||
let me = mob[mob.length - 1];
|
||||
me.isBoss = true;
|
||||
|
||||
@@ -3391,7 +3393,7 @@ const spawn = {
|
||||
};
|
||||
},
|
||||
grenadier(x, y, radius = 35 + Math.ceil(Math.random() * 20)) {
|
||||
mobs.spawn(x, y, 3, radius, "rgb(215,80,190)"); //rgb(255,100,200)
|
||||
mobs.spawn(x, y, 3, radius, "rgb(0,235,255)"); //rgb(255,100,200)
|
||||
let me = mob[mob.length - 1];
|
||||
me.vertices = Matter.Vertices.rotate(me.vertices, Math.PI, me.position); //make the pointy side of triangle the front
|
||||
me.isVerticesChange = true
|
||||
@@ -4063,6 +4065,7 @@ const spawn = {
|
||||
Matter.Body.setDensity(me, 0.00001) //very low density to not mess with the original mob's motion
|
||||
me.shield = true;
|
||||
me.damageReduction = 0.075
|
||||
me.isUnblockable = true
|
||||
me.isExtraShield = isExtraShield //this prevents spamming with tech.isShieldAmmo
|
||||
me.collisionFilter.category = cat.mobShield
|
||||
me.collisionFilter.mask = cat.bullet;
|
||||
@@ -4162,6 +4165,7 @@ const spawn = {
|
||||
me.leaveBody = false;
|
||||
me.isDropPowerUp = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
me.showHealthBar = false;
|
||||
me.isOrbital = true;
|
||||
// me.isShielded = true
|
||||
@@ -4393,6 +4397,7 @@ const spawn = {
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
|
||||
me.do = function() {
|
||||
let wireX = -50;
|
||||
@@ -4461,6 +4466,7 @@ const spawn = {
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
|
||||
me.do = function() {
|
||||
let wireX = -50 - 20;
|
||||
@@ -4512,6 +4518,7 @@ const spawn = {
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
|
||||
me.do = function() {
|
||||
let wireX = -50 - 35;
|
||||
@@ -4562,6 +4569,7 @@ const spawn = {
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
|
||||
me.do = function() {
|
||||
let wireX = -50 + 16;
|
||||
@@ -4612,6 +4620,7 @@ const spawn = {
|
||||
me.isDropPowerUp = false;
|
||||
me.showHealthBar = false;
|
||||
me.isBadTarget = true;
|
||||
me.isUnblockable = true;
|
||||
|
||||
me.do = function() {
|
||||
let wireX = -50 + 26;
|
||||
|
||||
11
js/tech.js
11
js/tech.js
@@ -168,7 +168,7 @@
|
||||
damageFromTech() {
|
||||
let dmg = 1 //m.fieldDamage
|
||||
if (tech.isCloakingDamage) dmg *= 1.35
|
||||
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.45
|
||||
if (tech.isFlipFlopDamage && tech.isFlipFlopOn) dmg *= 1.5
|
||||
if (tech.isAnthropicDamage && tech.isDeathAvoidedThisLevel) dmg *= 2.3703599
|
||||
if (tech.isDamageAfterKill) dmg *= (m.lastKillCycle + 300 > m.cycle) ? 2 : 0.66
|
||||
if (m.isSneakAttack && m.cycle > m.lastKillCycle + 240) dmg *= tech.sneakAttackDmg
|
||||
@@ -1805,7 +1805,7 @@
|
||||
},
|
||||
{
|
||||
name: "thermocouple",
|
||||
description: "if <strong>relay switch</strong> is in the <strong class='color-flop'>ON</strong> state<br>condense <strong>1-7</strong> <strong class='color-s'>ice IX</strong> crystals every second",
|
||||
description: "if <strong>relay switch</strong> is in the <strong class='color-flop'>ON</strong> state<br>condense <strong>1-9</strong> <strong class='color-s'>ice IX</strong> crystals every second",
|
||||
maxCount: 9,
|
||||
count: 0,
|
||||
frequency: 4,
|
||||
@@ -1823,7 +1823,7 @@
|
||||
},
|
||||
{
|
||||
name: "NAND gate",
|
||||
description: "if in the <strong class='color-flop'>ON</strong> state<br>do <strong>45%</strong> more <strong class='color-d'>damage</strong>",
|
||||
description: "if in the <strong class='color-flop'>ON</strong> state<br>do <strong>50%</strong> more <strong class='color-d'>damage</strong>",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 4,
|
||||
@@ -1841,7 +1841,7 @@
|
||||
},
|
||||
{
|
||||
name: "transistor",
|
||||
description: "if <strong class='color-flop'>ON</strong> regen <strong>22</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>4.1</strong> <strong class='color-f'>energy</strong> per second",
|
||||
description: "if <strong class='color-flop'>ON</strong> regen <strong>22</strong> <strong class='color-f'>energy</strong> per second<br>if <strong class='color-flop'>OFF</strong> drain <strong>2.2</strong> <strong class='color-f'>energy</strong> per second",
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 4,
|
||||
@@ -7536,7 +7536,8 @@
|
||||
description: `<strong class="lore-text">this</strong>`,
|
||||
maxCount: 1,
|
||||
count: 0,
|
||||
frequency: 2,
|
||||
frequency: 3,
|
||||
frequencyDefault: 3,
|
||||
isLore: true,
|
||||
// isNonRefundable: true,
|
||||
isExperimentHide: true,
|
||||
|
||||
22
todo.txt
22
todo.txt
@@ -1,28 +1,16 @@
|
||||
******************************************************** NEXT PATCH ********************************************************
|
||||
|
||||
new laserBombingBoss
|
||||
I didn't do any difficulty testing, so maybe let me know if it's too easy
|
||||
relativistic momentum: laser pushes harder and slows mobs a bit to give a more predictable effect
|
||||
laserBombingBoss targets faster at higher levels
|
||||
you can now block shielded mobs, but your shield gets disabled for a bit
|
||||
|
||||
laser and plasma bots will target mobs bullets
|
||||
non updating health bar bug fix
|
||||
fixed bug that made perfect diamagnetism have trouble blocking too many things at once
|
||||
and more small bug fixes, of course
|
||||
|
||||
******************************************************** TODO ********************************************************
|
||||
|
||||
mob: spawning seekers on death
|
||||
|
||||
"Lazer pulser Boss"
|
||||
Basically the blue lazer boss, but it has another color
|
||||
Instead of shooting one current stream of lasers, the laser is completely harmless
|
||||
If the boss focused the Lazer on the player for a certain amount of time, it'll glow brightly and send a fast, explosive pulse down the Lazer beam
|
||||
The harmless lazer beam serves like a sniper's lazer scope
|
||||
|
||||
laser damage seems low based on 2 runs
|
||||
history is low damage
|
||||
|
||||
buff laser push tech
|
||||
push like plasma?
|
||||
push harder
|
||||
|
||||
drones can combine with other drones to get bigger?
|
||||
drones that grab powers ups can grab more then one and get even bigger each time
|
||||
|
||||
|
||||
Reference in New Issue
Block a user