diff --git a/img/rupture.webp b/img/swarf.webp
similarity index 100%
rename from img/rupture.webp
rename to img/swarf.webp
diff --git a/img/topological defect.webp b/img/topological defect.webp
index c81a53c..a4be7c9 100644
Binary files a/img/topological defect.webp and b/img/topological defect.webp differ
diff --git a/img/yield stress.webp b/img/yield stress.webp
deleted file mode 100644
index a4be7c9..0000000
Binary files a/img/yield stress.webp and /dev/null differ
diff --git a/js/bullet.js b/js/bullet.js
index 674bfd5..b1bc458 100644
--- a/js/bullet.js
+++ b/js/bullet.js
@@ -558,46 +558,6 @@ const b = {
y: where.y + range * Math.sin(angle)
}
];
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
//check for collisions
best = {
x: null,
@@ -607,28 +567,8 @@ const b = {
v1: null,
v2: null
};
- // if (tech.isPulseAim && !m.crouch) { //find mobs in line of sight
- // let dist = 2200
- // for (let i = 0, len = mob.length; i < len; i++) {
- // const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
- // if (
- // explosionRadius < newDist &&
- // newDist < dist &&
- // !mob[i].isBadTarget &&
- // Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
- // Matter.Query.ray(body, path[0], mob[i].position).length === 0 &&
- // !mob[i].isInvulnerable
- // ) {
- // dist = newDist
- // best.who = mob[i]
- // path[path.length - 1] = mob[i].position
- // }
- // }
- // }
if (!best.who) {
- vertexCollision(path[0], path[1], mob);
- vertexCollision(path[0], path[1], map);
- vertexCollision(path[0], path[1], body);
+ best = vertexCollision(path[0], path[1], [mob, map, body]);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = {
x: best.x,
@@ -678,135 +618,20 @@ const b = {
});
}
},
- // photon(where, angle = m.angle) {
- // let best;
- // const path = [{
- // x: m.pos.x + 20 * Math.cos(angle),
- // y: m.pos.y + 20 * Math.sin(angle)
- // },
- // {
- // x: m.pos.x + range * Math.cos(angle),
- // y: m.pos.y + range * Math.sin(angle)
- // }
- // ];
- // const vertexCollision = function(v1, v1End, domain) {
- // for (let i = 0; i < domain.length; ++i) {
- // let vertices = domain[i].vertices;
- // const len = vertices.length - 1;
- // for (let j = 0; j < len; j++) {
- // results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- // if (results.onLine1 && results.onLine2) {
- // const dx = v1.x - results.x;
- // const dy = v1.y - results.y;
- // const dist2 = dx * dx + dy * dy;
- // if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- // best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[j],
- // v2: vertices[j + 1]
- // };
- // }
- // }
- // }
- // results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- // if (results.onLine1 && results.onLine2) {
- // const dx = v1.x - results.x;
- // const dy = v1.y - results.y;
- // const dist2 = dx * dx + dy * dy;
- // if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- // best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[0],
- // v2: vertices[len]
- // };
- // }
- // }
- // }
- // };
- // //check for collisions
- // best = {
- // x: null,
- // y: null,
- // dist2: Infinity,
- // who: null,
- // v1: null,
- // v2: null
- // };
- // if (tech.isPulseAim) { //find mobs in line of sight
- // let dist = 2200
- // for (let i = 0, len = mob.length; i < len; i++) {
- // const newDist = Vector.magnitude(Vector.sub(path[0], mob[i].position))
- // if (explosionRadius < newDist &&
- // newDist < dist &&
- // Matter.Query.ray(map, path[0], mob[i].position).length === 0 &&
- // Matter.Query.ray(body, path[0], mob[i].position).length === 0) {
- // dist = newDist
- // best.who = mob[i]
- // path[path.length - 1] = mob[i].position
- // }
- // }
- // }
- // if (!best.who) {
- // vertexCollision(path[0], path[1], mob);
- // vertexCollision(path[0], path[1], map);
- // vertexCollision(path[0], path[1], body);
- // if (best.dist2 != Infinity) { //if hitting something
- // path[path.length - 1] = {
- // x: best.x,
- // y: best.y
- // };
- // }
- // }
- // if (best.who) b.explosion(path[1], explosionRadius)
-
- // //draw laser beam
- // ctx.beginPath();
- // ctx.moveTo(path[0].x, path[0].y);
- // ctx.lineTo(path[1].x, path[1].y);
- // ctx.strokeStyle = "rgba(255,0,0,0.13)"
- // ctx.lineWidth = 60 * energy / 0.2
- // ctx.stroke();
- // ctx.strokeStyle = "rgba(255,0,0,0.2)"
- // ctx.lineWidth = 18
- // ctx.stroke();
- // ctx.strokeStyle = "#f00";
- // ctx.lineWidth = 4
- // ctx.stroke();
-
- // //draw little dots along the laser path
- // const sub = Vector.sub(path[1], path[0])
- // const mag = Vector.magnitude(sub)
- // for (let i = 0, len = Math.floor(mag * 0.03 * energy / 0.2); i < len; i++) {
- // const dist = Math.random()
- // simulation.drawList.push({
- // x: path[0].x + sub.x * dist + 13 * (Math.random() - 0.5),
- // y: path[0].y + sub.y * dist + 13 * (Math.random() - 0.5),
- // radius: 1 + 4 * Math.random(),
- // color: "rgba(255,0,0,0.5)",
- // time: Math.floor(2 + 33 * Math.random() * Math.random())
- // });
- // }
- // },
- fireworks(where, size) { //can occur after grenades detonate
+ clusterExplode(where, size) { //can occur after grenades detonate
const cycle = () => {
if (m.alive) {
if (simulation.paused || m.isBodiesAsleep) {
requestAnimationFrame(cycle)
} else {
count++
- if (count < 130) requestAnimationFrame(cycle);
- if (!(count % 10)) {
+ if (count < 84) requestAnimationFrame(cycle);
+ if (!(count % 7)) {
const unit = Vector.rotate({
x: 1,
y: 0
}, 6.28 * Math.random())
- b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.02 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end
+ b.explosion(Vector.add(where, Vector.mult(unit, size * (count * 0.01 + 0.03 * Math.random()))), size * (0.4 + Math.random() * 0.35), `hsla(${360 * Math.random()},100%,66%,0.6)`); //makes bullet do explosive damage at end
}
}
}
@@ -884,7 +709,7 @@ const b = {
} else if (tech.isPetalsExplode) {
b.fireFlower(this.position, this.explodeRad)
} else if (tech.isClusterExplode) {
- b.fireworks(this.position, this.explodeRad)
+ b.clusterExplode(this.position, this.explodeRad)
} else {
b.explosion(this.position, this.explodeRad); //makes bullet do explosive damage at end
}
@@ -1501,7 +1326,7 @@ const b = {
drawStringControlMagnitude: 1000 + 1000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
attached: false,
- glowColor: tech.isHookExplosion ? "rgba(200,0,0,0.07)" : tech.isHarmReduce ? "rgba(50,100,255,0.1)" : "rgba(0,200,255,0.07)",
+ glowColor: tech.hookNails ? "rgba(200,0,0,0.07)" : tech.isHarmReduce ? "rgba(50,100,255,0.1)" : "rgba(0,200,255,0.07)",
collisionFilter: {
category: cat.bullet,
mask: tech.isShieldPierce ? cat.body | cat.mob | cat.mobBullet : cat.body | cat.mob | cat.mobBullet | cat.mobShield,
@@ -1598,14 +1423,20 @@ const b = {
});
}
if (m.fieldCDcycle < m.cycle + 40) m.fieldCDcycle = m.cycle + 40 //extra long cooldown on hitting mobs
- if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
+ if (tech.hookNails) {
+ // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles
+ // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end
+ b.targetedNail(this.position, tech.hookNails)
+ const ANGLE = 2 * Math.PI * Math.random() //make a few random ones
+ for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2)
+ }
// if (this.powerUpDamage) this.density = 2 * 0.004 //double damage after pick up power up for 8 seconds
if (tech.isHarpoonPowerUp && simulation.cycle - 480 < tech.harpoonPowerUpCycle) {
Matter.Body.setDensity(this, 1.8 * 0.004); //+90% damage after pick up power up for 8 seconds
} else if (tech.isHarpoonFullHealth && who.health === 1) {
- Matter.Body.setDensity(this, 1.9 * 0.004); //+90% damage if mob has full health do
+ Matter.Body.setDensity(this, 2.11 * 0.004); //+90% damage if mob has full health do
simulation.ephemera.push({
name: "grapple outline",
count: 3, //cycles before it self removes
@@ -1688,7 +1519,7 @@ const b = {
if (this.pickUpTarget) {
if (tech.isReel && this.blockDist > 150) {
// console.log(0.0003 * Math.min(this.blockDist, 1000))
- m.energy += 0.00044 * Math.min(this.blockDist, 800) //max 0.352 energy
+ m.energy += 0.0009 * Math.min(this.blockDist, 800) //max 0.352 energy
simulation.drawList.push({ //add dmg to draw queue
x: m.pos.x,
y: m.pos.y,
@@ -1758,10 +1589,15 @@ const b = {
if (blocks.length) {
// console.log(blocks)
for (let i = 0; i < blocks.length; i++) {
- if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && !blocks[0].bodyA.mass < 60) {
+ if (blocks[i].bodyA.classType === "body" && !blocks[i].bodyA.isNotHoldable && blocks[0].bodyA.mass < 60) {
this.retract()
- if (tech.isHookExplosion) {
- b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
+ if (tech.hookNails) {
+ // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles
+ // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end
+ b.targetedNail(this.position, 3 * tech.hookNails)
+ const ANGLE = 2 * Math.PI * Math.random() //make a few random ones
+ for (let i = 0; i < 13; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2)
+
const blockVertices = blocks[i].bodyA.vertices
Composite.remove(engine.world, blocks[i].bodyA)
body.splice(body.indexOf(blocks[i].bodyA), 1)
@@ -1785,12 +1621,20 @@ const b = {
this.pickUpTarget = blocks[i].bodyA
this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos))
}
- } else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && !blocks[0].bodyB.mass < 60) {
- this.retract()
- this.pickUpTarget = blocks[i].bodyB
- this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos))
- if (tech.isHookExplosion) b.explosion(this.position, 250 + 150 * Math.random()); //makes bullet do explosive damage at end
}
+ // else if (blocks[i].bodyB.classType === "body" && !blocks[i].bodyB.isNotHoldable && blocks[0].bodyB.mass < 60) {
+ // this.retract()
+ // this.pickUpTarget = blocks[i].bodyB
+ // this.blockDist = Vector.magnitude(Vector.sub(this.pickUpTarget.position, m.pos))
+ // if (tech.hookNails) {
+ // // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles
+ // // b.explosion(this.position, 300 + 150 * Math.random()); //makes bullet do explosive damage at end
+ // b.targetedNail(this.position, tech.hookNails)
+ // const ANGLE = 2 * Math.PI * Math.random() //make a few random ones
+ // for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2)
+
+ // }
+ // }
}
// if (blocks[0].bodyA.mass > 2.5 && blocks[0].bodyA.mass > 15) {
@@ -1855,7 +1699,14 @@ const b = {
if (input.field && Matter.Query.collides(this, map).length) {
Matter.Body.setPosition(this, Vector.add(this.position, { x: -20 * Math.cos(this.angle), y: -20 * Math.sin(this.angle) }))
if (Matter.Query.collides(this, map).length) {
- if (tech.isHookExplosion) b.explosion(this.position, 150 + 50 * Math.random()); //makes bullet do explosive damage at end
+ if (tech.hookNails) {
+ // if (m.immuneCycle < m.cycle + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 5; //player is immune to damage for 5 cycles
+ // b.explosion(this.position, 200 + 150 * Math.random()); //makes bullet do explosive damage at end
+ b.targetedNail(this.position, tech.hookNails)
+ const ANGLE = 2 * Math.PI * Math.random() //make a few random ones
+ for (let i = 0; i < 4; i++) b.nail(this.position, { x: 10.5 * Math.cos(ANGLE), y: 10.5 * Math.sin(ANGLE) }, 1.2)
+
+ }
this.attached = true
Matter.Body.setVelocity(this, { x: 0, y: 0 });
Matter.Sleeping.set(this, true)
@@ -1976,7 +1827,7 @@ const b = {
friction: 1,
frictionAir: 0.4,
// thrustMag: 0.1,
- drain: tech.isRailEnergy ? 0.0006 : 0.006,
+ drain: tech.isRailEnergy ? 0 : 0.006,
turnRate: isReturn ? 0.1 : 0.03, //0.015
drawStringControlMagnitude: 3000 + 5000 * Math.random(),
drawStringFlip: (Math.round(Math.random()) ? 1 : -1),
@@ -2022,7 +1873,7 @@ const b = {
if (tech.isHarpoonPowerUp && simulation.cycle - 480 < tech.harpoonPowerUpCycle) {
Matter.Body.setDensity(this, 1.8 * tech.harpoonDensity); //+90% damage after pick up power up for 8 seconds
} else if (tech.isHarpoonFullHealth && who.health === 1) {
- Matter.Body.setDensity(this, 1.9 * tech.harpoonDensity); //+90% damage if mob has full health do
+ Matter.Body.setDensity(this, 2.11 * tech.harpoonDensity); //+90% damage if mob has full health do
simulation.ephemera.push({
name: "harpoon outline",
count: 2, //cycles before it self removes
@@ -2435,7 +2286,6 @@ const b = {
}
//calculate laser collision
- let best;
let range = tech.isPlasmaRange * (120 + (m.crouch ? 400 : 300) * Math.sqrt(Math.random())) //+ 100 * Math.sin(m.cycle * 0.3);
// const dir = m.angle // + 0.04 * (Math.random() - 0.5)
const path = [{
@@ -2447,49 +2297,8 @@ const b = {
y: m.pos.y + range * Math.sin(m.angle)
}
];
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
-
//check for collisions
- best = {
+ let best = {
x: null,
y: null,
dist2: Infinity,
@@ -2497,14 +2306,9 @@ const b = {
v1: null,
v2: null
};
- vertexCollision(path[0], path[1], mob);
- vertexCollision(path[0], path[1], map);
- vertexCollision(path[0], path[1], body);
+ best = vertexCollision(path[0], path[1], [mob, map, body]);
if (best.dist2 != Infinity) { //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
+ path[path.length - 1] = { x: best.x, y: best.y };
if (best.who.alive) {
const dmg = 0.9 * m.dmgScale; //********** SCALE DAMAGE HERE *********************
best.who.damage(dmg);
@@ -2571,6 +2375,7 @@ const b = {
}, dmg = tech.laserDamage, reflections = tech.laserReflections, isThickBeam = false, push = 1) {
const reflectivity = 1 - 1 / (reflections * 3)
let damage = m.dmgScale * dmg
+
let best = {
x: 1,
y: 1,
@@ -2586,59 +2391,9 @@ const b = {
x: whereEnd.x,
y: whereEnd.y
}];
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
const checkForCollisions = function () {
- best = {
- x: 1,
- y: 1,
- dist2: Infinity,
- who: null,
- v1: 1,
- v2: 1
- };
- vertexCollision(path[path.length - 2], path[path.length - 1], mob);
- vertexCollision(path[path.length - 2], path[path.length - 1], map);
- vertexCollision(path[path.length - 2], path[path.length - 1], body);
+ best = vertexCollision(path[path.length - 2], path[path.length - 1], [mob, map, body]);
};
const laserHitMob = function () {
if (best.who.alive) {
@@ -2895,7 +2650,7 @@ const b = {
} else if (tech.isSuperMine) {
b.targetedBall(this.position, 22 + 2 * tech.extraSuperBalls)
} else {
- b.targetedNail(this.position, 22, 40 + 10 * Math.random(), 1200, true, 2.2) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
+ b.targetedNail(this.position, 22, 40 + 10 * Math.random(), 1200, 2.2)
}
}
},
@@ -2993,7 +2748,7 @@ const b = {
if (Math.random() < 0.33) b.targetedBall(this.position, 1, 42 + 12 * Math.random(), 1200, false)
}
} else {
- this.shots -= b.targetedNail(this.position, 1, 45 + 5 * Math.random(), 1100, false, 2.3) //targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
+ this.shots -= b.targetedNail(this.position, 1, 45 + 5 * Math.random(), 1100, 2.3)
}
if (this.shots < 0) this.endCycle = 0
if (!(simulation.cycle % (this.lookFrequency * 6))) {
@@ -3508,10 +3263,7 @@ const b = {
}
requestAnimationFrame(respawnDrones);
},
- drone(where = {
- x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5),
- y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5)
- }, speed = 1) {
+ drone(where = { x: m.pos.x + 30 * Math.cos(m.angle) + 20 * (Math.random() - 0.5), y: m.pos.y + 30 * Math.sin(m.angle) + 20 * (Math.random() - 0.5) }, speed = 1) {
const me = bullet.length;
const THRUST = 0.0015
const dir = m.angle + 0.2 * (Math.random() - 0.5);
@@ -3688,7 +3440,7 @@ const b = {
for (let i = 0, len = powerUp.length; i < len; ++i) { //grab, but don't lock onto nearby power up
if (
Vector.magnitudeSquared(Vector.sub(this.position, powerUp[i].position)) < 20000 &&
- (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) &&
+ (powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isSuperDeterminism)
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
@@ -3719,7 +3471,7 @@ const b = {
let closeDist = Infinity;
for (let i = 0, len = powerUp.length; i < len; ++i) {
if (
- (powerUp[i].name !== "heal" || m.health < 0.93 * m.maxHealth || tech.isDroneGrab) &&
+ (powerUp[i].name !== "heal" || m.health < 0.97 * m.maxHealth || tech.isDroneGrab) &&
(powerUp[i].name !== "field" || !tech.isSuperDeterminism)
// &&(b.inventory.length > 1 || powerUp[i].name !== "ammo" || b.guns[b.activeGun].ammo !== Infinity || tech.isDroneGrab)
) {
@@ -3748,8 +3500,7 @@ const b = {
}
//look for power ups to lock onto
if (
- Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 &&
- Matter.Query.ray(body, this.position, powerUp[i].position).length === 0
+ Matter.Query.ray(map, this.position, powerUp[i].position).length === 0 //&& Matter.Query.ray(body, this.position, powerUp[i].position).length === 0
) {
const TARGET_VECTOR = Vector.sub(this.position, powerUp[i].position)
const DIST = Vector.magnitude(TARGET_VECTOR);
@@ -4545,7 +4296,7 @@ const b = {
Matter.Body.setVelocity(who, velocity);
}
},
- targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, isRandomAim = true, damage = 1.4) {
+ targetedNail(position, num = 1, speed = 40 + 10 * Math.random(), range = 1200, damage = 1.4) {
let shotsFired = 0
const targets = [] //target nearby mobs
for (let i = 0, len = mob.length; i < len; i++) {
@@ -4570,7 +4321,7 @@ const b = {
}
b.nail(position, Vector.mult(Vector.normalise(Vector.sub(WHERE, position)), speed), damage)
shotsFired++
- } else if (isRandomAim) { // aim in random direction
+ } else { // aim in random direction
const ANGLE = 2 * Math.PI * Math.random()
b.nail(position, {
x: speed * Math.cos(ANGLE),
@@ -5634,59 +5385,9 @@ const b = {
const perp2 = Vector.mult(Vector.rotate({ x: 1, y: 0 }, m.angle + Math.PI / 2), 0.6 * this.lockedOn.radius * Math.sin(simulation.cycle / this.lookFrequency))
const path = [{ x: this.vertices[0].x, y: this.vertices[0].y }, Vector.add(this.lockedOn.position, perp2)];
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
-
const checkForCollisions = function () {
- best = {
- x: 1,
- y: 1,
- dist2: Infinity,
- who: null,
- v1: 1,
- v2: 1
- };
- vertexCollision(path[path.length - 2], path[path.length - 1], mob);
- vertexCollision(path[path.length - 2], path[path.length - 1], map);
- vertexCollision(path[path.length - 2], path[path.length - 1], body);
+ best = { x: 1, y: 1, dist2: Infinity, who: null, v1: 1, v2: 1 };
+ best = vertexCollision(path[path.length - 2], path[path.length - 1], [mob, map, body]);
};
const laserHitMob = function () {
if (best.who.alive) {
@@ -5717,19 +5418,13 @@ const b = {
}
if (tech.isLaserPush) { //push mobs away
const index = path.length - 1
- Matter.Body.setVelocity(best.who, {
- x: best.who.velocity.x * 0.97,
- y: best.who.velocity.y * 0.97
- });
+ Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 });
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass))
Matter.Body.applyForce(best.who, path[index], force)
}
} else if (tech.isLaserPush && best.who.classType === "body") {
const index = path.length - 1
- Matter.Body.setVelocity(best.who, {
- x: best.who.velocity.x * 0.97,
- y: best.who.velocity.y * 0.97
- });
+ Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.97, y: best.who.velocity.y * 0.97 });
const force = Vector.mult(Vector.normalise(Vector.sub(path[index], path[Math.max(0, index - 1)])), 0.003 * push * Math.min(6, best.who.mass))
Matter.Body.applyForce(best.who, path[index], force)
}
@@ -5746,20 +5441,14 @@ const b = {
let lastBestOdd
let lastBestEven = best.who //used in hack below
if (best.dist2 !== Infinity) { //if hitting something
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
+ path[path.length - 1] = { x: best.x, y: best.y };
laserHitMob();
for (let i = 0; i < tech.laserReflections; i++) {
reflection();
checkForCollisions();
if (best.dist2 !== Infinity) { //if hitting something
lastReflection = best
- path[path.length - 1] = {
- x: best.x,
- y: best.y
- };
+ path[path.length - 1] = { x: best.x, y: best.y };
damage *= reflectivity
laserHitMob();
//I'm not clear on how this works, but it gets rid of a bug where the laser reflects inside a block, often vertically.
@@ -5947,51 +5636,9 @@ const b = {
let best;
let range = tech.isPlasmaRange * (120 + 300 * Math.sqrt(Math.random()))
const path = [{ x: this.position.x, y: this.position.y }, { x: this.position.x + range * unit.x, y: this.position.y + range * unit.y }];
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
//check for collisions
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
- vertexCollision(path[0], path[1], mob);
- vertexCollision(path[0], path[1], map);
- vertexCollision(path[0], path[1], body);
+ best = vertexCollision(path[0], path[1], [mob, map, body]);
if (best.dist2 != Infinity) { //if hitting something
path[path.length - 1] = { x: best.x, y: best.y };
if (best.who.alive) {
@@ -6001,12 +5648,7 @@ const b = {
//push mobs away
const force = Vector.mult(Vector.normalise(Vector.sub(m.pos, path[1])), -0.007 * Math.min(5, best.who.mass))
Matter.Body.applyForce(best.who, path[1], force)
- if (best.who.speed > 2.5) {
- Matter.Body.setVelocity(best.who, { //friction
- x: best.who.velocity.x * 0.75,
- y: best.who.velocity.y * 0.75
- });
- }
+ if (best.who.speed > 2.5) Matter.Body.setVelocity(best.who, { x: best.who.velocity.x * 0.75, y: best.who.velocity.y * 0.75 });
//draw mob damage circle
if (best.who.damageReduction) {
simulation.drawList.push({
@@ -7729,7 +7371,7 @@ const b = {
charge: 0,
railDo() {
if (this.charge > 0) {
- const DRAIN = (tech.isRailEnergy ? 0.0002 : 0.002)
+ const DRAIN = (tech.isRailEnergy ? 0 : 0.002)
//exit railgun charging without firing
if (m.energy < DRAIN) {
// m.energy += 0.025 + this.charge * 22 * this.drain
diff --git a/js/engine.js b/js/engine.js
index 3eecee3..9c79988 100644
--- a/js/engine.js
+++ b/js/engine.js
@@ -229,8 +229,8 @@ function collisionChecks(event) {
y: mob[k].velocity.y - 8 * Math.sin(angle)
});
- if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.34 * m.maxEnergy && mob[k].damageReduction > 0) {
- m.energy -= 0.33 * Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
+ if (tech.isAnnihilation && !mob[k].shield && !mob[k].isShielded && !mob[k].isBoss && mob[k].isDropPowerUp && m.energy > 0.1 && mob[k].damageReduction > 0) {
+ m.energy -= 0.1 //* Math.max(m.maxEnergy, m.energy) //0.33 * m.energy
if (m.immuneCycle === m.cycle + m.collisionImmuneCycles) m.immuneCycle = 0; //player doesn't go immune to collision damage
mob[k].death();
simulation.drawList.push({ //add dmg to draw queue
diff --git a/js/index.js b/js/index.js
index a2eb61b..5c22bad 100644
--- a/js/index.js
+++ b/js/index.js
@@ -39,6 +39,96 @@ function shuffle(array) {
}
return array;
}
+// function vertexCollision(v1, v1End, domain, best) {
+// let results
+// for (let i = 0; i < domain.length; ++i) {
+// let vertices = domain[i].vertices;
+// const len = vertices.length - 1;
+// for (let j = 0; j < len; j++) {
+// results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
+// if (results.onLine1 && results.onLine2) {
+// const dx = v1.x - results.x;
+// const dy = v1.y - results.y;
+// const dist2 = dx * dx + dy * dy;
+// if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
+// best = {
+// x: results.x,
+// y: results.y,
+// dist2: dist2,
+// who: domain[i],
+// v1: vertices[j],
+// v2: vertices[j + 1]
+// };
+// }
+// }
+// }
+// results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
+// if (results.onLine1 && results.onLine2) {
+// const dx = v1.x - results.x;
+// const dy = v1.y - results.y;
+// const dist2 = dx * dx + dy * dy;
+// if (dist2 < best.dist2) {
+// best = {
+// x: results.x,
+// y: results.y,
+// dist2: dist2,
+// who: domain[i],
+// v1: vertices[0],
+// v2: vertices[len]
+// };
+// }
+// }
+// }
+// return best
+// }
+//this function is used for finding the point where a ray hits things, used for lasers mostly
+function vertexCollision(v1, v1End, domains) { //= [map, body, [playerBody, playerHead]] //m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]
+ let results
+ let best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
+ for (let j = 0; j < domains.length; j++) {
+ let domain = domains[j]
+ for (let i = 0; i < domain.length; ++i) {
+ let vertices = domain[i].vertices;
+ const len = vertices.length - 1;
+ for (let j = 0; j < len; j++) {
+ results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[j],
+ v2: vertices[j + 1]
+ };
+ }
+ }
+ }
+ results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
+ if (results.onLine1 && results.onLine2) {
+ const dx = v1.x - results.x;
+ const dy = v1.y - results.y;
+ const dist2 = dx * dx + dy * dy;
+ if (dist2 < best.dist2) {
+ best = {
+ x: results.x,
+ y: results.y,
+ dist2: dist2,
+ who: domain[i],
+ v1: vertices[0],
+ v2: vertices[len]
+ };
+ }
+ }
+ }
+ }
+ return best
+}
+
//collision groups
// cat.player | cat.map | cat.body | cat.bullet | cat.powerUp | cat.mob | cat.mobBullet | cat.mobShield | cat.phased
diff --git a/js/level.js b/js/level.js
index 5292830..4e72d84 100644
--- a/js/level.js
+++ b/js/level.js
@@ -19,26 +19,26 @@ const level = {
// simulation.enableConstructMode() //tech.giveTech('motion sickness') //used to build maps in testing mode
// simulation.isHorizontalFlipped = true
// tech.giveTech("performance")
- // level.difficultyIncrease(8 * 2) //30 is near max on hard //60 is near max on why
- // m.maxHealth = m.health = 1
+ // level.difficultyIncrease(3 * 2) //30 is near max on hard //60 is near max on why
+ // m.maxHealth = m.health = 100000000
// m.maxEnergy = m.energy = 10000000
// tech.isRerollDamage = true
// powerUps.research.changeRerolls(99999)
// m.immuneCycle = Infinity //you can't take damage
// tech.tech[297].frequency = 100
// m.couplingChange(10)
- // m.setField("metamaterial cloaking") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
+ // m.setField("plasma torch") //1 standing wave 2 perfect diamagnetism 3 negative mass 4 molecular assembler 5 plasma torch 6 time dilation 7 metamaterial cloaking 8 pilot wave 9 wormhole 10 grappling hook
// m.energy = 0
// tech.isHookWire = true
// m.energy = 0
// simulation.molecularMode = 2
// m.damage(0.1);
- // b.giveGuns("super balls") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
+ // b.giveGuns("drones") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.giveGuns("laser") //0 nail gun 1 shotgun 2 super balls 3 wave 4 missiles 5 grenades 6 spores 7 drones 8 foam 9 harpoon 10 mine 11 laser
// b.guns[8].ammo = 100000000
// requestAnimationFrame(() => { tech.giveTech("Higgs mechanism") });
- // for (let i = 0; i < 1; ++i) tech.giveTech("optical amplifier")
- // for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("flame test")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("dazzler")
// for (let i = 0; i < 1; ++i) tech.giveTech("mass production")
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) tech.giveTech("orbital-bot") });
// requestAnimationFrame(() => { for (let i = 0; i < 10; i++) b.orbitBot(m.pos, false) });
@@ -46,26 +46,30 @@ const level = {
// for (let i = 0; i < 1; i++) tech.giveTech("tungsten carbide")
// m.lastKillCycle = m.cycle
- // for (let i = 0; i < 1; ++i) tech.giveTech("depolarization")
+ // for (let i = 0; i < 1; ++i) tech.giveTech("swarf")
// for (let i = 0; i < 1; ++i) tech.giveTech("CPT symmetry")
// for (let i = 0; i < 3; i++) powerUps.directSpawn(450, -50, "tech");
// for (let i = 0; i < 10; i++) powerUps.directSpawn(1750, -500, "research");
// for (let i = 0; i < 100; i++) powerUps.directSpawn(1750, -500, "coupling");
- // level.arena();
+ // spawn.mapRect(575, -700, 25, 425); //block mob line of site on testing
+ // level.testing();
- // for (let i = 0; i < 4; ++i) spawn.hopMother(1900, -500)
- // for (let i = 0; i < 4; ++i) spawn.stinger(1900, -500)
- // for (let i = 0; i < 1; ++i) spawn.timeSkipBoss(1900, -2500)
+ // for (let i = 0; i < 1; ++i) spawn.laserLayer(1400, -500)
+ // Matter.Body.setPosition(player, { x: -200, y: -3330 });
+ // for (let i = 0; i < 4; ++i) spawn.laserLayer(1300, -500 + 100 * Math.random())
+ // for (let i = 0; i < 3; ++i) spawn.laser(1900, -500)
+ // for (let i = 0; i < 1; ++i) spawn.laserBombingBoss(1900, -2500)
// spawn.beetleBoss(1900, -500, 25)
- // spawn.slasher2(2000, -1150)
// spawn.zombie(-3000, -500 + 300 * Math.random(), 30, 5, "white") // zombie(x, y, radius, sides, color)
// for (let i = 0; i < 5; ++i) spawn.starter(1000 + 1000 * Math.random(), -500 + 300 * Math.random())
// tech.addJunkTechToPool(2)
// tech.tech[322].frequency = 100
// spawn.tetherBoss(1900, -500, { x: 1900, y: -500 })
// for (let i = 0; i < 40; ++i) tech.giveTech()
+
level[simulation.isTraining ? "walk" : "initial"]() //normal starting level **************************************************
+ // for (let i = 0; i < 2; i++) spawn.ghoster(1300, -500) //ghosters need to spawn after the map loads
// spawn.bodyRect(2425, -120, 200, 200);
// console.log(body[body.length - 1].mass)
// simulation.isAutoZoom = false; //look in close
@@ -289,8 +293,8 @@ const level = {
simulation.updateTechHUD();
simulation.clearNow = true; //triggers in simulation.clearMap to remove all physics bodies and setup for new map
- //pop up new level info screen for a few seconds
- if (!localSettings.isHideHUD && !simulation.isChoosing && !simulation.isCheating && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor" || level.levels[level.onLevel] === "subway")) {
+ //pop up new level info screen for a few seconds //|| level.levels[level.onLevel] === "subway"
+ if (!localSettings.isHideHUD && !simulation.isCheating && m.alive && (level.levels[level.onLevel] === "final" || level.levels[level.onLevel] === "reactor")) {
//pause
if (!simulation.paused) {
simulation.paused = true;
@@ -325,7 +329,7 @@ const level = {
simulation.draw.cons();
simulation.draw.body();
level.customTopLayer();
- let count = countMax = simulation.testing ? 0 : 180
+ let count = countMax = simulation.testing ? 0 : 240
let newLevelDraw = () => {
count--
if (count > 0) {
@@ -346,40 +350,46 @@ const level = {
simulation.wipe();
m.look();
simulation.camera();
- // if (count < 30) {
- // }
- // if (count < 60) {
- // simulation.draw.cons();
- // simulation.draw.body();
- // level.customTopLayer();
- // simulation.draw.body();
- // simulation.draw.drawMapPath();
- // mobs.draw();
- // } else
- // if (count < 240) {
-
- // ctx.lineDashOffset = 900 * Math.random()
- // ctx.setLineDash([3, -8 + 0.5 * count]);
-
- const scale = 10
+ const scale = 15
ctx.setLineDash([scale * (countMax - count), scale * count]);
simulation.draw.wireFrame();
ctx.setLineDash([]);
-
-
- // }
- // else if (count === 91) { //hide text boss
- // document.getElementById("choose-grid").style.opacity = "0"
- // setTimeout(() => {
- // document.getElementById("choose-grid").style.visibility = "hidden"
- // }, 1000);
- // }
ctx.restore();
simulation.drawCursor();
}
requestAnimationFrame(newLevelDraw);
-
}
+ // else {
+ // //pause
+ // if (!simulation.paused) {
+ // simulation.paused = true;
+ // simulation.isChoosing = true; //stops p from un pausing on key down
+ // }
+ // let count = countMax = simulation.testing ? 0 : 60
+ // let newLevelDraw = () => {
+ // count--
+ // if (count > 0) {
+ // requestAnimationFrame(newLevelDraw);
+ // } else { //unpause
+ // // if (m.immuneCycle < m.cycle + 15) m.immuneCycle = m.cycle + 30; //player is immune to damage for 30 cycles
+ // if (simulation.paused) requestAnimationFrame(cycle);
+ // if (m.alive) simulation.paused = false;
+ // simulation.isChoosing = false; //stops p from un pausing on key down
+ // build.unPauseGrid()
+ // }
+ // //draw
+ // simulation.wipe();
+ // m.look();
+ // simulation.camera();
+ // const scale = 30
+ // ctx.setLineDash([scale * (countMax - count), scale * count]);
+ // simulation.draw.wireFrame();
+ // ctx.setLineDash([]);
+ // ctx.restore();
+ // simulation.drawCursor();
+ // }
+ // requestAnimationFrame(newLevelDraw);
+ // }
}
},
unPause() {
diff --git a/js/mob.js b/js/mob.js
index 6f5b85c..349d687 100644
--- a/js/mob.js
+++ b/js/mob.js
@@ -505,89 +505,48 @@ const mobs = {
ctx.fill();
}
},
- laser() {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
- if (this.seePlayer.recall && !this.isSlowed) {
- const seeRange = 2500;
- best = {
- x: null,
- y: null,
- dist2: Infinity,
- who: null,
- v1: null,
- v2: null
- };
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
- if (!m.isCloak) vertexCollision(this.position, look, [player]);
- // hitting player
- if (best.who === player) {
- if (m.immuneCycle < m.cycle) {
- const dmg = 0.0014 * simulation.dmgScale;
- m.damage(dmg);
- ctx.fillStyle = "#f00"; //draw damage
- ctx.beginPath();
- ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI);
- ctx.fill();
- }
- }
- //draw beam
- if (best.dist2 === Infinity) {
- best = look;
- }
- ctx.beginPath();
- ctx.moveTo(this.position.x, this.position.y);
- ctx.lineTo(best.x, best.y);
- ctx.strokeStyle = "#f00"; // Purple path
- ctx.lineWidth = 1;
- ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
- ctx.stroke(); // Draw it
- ctx.setLineDash([]);
- }
- },
+ // laser() {
+ // if (this.seePlayer.recall && !this.isSlowed) {
+ // const seeRange = 2500;
+ // best = {
+ // x: null,
+ // y: null,
+ // dist2: Infinity,
+ // who: null,
+ // v1: null,
+ // v2: null
+ // };
+ // const look = {
+ // x: this.position.x + seeRange * Math.cos(this.angle),
+ // y: this.position.y + seeRange * Math.sin(this.angle)
+ // };
+ // best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [player]]);
+
+ // // hitting player
+ // if (best.who === player) {
+ // if (m.immuneCycle < m.cycle) {
+ // const dmg = 0.0014 * simulation.dmgScale;
+ // m.damage(dmg);
+ // ctx.fillStyle = "#f00"; //draw damage
+ // ctx.beginPath();
+ // ctx.arc(best.x, best.y, dmg * 10000, 0, 2 * Math.PI);
+ // ctx.fill();
+ // }
+ // }
+ // //draw beam
+ // if (best.dist2 === Infinity) {
+ // best = look;
+ // }
+ // ctx.beginPath();
+ // ctx.moveTo(this.position.x, this.position.y);
+ // ctx.lineTo(best.x, best.y);
+ // ctx.strokeStyle = "#f00"; // Purple path
+ // ctx.lineWidth = 1;
+ // ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
+ // ctx.stroke(); // Draw it
+ // ctx.setLineDash([]);
+ // }
+ // },
wing(a, radius = 250, ellipticity = 0.4, dmg = 0.0006) {
const minorRadius = radius * ellipticity
const perp = { x: Math.cos(a), y: Math.sin(a) } //
@@ -658,47 +617,6 @@ const mobs = {
ctx.fillStyle = "rgba(0,0,0,0.07)";
ctx.fill();
//spring to random place on map
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
- //move to a random location
if (!(simulation.cycle % (this.seePlayerFreq * 4))) {
best = {
x: null,
@@ -713,8 +631,7 @@ const mobs = {
x: this.position.x + seeRange * Math.cos(this.angle),
y: this.position.y + seeRange * Math.sin(this.angle)
};
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
+ best = vertexCollision(this.position, look, [map, body]);
if (best.dist2 != Infinity) {
if (Math.random() > 0.5) {
this.springTarget.x = best.x;
@@ -1135,32 +1052,8 @@ const mobs = {
dmg *= tech.damageFromTech()
if (this.isDropPowerUp) {
if (this.health === 1) {
- if (tech.isMobFullHealth) {
- dmg *= 1.55
-
- simulation.ephemera.push({
- name: "damage outline",
- count: 5, //cycles before it self removes
- vertices: this.vertices,
- do() {
- this.count--
- if (this.count < 0) simulation.removeEphemera(this.name)
- //draw body
- ctx.beginPath();
- const vertices = this.vertices;
- ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1, len = vertices.length; j < len; ++j) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
- ctx.lineTo(vertices[0].x, vertices[0].y);
- ctx.lineWidth = 3 //60 * (0.25 - this.damageReductionGoal)
- ctx.strokeStyle = `#f05` //"rgba(150,150,225,0.5)";
- ctx.stroke();
- },
- })
- } else if (tech.isMobFullHealthCloak) {
- dmg *= 1.88
-
+ if (tech.isMobFullHealthCloak) {
+ dmg *= 2.11
simulation.ephemera.push({
name: "damage outline",
count: 7, //cycles before it self removes
diff --git a/js/player.js b/js/player.js
index 5a9876d..e0df3d5 100644
--- a/js/player.js
+++ b/js/player.js
@@ -559,7 +559,7 @@ const m = {
// 1.25 + Math.sin(m.cycle * 0.01)
if (tech.isDiaphragm) dmg *= 0.56 + 0.36 * Math.sin(m.cycle * 0.0075);
if (tech.isZeno) dmg *= 0.15
- if (tech.isFieldHarmReduction) dmg *= 0.5
+ if (tech.isFieldHarmReduction) dmg *= 0.65
if (tech.isHarmMACHO) dmg *= 0.4
if (tech.isImmortal) dmg *= 0.7
if (tech.energyRegen === 0) dmg *= 0.34
@@ -2192,7 +2192,7 @@ const m = {
}
},
setMaxEnergy(isMessage = true) {
- m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.4 * tech.isStandingWaveExpand
+ m.maxEnergy = (tech.isMaxEnergyTech ? 0.5 : 1) + tech.bonusEnergy + tech.healMaxEnergyBonus + tech.harmonicEnergy + 2.66 * tech.isGroundState + 3 * tech.isRelay * tech.isFlipFlopOn * tech.isRelayEnergy + 1.5 * (m.fieldMode === 1) + (m.fieldMode === 0 || m.fieldMode === 1) * 0.05 * m.coupling + 0.77 * tech.isStandingWaveExpand
if (isMessage) simulation.makeTextLog(`m.maxEnergy = ${(m.maxEnergy.toFixed(2))}`)
},
fieldMeterColor: "#0cf",
@@ -2243,6 +2243,8 @@ const m = {
m.fieldRegen = 0.001667 //10 energy per second plasma torch
} else if (m.fieldMode === 8) {
m.fieldRegen = 0.001667 //10 energy per second pilot wave
+ } else if (m.fieldMode === 10) {
+ m.fieldRegen = 0.0015 //9 energy per second grappling hook
} else {
m.fieldRegen = 0.001 //6 energy per second
}
@@ -3631,15 +3633,9 @@ const m = {
// if (!this.isAttached && !mob[i].isMobBullet) this.isPopping = true
mob[i].damage(dmg);
if (mob[i].speed > 5) {
- Matter.Body.setVelocity(mob[i], { //friction
- x: mob[i].velocity.x * 0.6,
- y: mob[i].velocity.y * 0.6
- });
+ Matter.Body.setVelocity(mob[i], { x: mob[i].velocity.x * 0.6, y: mob[i].velocity.y * 0.6 });
} else {
- Matter.Body.setVelocity(mob[i], { //friction
- x: mob[i].velocity.x * 0.93,
- y: mob[i].velocity.y * 0.93
- });
+ Matter.Body.setVelocity(mob[i], { x: mob[i].velocity.x * 0.93, y: mob[i].velocity.y * 0.93 });
}
} else if (sub < dischargeRange + mob[i].radius && Matter.Query.ray(map, mob[i].position, this.position).length === 0) {
arcList.push(mob[i]) //populate electrical arc list
@@ -3684,10 +3680,7 @@ const m = {
//slowly slow down if too fast
if (this.speed > 10) {
const scale = 0.998
- Matter.Body.setVelocity(this, {
- x: scale * this.velocity.x,
- y: scale * this.velocity.y
- });
+ Matter.Body.setVelocity(this, { x: scale * this.velocity.x, y: scale * this.velocity.y });
}
//graphics
@@ -3703,10 +3696,7 @@ const m = {
ctx.arc(this.position.x, this.position.y, radius, 0, 2 * Math.PI);
ctx.fill();
//draw arcs
- const unit = Vector.rotate({
- x: 1,
- y: 0
- }, Math.random() * 6.28)
+ const unit = Vector.rotate({ x: 1, y: 0 }, Math.random() * 6.28)
let len = 8
const step = this.circleRadius / len
let x = this.position.x
@@ -3761,13 +3751,6 @@ const m = {
// m.plasmaBall.reset()
}
- // const scale = 0.7
- // Matter.Body.scale(m.plasmaBall, scale, scale); //shrink fast
- // if (m.plasmaBall.circleRadius < m.plasmaBall.radiusLimit) {
- // m.plasmaBall.isAttached = true
- // m.plasmaBall.isOn = true
- // m.plasmaBall.setPositionToNose()
- // }
} else if (m.energy > m.plasmaBall.drain) { //charge up when attached
if (tech.isCapacitor) {
m.energy -= m.plasmaBall.drain * 2;
@@ -4233,16 +4216,14 @@ const m = {
//not shooting (or using field) enable cloak
if (m.energy < 0.05 && m.fireCDcycle < m.cycle && !input.fire) m.fireCDcycle = m.cycle
if (m.fireCDcycle + 10 < m.cycle && !input.fire) { //automatically cloak if not firing
- const drain = 0.02
- if (!m.isCloak && m.energy > drain + 0.03) {
- m.energy -= drain
+ // const drain = 0.02
+ if (!m.isCloak) { //&& m.energy > drain + 0.03
+ // m.energy -= drain
m.isCloak = true //enter cloak
m.fieldHarmReduction = 0.33; //66% reduction
m.enterCloakCycle = m.cycle
if (tech.isCloakHealLastHit && m.lastHit > 0) {
const heal = Math.min(0.75 * m.lastHit, m.energy)
- // if (m.energy > heal) {
- // m.energy -= heal * 0.8
m.addHealth(heal); //heal from last hit
m.lastHit = 0
simulation.drawList.push({ //add dmg to draw queue
@@ -4252,7 +4233,6 @@ const m = {
color: "rgba(0,255,200,0.6)",
time: 16
});
- // }
}
if (tech.isIntangible) {
for (let i = 0; i < bullet.length; i++) {
@@ -4272,26 +4252,26 @@ const m = {
}
if (tech.isCloakStun) { //stun nearby mobs after exiting cloak
let isMobsAround = false
- const stunRange = m.fieldDrawRadius * 1.5
- const drain = 0.1
- if (m.energy > drain) {
- for (let i = 0, len = mob.length; i < len; ++i) {
- if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) {
- isMobsAround = true
- mobs.statusStun(mob[i], 180)
- }
- }
- if (isMobsAround) {
- m.energy -= drain
- simulation.drawList.push({
- x: m.pos.x,
- y: m.pos.y,
- radius: stunRange,
- color: "hsla(0,50%,100%,0.7)",
- time: 7
- });
+ const stunRange = m.fieldDrawRadius * 1.25
+ // const drain = 0.01
+ // if (m.energy > drain) {
+ for (let i = 0, len = mob.length; i < len; ++i) {
+ if (Vector.magnitude(Vector.sub(mob[i].position, m.pos)) < stunRange && Matter.Query.ray(map, mob[i].position, m.pos).length === 0 && !mob[i].isBadTarget) {
+ isMobsAround = true
+ mobs.statusStun(mob[i], 120)
}
}
+ // if (isMobsAround) {
+ // m.energy -= drain
+ // simulation.drawList.push({
+ // x: m.pos.x,
+ // y: m.pos.y,
+ // radius: stunRange,
+ // color: "hsla(0,50%,100%,0.7)",
+ // time: 7
+ // });
+ // }
+ // }
}
}
@@ -4580,13 +4560,13 @@ const m = {
{
name: "wormhole",
//wormholes attract blocks and power ups
- description: "use energy to tunnel through a wormhole
+5% chance to duplicate spawned power ups
generate 6 energy per second", //
bullets may also traverse wormholes
+ description: "use energy to tunnel through a wormhole
+7% chance to duplicate spawned power ups
generate 6 energy per second", //
bullets may also traverse wormholes
drain: 0,
effect: function () {
m.fieldMeterColor = "#bbf" //"#0c5"
m.eyeFillColor = m.fieldMeterColor
- m.duplicateChance = 0.05
+ m.duplicateChance = 0.07
m.fieldRange = 0
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -4639,10 +4619,7 @@ const m = {
if (dist2 < 600000) { //&& !(m.health === m.maxHealth && powerUp[i].name === "heal")
powerUp[i].force.x += 4 * (dxP / dist2) * powerUp[i].mass; // float towards hole
powerUp[i].force.y += 4 * (dyP / dist2) * powerUp[i].mass - powerUp[i].mass * simulation.g; //negate gravity
- Matter.Body.setVelocity(powerUp[i], { //extra friction
- x: powerUp[i].velocity.x * 0.05,
- y: powerUp[i].velocity.y * 0.05
- });
+ Matter.Body.setVelocity(powerUp[i], { x: powerUp[i].velocity.x * 0.05, 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
@@ -4811,10 +4788,7 @@ const m = {
this.drain = tech.isFreeWormHole ? 0 : 0.05 + 0.005 * Math.sqrt(mag)
}
const unit = Vector.perp(Vector.normalise(sub))
- const where = {
- x: m.pos.x + 30 * Math.cos(m.angle),
- y: m.pos.y + 30 * Math.sin(m.angle)
- }
+ const where = { x: m.pos.x + 30 * Math.cos(m.angle), y: m.pos.y + 30 * Math.sin(m.angle) }
m.fieldRange = 0.97 * m.fieldRange + 0.03 * (50 + 10 * Math.sin(simulation.cycle * 0.025))
const edge2a = Vector.add(Vector.mult(unit, 1.5 * m.fieldRange), simulation.mouseInGame)
const edge2b = Vector.add(Vector.mult(unit, -1.5 * m.fieldRange), simulation.mouseInGame)
@@ -5135,7 +5109,7 @@ const m = {
{
name: "grappling hook",
// description: `use energy to pull yourself towards the map
generate 6 energy per second`,
- description: `use energy to fire a hook that pulls player
damages mobs and grabs blocks
generate 6 energy per second`,
+ description: `use energy to fire a hook that pulls player
damages mobs and grabs blocks
generate 9 energy per second`,
effect: () => {
m.fieldFire = true;
// m.holdingMassScale = 0.01; //can hold heavier blocks with lower cost to jumping
@@ -5159,7 +5133,7 @@ const m = {
m.grabPowerUp();
} 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.isHookDefense && m.energy > 0.33 && m.fieldCDcycle < m.cycle) {
+ if (tech.isHookDefense && m.energy > 0.15 && m.fieldCDcycle < m.cycle) {
const range = 300
for (let i = 0; i < mob.length; i++) {
if (!mob[i].isBadTarget &&
@@ -5167,7 +5141,7 @@ const m = {
Vector.magnitude(Vector.sub(m.pos, mob[i].position)) < range &&
Matter.Query.ray(map, m.pos, mob[i].position).length === 0
) {
- m.energy -= 0.18
+ m.energy -= 0.1
if (m.fieldCDcycle < m.cycle + 30) m.fieldCDcycle = m.cycle + 30
const angle = Math.atan2(mob[i].position.y - player.position.y, mob[i].position.x - player.position.x);
b.harpoon(m.pos, mob[i], angle, 0.75, true, 20) // harpoon(where, target, angle = m.angle, harpoonSize = 1, isReturn = false, totalCycles = 35, isReturnAmmo = true, thrust = 0.1) {
diff --git a/js/powerup.js b/js/powerup.js
index 5292b4d..c836f6e 100644
--- a/js/powerup.js
+++ b/js/powerup.js
@@ -332,7 +332,7 @@ const powerUps = {
simulation.circleFlare(0.043);
}
if (tech.isCancelRerolls) {
- for (let i = 0, len = 6 + 6 * Math.random(); i < len; i++) {
+ for (let i = 0, len = 10 + 4 * Math.random(); i < len; i++) {
let spawnType
if (Math.random() < 0.4 && !tech.isEnergyNoAmmo) {
spawnType = "ammo"
diff --git a/js/spawn.js b/js/spawn.js
index a13550e..9f7c1df 100644
--- a/js/spawn.js
+++ b/js/spawn.js
@@ -26,16 +26,17 @@ const spawn = {
"springer", "springer", "springer",
"stinger", "stinger", "stinger",
"flutter", "flutter",
+ "striker", "striker",
"shooter", "shooter",
"grenadier", "grenadier",
- "striker", "striker",
- "laser", "laser",
"pulsar", "pulsar",
+ "laser", "laser",
+ "laserLayer", "laserLayer",
"sneaker", "launcher", "launcherOne", "exploder", "sucker", "sniper", "spinner", "grower", "beamer", "spawner", "ghoster", "focuser"
],
mobTypeSpawnOrder: [], //preset list of mob names calculated at the start of a run by the randomSeed
mobTypeSpawnIndex: 0, //increases as the mob type cycles
- allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter", "stinger"],
+ allowedGroupList: ["spinner", "striker", "springer", "laser", "focuser", "beamer", "exploder", "spawner", "shooter", "launcher", "launcherOne", "stabber", "sniper", "pulsar", "grenadier", "slasher", "flutter", "stinger", "laserLayer"],
setSpawnList() { //this is run at the start of each new level to determine the possible mobs for the level
spawn.pickList.splice(0, 1);
const push = spawn.mobTypeSpawnOrder[spawn.mobTypeSpawnIndex++ % spawn.mobTypeSpawnOrder.length]
@@ -892,43 +893,6 @@ const spawn = {
};
}
me.lasers = function (where, angle, dmg = 0.1 * simulation.dmgScale) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- };
-
const seeRange = 7000;
best = {
x: null,
@@ -942,10 +906,7 @@ const spawn = {
x: where.x + seeRange * Math.cos(angle),
y: where.y + seeRange * Math.sin(angle)
};
- // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- vertexCollision(where, look, body);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
if (m.immuneCycle < m.cycle + 60 + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 60 + m.collisionImmuneCycles; //player is immune to damage extra time
m.damage(dmg);
@@ -1101,499 +1062,6 @@ const spawn = {
}
};
},
- // finalBoss(x, y, radius = 300) {
- // mobs.spawn(x, y, 6, radius, "rgb(150,150,255)");
- // let me = mob[mob.length - 1];
- // setTimeout(() => { //fix mob in place, but allow rotation
- // me.constraint = Constraint.create({
- // pointA: {
- // x: me.position.x,
- // y: me.position.y
- // },
- // bodyB: me,
- // stiffness: 1,
- // damping: 1
- // });
- // Composite.add(engine.world, me.constraint);
- // }, 2000); //add in a delay in case the level gets flipped left right
- // me.isBoss = true;
- // me.isFinalBoss = true;
- // me.frictionAir = 0.01;
- // me.memory = Infinity;
- // me.hasRunDeathScript = false
- // me.locatePlayer();
- // // const density = 0.2
- // Matter.Body.setDensity(me, 0.2); //extra dense //normal is 0.001 //makes effective life much larger
- // // spawn.shield(me, x, y, 1);
- // me.onDamage = function() {};
- // me.cycle = 660;
- // me.endCycle = 780;
- // me.totalCycles = 0
- // me.mode = 0;
- // me.damageReduction = 0.25 //reset on each new mode
- // me.pushAway = function(magX = 0.13, magY = 0.05) {
- // for (let i = 0, len = body.length; i < len; ++i) { //push blocks away horizontally
- // body[i].force.x += magX * body[i].mass * (body[i].position.x > this.position.x ? 1 : -1)
- // body[i].force.y -= magY * body[i].mass
- // }
- // for (let i = 0, len = bullet.length; i < len; ++i) { //push blocks away horizontally
- // bullet[i].force.x += magX * bullet[i].mass * (bullet[i].position.x > this.position.x ? 1 : -1)
- // bullet[i].force.y -= magY * bullet[i].mass
- // }
- // for (let i = 0, len = powerUp.length; i < len; ++i) { //push blocks away horizontally
- // powerUp[i].force.x += magX * powerUp[i].mass * (powerUp[i].position.x > this.position.x ? 1 : -1)
- // powerUp[i].force.y -= magY * powerUp[i].mass
- // }
- // player.force.x += magX * player.mass * (player.position.x > this.position.x ? 1 : -1)
- // player.force.y -= magY * player.mass
- // }
- // me.do = function() {
- // this.modeDo(); //this does different things based on the mode
- // this.checkStatus();
- // this.cycle++; //switch modes÷ if time isn't paused
- // this.totalCycles++;
- // if (this.health > 0.3) {
- // if (this.cycle > this.endCycle) {
- // this.showHealthBar = true
- // this.cycle = 0;
- // this.mode++
- // this.damageReduction = 0.25
- // if (this.totalCycles > 180) this.pushAway();
- // if (this.mode > 3) {
- // this.mode = 0;
- // this.fill = "#50f";
- // this.rotateVelocity = Math.abs(this.rotateVelocity) * (player.position.x > this.position.x ? 1 : -1) //rotate so that the player can get away
- // this.modeDo = this.modeLasers
- // //push blocks and player away, since this is the end of suck, and suck causes blocks to fall on the boss and stun it
- // Matter.Body.scale(this, 1000, 1000);
- // if (!this.isShielded) spawn.shield(this, this.position.x, this.position.y, 1); // regen shield to also prevent stun
- // } else if (this.mode === 1) {
- // this.fill = "#50f"; // this.fill = "rgb(150,150,255)";
- // this.modeDo = this.modeSpawns
- // } else if (this.mode === 2) {
- // this.fill = "#50f";
- // this.modeDo = this.modeBombs
- // } else if (this.mode === 3) {
- // for (let i = 0; i < mob.length; i++) {
- // if (mob[i].isMine) mob[i].isExploding = true //explode the mines at the start of new round
- // }
- // this.fill = "#000";
- // this.modeDo = this.modeSuck
- // Matter.Body.scale(this, 0.001, 0.001);
- // this.damageReduction = 0.000025
- // this.showHealthBar = false
- // }
-
- // if (tech.isGunCycle) {
- // b.inventoryGun++;
- // if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
- // simulation.switchGun();
- // }
- // }
- // } else if (this.mode !== 3) { //all three modes at once , this runs once
- // this.showHealthBar = true
- // this.pushAway();
- // this.cycle = 0;
- // this.endCycle = Infinity
- // this.damageReduction = 0.15
- // if (this.mode === 2) {
- // Matter.Body.scale(this, 500, 500);
- // } else {
- // Matter.Body.scale(this, 0.5, 0.5);
- // }
- // this.mode = 3
- // this.fill = "#000";
- // this.eventHorizon = 750
- // this.spawnInterval = 600
- // this.rotateVelocity = 0.001 * (player.position.x > this.position.x ? 1 : -1) //rotate so that the player can get away
- // // if (!this.isShielded) spawn.shield(this, x, y, 1); //regen shield here ?
- // this.modeDo = this.modeAll
- // this.eventHorizonRadius = 700
- // if (tech.isGunCycle) {
- // b.inventoryGun++;
- // if (b.inventoryGun > b.inventory.length - 1) b.inventoryGun = 0;
- // simulation.switchGun();
- // }
- // }
- // // }
- // };
- // me.modeDo = function() {}
- // me.modeAll = function() {
- // this.modeBombs()
- // this.modeSpawns()
- // this.modeSuck()
- // this.modeLasers()
- // }
- // me.bombInterval = 36 - 0.5 * simulation.difficultyMode * simulation.difficultyMode
- // me.modeBombs = function() {
- // if (!(this.cycle % 20)) {
- // if (m.pos.x < 750) {
- // spawn.mine(m.pos.x + 200 * (Math.random() - 0.5), -500)
- // } else {
- // spawn.mine(Math.min(Math.max(770, m.pos.x + 200 * (Math.random() - 0.5)), 5350), -1500)
- // }
- // }
- // if (!(this.cycle % 10)) spawn.mine(800 + 4550 * Math.random(), -1500)
-
- // //mines fall
- // for (let i = 0; i < mob.length; i++) {
- // // if (mob[i].isMine && mob[i].position.y < -5) Matter.Body.setPosition(mob[i], { x: mob[i].position.x, y: mob[i].position.y + 5 })
- // if (mob[i].isMine && mob[i].position.y < -14) mob[i].force.y += mob[i].mass * 0.03;
- // }
-
- // }
- // me.spawnInterval = 395
- // me.modeSpawns = function() {
- // if (!(this.cycle % this.spawnInterval) && mob.length < 40) {
- // if (this.mode !== 3) Matter.Body.setAngularVelocity(this, 0.1)
- // //fire a bullet from each vertex
- // const whoSpawn = spawn.fullPickList[Math.floor(Math.random() * spawn.fullPickList.length)];
- // for (let i = 0, len = 2 + this.totalCycles / 1000; i < len; i++) {
- // const vertex = this.vertices[i % 6]
- // spawn[whoSpawn](vertex.x + 50 * (Math.random() - 0.5), vertex.y + 50 * (Math.random() - 0.5));
- // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, vertex))), -18) //give the mob a rotational velocity as if they were attached to a vertex
- // Matter.Body.setVelocity(mob[mob.length - 1], {
- // x: this.velocity.x + velocity.x,
- // y: this.velocity.y + velocity.y
- // });
- // }
- // if (!(this.cycle % 2 * this.spawnInterval) && mob.length < 40) {
- // const len = (this.totalCycles / 1000 + simulation.difficulty / 2 - 30) / 15
- // for (let i = 0; i < len; i++) {
- // spawn.randomLevelBoss(3000 * (simulation.isHorizontalFlipped ? -1 : 1) + 2000 * (Math.random() - 0.5), -1100 + 200 * (Math.random() - 0.5))
- // }
- // }
- // }
- // }
- // me.eventHorizon = 0
- // me.eventHorizonRadius = 1300
- // me.modeSuck = function() {
- // if (!(this.cycle % 30)) {
- // const index = Math.floor((this.cycle % 360) / 60)
- // spawn.seeker(this.vertices[index].x, this.vertices[index].y, 20 * (0.5 + Math.random()), 9); //give the bullet a rotational velocity as if they were attached to a vertex
- // const who = mob[mob.length - 1]
- // Matter.Body.setDensity(who, 0.00003); //normal is 0.001
- // who.timeLeft = 720 + 10 * simulation.difficulty //* (0.8 + 0.4 * Math.random());
- // who.accelMag = 0.0003 * simulation.accelScale; //* (0.8 + 0.4 * Math.random())
- // who.frictionAir = 0.01 //* (0.8 + 0.4 * Math.random());
- // const velocity = Vector.mult(Vector.perp(Vector.normalise(Vector.sub(this.position, this.vertices[index]))), -7)
- // Matter.Body.setVelocity(who, {
- // x: this.velocity.x + velocity.x,
- // y: this.velocity.y + velocity.y
- // });
- // }
-
- // //eventHorizon waves in and out
- // if (this.cycle + 30 > this.endCycle) { //shrink fast in last bit of cycle
- // this.eventHorizon = 0.93 * this.eventHorizon
- // } else {
- // this.eventHorizon = 0.97 * this.eventHorizon + 0.03 * (this.eventHorizonRadius * (1 - 0.5 * Math.cos(this.cycle * 0.015)))
- // }
- // //draw darkness
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.2, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,20,40,0.6)";
- // ctx.fill();
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.4, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,20,40,0.4)";
- // ctx.fill();
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.6, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,20,40,0.3)";
- // ctx.fill();
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon * 0.8, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,20,40,0.2)";
- // ctx.fill();
- // ctx.beginPath();
- // ctx.arc(this.position.x, this.position.y, this.eventHorizon, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,0,0,0.05)";
- // ctx.fill();
- // //when player is inside event horizon
- // if (Vector.magnitude(Vector.sub(this.position, player.position)) < this.eventHorizon) {
- // if (m.immuneCycle < m.cycle) {
- // if (m.energy > 0) m.energy -= 0.02
- // if (m.energy < 0.05 && m.immuneCycle < m.cycle) m.damage(0.0004 * simulation.dmgScale);
- // }
- // const angle = Math.atan2(player.position.y - this.position.y, player.position.x - this.position.x);
- // player.force.x -= 0.0017 * Math.cos(angle) * player.mass * (m.onGround ? 1.7 : 1);
- // player.force.y -= 0.0017 * Math.sin(angle) * player.mass;
- // //draw line to player
- // ctx.beginPath();
- // ctx.moveTo(this.position.x, this.position.y);
- // ctx.lineTo(m.pos.x, m.pos.y);
- // ctx.lineWidth = Math.min(60, this.radius * 2);
- // ctx.strokeStyle = "rgba(0,0,0,0.5)";
- // ctx.stroke();
- // ctx.beginPath();
- // ctx.arc(m.pos.x, m.pos.y, 40, 0, 2 * Math.PI);
- // ctx.fillStyle = "rgba(0,0,0,0.3)";
- // ctx.fill();
- // }
- // this.curl(this.eventHorizon);
- // }
- // me.rotateVelocity = 0.0025
- // me.rotateCount = 0;
- // me.lasers = function(where, angle, dmg = 0.14 * simulation.dmgScale) {
- // const vertexCollision = function(v1, v1End, domain) {
- // for (let i = 0; i < domain.length; ++i) {
- // let vertices = domain[i].vertices;
- // const len = vertices.length - 1;
- // for (let j = 0; j < len; j++) {
- // results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- // if (results.onLine1 && results.onLine2) {
- // const dx = v1.x - results.x;
- // const dy = v1.y - results.y;
- // const dist2 = dx * dx + dy * dy;
- // if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[j],
- // v2: vertices[j + 1]
- // };
- // }
- // }
- // results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- // if (results.onLine1 && results.onLine2) {
- // const dx = v1.x - results.x;
- // const dy = v1.y - results.y;
- // const dist2 = dx * dx + dy * dy;
- // if (dist2 < best.dist2) best = {
- // x: results.x,
- // y: results.y,
- // dist2: dist2,
- // who: domain[i],
- // v1: vertices[0],
- // v2: vertices[len]
- // };
- // }
- // }
- // };
-
- // const seeRange = 7000;
- // best = {
- // x: null,
- // y: null,
- // dist2: Infinity,
- // who: null,
- // v1: null,
- // v2: null
- // };
- // const look = {
- // x: where.x + seeRange * Math.cos(angle),
- // y: where.y + seeRange * Math.sin(angle)
- // };
- // // vertexCollision(where, look, mob);
- // vertexCollision(where, look, map);
- // vertexCollision(where, look, body);
- // if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
- // if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
- // if (m.immuneCycle < m.cycle + 60 + m.collisionImmuneCycles) m.immuneCycle = m.cycle + 60 + m.collisionImmuneCycles; //player is immune to damage extra time
- // m.damage(dmg);
- // simulation.drawList.push({ //add dmg to draw queue
- // x: best.x,
- // y: best.y,
- // radius: dmg * 1500,
- // color: "rgba(80,0,255,0.5)",
- // time: 20
- // });
- // }
- // //draw beam
- // if (best.dist2 === Infinity) best = look;
- // ctx.moveTo(where.x, where.y);
- // ctx.lineTo(best.x, best.y);
- // }
- // me.modeLasers = function() {
- // if (!this.isStunned) {
- // let slowed = false //check if slowed
- // for (let i = 0; i < this.status.length; i++) {
- // if (this.status[i].type === "slow") {
- // slowed = true
- // break
- // }
- // }
- // if (!slowed) {
- // this.rotateCount++
- // Matter.Body.setAngle(this, this.rotateCount * this.rotateVelocity)
- // Matter.Body.setAngularVelocity(this, 0)
- // Matter
- // }
- // }
- // if (this.cycle < 240) { //damage scales up over 2 seconds to give player time to move
- // const scale = this.cycle / 240
- // const dmg = (this.cycle < 120) ? 0 : 0.14 * simulation.dmgScale * scale
- // ctx.beginPath();
- // this.lasers(this.vertices[0], this.angle + Math.PI / 6, dmg);
- // this.lasers(this.vertices[1], this.angle + 3 * Math.PI / 6, dmg);
- // this.lasers(this.vertices[2], this.angle + 5 * Math.PI / 6, dmg);
- // this.lasers(this.vertices[3], this.angle + 7 * Math.PI / 6, dmg);
- // this.lasers(this.vertices[4], this.angle + 9 * Math.PI / 6, dmg);
- // this.lasers(this.vertices[5], this.angle + 11 * Math.PI / 6, dmg);
- // ctx.strokeStyle = "#50f";
- // ctx.lineWidth = 1.5 * scale;
- // ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]);
- // ctx.stroke(); // Draw it
- // ctx.setLineDash([]);
- // ctx.lineWidth = 20;
- // ctx.strokeStyle = `rgba(80,0,255,${0.07 * scale})`;
- // ctx.stroke(); // Draw it
- // } else {
- // ctx.beginPath();
- // this.lasers(this.vertices[0], this.angle + Math.PI / 6);
- // this.lasers(this.vertices[1], this.angle + 3 * Math.PI / 6);
- // this.lasers(this.vertices[2], this.angle + 5 * Math.PI / 6);
- // this.lasers(this.vertices[3], this.angle + 7 * Math.PI / 6);
- // this.lasers(this.vertices[4], this.angle + 9 * Math.PI / 6);
- // this.lasers(this.vertices[5], this.angle + 11 * Math.PI / 6);
- // ctx.strokeStyle = "#50f";
- // ctx.lineWidth = 1.5;
- // ctx.setLineDash([70 + 300 * Math.random(), 55 * Math.random()]);
- // ctx.stroke(); // Draw it
- // ctx.setLineDash([]);
- // ctx.lineWidth = 20;
- // ctx.strokeStyle = "rgba(80,0,255,0.07)";
- // ctx.stroke(); // Draw it
- // }
- // }
- // me.onDeath = function() {
- // if (!this.hasRunDeathScript) {
- // this.hasRunDeathScript = true
- // //make a block body to replace this one
- // //this body is too big to leave behind in the normal way mobs.replace()
- // const len = body.length;
- // const v = Matter.Vertices.hull(Matter.Vertices.clockwiseSort(this.vertices)) //might help with vertex collision issue, not sure
- // body[len] = Matter.Bodies.fromVertices(this.position.x, this.position.y, v);
- // Matter.Body.setVelocity(body[len], { x: 0, y: -3 });
- // Matter.Body.setAngularVelocity(body[len], this.angularVelocity);
- // 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";
- // Composite.add(engine.world, body[len]); //add to world
- // const expand = function(that, massLimit) {
- // const scale = 1.05;
- // Matter.Body.scale(that, scale, scale);
- // if (that.mass < massLimit) setTimeout(expand, 20, that, massLimit);
- // };
- // expand(body[len], 200)
-
- // function unlockExit() {
- // if (simulation.isHorizontalFlipped) {
- // level.exit.x = -5500 - 100;
- // } else {
- // level.exit.x = 5500;
- // }
- // level.exit.y = -330;
- // Matter.Composite.remove(engine.world, map[map.length - 1]);
- // map.splice(map.length - 1, 1);
- // simulation.draw.setPaths(); //redraw map draw path
- // // level.levels.push("null")
- // }
-
- // //add lore level as next level if player took lore tech earlier in the game
- // if (lore.techCount > (lore.techGoal - 1) && !simulation.isCheating) {
- // simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`, 360);
- // setTimeout(function() {
- // simulation.makeTextLog(`level.levels.push("null")`, 720);
- // unlockExit()
- // level.levels.push("null")
- // }, 4000);
- // //remove block map element so exit is clear
- // } else { //reset game
- // let count = 0
-
- // function loop() {
- // if (!simulation.paused && !simulation.onTitlePage) {
- // count++
- // if (count < 660) {
- // if (count === 1) simulation.makeTextLog(`//enter testing mode to set level.levels.length to Infinite`);
- // if (!(count % 60)) simulation.makeTextLog(`simulation.analysis = ${((count / 60 - Math.random()) * 0.1).toFixed(3)}`);
- // } else if (count === 660) {
- // simulation.makeTextLog(`simulation.analysis = 1 //analysis complete`);
- // } else if (count === 780) {
- // simulation.makeTextLog(`undefined = ${lore.techCount}/${lore.techGoal}`)
- // } else if (count === 1020) {
- // simulation.makeTextLog(`Engine.clear(engine) //simulation successful`);
- // } else if (count === 1260) {
- // // tech.isImmortal = false;
- // // m.death()
- // // m.alive = false;
- // // simulation.paused = true;
- // // m.health = 0;
- // // m.displayHealth();
- // document.getElementById("health").style.display = "none"
- // document.getElementById("health-bg").style.display = "none"
- // document.getElementById("text-log").style.opacity = 0; //fade out any active text logs
- // document.getElementById("fade-out").style.opacity = 1; //slowly fades out
- // // build.shareURL(false)
- // setTimeout(function() {
- // if (!simulation.onTitlePage) {
- // simulation.paused = true;
- // // simulation.clearMap();
- // // Matter.Composite.clear(composite, keepStatic, [deep = false])
- // // Composite.clear(engine.composite);
- // engine.world.bodies.forEach((body) => { Matter.Composite.remove(engine.world, body) })
- // Engine.clear(engine);
- // simulation.splashReturn();
- // }
- // }, 6000);
- // return
- // }
- // }
- // if (simulation.testing) {
- // unlockExit()
- // setTimeout(function() {
- // simulation.makeTextLog(`level.levels.length = Infinite`);
- // }, 1500);
- // } else {
- // if (!simulation.onTitlePage) requestAnimationFrame(loop);
- // }
- // }
- // requestAnimationFrame(loop);
- // }
- // // for (let i = 0; i < 3; i++)
- // level.difficultyIncrease(simulation.difficultyMode) //ramp up damage
- // //remove power Ups, to avoid spamming console
- // function removeAll(array) {
- // for (let i = 0; i < array.length; ++i) Matter.Composite.remove(engine.world, array[i]);
- // }
- // removeAll(powerUp);
- // powerUp = [];
-
- // //pull in particles
- // for (let i = 0, len = body.length; i < len; ++i) {
- // const velocity = Vector.mult(Vector.normalise(Vector.sub(this.position, body[i].position)), 65)
- // const pushUp = Vector.add(velocity, { x: 0, y: -0.5 })
- // Matter.Body.setVelocity(body[i], Vector.add(body[i].velocity, pushUp));
- // }
- // //damage all mobs
- // for (let j = 0; j < 8; j++) { //in case some mobs leave things after they die
- // for (let i = 0, len = mob.length; i < len; ++i) {
- // if (mob[i] !== this) {
- // if (mob[i].isInvulnerable) { //disable invulnerability
- // mob[i].isInvulnerable = false
- // mob[i].damageReduction = 1
- // }
- // mob[i].damage(Infinity, true);
- // }
- // }
- // }
-
- // //draw stuff
- // for (let i = 0, len = 22; i < len; i++) {
- // simulation.drawList.push({ //add dmg to draw queue
- // x: this.position.x,
- // y: this.position.y,
- // radius: (i + 1) * 150,
- // color: `rgba(255,255,255,0.17)`,
- // time: 5 * (len - i + 1)
- // });
- // }
- // }
- // };
- // },
zombie(x, y, radius, sides, color) { //mob that attacks other mobs
mobs.spawn(x, y, sides, radius, color);
let me = mob[mob.length - 1];
@@ -2229,7 +1697,7 @@ const spawn = {
me.isInvulnerable = true
me.startingDamageReduction = me.damageReduction
me.damageReduction = 0
- me.invulnerabilityCountDown = 40 + simulation.difficulty
+ me.invulnerabilityCountDown = 25 + simulation.difficulty
me.onHit = function () { //run this function on hitting player
if (powerUps.ejectTech()) {
powerUps.ejectGraphic("150, 138, 255");
@@ -2276,10 +1744,7 @@ const spawn = {
for (let i = 0; i < Math.min(powerUp.length, this.vertices.length); i++) {
powerUp[i].collisionFilter.mask = 0
Matter.Body.setPosition(powerUp[i], this.vertices[i])
- Matter.Body.setVelocity(powerUp[i], {
- x: 0,
- y: 0
- })
+ Matter.Body.setVelocity(powerUp[i], { x: 0, y: 0 })
}
}
this.seePlayerByHistory(50);
@@ -2294,7 +1759,7 @@ const spawn = {
me.frictionAir = 0.01
me.seeAtDistance2 = 1000000;
me.accelMag = 0.0002 + 0.0004 * simulation.accelScale;
- Matter.Body.setDensity(me, 0.00035); //normal is 0.001
+ Matter.Body.setDensity(me, 0.0003); //normal is 0.001
me.collisionFilter.mask = cat.bullet | cat.player //| cat.body
me.memory = Infinity;
me.seePlayerFreq = 30
@@ -2308,7 +1773,7 @@ const spawn = {
me.foundPlayer();
}
- me.damageReduction = 0.16 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
+ me.damageReduction = 0.15 / (tech.isScaleMobsWithDuplication ? 1 + tech.duplicationChance() : 1)
// me.isInvulnerable = true
// me.startingDamageReduction = me.damageReduction
// me.damageReduction = 0
@@ -3215,10 +2680,7 @@ const spawn = {
me.seePlayerFreq = 31;
const springStiffness = 0.00003; //simulation.difficulty
const springDampening = 0.0002;
- me.springTarget = {
- x: me.position.x,
- y: me.position.y
- };
+ me.springTarget = { x: me.position.x, y: me.position.y };
const len = cons.length;
cons[len] = Constraint.create({
pointA: me.springTarget,
@@ -3314,47 +2776,6 @@ const spawn = {
} else {
this.torque = this.lookTorque * this.inertia;
//spring to random place on map
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
- //move to a random location
if (!(simulation.cycle % (this.seePlayerFreq))) {
best = {
x: null,
@@ -3365,11 +2786,8 @@ const spawn = {
v2: null
};
const seeRange = 3000;
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
+ const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) };
+ best = vertexCollision(this.position, look, [map]);
if (best.dist2 != Infinity) {
this.springTarget.x = best.x;
this.springTarget.y = best.y;
@@ -3899,46 +3317,6 @@ const spawn = {
const seeRange = 550 + 35 * simulation.difficultyMode;
if (this.distanceToPlayer() < seeRange) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
best = {
x: null,
y: null,
@@ -3948,13 +3326,8 @@ const spawn = {
v2: null
};
const seeRangeRandom = seeRange - 200 - 150 * Math.random()
- const look = {
- x: this.position.x + seeRangeRandom * Math.cos(this.angle),
- y: this.position.y + seeRangeRandom * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
- if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]);
+ const look = { x: this.position.x + seeRangeRandom * Math.cos(this.angle), y: this.position.y + seeRangeRandom * Math.sin(this.angle) };
+ best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
// hitting player
if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
@@ -4272,46 +3645,6 @@ const spawn = {
this.torque -= 0.000004 * this.inertia;
}
if (simulation.cycle % this.laserInterval > this.laserInterval / 2) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
const seeRange = 8000;
best = {
x: null,
@@ -4321,13 +3654,8 @@ const spawn = {
v1: null,
v2: null
};
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
- if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]);
+ const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) };
+ best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
// hitting player
if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
@@ -4390,26 +3718,6 @@ const spawn = {
me.targetingCount = 0;
me.targetingTime = 60 - Math.min(58, 3 * simulation.difficulty)
me.do = function () {
-
- // //wings
- // const wing = (simulation.cycle % 9) > 4 ? this.vertices[0] : this.vertices[2] //Vector.add(this.position, { x: 100, y: 0 })
- // const radius = 200
- // //draw
- // ctx.beginPath();
- // ctx.arc(wing.x, wing.y, radius, 0, 2 * Math.PI); //* this.fireCycle / this.fireDelay
- // ctx.fillStyle = "rgba(0,235,255,0.3)";
- // ctx.fill();
- // //check damage
- // const hitPlayer = Matter.Query.ray([player], this.position, wing, radius)
- // if (hitPlayer.length && m.immuneCycle < m.cycle) {
- // m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage
- // m.damage(0.02 * simulation.dmgScale);
- // }
-
-
-
-
-
this.seePlayerByLookingAt();
this.checkStatus();
this.attraction();
@@ -4427,46 +3735,6 @@ const spawn = {
} else if (c < -threshold) {
this.torque -= 0.000004 * this.inertia;
}
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
const seeRange = 8000;
best = {
@@ -4477,12 +3745,8 @@ const spawn = {
v1: null,
v2: null
};
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]);
+ const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) };
+ best = vertexCollision(this.position, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]);
// hitting player
if (best.who === playerBody || best.who === playerHead) {
@@ -4844,6 +4108,152 @@ const spawn = {
}
};
},
+ laserLayer(x, y, radius = 18 + Math.floor(6 * Math.random())) {
+ const color = "#f09"
+ mobs.spawn(x, y, 4, radius, color);
+ 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
+ for (let i = 0; i < 4; i += 2) {
+ let spike = Vector.mult(Vector.normalise(Vector.sub(me.vertices[i], me.position)), radius * 2)
+ me.vertices[i].x = me.position.x + spike.x
+ me.vertices[i].y = me.position.y + spike.y
+ }
+ Matter.Body.rotate(me, Math.random() * Math.PI * 2);
+ me.accelMag = 0.0002 * simulation.accelScale;
+ // me.frictionAir = 1
+
+ me.lasers = [] //keeps track of static laser beams
+ me.laserLimit = simulation.difficultyMode < 3 ? 1 : 2
+ me.fireDelay = Math.max(75, 140 - simulation.difficulty * 0.5)
+ me.cycle = 0
+ me.laserDelay = 150 + Math.floor(Math.random() * 120)
+ me.addLaser = function () {
+ if (this.cycle > this.laserDelay) {
+ this.cycle = 0
+ const seeRange = 6000;
+ const angle = this.angle + Math.PI / 4
+ const v1 = { x: this.position.x + seeRange * Math.cos(angle), y: this.position.y + seeRange * Math.sin(angle) };
+ const v2 = { x: this.position.x + seeRange * Math.cos(angle + Math.PI), y: this.position.y + seeRange * Math.sin(angle + Math.PI) };
+ //find where v1,v2 hit walls and make them stop there
+ let best1 = vertexCollision(this.position, v1, [map]);
+ let best2 = vertexCollision(this.position, v2, [map]);
+ if (best2.who === null) {
+ best2.x = v2.x
+ best2.y = v2.y
+ }
+ if (best1.who === null) { //if the path never hits the map , just stop at seeRange
+ best1.x = v1.x
+ best1.y = v1.y
+ }
+ if (best1.y > best2.y) { //make laser beams always fire from top to bottom so they are predicable, and not stopped by blocks on the ground
+ const save1X = best1.x
+ const save1Y = best1.y
+ best1.x = best2.x
+ best1.y = best2.y
+ best2.x = save1X
+ best2.y = save1Y
+ }
+
+ this.lasers.push({ a: { x: best1.x, y: best1.y }, b: { x: best2.x, y: best2.y }, fade: 0 })
+ //friction to animate the mob dropping something
+ Matter.Body.setVelocity(this, Vector.mult(this.velocity, 0.05));
+ Matter.Body.setAngularVelocity(this, this.angularVelocity * 0.05)
+ // simulation.drawList.push({ x: best1.x, y: best1.y, radius: 10, color: "rgba(255,0,100,0.3)", time: simulation.drawTime * 2 });
+ // simulation.drawList.push({ x: best2.x, y: best2.y, radius: 10, color: "rgba(255,0,100,0.3)", time: simulation.drawTime * 2 });
+
+ if (this.lasers.length > this.laserLimit) this.lasers.shift() //cap total lasers
+ if (!this.seePlayer.recall && (Vector.magnitude(Vector.sub(this.position, this.driftGoal)) < 200 || 0.3 > Math.random())) {
+ //used in drift when can't find player
+ const radius = Math.random() * 1000;
+ const angle = Math.random() * 2 * Math.PI;
+ this.driftGoal = Vector.add(this.driftCenter, { x: radius * Math.cos(angle), y: radius * Math.sin(angle) })
+ }
+ }
+ }
+ me.fireLaser = function () {
+ for (let i = 0; i < this.lasers.length; i++) { //fire all lasers in the array
+ let best = vertexCollision(this.lasers[i].a, this.lasers[i].b, m.isCloak ? [body] : [body, [playerBody, playerHead]]); //not checking map to fix not hitting player bug, this might make some lasers look strange when the map changes
+ if (this.lasers[i].fade > 0.99) {
+ if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) { // hitting player
+ m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage after getting hit
+ const dmg = 0.05 * simulation.dmgScale;
+ m.damage(dmg);
+ simulation.drawList.push({ //add dmg to draw queue
+ x: best.x,
+ y: best.y,
+ radius: dmg * 1500,
+ color: "rgba(255,0,100,0.5)",
+ time: 20
+ });
+ this.lasers.splice(i, 1) //remove this laser node
+ if (this.distanceToPlayer < 1000) { //mob jumps away from player
+ const forceMag = 0.03 * this.mass;
+ const angle = Math.atan2(this.seePlayer.position.y - this.position.y, this.seePlayer.position.x - this.position.x);
+ this.force.x -= 2 * forceMag * Math.cos(angle);
+ this.force.y -= 2 * forceMag * Math.sin(angle); // - 0.0007 * this.mass; //antigravity
+ }
+ } else if (best.who && best.who.classType === "body") { //hitting block
+ ctx.beginPath();
+ ctx.moveTo(best.x, best.y);
+ ctx.lineTo(this.lasers[i].a.x, this.lasers[i].a.y);
+ ctx.strokeStyle = `rgb(255,0,100)`;
+ ctx.lineWidth = 2;
+ ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
+ ctx.stroke();
+ ctx.setLineDash([]);
+ } else { //hitting nothing
+ ctx.beginPath();
+ ctx.moveTo(this.lasers[i].b.x, this.lasers[i].b.y);
+ ctx.lineTo(this.lasers[i].a.x, this.lasers[i].a.y);
+ ctx.strokeStyle = `rgb(255,0,100)`;
+ ctx.lineWidth = 2;
+ ctx.setLineDash([50 + 120 * Math.random(), 50 * Math.random()]);
+ ctx.stroke();
+ ctx.setLineDash([]);
+ }
+ } else {//fade in warning
+ this.lasers[i].fade += 0.01
+ ctx.beginPath();
+ ctx.moveTo(this.lasers[i].a.x, this.lasers[i].a.y);
+ ctx.lineTo(this.lasers[i].b.x, this.lasers[i].b.y);
+ ctx.lineWidth = 5 + 5 * this.lasers[i].fade;
+ ctx.strokeStyle = `rgba(255,0,100,${0.02 + 0.1 * this.lasers[i].fade})`;
+ ctx.stroke();
+ }
+ }
+ }
+ me.driftCenter = { ...me.position }; //copy position with out reference so it doesn't change as mob moves
+ const r = Math.random() * 100;
+ const a = Math.random() * 2 * Math.PI;
+ me.driftGoal = Vector.add(me.driftCenter, { x: r * Math.cos(a), y: r * Math.sin(a) }) //updated in addLaser()
+ me.drift = function () {
+ //accelerate towards the player
+ if (this.seePlayer.recall) {
+ const force = Vector.mult(Vector.normalise(Vector.sub(this.seePlayer.position, this.position)), this.accelMag * this.mass)
+ this.force.x += force.x;
+ this.force.y += force.y;
+ } else { //drift
+ const force = Vector.mult(Vector.normalise(Vector.sub(this.driftGoal, this.position)), 0.00002 * this.mass)
+ // const force = Vector.mult(this.driftGoal, 0.0001 * this.mass)
+ this.force.x += force.x;
+ this.force.y += force.y;
+ }
+ },
+ me.do = function () {
+ this.cycle++
+ this.torque = this.lookTorque * this.inertia * 0.6;
+ this.seePlayerCheck();
+ this.checkStatus();
+ this.drift();
+ //add new laser to lasers array
+ this.addLaser()
+ this.fireLaser()
+ // if (this.seePlayer.recall) {
+ // //set direction to turn to fire
+ // if (!(simulation.cycle % this.seePlayerFreq)) this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
+ // }
+ };
+ },
laser(x, y, radius = 30) {
const color = "#f00"
mobs.spawn(x, y, 3, radius, color);
@@ -4866,46 +4276,6 @@ const spawn = {
if (!(simulation.cycle % this.seePlayerFreq)) this.fireDir = Vector.normalise(Vector.sub(this.seePlayer.position, this.position));
if (simulation.cycle % this.laserInterval > this.laserInterval / 2) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) {
- best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- }
- };
const seeRange = 8000;
best = {
x: null,
@@ -4915,13 +4285,8 @@ const spawn = {
v1: null,
v2: null
};
- const look = {
- x: this.position.x + seeRange * Math.cos(this.angle),
- y: this.position.y + seeRange * Math.sin(this.angle)
- };
- vertexCollision(this.position, look, map);
- vertexCollision(this.position, look, body);
- if (!m.isCloak) vertexCollision(this.position, look, [playerBody, playerHead]);
+ const look = { x: this.position.x + seeRange * Math.cos(this.angle), y: this.position.y + seeRange * Math.sin(this.angle) };
+ best = vertexCollision(this.position, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
// hitting player
if ((best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
@@ -4963,10 +4328,7 @@ const spawn = {
setTimeout(() => { //fix mob in place, but allow rotation
me.constraint = Constraint.create({
- pointA: {
- x: me.position.x,
- y: me.position.y
- },
+ pointA: { x: me.position.x, y: me.position.y },
bodyB: me,
stiffness: 1,
damping: 1
@@ -4988,7 +4350,6 @@ const spawn = {
me.do = function () {
this.fill = '#' + Math.random().toString(16).substr(-6); //flash colors
this.checkStatus();
-
if (!this.isStunned) {
//check if slowed
let slowed = false
@@ -5003,7 +4364,6 @@ const spawn = {
Matter.Body.setAngle(this, this.count * this.rotateVelocity)
Matter.Body.setAngularVelocity(this, 0)
}
-
ctx.beginPath();
this.lasers(this.vertices[0], this.angle + Math.PI / 3);
this.lasers(this.vertices[1], this.angle + Math.PI);
@@ -5017,53 +4377,8 @@ const spawn = {
ctx.strokeStyle = "rgba(80,0,255,0.07)";
ctx.stroke(); // Draw it
}
-
-
- // Matter.Body.setVelocity(this, {
- // x: 0,
- // y: 0
- // });
- // Matter.Body.setPosition(this, this.startingPosition);
-
};
me.lasers = function (where, angle) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[j],
- v2: vertices[j + 1]
- };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = {
- x: results.x,
- y: results.y,
- dist2: dist2,
- who: domain[i],
- v1: vertices[0],
- v2: vertices[len]
- };
- }
- }
- };
-
const seeRange = 7000;
best = {
x: null,
@@ -5073,14 +4388,9 @@ const spawn = {
v1: null,
v2: null
};
- const look = {
- x: where.x + seeRange * Math.cos(angle),
- y: where.y + seeRange * Math.sin(angle)
- };
- // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- vertexCollision(where, look, body);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ const look = { x: where.x + seeRange * Math.cos(angle), y: where.y + seeRange * Math.sin(angle) };
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
const dmg = 0.14 * simulation.dmgScale;
@@ -5115,9 +4425,6 @@ const spawn = {
me.collisionFilter.mask = cat.map | cat.body | cat.bullet | cat.player //can't touch other mobs
Matter.Body.rotate(me, Math.PI * 0.1);
spawn.shield(me, x, y);
- // me.onDamage = function () {};
- // me.onHit = function() { //run this function on hitting player
- // };
me.onDeath = function () {
if (this.spikeLength > 4) {
this.spikeLength = 4
@@ -5157,11 +4464,6 @@ const spawn = {
} else {
if (this.isSpikeGrowing) {
this.spikeLength += Math.pow(this.spikeGrowth += 0.02, 8)
- // if (this.spikeLength < 2) {
- // this.spikeLength += 0.035
- // } else {
- // this.spikeLength += 1
- // }
if (this.spikeLength > spikeMax) {
this.isSpikeGrowing = false;
this.spikeGrowth = 0
@@ -5182,7 +4484,6 @@ const spawn = {
}
};
},
-
striker(x, y, radius = 14 + Math.ceil(Math.random() * 25)) {
mobs.spawn(x, y, 5, radius, "rgb(221,102,119)");
let me = mob[mob.length - 1];
@@ -5306,33 +4607,9 @@ const spawn = {
}
};
me.laserSword = function (where, angle, length) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let vertices = domain[i].vertices;
- const len = vertices.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, vertices[j], vertices[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[j], v2: vertices[j + 1] };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, vertices[0], vertices[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: vertices[0], v2: vertices[len] };
- }
- }
- };
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + length * Math.cos(angle), y: where.y + length * Math.sin(angle) };
- // vertexCollision(where, look, body); // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map] : [map, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -5934,33 +5211,11 @@ const spawn = {
ctx.stroke();
}
me.laserSword = function (where, angle) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let v = domain[i].vertices;
- const len = v.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
- }
- }
- };
+
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- vertexCollision(where, look, body); // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -6056,33 +5311,9 @@ const spawn = {
}
}
me.laserSword = function (where, angle) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let v = domain[i].vertices;
- const len = v.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
- }
- }
- };
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- vertexCollision(where, look, body); // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -6172,33 +5403,9 @@ const spawn = {
}
}
me.laserSword = function (where, angle) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let v = domain[i].vertices;
- const len = v.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
- }
- }
- };
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- vertexCollision(where, look, body); // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
if (best.who && (best.who === playerBody || best.who === playerHead) && m.immuneCycle < m.cycle) {
m.immuneCycle = m.cycle + m.collisionImmuneCycles + 60; //player is immune to damage for an extra second
m.damage(this.swordDamage);
@@ -6306,33 +5513,10 @@ const spawn = {
}
}
me.laserSpear = function (where, angle) {
- const vertexCollision = function (v1, v1End, domain) {
- for (let i = 0; i < domain.length; ++i) {
- let v = domain[i].vertices;
- const len = v.length - 1;
- for (let j = 0; j < len; j++) {
- results = simulation.checkLineIntersection(v1, v1End, v[j], v[j + 1]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2 && (!domain[i].mob || domain[i].alive)) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[j], v2: v[j + 1] };
- }
- }
- results = simulation.checkLineIntersection(v1, v1End, v[0], v[len]);
- if (results.onLine1 && results.onLine2) {
- const dx = v1.x - results.x;
- const dy = v1.y - results.y;
- const dist2 = dx * dx + dy * dy;
- if (dist2 < best.dist2) best = { x: results.x, y: results.y, dist2: dist2, who: domain[i], v1: v[0], v2: v[len] };
- }
- }
- };
best = { x: null, y: null, dist2: Infinity, who: null, v1: null, v2: null };
const look = { x: where.x + this.swordRadius * Math.cos(angle), y: where.y + this.swordRadius * Math.sin(angle) };
- vertexCollision(where, look, body); // vertexCollision(where, look, mob);
- vertexCollision(where, look, map);
- if (!m.isCloak) vertexCollision(where, look, [playerBody, playerHead]);
+ best = vertexCollision(where, look, m.isCloak ? [map, body] : [map, body, [playerBody, playerHead]]);
+
if (best.who && (best.who === playerBody || best.who === playerHead)) {
this.swordRadiusGrowRate = 1 / this.swordRadiusGrowRateInitial //!!!! this retracts the sword if it hits the player
@@ -6543,10 +5727,10 @@ const spawn = {
mobs.spawn(x, y, 7, radius, "transparent");
let me = mob[mob.length - 1];
me.seeAtDistance2 = 300000;
- me.accelMag = 0.00004 + 0.00015 * simulation.accelScale;
+ me.accelMag = 0.00007 + 0.0001 * simulation.accelScale;
if (map.length) me.searchTarget = map[Math.floor(Math.random() * (map.length - 1))].position; //required for search
- // Matter.Body.setDensity(me, 0.0015); //normal is 0.001
- me.damageReduction = 0.5
+ Matter.Body.setDensity(me, 0.0002); //normal is 0.001
+ me.damageReduction = 0.1
me.stroke = "transparent"; //used for drawGhost
me.alpha = 1; //used in drawGhost
me.isNotCloaked = false; //used in drawGhost
@@ -6555,14 +5739,35 @@ const spawn = {
me.collisionFilter.mask = cat.bullet //| cat.body
me.showHealthBar = false;
me.memory = 600;
- me.do = function () {
- //cap max speed to avoid getting launched by deflection, explosion
- if (this.speed > 7) {
- Matter.Body.setVelocity(this, {
- x: this.velocity.x * 0.8,
- y: this.velocity.y * 0.8
- });
+ me.delay = 60
+ me.cd = 0;
+ me.onHit = function () {
+ if (this.cd < simulation.cycle) {
+ this.cd = simulation.cycle + this.delay;
+ //dislodge ammo
+ if (b.inventory.length) {
+ let isRemovedAmmo = false
+ const numRemoved = 3
+ for (let j = 0; j < numRemoved; j++) {
+ for (let i = 0; i < b.inventory.length; i++) {
+ const gun = b.guns[b.inventory[i]]
+ if (gun.ammo > 0 && gun.ammo !== Infinity) {
+ gun.ammo -= Math.ceil((0.6 * Math.random() + 0.6 * Math.random()) * gun.ammoPack) //Math.ceil(Math.random() * target.ammoPack)
+ if (gun.ammo < 0) gun.ammo = 0
+ isRemovedAmmo = true
+ }
+ }
+ }
+ if (isRemovedAmmo) {
+ simulation.updateGunHUD();
+ for (let j = 0; j < numRemoved; j++) powerUps.directSpawn(this.position.x + 10 * Math.random(), this.position.y + 10 * Math.random(), "ammo");
+ powerUps.ejectGraphic();
+ }
+ }
}
+ };
+ me.do = function () {
+ if (this.speed > 7) Matter.Body.setVelocity(this, { x: this.velocity.x * 0.8, y: this.velocity.y * 0.8 }); //cap max speed to avoid getting launched by deflection, explosion
this.seePlayerCheckByDistance();
this.checkStatus();
this.attraction();
@@ -6586,9 +5791,7 @@ const spawn = {
ctx.beginPath();
const vertices = this.vertices;
ctx.moveTo(vertices[0].x, vertices[0].y);
- for (let j = 1, len = vertices.length; j < len; ++j) {
- ctx.lineTo(vertices[j].x, vertices[j].y);
- }
+ for (let j = 1, len = vertices.length; j < len; ++j) ctx.lineTo(vertices[j].x, vertices[j].y);
ctx.lineTo(vertices[0].x, vertices[0].y);
// ctx.lineWidth = 1;
ctx.fillStyle = `rgba(255,255,255,${this.alpha * this.alpha})`;
diff --git a/js/tech.js b/js/tech.js
index 7900dfa..a62ab72 100644
--- a/js/tech.js
+++ b/js/tech.js
@@ -218,7 +218,7 @@ const tech = {
}
},
hasExplosiveDamageCheck() {
- return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb) || tech.isHookExplosion
+ return tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isBoomBotUpgrade || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb)
},
damage: 1, //used for tech changes to player damage that don't have complex conditions
damageFromTech() {
@@ -1215,6 +1215,38 @@ const tech = {
b.setFireCD();
}
},
+ {
+ name: "dynamical systems",
+ description: `use ${powerUps.orb.research(2)}
+30% damage`,
+ // isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return powerUps.research.count > 1 || build.isExperimentSelection
+ },
+ requires: "",
+ // allowed() {
+ // return (m.fieldMode === 5 || m.fieldMode === 7 || m.fieldMode === 8) && (build.isExperimentSelection || powerUps.research.count > 1)
+ // },
+ // requires: "cloaking, pilot wave, or plasma torch",
+ damage: 1.3,
+ effect() {
+ tech.damage *= this.damage
+ tech.isCloakingDamage = true
+ for (let i = 0; i < 2; i++) {
+ if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
+ }
+ },
+ remove() {
+ tech.isCloakingDamage = false
+ if (this.count > 0) {
+ tech.damage /= this.damage
+ powerUps.research.changeRerolls(2)
+ }
+ }
+ },
{
name: "heuristics",
description: "+22% fire rate
spawn a gun",
@@ -1412,24 +1444,24 @@ const tech = {
tech.healSpawn = 0;
}
},
- {
- name: "yield stress",
- description: "+55% damage
to mobs at maximum health",
- maxCount: 1,
- count: 0,
- frequency: 1,
- frequencyDefault: 1,
- allowed() {
- return m.fieldMode !== 7 && tech.mobSpawnWithHealth === 0
- },
- requires: "not cloaking, reaction inhibitor",
- effect() {
- tech.isMobFullHealth = true
- },
- remove() {
- tech.isMobFullHealth = false
- }
- },
+ // {
+ // name: "yield stress",
+ // description: "+55% damage
to mobs at maximum health",
+ // maxCount: 1,
+ // count: 0,
+ // frequency: 1,
+ // frequencyDefault: 1,
+ // allowed() {
+ // return m.fieldMode !== 7 && tech.mobSpawnWithHealth === 0
+ // },
+ // requires: "not cloaking, reaction inhibitor",
+ // effect() {
+ // tech.isMobFullHealth = true
+ // },
+ // remove() {
+ // tech.isMobFullHealth = false
+ // }
+ // },
{
name: "cascading failure",
description: "+222% damage
to mobs below 25% health",
@@ -1456,7 +1488,7 @@ const tech = {
frequency: 1,
frequencyDefault: 1,
allowed() {
- return !tech.isMobFullHealth
+ return !tech.isMobFullHealthCloak
},
requires: "not topological defect",
effect() {
@@ -2676,6 +2708,34 @@ const tech = {
tech.isHarmArmor = false;
}
},
+ {
+ name: "tessellation",
+ description: `use ${powerUps.orb.research(2)}
+35% defense`,
+ // description: "use 4 research
reduce defense by 50%",
+ // isFieldTech: true,
+ maxCount: 1,
+ count: 0,
+ frequency: 1,
+ frequencyDefault: 1,
+ allowed() {
+ return powerUps.research.count > 1 || build.isExperimentSelection
+ },
+ requires: "",
+ // allowed() {
+ // return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 3)
+ // },
+ // requires: "perfect diamagnetism, negative mass, grappling hook, pilot wave",
+ effect() {
+ tech.isFieldHarmReduction = true
+ for (let i = 0; i < 2; i++) {
+ if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
+ }
+ },
+ remove() {
+ tech.isFieldHarmReduction = false
+ if (this.count > 0) powerUps.research.changeRerolls(2)
+ }
+ },
{
name: "Pauli exclusion",
description: `after mob collisions
become invulnerable for +3.5 seconds`,
@@ -2796,14 +2856,14 @@ const tech = {
},
{
name: "heat engine",
- description: `+50% damage
–50 maximum energy`,
+ description: `+40% damage
–50 maximum energy`,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed: () => true,
requires: "not CPT",
- damage: 1.5,
+ damage: 1.4,
effect() {
tech.damage *= this.damage
tech.isMaxEnergyTech = true;
@@ -4184,7 +4244,7 @@ const tech = {
{
name: "commodities exchange",
descriptionFunction() {
- return `clicking cancel for a field, tech, or gun
spawns 6-12 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
+ return `clicking cancel for a field, tech, or gun
spawns 10-14 ${powerUps.orb.heal()}, ${powerUps.orb.ammo()}, or ${powerUps.orb.research(1)}`
},
maxCount: 1,
count: 0,
@@ -4912,7 +4972,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isFoamMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
+ return tech.hookNails + tech.isMineDrop + tech.isNailBotUpgrade + tech.fragments + tech.nailsDeathMob + (tech.haveGunCheck("super balls") + (tech.haveGunCheck("mine") && !tech.isFoamMine) + (tech.haveGunCheck("nail gun")) + tech.isNeedles + tech.isNailShot + tech.isRivets) * 2 > 1
},
requires: "nails, nail gun, rivets, shotgun, super balls, mine",
effect() {
@@ -4951,7 +5011,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || ((tech.isMineDrop || tech.haveGunCheck("mine")) && !(tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
+ return tech.isNailBotUpgrade || tech.hookNails || tech.fragments || tech.nailsDeathMob || ((tech.isMineDrop || tech.haveGunCheck("mine")) && !(tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isShieldPierce) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot))
},
requires: "nail gun, nails, rivets, mine, not ceramic needles",
effect() {
@@ -5842,7 +5902,7 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || tech.isHookExplosion || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
+ return !tech.isImmuneExplosion && (build.isExperimentSelection || powerUps.research.count > 1) && (tech.haveGunCheck("missiles") || (m.fieldMode === 4 && simulation.molecularMode === 1) || tech.missileBotCount > 0 || tech.isIncendiary || tech.isPulseLaser || tech.isTokamak || (tech.haveGunCheck("grenades") && !tech.isNeutronBomb))
},
requires: "an explosive damage source, not rocket propelled grenade",
effect() {
@@ -6123,7 +6183,7 @@ const tech = {
frequencyDefault: 2,
allowed() {
// return (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("mines"))
- return tech.isMineDrop || tech.isNailBotUpgrade || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles)
+ return tech.isMineDrop || tech.isNailBotUpgrade || tech.hookNails || tech.fragments || tech.nailsDeathMob || (tech.haveGunCheck("mine") && !(tech.isLaserMine || tech.isFoamMine || tech.isSuperMine)) || (tech.haveGunCheck("nail gun") && !tech.isRivets && !tech.isNeedles) || (tech.haveGunCheck("shotgun") && (tech.isNeedles || tech.isNailShot) && !tech.isRivets && !tech.isNeedles)
},
//
requires: "nail gun, not rotary cannon, rivets, or needles",
@@ -7074,7 +7134,7 @@ const tech = {
// },
{
name: "alternator",
- description: "+90% harpoon energy efficiency",
+ description: "harpoon no longer uses any energy",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -7113,7 +7173,7 @@ const tech = {
{
name: "Bessemer process",
descriptionFunction() {
- return `+${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}% harpoon size and damage
(1/10 √ harpoon ammo)`
+ return `+${(10 * Math.sqrt(b.guns[9].ammo)).toFixed(0)}% harpoon size and damage
(effect scales by 1/10 √ harpoon ammo)`
},
isGunTech: true,
maxCount: 1,
@@ -7179,7 +7239,7 @@ const tech = {
{
name: "UHMWPE",
descriptionFunction() {
- return `+${(b.guns[9].ammo * 1.25).toFixed(0)}% harpoon rope length
(1/80 of harpoon ammo)`
+ return `+${(b.guns[9].ammo * 1.25).toFixed(0)}% harpoon rope length
(effect scales by 1/80 of harpoon ammo)`
},
isGunTech: true,
maxCount: 1,
@@ -7219,7 +7279,7 @@ const tech = {
},
{
name: "brittle",
- description: "+88% harpoon/grapple damage
to mobs at maximum health",
+ description: "+111% harpoon/grapple damage
to mobs at maximum health",
isGunTech: true,
maxCount: 1,
count: 0,
@@ -7673,7 +7733,7 @@ const tech = {
},
{
name: "zero point energy",
- description: `use ${powerUps.orb.research(2)}
+100 maximum energy`,
+ description: `use ${powerUps.orb.research(2)}
+166 maximum energy`,
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -7684,7 +7744,7 @@ const tech = {
},
requires: "standing wave, pilot wave, time dilation",
effect() {
- tech.harmonicEnergy = 1
+ tech.harmonicEnergy = 1.66
m.setMaxEnergy()
for (let i = 0; i < 2; i++) {
if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
@@ -7698,7 +7758,7 @@ const tech = {
},
{
name: "expansion",
- description: "using standing wave field expands its radius
+40 maximum energy",
+ description: "using standing wave field expands its radius
+77 maximum energy",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -7860,30 +7920,6 @@ const tech = {
tech.isBigField = false;
}
},
- {
- name: "tessellation",
- description: `use ${powerUps.orb.research(2)}
+50% defense`,
- // description: "use 4 research
reduce defense by 50%",
- isFieldTech: true,
- maxCount: 1,
- count: 0,
- frequency: 3,
- frequencyDefault: 3,
- allowed() {
- return (m.fieldMode === 8 || m.fieldMode === 2 || m.fieldMode === 3 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 3)
- },
- requires: "perfect diamagnetism, negative mass, grappling hook, pilot wave",
- effect() {
- tech.isFieldHarmReduction = true
- for (let i = 0; i < 2; i++) {
- if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
- }
- },
- remove() {
- tech.isFieldHarmReduction = false
- if (this.count > 0) powerUps.research.changeRerolls(2)
- }
- },
{
name: "radiative equilibrium",
descriptionFunction() {
@@ -7978,7 +8014,7 @@ const tech = {
},
{
name: "annihilation",
- description: "after colliding with non-boss mobs
they are annihilated and –33% energy",
+ description: "after colliding with non-boss mobs
they are annihilated and –10 energy",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8291,9 +8327,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return m.fieldMode === 5 || m.fieldMode === 6 || m.fieldMode === 7 || m.fieldMode === 8 || m.fieldMode === 4
+ return m.fieldMode === 6 || m.fieldMode === 7 || m.fieldMode === 8
},
- requires: "cloaking, molecular assembler, plasma torch, pilot wave",
+ requires: "time dilation, cloaking, pilot wave",
damage: 1.35,
effect() {
tech.damage *= this.damage
@@ -8315,9 +8351,9 @@ const tech = {
frequency: 2,
frequencyDefault: 2,
allowed() {
- return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10) && !tech.isPrinter && !tech.isReel && !tech.isHookExplosion
+ return (m.fieldMode === 5 || m.fieldMode === 4 || m.fieldMode === 10) && !tech.isPrinter && !tech.isReel && !tech.hookNails
},
- requires: "plasma torch, molecular assembler, grappling hook, not printer, reel, rupture",
+ requires: "plasma torch, molecular assembler, grappling hook, not printer, reel, swarf",
effect() {
tech.isTokamak = true;
},
@@ -8705,7 +8741,7 @@ const tech = {
{
name: "dazzler",
link: `dazzler`,
- description: "after decloaking stun nearby mobs
and drain –10 energy",
+ description: "after decloaking
stun nearby mobs for 2 second",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -8724,16 +8760,16 @@ const tech = {
},
{
name: "topological defect",
- description: "+88% damage
to mobs at maximum health",
+ description: "+111% damage
to mobs at maximum health",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
- return (m.fieldMode === 8 || m.fieldMode === 7) && tech.mobSpawnWithHealth === 0 && !tech.isMobFullHealth
+ return (m.fieldMode === 8 || m.fieldMode === 7) && tech.mobSpawnWithHealth === 0
},
- requires: "cloaking, pilot wave, not reaction inhibitor, yield stress",
+ requires: "cloaking, pilot wave, not reaction inhibitor",
effect() {
tech.isMobFullHealthCloak = true
},
@@ -8760,34 +8796,6 @@ const tech = {
// tech.sneakAttackDmg = 4.33 //333% + 100%
// }
// },
- {
- name: "dynamical systems",
- description: `use ${powerUps.orb.research(2)}
+35% damage`,
- isFieldTech: true,
- maxCount: 1,
- count: 0,
- frequency: 3,
- frequencyDefault: 3,
- allowed() {
- return (m.fieldMode === 5 || m.fieldMode === 7 || m.fieldMode === 8) && (build.isExperimentSelection || powerUps.research.count > 1)
- },
- requires: "cloaking, pilot wave, or plasma torch",
- damage: 1.35,
- effect() {
- tech.damage *= this.damage
- tech.isCloakingDamage = true
- for (let i = 0; i < 2; i++) {
- if (powerUps.research.count > 0) powerUps.research.changeRerolls(-1)
- }
- },
- remove() {
- tech.isCloakingDamage = false
- if (this.count > 0) {
- tech.damage /= this.damage
- powerUps.research.changeRerolls(2)
- }
- }
- },
{
name: "WIMPs",
description: `at the end of each level spawn ${powerUps.orb.research(4)}
and a dangerous particle that slowly chases you`,
@@ -8818,9 +8826,9 @@ const tech = {
frequency: 3,
frequencyDefault: 3,
allowed() {
- return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9 || m.fieldMode === 10) && (build.isExperimentSelection || powerUps.research.count > 2)
+ return (m.fieldMode === 8 || m.fieldMode === 6 || m.fieldMode === 9) && (build.isExperimentSelection || powerUps.research.count > 2)
},
- requires: "wormhole, time dilation, negative mass, pilot wave, grappling hook",
+ requires: "wormhole, time dilation, negative mass, pilot wave",
effect() {
tech.fieldDuplicate = 0.11
powerUps.setPowerUpMode(); //needed after adjusting duplication chance
@@ -8988,7 +8996,7 @@ const tech = {
},
{
name: "CIWS",
- description: "grappling hook uses 18 energy
to fire harpoons at nearby mobs",
+ description: "grappling hook uses 10 energy
to fire harpoons at nearby mobs",
isFieldTech: true,
maxCount: 1,
count: 0,
@@ -9006,10 +9014,11 @@ const tech = {
}
},
{
- name: "rupture",
- description: "after grappling hook impacts solid objects
generate an explosion",
+ name: "swarf",
+ // description: "after grappling hook impacts solid objects generate an explosion and become briefly invulnerable",
+ description: "after grappling hook impacts something
eject nails splinters towards nearby mobs",
isFieldTech: true,
- maxCount: 1,
+ maxCount: 3,
count: 0,
frequency: 2,
frequencyDefault: 2,
@@ -9018,24 +9027,24 @@ const tech = {
},
requires: "grappling hook, not reel, tokamak",
effect() {
- tech.isHookExplosion = true
+ tech.hookNails += 4
},
remove() {
- tech.isHookExplosion = false
+ tech.hookNails = 0
}
},
{
name: "reel",
- description: "+400% block collision damage
+30 energy when reeling in far away blocks",
+ description: "+400% block collision damage
up to +75 energy after reeling in blocks",
isFieldTech: true,
maxCount: 1,
count: 0,
frequency: 1,
frequencyDefault: 1,
allowed() {
- return m.fieldMode === 10 && !tech.isTokamak && tech.blockDamage === 0.075 && !tech.isHookExplosion
+ return m.fieldMode === 10 && !tech.isTokamak && tech.blockDamage === 0.075 && !tech.hookNails
},
- requires: "grappling hook, not mass driver, rupture, tokamak",
+ requires: "grappling hook, not mass driver, swarf, tokamak",
effect() {
tech.blockDamage = 0.375
tech.isReel = true
@@ -11910,7 +11919,7 @@ const tech = {
isFastFoam: null,
isSporeGrowth: null,
isStimulatedEmission: null,
- nailGun: null,
+ // nailGun: null,
nailInstantFireRate: null,
isCapacitor: null,
isEnergyNoAmmo: null,
@@ -12148,12 +12157,11 @@ const tech = {
isPrinter: null,
// isHookWire: null,
isHookDefense: null,
- isHookExplosion: null,
+ hookNails: null,
isHarpoonDefense: null,
isReel: null,
harpoonPowerUpCycle: null,
isHarpoonFullHealth: null,
- isMobFullHealth: null,
isMobFullHealthCloak: null,
isMobLowHealth: null,
isDamageCooldown: null,
diff --git a/todo.txt b/todo.txt
index 3bf436e..30494eb 100644
--- a/todo.txt
+++ b/todo.txt
@@ -1,16 +1,71 @@
******************************************************** NEXT PATCH **************************************************
-tech: hyperpolarization - reduce the CD on depolarization by 1 second
+mob: laserLayer - leaves behind lasers that persist for a few seconds
+ghoster mobs do 66% less damage, but they eject your ammo
-metamaterial absorber 22->25% chance to get power up for mobs not killed
-symbiosis -0.5 -> 0.25 max health after killing a mob
-dazzler -15->10 energy after decloaking and stunning mobs
-Hilbert space 142->300% damage
+grappling hook tech rupture renamed swarf
+ fires several nails at nearby mobs, not explosions
+grappling hook 6->9 energy per second
+CIWS 18->10 energy
+reel +40->75 energy reeling blocks
+wormhole 5->7% duplication
+cloaking no longer drains energy, this fixes a can't cloak bug
+ dazzler no longer drains energy
+ dazzler range reduced by 15%
+ dazzler stuns for 3->2 seconds
+zero point energy 100->166 max energy
+expansion 40->77 max energy
+annihilation -33% of max energy -> 10 energy
+dynamical systems is no longer a field tech 35->30 damage
+tessellation is no longer a field tech 50->35 defense
+yield stress removed
+ topological defect 80->111% damage
+ brittle 80->111% damage
+commodities exchange 6-12 -> 10-14 power ups
+heat engine 50->40% damage
+flame test grenades clusters explode 40% faster
+alternator uses 10->0% energy for harpoon
+
+finally made a shared vertexCollision function
+ this might cause some bugs with laser-like effects...
-fixed bug with 1000x more frequent enthalpy
*********************************************************** TODO *****************************************************
+increase damage for each not picked up power up on the level
+
+make a laserLayerBoss
+ add lasers on player's history
+
+button/switch input ideas from Cocoon game
+ pick up blocks that have a rubber band attached to a sliding switch
+ as player moves the vector direction of the rubber band will move the slider left or right
+ use this to open doors, move larger blocks, ...
+ switches that toggle left, right when player presses input.field while standing nearby
+ replace laser off on switch?
+ platform that rises up when player presses input.field while standing
+ How to instruct player to use field on these?
+ color with field #0ff
+ draw field effect
+ make it still functional without the field button
+
+tech: - getting a new gun also gives you 2 random tech for that gun
+ or a field?
+ can these guntech tech be converted into a player choice?
+
+tech: interest - research and ammo increases by 10% at the start of each level?
+ spawn research and ammo at start of new level
+ extend to current health?
+
+how to reduce the number of clicks and keypresses
+ auto fire mode
+ player shoots at whatever is nearby
+ should player have to look towards mobs?
+ increase ammo?
+
+animate egg laying mobs
+ just draw a circle when it happens?
+
improve new player experience
training is too long to be a tutorial
before nail gun level offer player option to continue or switch to normal game
@@ -51,7 +106,7 @@ make grappling hook of different shapes
longer
circular with spikes
indicate tech upgrades?
- rupture, reel, tokamak
+ swarf, reel, tokamak
do this in draw or in verticies?
draw can have different colors
@@ -1097,6 +1152,7 @@ possible names for tech
Pyroelectricity - voltage from temp changes - upgrade from piezoelectricity
Unruh effect - accelerating makes heat/thermal particles
configuration space - holds the position of everything
+ stress–energy tensor
******************************************************** CARS IMAGES ********************************************************